11 #include "TTClassWrapperPd.h"
22 static std::map<std::string,t_object*> wrappedPdClasses;
25 t_eobj* wrappedClass_new(t_symbol* name,
long argc, t_atom* argv)
27 WrappedClass* wrappedPdClass = NULL;
31 long attrstart = attr_args_offset(argc, argv);
36 wrappedPdClass = (WrappedClass*)wrappedPdClasses[name->s_name];
41 if (wrappedPdClass->validityCheck)
42 err = wrappedPdClass->validityCheck(wrappedPdClass->validityCheckArgument);
52 x->wrappedClassDefinition = wrappedPdClass;
53 x->maxNumChannels = 2;
54 if (attrstart && argv)
55 x->maxNumChannels = atom_getlong(argv);
59 if (wrappedPdClass->options && !wrappedPdClass->options->lookup(
TT(
"numChannelsUseFixedRatioInputsToOutputs"), v)) {
65 x->numInputs = x->maxNumChannels * inputs;
66 x->numOutputs = x->maxNumChannels * outputs;
68 else if (wrappedPdClass->options && !wrappedPdClass->options->lookup(
TT(
"fixedNumChannels"), v)) {
72 x->numInputs = numChannels;
73 x->numOutputs = numChannels;
75 else if (wrappedPdClass->options && !wrappedPdClass->options->lookup(
TT(
"fixedNumOutputChannels"), v)) {
79 x->numInputs = x->maxNumChannels;
80 x->numOutputs = numChannels;
83 x->numInputs = x->maxNumChannels;
84 x->numOutputs = x->maxNumChannels;
87 if (wrappedPdClass->options && !wrappedPdClass->options->lookup(
TT(
"additionalSignalInputSetsAttribute"), v)) {
88 x->numControlSignals = v.
size();
89 x->controlSignalNames =
new TTSymbol[x->numControlSignals];
90 for (
TTUInt16 i=0; i<x->numControlSignals; i++) {
92 x->controlSignalNames[i] = v[i];
96 x->wrappedObject =
new TTAudioObject(wrappedPdClass->ttblueClassName, x->maxNumChannels);
97 x->audioIn =
new TTAudio(x->numInputs);
98 x->audioOut =
new TTAudio(x->numOutputs);
99 attr_args_process(x,argc,argv);
108 eobj_dspsetup(x,x->numInputs,0);
113 if (wrappedPdClass->options && !wrappedPdClass->options->lookup(
TT(
"controlOutletFromNotification"), v)) {
118 notificationName = v[1];
123 x->controlOutlet = outlet_new((t_object*)x, NULL);
125 x->controlCallback =
new TTObject(
"callback");
126 x->controlCallback->set(
"function",
TTPtr(&wrappedClass_receiveNotificationForOutlet));
127 x->controlCallback->set(
"baton",
TTPtr(x));
133 x->wrappedObject->registerObserverForNotifications(*x->controlCallback);
137 x->outlets =
new t_outlet*[x->numOutputs];
138 for (
short i=0; i < x->numOutputs; i++)
139 x->outlets[i] = outlet_new(&x->obj.o_obj, &s_signal);
149 for (
short i = 1; i < x->numInputs; i++ )
151 inlet_free(x->inlets[i]);
153 for (
short i = 0; i < x->numOutputs; i++ )
155 outlet_free(x->outlets[i]);
157 delete x->wrappedObject;
160 delete[] x->controlSignalNames;
167 t_symbol* s = gensym((
char*)
string.c_str());
169 outlet_anything((t_outlet*)self->controlOutlet, s, 0, NULL);
173 t_max_err wrappedClass_attrGet(
TTPtr self, t_object* attr,
long* argc, t_atom** argv)
175 t_symbol* attrName = (t_symbol*)object_method(attr, _sym_getname);
179 TTPtr rawpointer = NULL;
182 rawpointer = x->wrappedClassDefinition->pdNamesToTTNames[attrName->s_name];
189 x->wrappedObject->get(ttAttrName, v);
193 *argv = (t_atom *)sysmem_newptr(
sizeof(t_atom) * v.
size());
195 for (i=0; i<v.
size(); i++) {
199 atom_setfloat(*argv+i, value);
204 atom_setsym(*argv+i, gensym((
char*)value.
c_str()));
209 atom_setlong(*argv+i, value);
216 t_max_err wrappedClass_attrSet(
TTPtr self, t_object* attr,
long argc, t_atom* argv)
221 t_symbol* attrName = (t_symbol*)object_method(attr, _sym_getname);
226 ptr = x->wrappedClassDefinition->pdNamesToTTNames[attrName->s_name];
233 for (i=0; i<argc; i++) {
234 if (atom_gettype(argv+i) == A_LONG)
235 v[i] = (
TTInt32)atom_getlong(argv+i);
236 else if (atom_gettype(argv+i) == A_FLOAT)
237 v[i] = atom_getfloat(argv+i);
238 else if (atom_gettype(argv+i) == A_SYM)
239 v[i] =
TT(atom_getsym(argv+i)->s_name);
241 pd_error((t_object*)x,
"bad type for attribute setter");
243 x->wrappedObject->set(ttAttrName, v);
250 void wrappedClass_anything(
TTPtr self, t_symbol* s,
long argc, t_atom* argv)
258 ttName = x->wrappedClassDefinition->pdNamesToTTNames[s->s_name];
259 if (ttName.string().empty()) {
260 pd_error((t_object*)x,
"no method found for %s", s->s_name);
266 for (
long i=0; i<argc; i++) {
267 if (atom_gettype(argv+i) == A_LONG)
268 v_in[i] = (
TTInt32)atom_getlong(argv+i);
269 else if (atom_gettype(argv+i) == A_FLOAT)
270 v_in[i] = atom_getfloat(argv+i);
271 else if (atom_gettype(argv+i) == A_SYM)
272 v_in[i] =
TT(atom_getsym(argv+i)->s_name);
274 pd_error((t_object*)x,
"bad type for message arg");
277 x->wrappedObject->send(ttName, v_in, v_out);
281 long ac = v_out.
size();
284 t_atom* av = (t_atom*)malloc(
sizeof(t_atom) * ac);
286 for (
long i=0; i<ac; i++) {
290 atom_setsym(av+i, gensym((
char*)ttSym.
c_str()));
295 atom_setfloat(av+i, f);
300 atom_setfloat(av+i, l);
303 outlet_anything(x->dumpOut, s, ac, av);
311 void wrappedClass_assist(
WrappedInstancePtr self,
void *b,
long msg,
long arg,
char *dst)
315 strcpy(dst,
"signal input, control messages");
317 if (arg > self->numInputs-self->numControlSignals-1)
319 snprintf(dst, 256,
"control signal for \"%s\"", self->controlSignalNames[arg - self->numInputs+1].c_str());
321 strcpy(dst,
"signal input");
325 if (arg < self->numOutputs)
326 strcpy(dst,
"signal output");
328 strcpy(dst,
"dumpout");
333 void wrappedClass_perform64(
WrappedInstancePtr self, t_object* dsp64,
double **ins,
long numins,
double **outs,
long numouts,
long sampleframes,
long flags,
void *userparam)
338 self->numChannels = numouts;
340 for (i=0; i <
self->numControlSignals; i++) {
341 int signal_index =
self->numInputs -
self->numControlSignals + i;
343 if (self->signals_connected[signal_index])
344 self->wrappedObject->set(self->controlSignalNames[i], *ins[signal_index]);
347 self->audioIn->setNumChannels(self->numInputs-self->numControlSignals);
348 self->audioOut->setNumChannels(self->numOutputs);
349 self->audioOut->allocWithVectorSize(sampleframes);
351 for (i=0; i <
self->numInputs-
self->numControlSignals; i++)
352 self->audioIn->setVector(i, self->vs, ins[i]);
354 self->wrappedObject->process(self->audioIn, self->audioOut);
356 for (i=0; i <
self->numOutputs; i++)
357 self->audioOut->getVectorCopy(i, self->vs, outs[i]);
362 void wrappedClass_dsp64(
WrappedInstancePtr self, t_object* dsp64,
short *count,
double samplerate,
long maxvectorsize,
long flags)
364 for (
int i=0; i < (
self->numInputs +
self->numOutputs); i++)
365 self->signals_connected[i] = count[i];
368 self->wrappedObject->set(
TT(
"sampleRate"), samplerate);
370 self->vs = maxvectorsize;
372 self->audioIn->setVectorSizeWithInt(self->vs);
373 self->audioOut->setVectorSizeWithInt(self->vs);
379 TTErr wrapTTClassAsPdClass(
TTSymbol ttblueClassName,
const char* pdClassName, WrappedClassPtr* c)
381 return wrapTTClassAsPdClass(ttblueClassName, pdClassName, c, (WrappedClassOptionsPtr)NULL);
384 void object_obex_dumpout(
void *x, t_symbol *s,
long argc, t_atom *argv)
388 }
catch (
const std::exception & e ){
393 TTErr wrapTTClassAsPdClass(
TTSymbol ttblueClassName,
const char* pdClassName, WrappedClassPtr* c, WrappedClassOptionsPtr options)
397 WrappedClass* wrappedPdClass = NULL;
399 TTCString nameCString = NULL;
400 t_symbol* namePdSymbol = NULL;
403 common_symbols_init();
411 wrappedPdClass =
new WrappedClass;
412 wrappedPdClass->pdClassName = gensym((
char*)pdClassName);
413 wrappedPdClass->pdClass = eclass_new( (
char*)pdClassName,
414 (method)wrappedClass_new,
415 (method)wrappedClass_free,
416 sizeof(WrappedInstance),
420 wrappedPdClass->ttblueClassName = ttblueClassName;
421 wrappedPdClass->validityCheck = NULL;
422 wrappedPdClass->validityCheckArgument = NULL;
423 wrappedPdClass->options = options;
426 error(
"Jamoma ClassWrapper failed to load %s", ttblueClassName.
c_str());
434 nameSize = strlen(name.
c_str());
435 nameCString =
new char[nameSize+1];
436 strncpy(nameCString, name.
c_str(), nameSize+1);
438 namePdSymbol = gensym(nameCString);
439 wrappedPdClass->pdNamesToTTNames[namePdSymbol->s_name] = (t_object*)name.
rawpointer();
440 eclass_addmethod((t_eclass*)wrappedPdClass->pdClass, (method)wrappedClass_anything, nameCString, A_GIMME, 0);
442 delete[] nameCString;
449 t_symbol* pdType = _sym_long;
453 nameSize = strlen(name.
c_str());
454 nameCString =
new char[nameSize+1];
455 strncpy(nameCString, name.
c_str(), nameSize+1);
456 namePdSymbol = gensym(nameCString);
458 if (name ==
TT(
"maxNumChannels"))
460 if (name ==
TT(
"bypass")) {
461 if (wrappedPdClass->options && !wrappedPdClass->options->lookup(
TT(
"generator"), v))
465 o.instance()->findAttribute(name, &attr);
466 wrappedPdClass->pdNamesToTTNames[namePdSymbol->s_name] = (t_object*)name.
rawpointer();
469 CLASS_ATTR_FLOAT(wrappedPdClass->pdClass,nameCString,0,t_eclass,c_attr);
471 CLASS_ATTR_DOUBLE(wrappedPdClass->pdClass,nameCString,0,t_eclass,c_attr);
473 CLASS_ATTR_SYMBOL(wrappedPdClass->pdClass,nameCString,0,t_eclass,c_attr);
475 CLASS_ATTR_LONG(wrappedPdClass->pdClass,nameCString,0,t_eclass,c_attr);
487 delete[] nameCString;
491 eclass_addmethod(wrappedPdClass->pdClass, (method)wrappedClass_dsp64,
"dsp64", A_CANT, 0L);
492 eclass_addmethod(wrappedPdClass->pdClass, (method)object_obex_dumpout,
"dumpout", A_CANT, 0);
493 eclass_addmethod(wrappedPdClass->pdClass, (method)wrappedClass_assist,
"assist", A_CANT, 0L);
496 eclass_dspinit(wrappedPdClass->pdClass);
497 eclass_register(CLASS_BOX, wrappedPdClass->pdClass);
501 wrappedPdClasses[wrappedPdClass->pdClassName->s_name] = (t_object*)wrappedPdClass;
507 TTErr err = wrapTTClassAsPdClass(ttblueClassName, pdClassName, c);
510 (*c)->validityCheck = validityCheck;
511 (*c)->validityCheckArgument = (*c)->pdClass;
518 TTErr err = wrapTTClassAsPdClass(ttblueClassName, pdClassName, c, options);
521 (*c)->validityCheck = validityCheck;
522 (*c)->validityCheckArgument = (*c)->pdClass;
530 TTErr err = wrapTTClassAsPdClass(ttblueClassName, pdClassName, c);
533 (*c)->validityCheck = validityCheck;
534 (*c)->validityCheckArgument = validityCheckArgument;
541 TTErr err = wrapTTClassAsPdClass(ttblueClassName, pdClassName, c, options);
544 (*c)->validityCheck = validityCheck;
545 (*c)->validityCheckArgument = validityCheckArgument;
555 for (
int i=0; i<ac; i++)
560 TTErr TTAtomsFromValue(
const TTValue& v,
long* ac, t_atom** av)
568 *av =
new t_atom[size];
571 for (
int i=0; i<size; i++) {
572 atom_setfloat((*av)+i, v[i]);
std::uint16_t TTUInt16
16 bit unsigned integer
TTDataType type
The data type of the attribute value.
TTFOUNDATION_EXPORT TTEnvironment * ttEnvironment
The environment object has one instance, which is global in scope.
Create and use Jamoma object instances.
size_type size() const noexcept
Return the number of elements.
This class represents a single attribute, as used by the TTObjectBase class.
Wrap audio objects for convenience.
TTErr(TTObjectBase::* TTMethod)(const TTSymbol methodName, const TTValue &anInputValue, TTValue &anOutputValue)
A type that can be used to store a pointer to a message for an object.
TTErr setAttributeValue(const TTSymbol name, TTValue &value)
Set an attribute value for an object.
double TTFloat64
64 bit floating point number
#define TT
This macro is defined as a shortcut for doing a lookup in the symbol table.
void append(const T &anElementValueToAppend)
Insert a single TTElement at the end.
WrappedInstance * WrappedInstancePtr
Pointer to a wrapped instance of our object.
void * TTPtr
A generic pointer.
This class is used to create a backward communication channel to notify a client that something chang...
TTPtr rawpointer() const
Get the value of the raw pointer into the symbol table.
TTErr(* TTValidityCheckFunction)(const TTPtr data)
A type that can be used to store a pointer to a validity checking function.
The TTSymbol class is used to represent a string and efficiently pass and compare that string...
const char * c_str() const
Return a pointer to the internal string as a C-string.
std::int32_t TTInt32
32 bit signed integer
void TTDSP_EXPORT TTDSPInit(const char *pathToBinaries=NULL)
Initialise the Jamoma DSP library, as well as Jamoma Foundation foundation if needed.
void clear()
Clear all values from the vector, leaving with size of 0.
Set this flag if the method you are binding to this message is prototyped with a single TTValue& argu...
Something went wrong, but what exactly is not known. Typically used for context-specific problems...
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
std::uint32_t TTUInt32
32 bit unsigned integer
TTErr notify(const TTValue &anInputValue, TTValue &anUnusedOutputValue)
Message called because we are registered as an observer to some other object, and then calls our exte...
The TTString class is used to represent a string.
void resize(size_type n)
Change the number of elements.
[doxygenAppendixC_copyExample]
Wrap TTAudioSignal instances for convenience.