18 #include "jpatcher_api.h"
22 typedef struct _unpack {
33 t_object* patcherview;
41 t_unpack* UnpackNew(t_symbol *msg,
long argc, t_atom* argv);
42 void UnpackFree(t_unpack*
self);
43 t_max_err UnpackNotify(t_unpack*
self, t_symbol *s, t_symbol *msg, t_object* sender,
TTPtr data);
44 void UnpackQFn(t_unpack*
self);
45 void UnpackAssist(t_unpack*
self,
void* b,
long msg,
long arg,
char* dst);
46 TTErr UnpackReset(t_unpack*
self,
long vectorSize);
48 void UnpackIterateResetCallback(t_unpack*
self, t_object* obj);
49 void UnpackIterateSetupCallback(t_unpack*
self, t_object* obj);
50 void UnpackAttachToPatchlinesForPatcher(t_unpack*
self, t_object* patcher);
51 void UnpackDsp64(t_unpack*
self, t_object* dsp64,
short *count,
double samplerate,
long maxvectorsize,
long flags);
56 static t_class* sUnpackClass;
67 common_symbols_init();
69 c = class_new(
"j.unpack=", (method)UnpackNew, (method)UnpackFree,
sizeof(t_unpack), (method)0L, A_GIMME, 0);
71 class_addmethod(c, (method)UnpackNotify,
"notify", A_CANT, 0);
72 class_addmethod(c, (method)UnpackReset,
"audio.reset", A_CANT, 0);
73 class_addmethod(c, (method)UnpackConnect,
"audio.connect", A_OBJ, A_LONG, 0);
76 class_addmethod(c, (method)UnpackDsp64,
"dsp64", A_CANT, 0);
77 class_addmethod(c, (method)UnpackAssist,
"assist", A_CANT, 0);
78 class_addmethod(c, (method)object_obex_dumpout,
"dumpout", A_CANT, 0);
84 class_register(_sym_box, c);
93 t_unpack* UnpackNew(t_symbol *msg,
long argc, t_atom* argv)
97 long attrstart = attr_args_offset(argc, argv);
102 self = (t_unpack*)object_alloc(sUnpackClass);
104 self->maxNumChannels = 2;
105 if (attrstart && argv)
106 self->maxNumChannels = atom_getlong(argv);
116 attr_args_process(
self, argc, argv);
118 object_obex_store((
void*)
self, _sym_dumpout, (
object*)outlet_new(
self, NULL));
119 dsp_setup((t_pxobject*)
self, 1);
120 for (i=0; i <
self->maxNumChannels; i++)
121 outlet_new((t_pxobject*)
self,
"signal");
123 self->qelem = qelem_new(
self, (method)UnpackQFn);
124 self->obj.z_misc = Z_NO_INPLACE | Z_PUT_LAST;
130 void UnpackFree(t_unpack*
self)
132 dsp_free((t_pxobject*)
self);
133 if (self->patcherview) {
134 object_detach_byptr(
self, self->patcherview);
135 self->patcherview = NULL;
138 qelem_free(self->qelem);
145 t_max_err UnpackNotify(t_unpack*
self, t_symbol *s, t_symbol *msg, t_object* sender,
TTPtr data)
147 if (sender == self->patcherview) {
148 if (msg == _sym_attr_modified) {
149 t_symbol *name = (t_symbol*)object_method((t_object*)data, _sym_getname);
150 if (name == _sym_dirty) {
151 qelem_set(self->qelem);
154 else if (msg == _sym_free)
155 self->patcherview = NULL;
158 if (msg == _sym_free) {
160 t_object* sourceObject;
163 t_object* destObject;
166 #ifdef DEBUG_NOTIFICATIONS
167 object_post(SELF,
"patch line deleted");
168 #endif // DEBUG_NOTIFICATIONS
171 sourceBox = jpatchline_get_box1(sender);
174 sourceObject = jbox_get_object(sourceBox);
175 sourceOutlet = jpatchline_get_outletnum(sender);
176 destBox = jpatchline_get_box2(sender);
179 destObject = jbox_get_object(destBox);
180 destInlet = jpatchline_get_inletnum(sender);
183 if ( zgetfn(sourceObject, gensym(
"audio.object")) && zgetfn(destObject, gensym(
"audio.object")) ) {
184 #ifdef DEBUG_NOTIFICATIONS
185 object_post(SELF,
"deleting audio graph patchline!");
186 #endif // DEBUG_NOTIFICATIONS
188 object_method(destObject, gensym(
"audio.drop"), destInlet, sourceObject, sourceOutlet);
189 UnpackReset(
self, self->vectorSize);
200 void UnpackQFn(t_unpack*
self)
204 #ifdef DEBUG_NOTIFICATIONS
205 object_post(SELF,
"patcher dirtied");
206 #endif // DEBUG_NOTIFICATIONS
208 object_method(self->patcher, gensym(
"iterate"), (method)UnpackIterateSetupCallback,
self, PI_DEEP, &result);
212 UnpackAttachToPatchlinesForPatcher(
self, self->patcher);
217 void UnpackAssist(t_unpack*
self,
void* b,
long msg,
long arg,
char* dst)
220 strcpy(dst,
"multichannel audio connection and control messages");
222 if (arg == self->maxNumChannels)
223 strcpy(dst,
"dumpout");
225 snprintf(dst, 256,
"(signal) single-channel output Nr. %ld", arg + 1);
229 TTErr UnpackReset(t_unpack*
self,
long vectorSize)
231 self->hasReset =
true;
232 self->hasConnections =
false;
233 return self->audioGraphObject->resetAudio();
239 self->hasConnections =
true;
240 return self->audioGraphObject->connectAudio(audioSourceObject, sourceOutletNumber);
244 void UnpackIterateResetCallback(t_unpack*
self, t_object* obj)
246 t_max_err err = MAX_ERR_NONE;
247 method audioResetMethod = zgetfn(obj, gensym(
"audio.reset"));
249 if (audioResetMethod)
250 err = (t_max_err)audioResetMethod(obj, self->vectorSize);
254 void UnpackIterateSetupCallback(t_unpack*
self, t_object* obj)
256 t_max_err err = MAX_ERR_NONE;
257 method audioSetupMethod = zgetfn(obj, gensym(
"audio.setup"));
259 if (audioSetupMethod)
260 err = (t_max_err)audioSetupMethod(obj);
264 void UnpackAttachToPatchlinesForPatcher(t_unpack*
self, t_object* patcher)
266 t_object* patchline = object_attr_getobj(patcher, _sym_firstline);
267 t_object* box = jpatcher_get_firstobject(patcher);
270 object_attach_byptr_register(
self, patchline, _sym_nobox);
271 patchline = object_attr_getobj(patchline, _sym_nextline);
275 t_symbol *classname = jbox_get_maxclass(box);
277 if (classname == _sym_jpatcher) {
278 t_object* subpatcher = jbox_get_object(box);
280 UnpackAttachToPatchlinesForPatcher(
self, subpatcher);
282 box = jbox_get_nextobject(box);
288 void UnpackPerform64(t_unpack*
self, t_object* dsp64,
double **ins,
long numins,
double **outs,
long numouts,
long sampleframes,
long flags,
void *userparam)
292 if (self->hasConnections) {
293 self->audioGraphObject->lockProcessing();
294 self->audioGraphObject->preprocess(self->initData);
295 self->audioGraphObject->process(self->audioSignal, self->sampleStamp);
296 self->sampleStamp += sampleframes;
297 self->audioGraphObject->unlockProcessing();
299 numChannels = TTClip<TTUInt16>(
self->numChannels, 0,
self->audioSignal->getNumChannelsAsInt());
300 for (
TTUInt16 channel=0; channel < numChannels; channel++)
301 self->audioSignal->getVectorCopy(channel, self->vectorSize, outs[channel]);
303 if (numChannels < self->maxNumChannels) {
304 for (
TTUInt16 channel=numChannels; channel <
self->maxNumChannels; channel++)
305 for (
int i=0 ; i <
self->vectorSize; i++)
306 outs[channel][i] = 0.0;
310 for (
TTUInt16 channel=0; channel <
self->numChannels; channel++) {
311 for (
int i=0 ; i <
self->vectorSize; i++)
312 outs[channel][i] = 0.0;
316 self->hasReset =
false;
321 void UnpackDsp64(t_unpack*
self, t_object* dsp64,
short *count,
double samplerate,
long maxvectorsize,
long flags)
327 self->vectorSize = maxvectorsize;
329 #ifdef DEBUG_NOTIFICATIONS
330 object_post(SELF,
"dsp method called");
331 #endif // DEBUG_NOTIFICATIONS
333 t_object* patcher = NULL;
334 t_object* parent = NULL;
335 t_object* patcherview = NULL;
338 err = object_obex_lookup(
self, gensym(
"#P"), &patcher);
342 parent = object_attr_getobj(patcher, _sym_parentpatcher);
367 if (!self->hasReset) {
369 object_method(patcher, gensym(
"iterate"), (method)UnpackIterateResetCallback,
self, PI_DEEP, &result);
370 object_method(patcher, gensym(
"iterate"), (method)UnpackIterateSetupCallback,
self, PI_DEEP, &result);
375 if (!self->patcherview) {
376 patcherview = jpatcher_get_firstview(patcher);
377 self->patcherview = patcherview;
378 self->patcher = patcher;
379 object_attach_byptr_register(
self, patcherview, _sym_nobox);
384 UnpackAttachToPatchlinesForPatcher(
self, self->patcher);
386 self->numChannels = 0;
387 for (i=1; i <=
self->maxNumChannels; i++) {
391 self->audioGraphObject->getUnitGenerator().set(kTTSym_sampleRate, samplerate);
392 self->audioGraphObject->resetSampleStamp();
393 self->sampleStamp = 0;
395 self->initData.vectorSize =
self->vectorSize;
397 object_method(dsp64, gensym(
"dsp_add64"),
self, UnpackPerform64, 0, NULL);
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
std::uint16_t TTUInt16
16 bit unsigned integer
TTErr TTObjectBaseRelease(TTObjectBasePtr *anObject)
DEPRECATED.
std::uint64_t TTUInt64
64 bit unsigned integer
TTFOUNDATION_EXPORT TTEnvironment * ttEnvironment
The environment object has one instance, which is global in scope.
Base class for all first-class Jamoma objects.
TTErr setAttributeValue(const TTSymbol name, TTValue &value)
Set an attribute value for an object.
int C74_EXPORT main(void)
Set up this class as a Max external the first time an object of this kind is instantiated.
#define TT
This macro is defined as a shortcut for doing a lookup in the symbol table.
void * TTPtr
A generic pointer.
TTErr TTObjectBaseInstantiate(const TTSymbol className, TTObjectBasePtr *returnedObjectPtr, const TTValue arguments)
DEPRECATED.
The TTAudioSignal class represents N vectors of audio samples for M channels.
A thin wrapper of Jamoma AudioGraph for use in the Cycling '74 Max/MSP environment.
TTErr MaxAudioGraphObject(t_object *x, TTAudioGraphObjectBasePtr *returnedAudioGraphObject)
Returns a pointer to the Jamoma Audio Graph object that is wrapped by this Max object.
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
The TTAudioGraphObjectBase wraps a TTDSP object such that it is possible to build a dynamic graph of ...
[doxygenAppendixC_bitmaskExample]
TTErr MaxAudioGraphDrop(t_object *x, long inletNumber, t_object *sourceMaxObject, long sourceOutletNumber)
Method called when a connection from an upstream node is dropped.
void resize(size_type n)
Change the number of elements.
[doxygenAppendixC_copyExample]