17 #include "jpatcher_api.h"
32 t_object* patcherview;
36 t_atom *output_buffer;
44 OutPtr OutNew(t_symbol *msg,
long argc, t_atom* argv);
45 void OutFree(OutPtr
self);
46 t_max_err OutNotify(OutPtr
self, t_symbol *s, t_symbol *msg, t_object* sender,
TTPtr data);
47 void OutQFn(OutPtr
self);
48 void OutAssist(OutPtr
self,
void* b,
long msg,
long arg,
char* dst);
49 TTErr OutReset(OutPtr
self,
long vectorSize);
51 void OutIterateResetCallback(OutPtr
self, t_object* obj);
52 void OutIterateSetupCallback(OutPtr
self, t_object* obj);
53 void OutAttachToPatchlinesForPatcher(OutPtr
self, t_object* patcher);
54 t_int* OutPerform(t_int* w);
55 void OutTick(OutPtr
self);
56 void OutDsp(OutPtr
self, t_signal** sp,
short* count);
61 static t_class* sOutClass;
72 common_symbols_init();
74 c = class_new(
"j.unsig=", (method)OutNew, (method)OutFree,
sizeof(Out), (method)0L, A_GIMME, 0);
76 class_addmethod(c, (method)OutNotify,
"notify", A_CANT, 0);
77 class_addmethod(c, (method)OutReset,
"audio.reset", A_CANT, 0);
78 class_addmethod(c, (method)OutConnect,
"audio.connect", A_OBJ, A_LONG, 0);
81 class_addmethod(c, (method)OutDsp,
"dsp", A_CANT, 0);
82 class_addmethod(c, (method)OutAssist,
"assist", A_CANT, 0);
83 class_addmethod(c, (method)object_obex_dumpout,
"dumpout", A_CANT, 0);
89 class_register(_sym_box, c);
98 OutPtr OutNew(t_symbol *msg,
long argc, t_atom* argv)
102 long attrstart = attr_args_offset(argc, argv);
107 self = OutPtr(object_alloc(sOutClass));
109 self->maxNumChannels = 2;
110 if (attrstart && argv)
111 self->maxNumChannels = atom_getlong(argv);
115 self->output_buffer = (t_atom *)malloc(self->maxNumChannels *
sizeof(t_atom));
123 attr_args_process(
self, argc, argv);
125 object_obex_store((
void*)
self, _sym_dumpout, (
object*)outlet_new(
self, NULL));
126 self->s_out = listout((t_pxobject *)
self);
127 dsp_setup((t_pxobject*)
self, 1);
128 self->clock = clock_new(
self, (method)OutTick);
130 self->qelem = qelem_new(
self, (method)OutQFn);
131 self->obj.z_misc = Z_NO_INPLACE | Z_PUT_LAST;
137 void OutFree(OutPtr
self)
139 dsp_free((t_pxobject*)
self);
140 object_free(self->clock);
141 if (self->patcherview) {
142 object_detach_byptr(
self, self->patcherview);
143 self->patcherview = NULL;
145 if (self->output_buffer)
146 free(self->output_buffer);
149 qelem_free(self->qelem);
156 t_max_err OutNotify(OutPtr
self, t_symbol *s, t_symbol *msg, t_object* sender,
TTPtr data)
158 if (sender == self->patcherview) {
159 if (msg == _sym_attr_modified) {
160 t_symbol *name = (t_symbol*)object_method((t_object*)data, _sym_getname);
161 if (name == _sym_dirty) {
162 qelem_set(self->qelem);
165 else if (msg == _sym_free)
166 self->patcherview = NULL;
169 if (msg == _sym_free) {
171 t_object* sourceObject;
174 t_object* destObject;
177 #ifdef DEBUG_NOTIFICATIONS
178 object_post(SELF,
"patch line deleted");
179 #endif // DEBUG_NOTIFICATIONS
182 sourceBox = jpatchline_get_box1(sender);
185 sourceObject = jbox_get_object(sourceBox);
186 sourceOutlet = jpatchline_get_outletnum(sender);
187 destBox = jpatchline_get_box2(sender);
190 destObject = jbox_get_object(destBox);
191 destInlet = jpatchline_get_inletnum(sender);
194 if ( zgetfn(sourceObject, gensym(
"audio.object")) && zgetfn(destObject, gensym(
"audio.object")) ) {
195 #ifdef DEBUG_NOTIFICATIONS
196 object_post(SELF,
"deleting audio graph patchline!");
197 #endif // DEBUG_NOTIFICATIONS
199 object_method(destObject, gensym(
"audio.drop"), destInlet, sourceObject, sourceOutlet);
210 void OutQFn(OutPtr
self)
214 #ifdef DEBUG_NOTIFICATIONS
215 object_post(SELF,
"patcher dirtied");
216 #endif // DEBUG_NOTIFICATIONS
218 object_method(self->patcher, gensym(
"iterate"), (method)OutIterateSetupCallback,
self, PI_DEEP, &result);
222 OutAttachToPatchlinesForPatcher(
self, self->patcher);
227 void OutAssist(OutPtr
self,
void* b,
long msg,
long arg,
char* dst)
230 strcpy(dst,
"multichannel audio connection");
233 strcpy(dst,
"dumpout");
235 strcpy(dst,
"unsig list");
241 TTErr OutReset(OutPtr
self,
long vectorSize)
243 self->hasReset =
true;
244 self->hasConnections =
false;
245 return self->audioGraphObject->resetAudio();
251 self->hasConnections =
true;
252 return self->audioGraphObject->connectAudio(audioSourceObject, sourceOutletNumber);
256 void OutIterateResetCallback(OutPtr
self, t_object* obj)
258 t_max_err err = MAX_ERR_NONE;
259 method audioResetMethod = zgetfn(obj, gensym(
"audio.reset"));
261 if (audioResetMethod)
262 err = (t_max_err)audioResetMethod(obj, self->vectorSize);
266 void OutIterateSetupCallback(OutPtr
self, t_object* obj)
268 t_max_err err = MAX_ERR_NONE;
269 method audioSetupMethod = zgetfn(obj, gensym(
"audio.setup"));
271 if (audioSetupMethod)
272 err = (t_max_err)audioSetupMethod(obj);
276 void OutAttachToPatchlinesForPatcher(OutPtr
self, t_object* patcher)
278 t_object* patchline = object_attr_getobj(patcher, _sym_firstline);
279 t_object* box = jpatcher_get_firstobject(patcher);
282 object_attach_byptr_register(
self, patchline, _sym_nobox);
283 patchline = object_attr_getobj(patchline, _sym_nextline);
287 t_symbol *classname = jbox_get_maxclass(box);
289 if (classname == _sym_jpatcher) {
290 t_object* subpatcher = jbox_get_object(box);
292 OutAttachToPatchlinesForPatcher(
self, subpatcher);
294 box = jbox_get_nextobject(box);
300 t_int* OutPerform(t_int* w)
302 OutPtr
self = (OutPtr)(w[1]);
305 if (!self->obj.z_disabled) {
306 if (self->hasConnections) {
307 self->audioGraphObject->lockProcessing();
308 self->audioGraphObject->preprocess(self->initData);
309 self->audioGraphObject->process(self->audioSignal, self->sampleCount);
310 self->sampleCount +=
self->vectorSize;
311 self->audioGraphObject->unlockProcessing();
313 numChannels = TTClip<TTUInt16>(
self->maxNumChannels, 0,
self->audioSignal->getNumChannelsAsInt());
315 for (
TTUInt16 channel=0; channel<numChannels; channel++) {
316 atom_setfloat(self->output_buffer+channel, self->audioSignal->getSample(channel, 0));
318 self->numChannels = numChannels;
319 clock_delay(self->clock, 0);
324 self->hasReset =
false;
329 void OutTick(OutPtr
self)
331 outlet_list(self->s_out, NULL, self->numChannels, self->output_buffer);
335 void OutDsp(OutPtr
self, t_signal** sp,
short* count)
339 void **audioVectors = NULL;
343 self->vectorSize = sp[0]->s_n;
345 #ifdef DEBUG_NOTIFICATIONS
346 object_post(SELF,
"dsp method called");
347 #endif // DEBUG_NOTIFICATIONS
370 if (!self->hasReset) {
371 t_object* patcher = NULL;
372 t_object* parent = NULL;
373 t_object* patcherview = NULL;
376 err = object_obex_lookup(
self, gensym(
"#P"), &patcher);
380 parent = object_attr_getobj(patcher, _sym_parentpatcher);
384 object_method(patcher, gensym(
"iterate"), (method)OutIterateResetCallback,
self, PI_DEEP, &result);
385 object_method(patcher, gensym(
"iterate"), (method)OutIterateSetupCallback,
self, PI_DEEP, &result);
389 if (!self->patcherview) {
390 patcherview = jpatcher_get_firstview(patcher);
391 self->patcherview = patcherview;
392 self->patcher = patcher;
393 object_attach_byptr_register(
self, patcherview, _sym_nobox);
399 OutAttachToPatchlinesForPatcher(
self, self->patcher);
403 audioVectors = (
void**)sysmem_newptr(
sizeof(
void*) * (1));
405 audioVectors[k] =
self;
414 self->numChannels =
self->maxNumChannels;
415 self->audioGraphObject->getUnitGenerator().get(kTTSym_sampleRate, sp[0]->s_sr);
416 self->audioGraphObject->resetSampleStamp();
417 self->sampleCount = 0;
419 dsp_addv(OutPerform, k, audioVectors);
420 sysmem_freeptr(audioVectors);
422 self->initData.vectorSize =
self->vectorSize;
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
std::uint16_t TTUInt16
16 bit unsigned integer
int C74_EXPORT main(void)
Set up this class as a Max external the first time an object of this kind is instantiated.
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.
#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]