t_object *wrappedModularClass_new(t_symbol *name, long argc, t_atom *argv)
{
	WrappedClass*				wrappedMaxClass = NULL;
    WrappedModularInstancePtr	x = NULL;
	TTErr						err = kTTErrNone;
	
	// Find the WrappedClass
	hashtab_lookup(wrappedMaxClasses, name, (t_object**)&wrappedMaxClass);
	
	// If the WrappedClass has a validity check defined, then call the validity check function.
	// If it returns an error, then we won't instantiate the object.
	if (wrappedMaxClass) {
		if (wrappedMaxClass->validityCheck)
			err = wrappedMaxClass->validityCheck(wrappedMaxClass->validityCheckArgument);
		else
			err = kTTErrNone;
	}
	else
		err = kTTErrGeneric;
	
	if (!err)
		x = (WrappedModularInstancePtr)object_alloc(wrappedMaxClass->maxClass);
	
    if (x) {
		
		x->wrappedClassDefinition = wrappedMaxClass;
		
		x->useInternals = NO;
        x->internals = new TTHash();
		x->address = kTTAdrsEmpty;
		x->argv = NULL;
		x->iterateInternals = NO;
		
#ifdef ARRAY_EXTERNAL
		x->arrayFormatInteger = TTString();
		x->arrayFormatString = TTString();
#endif
        
        x->patcherPtr = NULL;
        x->patcherContext = kTTSymEmpty;
        x->patcherClass = kTTSymEmpty;
        x->patcherName = kTTSymEmpty;
        x->patcherAddress = kTTAdrsEmpty;
		
		// dumpout
		object_obex_store((void *)x, _sym_dumpout, (object *)outlet_new(x,NULL));
		
		// Make specific things
		ModularSpec *spec = (ModularSpec*)wrappedMaxClass->specificities;
		if (spec) {
			if (spec->_new)
				spec->_new((TTPtr)x, argc, argv);
		}
		else
			// handle attribute args
			attr_args_process(x, argc, argv);
	}
	return (t_object*)x;
}
ObjectPtr wrappedClass_new(SymbolPtr name, AtomCount argc, AtomPtr argv)
{	
	WrappedClass*		wrappedMaxClass = NULL;
    WrappedInstancePtr	self = NULL;
	TTValue				v;
	TTErr				err = kTTErrNone;
	TTUInt8				numInputs = 1;
	TTUInt8				numOutputs = 1;
 	long				attrstart = attr_args_offset(argc, argv);		// support normal arguments
	
	// Find the WrappedClass
	hashtab_lookup(wrappedMaxClasses, name, (ObjectPtr*)&wrappedMaxClass);
	
	// If the WrappedClass has a validity check defined, then call the validity check function.
	// If it returns an error, then we won't instantiate the object.
	if (wrappedMaxClass) {
		if (wrappedMaxClass->validityCheck)
			err = wrappedMaxClass->validityCheck(wrappedMaxClass->validityCheckArgument);
		else
			err = kTTErrNone;
	}
	else
		err = kTTErrGeneric;
	
	if (!err)
		self = (WrappedInstancePtr)object_alloc(wrappedMaxClass->maxClass);
    if (self){

		if (wrappedMaxClass->options && !wrappedMaxClass->options->lookup(TT("argumentDefinesNumInlets"), v)) {
			long argumentOffsetToDefineTheNumberOfInlets = v;
			if ((attrstart-argumentOffsetToDefineTheNumberOfInlets > 0) && argv+argumentOffsetToDefineTheNumberOfInlets)
				numInputs = atom_getlong(argv+argumentOffsetToDefineTheNumberOfInlets);
		}
		for (TTUInt16 i=numInputs-1; i>0; i--)
			self->inlets[i-1] = proxy_new(self, i, NULL);
		
    	object_obex_store((void*)self, _sym_dumpout, (object*)outlet_new(self, NULL));	// dumpout
		if (wrappedMaxClass->options && !wrappedMaxClass->options->lookup(TT("argumentDefinesNumOutlets"), v)) {
			long argumentOffsetToDefineTheNumberOfOutlets = v;
			if ((attrstart-argumentOffsetToDefineTheNumberOfOutlets > 0) && argv+argumentOffsetToDefineTheNumberOfOutlets)
				numOutputs = atom_getlong(argv+argumentOffsetToDefineTheNumberOfOutlets);
		}
		for (TTInt16 i=numOutputs-1; i>=0; i--)
			self->audioGraphOutlets[i] = outlet_new(self, "audio.connect");

		self->wrappedClassDefinition = wrappedMaxClass;
		v.setSize(3);
		v.set(0, wrappedMaxClass->ttClassName);
		v.set(1, numInputs);
		v.set(2, numOutputs);
		err = TTObjectInstantiate(TT("audio.object"), (TTObjectPtr*)&self->audioGraphObject, v);
				
		attr_args_process(self, argc, argv);
	}
	return ObjectPtr(self);
}
t_eobj* wrappedClass_new(t_symbol* name, long argc, t_atom* argv)
{	
	WrappedClass*		wrappedPdClass = NULL;
    WrappedInstancePtr	x = NULL;
	TTValue				sr(sys_getsr());
	TTValue				v, none;
 	long				attrstart = attr_args_offset(argc, argv);		// support normal arguments
	TTErr				err = kTTErrNone;
	
	// Find the WrappedClass
    //hashtab_lookup(wrappedPdClasses, name, (t_object**)&wrappedPdClass);
    wrappedPdClass = (WrappedClass*)wrappedPdClasses[name->s_name];
	
	// If the WrappedClass has a validity check defined, then call the validity check function.
	// If it returns an error, then we won't instantiate the object.
	if (wrappedPdClass) {
		if (wrappedPdClass->validityCheck)
			err = wrappedPdClass->validityCheck(wrappedPdClass->validityCheckArgument);
		else
			err = kTTErrNone;
	}
	else
		err = kTTErrGeneric;
	
	if (!err)
        x = (WrappedInstancePtr)eobj_new(wrappedPdClass->pdClass);
    if (x) {
		x->wrappedClassDefinition = wrappedPdClass;
		x->maxNumChannels = 2;		// An initial argument to this object will set the maximum number of channels
		if (attrstart && argv)
			x->maxNumChannels = atom_getlong(argv);
		
		ttEnvironment->setAttributeValue(kTTSym_sampleRate, sr);
		
		if (wrappedPdClass->options && !wrappedPdClass->options->lookup(TT("numChannelsUseFixedRatioInputsToOutputs"), v)) {
		   TTUInt16	inputs;
		   TTUInt16	outputs;
		   
		   inputs = v[0];
		   outputs = v[1];
		   x->numInputs = x->maxNumChannels * inputs;
		   x->numOutputs = x->maxNumChannels * outputs;
		}
		else if (wrappedPdClass->options && !wrappedPdClass->options->lookup(TT("fixedNumChannels"), v)) {
			TTUInt16 numChannels;
			
			numChannels = v[0];
			x->numInputs = numChannels;
			x->numOutputs = numChannels;
		}
		else if (wrappedPdClass->options && !wrappedPdClass->options->lookup(TT("fixedNumOutputChannels"), v)) {
			TTUInt16 numChannels;
			
			numChannels = v[0];
			x->numInputs = x->maxNumChannels;
			x->numOutputs = numChannels;
		}
		else {
		   x->numInputs = x->maxNumChannels;
		   x->numOutputs = x->maxNumChannels;
		}
		
		if (wrappedPdClass->options && !wrappedPdClass->options->lookup(TT("additionalSignalInputSetsAttribute"), v)) {
			x->numControlSignals = v.size();
			x->controlSignalNames = new TTSymbol[x->numControlSignals];
			for (TTUInt16 i=0; i<x->numControlSignals; i++) {
				x->numInputs++;
				x->controlSignalNames[i] = v[i];
			}
		}
		
		x->wrappedObject = new TTAudioObject(wrappedPdClass->ttblueClassName, x->maxNumChannels);
		x->audioIn = new TTAudio(x->numInputs);
		x->audioOut = new TTAudio(x->numOutputs);
		attr_args_process(x,argc,argv);				// handle attribute args

		/*
		x->dumpOut = outlet_new((t_object*)x,NULL);

        for (short i=1; i < x->numInputs; i++)
            inlet_new(&x->obj.o_obj, &x->obj.o_obj.ob_pd, &s_signal, &s_signal);
		*/

        // eobj_dspsetup(x,x->numInputs,0);
        // dsp_setup(x, x->numInputs);			// inlets
				
		//if (wrappedPdClass->options && !wrappedPdClass->options->lookup(TT("numControlOutlets"), v))
		//	v.get(0, numControlOutlets);
		if (wrappedPdClass->options && !wrappedPdClass->options->lookup(TT("controlOutletFromNotification"), v)) {
            TTUInt16    outletIndex = 0;
            TTSymbol	notificationName;
            
 			outletIndex = v[0];
 			notificationName = v[1];
            
            // TODO: to support more than one notification->outlet we need see how many args are actually passed-in
            // and then we need to track them in a hashtab or something...
            
            x->controlOutlet = outlet_new((t_object*)x, NULL);
            
            x->controlCallback = new TTObject("callback");
            x->controlCallback->set("function", TTPtr(&wrappedClass_receiveNotificationForOutlet));
            x->controlCallback->set("baton", TTPtr(x));	
 
        	// dynamically add a message to the callback object so that it can handle the 'objectFreeing' notification
            x->controlCallback->instance()->registerMessage(notificationName, (TTMethod)&TTCallback::notify, kTTMessagePassValue);
            
            // tell the source that is passed in that we want to watch it
            x->wrappedObject->registerObserverForNotifications(*x->controlCallback);

        }
        
        x->outlets = new t_outlet*[x->numOutputs];
		for (short i=0; i < x->numOutputs; i++)
            x->outlets[i] = outlet_new(&x->obj.o_obj, &s_signal);

        // x->obj.z_misc = Z_NO_INPLACE;
	}
    return (t_eobj*)x;
}