Example #1
0
// Qelem function, which clumps together dirty notifications before making the new connections
void UnpackQFn(UnpackPtr self)
{
	t_atom result;

	#ifdef DEBUG_NOTIFICATIONS
	object_post(SELF, "patcher dirtied");
	#endif // DEBUG_NOTIFICATIONS
	
	object_method(self->patcher, gensym("iterate"), (method)UnpackIterateSetupCallback, self, PI_DEEP, &result);

	// attach to all of the patch cords so we will know if one is deleted
	// we are not trying to detach first -- hopefully this is okay and multiple attachments will be filtered (?)
	UnpackAttachToPatchlinesForPatcher(self, self->patcher);
}
Example #2
0
void UnpackAttachToPatchlinesForPatcher(UnpackPtr self, ObjectPtr patcher)
{
	ObjectPtr	patchline = object_attr_getobj(patcher, _sym_firstline);
	ObjectPtr	box = jpatcher_get_firstobject(patcher);
	
	while (patchline) {
		object_attach_byptr_register(self, patchline, _sym_nobox);
		patchline = object_attr_getobj(patchline, _sym_nextline);
	}
		
	while (box) {
		SymbolPtr	classname = jbox_get_maxclass(box);
		
		if (classname == _sym_jpatcher) {
			ObjectPtr	subpatcher = jbox_get_object(box);
			
			UnpackAttachToPatchlinesForPatcher(self, subpatcher);
		}
		box = jbox_get_nextobject(box);
	}
}
Example #3
0
void UnpackAttachToPatchlinesForPatcher(t_unpack* self, t_object* patcher)
{
	t_object*	patchline = object_attr_getobj(patcher, _sym_firstline);
	t_object*	box = jpatcher_get_firstobject(patcher);

	while (patchline) {
		object_attach_byptr_register(self, patchline, _sym_nobox);
		patchline = object_attr_getobj(patchline, _sym_nextline);
	}

	while (box) {
		t_symbol *classname = jbox_get_maxclass(box);

		if (classname == _sym_jpatcher) {
			t_object*	subpatcher = jbox_get_object(box);

			UnpackAttachToPatchlinesForPatcher(self, subpatcher);
		}
		box = jbox_get_nextobject(box);
	}
}
Example #4
0
// DSP Method
void UnpackDsp64(UnpackPtr self, ObjectPtr dsp64, short *count, double samplerate, long maxvectorsize, long flags)
{
	TTUInt16	i;
	MaxErr		err;
	long		result = 0;
	
	self->vectorSize = maxvectorsize;
	
#ifdef DEBUG_NOTIFICATIONS
	object_post(SELF, "dsp method called");
#endif // DEBUG_NOTIFICATIONS
	
	/*	We need to figure out what objects are connected to what inlets to build the graph:
	 
	 1. Broadcast 'audio.reset' to every object in the patcher, to remove all existing connections.
	 2. Broadcast 'audio.setup' to every object in the patcher, to tell objects to then send
	 'audio.connect' messages to any objects below them.
	 3. When an object received 'audio.connect', then it makes the connection.
	 
	 At this point, the graph is configured and we just need to execute it.
	 We execute the graph from our perform method, which MSP calls once per signal vector.
	 
	 5. Crawl the graph from bottom to top, calling the audio graph preprocess method (prepare for process)
	 6. Crawl the graph from bottom to top, calling the audio graph process method (calculate the samples)
	 7. (Maybe) crawl the graph from bottom to top, calling a audio graph postprocess method
	 
	 For steps 1 & 2, we have to traverse thge patcher twice, 
	 because we have to clear all connections first, then add connections.
	 It won't work to do them both during the same traversal because situations arise
	 Where we setup the chain and then it gets reset again by another object 
	 (since the order in which we traverse objects is undefined).
	 */ 
	
	if (!self->hasReset) {
		ObjectPtr	patcher = NULL;
		ObjectPtr	parent = NULL;
		ObjectPtr	patcherview = NULL;
		
		// first find the top-level patcher
		err = object_obex_lookup(self, gensym("#P"), &patcher);
		parent = patcher;
		while (parent) {
			patcher = parent;
			parent = object_attr_getobj(patcher, _sym_parentpatcher);
		}
		
		// now iterate recursively from the top-level patcher down through all of the subpatchers
		object_method(patcher, gensym("iterate"), (method)UnpackIterateResetCallback, self, PI_DEEP, &result);
		object_method(patcher, gensym("iterate"), (method)UnpackIterateSetupCallback, self, PI_DEEP, &result);
		
		// now let's attach to the patcherview to get notifications about any further changes to the patch cords
		// the patcher 'dirty' attribute is not modified for each change, but the patcherview 'dirty' attribute is
		if (!self->patcherview) {
			patcherview = jpatcher_get_firstview(patcher);
			self->patcherview = patcherview;
			self->patcher = patcher;
			object_attach_byptr_register(self, patcherview, _sym_nobox);			
		}
	}
	
	// now we want to go a step further and attach to all of the patch cords 
	// this is how we will know if one is deleted
	UnpackAttachToPatchlinesForPatcher(self, self->patcher);
		
	self->numChannels = 0;
	for (i=1; i <= self->maxNumChannels; i++) {
		self->numChannels++;
	}
	
	self->audioGraphObject->getUnitGenerator()->setAttributeValue(kTTSym_sampleRate, samplerate);
	self->audioGraphObject->resetSampleStamp();
	self->sampleStamp = 0;
	
	self->initData.vectorSize = self->vectorSize;
	
	object_method(dsp64, gensym("dsp_add64"), self, UnpackPerform64, 0, NULL);
	//dsp_add64(dsp64, (ObjectPtr)self, (t_perfroutine64)UnpackPerform64, 0, NULL);
}