Jamoma API  0.6.0.a19
JamomaModularForMax.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationMaxLibrary
4  *
5  * @brief JamomaModular For Max Shared Library
6  *
7  * @details Functions and resources based on Modular framework used by Max objects
8  *
9  * @authors Théo de la Hogue, Tim Place, Trond Lossius
10  *
11  * @copyright © 2013, Théo de la Hogue & Tim Place @n
12  * This code is licensed under the terms of the "New BSD License" @n
13  * http://creativecommons.org/licenses/BSD/
14  */
15 
16 #include "JamomaModularForMax.h"
17 
18 /***********************************************************************************
19 *
20 * C EXTERN METHODS
21 *
22 ************************************************************************************/
23 
24 
25 // Method to deal with TTSubscriber
26 ///////////////////////////////////////////////////////////////////////
27 
28 TTErr jamoma_subscriber_create(t_object *x, TTObject& anObject, TTAddress relativeAddress, TTObject& returnedSubscriber, TTSymbol& returnedAddress, TTNodePtr *returnedNode, TTNodePtr *returnedContextNode)
29 {
30  TTValue v, args;
31  TTList aContextList;
32  TTAddress newRelativeAddress, newContextAddress;
33  TTBoolean newInstance, newContextInstance;
34  TTErr err;
35 
36  // prepare arguments
37  args.append(anObject);
38  args.append(relativeAddress);
39 
40  returnedSubscriber = TTObject(kTTSym_Subscriber, args);
41 
42  // Get all Context above the object and their name
43  jamoma_subscriber_get_patcher_list(x, aContextList);
44  args = TTValue((TTPtr)&aContextList);
45 
46  *returnedNode = NULL;
47  err = returnedSubscriber.send(kTTSym_Subscribe, args, v);
48 
49  if (v.size() == 2) {
50  *returnedNode = TTNodePtr((TTPtr)v[0]);
51  *returnedContextNode = TTNodePtr((TTPtr)v[1]);
52  }
53 
54  // Check if the subscription is ok (or the binding in case of NULL object)
55  if (!err && *returnedNode) {
56 
57  if (anObject.valid()) {
58 
59  // Is a new instance have been created ?
60  returnedSubscriber.get("newInstanceCreated", v);
61  newInstance = v[0];
62 
63  // Is a new context instance have been created ?
64  returnedSubscriber.get("newContextInstanceCreated", v);
65  newContextInstance = v[0];
66 
67  // warn the user he has an object with duplicate instance
68  if (newInstance) {
69 
70  returnedSubscriber.get("relativeAddress", v);
71  newRelativeAddress = v[0];
72  object_warn(x, "Jamoma cannot register multiple objects with the same OSC identifier (%s). Using %s instead.", relativeAddress.c_str(), newRelativeAddress.c_str());
73  }
74 
75  // check why a new context instance have been created
76  if (newContextInstance) {
77 
78  returnedSubscriber.get("contextAddress", v);
79  newContextAddress = v[0];
80 
81  t_object *patcher;
82  TTSymbol patcherContext;
83  TTSymbol patcherClass;
84  TTSymbol patcherName;
85  TTAddress patcherArg;
86  long argc = 0;
87  t_atom * argv = NULL;
88 
89  // get patcher info
90  jamoma_patcher_get_info(x, &patcher, patcherContext, patcherClass, patcherName);
91 
92  // get patcher argument (dedicated for the name)
93  jamoma_patcher_get_args(patcher, &argc, &argv);
94 
95  if (patcherContext == kTTSym_model && argc == 1) {
96 
97  if (atom_gettype(argv) == A_SYM)
98  patcherArg = TTAddress(atom_getsym(argv)->s_name);
99  }
100  else if (patcherContext == kTTSym_view && argc == 2) {
101 
102  if (atom_gettype(argv+1) == A_SYM)
103  patcherArg = TTAddress(atom_getsym(argv+1)->s_name);
104  }
105 
106  // free args
107  sysmem_freeptr(argv);
108 
109  // warn the user that it should provide unique name
110 
111  // if no name has been provided
112  if (patcherArg == kTTAdrsEmpty && patcherContext == kTTSym_model && jamoma_patcher_get_hierarchy(x) != gensym("poly"))
113  object_warn(patcher, "No name provided to %s %s. Using %s.", patcherClass.c_str(), patcherContext.c_str(), newContextAddress.getNameInstance().c_str());
114 
115  // if a duplicate name.instance was passed in argument
116  else if ( jamoma_patcher_get_hierarchy(x) != gensym("poly") )
117  object_warn(patcher, "Duplicate name provided to %s %s (%s). Using %s.", patcherClass.c_str(), patcherContext.c_str(), patcherArg.c_str(), newContextAddress.getNameInstance().c_str());
118 
119  }
120 
121  returnedSubscriber.get(kTTSym_nodeAddress, v);
122  returnedAddress = v[0];
123 
124  JamomaDebug object_post(x, "registers at %s", returnedAddress.c_str());
125  }
126 
127  return kTTErrNone;
128  }
129 
130  if (anObject.valid())
131  object_error(x, "Jamoma cannot registers %s", relativeAddress.c_str());
132  else
133  // don't display this message because the objects can try many times before to binds
134  ; //object_error(x, "Jamoma cannot binds %s", relativeAddress->s_name);
135 
136  return kTTErrGeneric;
137 }
138 
139 /** Get the hierarchy of the patcher : bpatcher, subpatcher or top level one*/
140 t_symbol *jamoma_patcher_get_hierarchy(t_object *patcher)
141 {
142  t_object *box = object_attr_getobj(patcher, _sym_box);
143  t_symbol *objclass = NULL;
144 
145  if (box)
146  objclass = object_classname(box);
147 
148  if (objclass == _sym_bpatcher)
149  return objclass;
150 
151  else if (objclass == _sym_newobj)
152  return _sym_subpatcher;
153 
154  else {
155 
156  if (object_attr_getobj(patcher, _sym_parentpatcher)) // a real topmost patcher shouldn't have parent
157  return gensym("poly"); // poly case
158 
159  return _sym_topmost;
160 
161  }
162 }
163 
164 /** Convenient method to get the patcher easily */
165 t_object *jamoma_patcher_get(t_object *obj)
166 {
167  t_object *patcher = NULL;
168  object_obex_lookup(obj, SymbolGen("#P"), &patcher);
169 
170  // If obj is in a bpatcher, the patcher is NULL
171  if (!patcher){
172  patcher = object_attr_getobj(obj, _sym_parentpatcher);
173  }
174 
175  return patcher;
176 }
177 
178 /** Parse #N inside address and replace them by parent patcher arguments if there are */
179 t_symbol *jamoma_parse_dieze(t_object *x, t_symbol *address)
180 {
181  TTString diezeStr, argsStr, addressStr = address->s_name;
182  t_symbol *hierarchy;
183  t_object *patcher = jamoma_patcher_get(x);
184  /* TODO : use a TTRegex for this parsing
185  char dieze[5];
186  char args[64];
187  size_t found = 0;
188  long i, sd, sa;
189  */
190  long i;
191  long ac = 0;
192  t_atom *av = NULL;
193 
194  // If x is in a bpatcher, the patcher is NULL
195  if (!patcher){
196  patcher = object_attr_getobj(x, _sym_parentpatcher);
197  }
198 
199  if (patcher) {
200 
201  hierarchy = jamoma_patcher_get_hierarchy(patcher);
202 
203  // Try to get the patcher arguments
204  jamoma_patcher_get_args(patcher, &ac, &av);
205  if (hierarchy == _sym_subpatcher) {
206 
207  // remove first 'p' or 'patcher'
208  if (ac > 0 && av) {
209  if (atom_getsym(av) == _sym_p || atom_getsym(av) == _sym_patcher) {
210  ac--;
211  av++;
212  }
213  }
214 
215  av++;
216  ac--;
217  }
218 
219  // if there are arguments
220  if (ac > 0 && av) {
221 
222  i = 1;
223 
224  //object_post(x, "in jamoma_parse_dieze : TODO : use a TTRegex for this parsing");
225  /* TODO : use a TTRegex for this parsing
226  do {
227 
228  // prepare to parse #i
229  snprintf(dieze, sizeof(dieze), "#%li", i);
230  found = addressStr.find(dieze);
231 
232  // if #i found
233  if (found != string::npos) {
234 
235  // get av+i atom
236  if (i-1 < ac) {
237 
238  if (atom_gettype(av+i-1) == A_LONG)
239  snprintf(args, sizeof(args), "%li", atom_getlong(av+i-1));
240  else if (atom_gettype(av+i-1) == A_SYM)
241  snprintf(args, sizeof(args), "%s", atom_getsym(av+i-1)->s_name);
242  else {
243  i++;
244  continue;
245  }
246 
247  diezeStr = dieze;
248  argsStr = args;
249  sd = diezeStr.size();
250  sa = argsStr.size();
251  addressStr.replace(found, sd, args, sa);
252  }
253  }
254  i++;
255 
256  } while (i-1 < ac); // while there are argument
257  */
258 
259  return gensym((char*)addressStr.data());
260  }
261  }
262 
263  return address;
264 }
265 
266 void jamoma_subscriber_get_patcher_list(t_object *x, TTList& aContextListToFill)
267 {
268  TTValue v;
269  t_object *objPtr = x;
270  t_object *patcherPtr = NULL;
271  TTSymbol patcherContext;
272  TTSymbol patcherName;
273  TTSymbol patcherInstance;
274  TTSymbol patcherClass;
275  TTSymbol lowerContext;
276 
277  // Edit the list of all patcher's name and pointer
278  // above the object x looking at all parent patcher
279  do {
280  // get all info from the current object
281  jamoma_patcher_get_info(objPtr, &patcherPtr, patcherContext, patcherClass, patcherName);
282 
283  if (patcherName && patcherPtr) {
284  /* théo - when commenting this part we allow to subscribe view into model and model into view
285  // check if the patcher have the same context than lower patchers
286  if (patcherContext == lowerContext || lowerContext == kTTSymEmpty) {
287 
288  // keep it as lowerContext
289  lowerContext = patcherContext;
290  */
291  // store each name.instance part of the patcherName (level.i/sub.j/name.k)
292  jamoma_subscriber_fill_list(aContextListToFill, TTAddress(patcherName), patcherPtr);
293 
294  // replace current object by his parent patcher
295  objPtr = patcherPtr;
296  /* théo - when commenting this part we allow to subscribe view into model and model into view
297  }
298  else {
299 
300  // skip the patcher to go directly to an upper one
301  objPtr = patcherPtr;
302  }
303  */
304  }
305  else
306  break;
307 
308  } while (jamoma_patcher_get_hierarchy(objPtr) != _sym_topmost);
309 }
310 
311 void jamoma_subscriber_fill_list(TTList& listToFill, TTAddress address, TTPtr pointer)
312 {
313  TTSymbol level = address.getNameInstance();
314  TTValue v(level, pointer);
315  listToFill.insert(0, v);
316 
317  TTAddress parent = address.getParent();
318  if (parent != kTTAdrsEmpty)
319  jamoma_subscriber_fill_list(listToFill, parent, pointer);
320 }
321 
322 // Method to deal with TTContainer
323 ///////////////////////////////////////////////////////////////////////
324 
325 /** Create a container object */
326 TTErr jamoma_container_create(t_object *x, TTObject& returnedContainer)
327 {
328  TTValue args, none;
329  TTObject returnAddressCallback, returnValueCallback;
330 
331  // prepare arguments
332  returnAddressCallback = TTObject("callback");
333  returnAddressCallback.set(kTTSym_baton, TTPtr(x));
334  returnAddressCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_address));
335  args.append(returnAddressCallback);
336 
337  returnValueCallback = TTObject("callback");
338  returnValueCallback.set(kTTSym_baton, TTPtr(x));
339  returnValueCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value));
340  args.append(returnValueCallback);
341 
342  returnedContainer = TTObject(kTTSym_Container, args);
343 
344  return kTTErrNone;
345 }
346 
347 /** Send Max data to a node (e.g., a j.parameter object) using a container object. */
348 TTErr jamoma_container_send(TTObject& aContainer, t_symbol *relativeAddressAndAttribute, long argc, const t_atom *argv)
349 {
350  TTAddress anAddress;
351  TTValue v, data, none;
352 
353  if (aContainer.valid()) {
354 
355  anAddress = relativeAddressAndAttribute->s_name;
356 
357  if (anAddress.getType() != kAddressRelative) {
358  error("%s is an absolute address", relativeAddressAndAttribute->s_name);
359  return kTTErrGeneric;
360  }
361 
362  // Are we to send a message to an attribute of the node? If not we'll send the message to the value attribute of the node, so that the node value gets updated.
363  if (anAddress.getAttribute() == NO_ATTRIBUTE)
364  anAddress = anAddress.appendAttribute(kTTSym_value);
365  else
366  anAddress = anAddress.appendAttribute(ToTTName(anAddress.getAttribute()));
367 
368  data.append(anAddress);
369 
370  jamoma_ttvalue_from_Atom(v, _sym_nothing, argc, argv);
371  data.append((TTPtr)&v);
372 
373  // data is [address, attribute, [x, x, ,x , ...]]
374  return aContainer.send(kTTSym_Send, data, none);
375  }
376 
377  return kTTErrGeneric;
378 }
379 
380 // Method to deal with #TTNodeInfo
381 ///////////////////////////////////////////////////////////////////////
382 
383 TTErr JAMOMA_EXPORT jamoma_node_info_create(t_object *x, TTObject& returnedNodeInfo)
384 {
385  returnedNodeInfo = TTObject(kTTSym_NodeInfo);
386  return kTTErrNone;
387 }
388 
389 // Method to deal with TTData
390 ///////////////////////////////////////////////////////////////////////
391 
392 /** Create a data object */
393 TTErr jamoma_data_create(t_object *x, TTObject& returnedData, TTSymbol service)
394 {
395  // create a data
396  returnedData = TTObject(kTTSym_Data, service);
397 
398  // prepare its callback
399  returnedData.set(kTTSym_baton, TTPtr(x));
400  returnedData.set(kTTSym_function, TTPtr(&jamoma_callback_return_value_typed));
401  returnedData.set(TTSymbol("rampDriveDefault"), TTSymbol("max"));
402 
403  return kTTErrNone;
404 }
405 
406 /** Send Max data command */
407 TTErr jamoma_data_command(TTObject& aData, t_symbol *msg, long argc, const t_atom *argv)
408 {
409  TTValue v, none;
410 
411  if (aData.valid())
412  {
413  jamoma_ttvalue_from_Atom(v, msg, argc, argv);
414 
415  return aData.send(kTTSym_Command, v, none);
416  }
417 
418  return kTTErrGeneric;
419 }
420 
421 // Method to deal with TTSender
422 ///////////////////////////////////////////////////////////////////////
423 
424 /** Create a sender object */
425 TTErr jamoma_sender_create(t_object *x, TTObject& returnedSender)
426 {
427  returnedSender = TTObject(kTTSym_Sender);
428  return kTTErrNone;
429 }
430 
431 /** Create a sender object for audio signal */
432 TTErr jamoma_sender_create_audio(t_object *x, TTObject& returnedSender)
433 {
434  TTObject audio;
435 
436  // prepare arguments
437  audio = TTObject(kTTSym_audiosignal, 1);
438 
439  returnedSender = TTObject(kTTSym_Sender, audio);
440  return kTTErrNone;
441 }
442 
443 /** Send Max data using a sender object */
444 TTErr jamoma_sender_send(TTObject& aSender, t_symbol *msg, long argc, const t_atom *argv)
445 {
446  TTValue v, none;
447 
448  if (aSender.valid()) {
449 
450  jamoma_ttvalue_from_Atom(v, msg, argc, argv);
451 
452  return aSender.send(kTTSym_Send, v, none);
453  }
454 
455  return kTTErrGeneric;
456 }
457 
458 // Method to deal with TTReceiver
459 ///////////////////////////////////////////////////////////////////////
460 
461 /** Create a receiver object */
462 TTErr jamoma_receiver_create(t_object *x, TTObject& returnedReceiver)
463 {
464  TTValue args;
465  TTObject returnAddressCallback, returnValueCallback;
466 
467  // prepare arguments
468  returnAddressCallback = TTObject("callback");
469  returnAddressCallback.set(kTTSym_baton, TTPtr(x));
470  returnAddressCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_address));
471  args.append(returnAddressCallback);
472 
473  returnValueCallback = TTObject("callback");
474  returnValueCallback.set(kTTSym_baton, TTPtr(x));
475  returnValueCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value_typed));
476  args.append(returnValueCallback);
477 
478  returnedReceiver = TTObject(kTTSym_Receiver, args);
479  return kTTErrNone;
480 }
481 
482 /** Create a receiver object for audio signal */
483 TTErr jamoma_receiver_create_audio(t_object *x, TTObject& returnedReceiver)
484 {
485  TTValue args;
486  TTObject returnAddressCallback, audio, empty;
487 
488  // prepare arguments
489  returnAddressCallback = TTObject("callback");
490  returnAddressCallback.set(kTTSym_baton, TTPtr(x));
491  returnAddressCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_address));
492  args.append(returnAddressCallback);
493 
494  args.append(empty); // no return value callback
495 
496  audio = TTObject(kTTSym_audiosignal, 1);
497  args.append(audio);
498 
499  returnedReceiver = TTObject(kTTSym_Receiver, args);
500  return kTTErrNone;
501 }
502 
503 // Method to deal with TTPresetManager
504 ///////////////////////////////////////////////////////////////////////
505 
506 /** Create a preset manager object */
507 TTErr jamoma_presetManager_create(t_object *x, TTObject& returnedPresetManager)
508 {
509  TTObject returnLineCallback;
510 
511  // prepare arguments
512  returnLineCallback = TTObject("callback");
513  returnLineCallback.set(kTTSym_baton, TTPtr(x));
514  returnLineCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value));
515 
516  returnedPresetManager = TTObject(kTTSym_PresetManager, returnLineCallback);
517  return kTTErrNone;
518 }
519 
520 /** Create a cue manager object */
521 TTErr jamoma_cueManager_create(t_object *x, TTObject& returnedCueManager)
522 {
523  TTObject returnLineCallback;
524 
525  // prepare arguments
526  returnLineCallback = TTObject("callback");
527  returnLineCallback.set(kTTSym_baton, TTPtr(x));
528  returnLineCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value));
529 
530  returnedCueManager = TTObject(kTTSym_CueManager, returnLineCallback);
531  return kTTErrNone;
532 }
533 
534 // Method to deal with TTInput
535 ///////////////////////////////////////////////////////////////////////
536 
537 /** Create an input object for any signal */
538 TTErr jamoma_input_create(t_object *x, TTObject& returnedInput)
539 {
540  TTValue baton;
541  TTObject signalOutCallback;
542 
543  // prepare arguments
544  signalOutCallback = TTObject("callback");
545  baton = TTValue(TTPtr(x), TTPtr(jps_return_signal));
546  signalOutCallback.set(kTTSym_baton, baton);
547  signalOutCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value_typed));
548 
549  returnedInput = TTObject(kTTSym_Input, signalOutCallback);
550  returnedInput.set("type", TTSymbol("control"));
551  return kTTErrNone;
552 }
553 
554 /** Create an input object for audio signal */
555 TTErr jamoma_input_create_audio(t_object *x, TTObject& returnedInput)
556 {
557  returnedInput = TTObject("Input.audio");
558  return kTTErrNone;
559 }
560 
561 /** Send any signal to an input object */
562 TTErr jamoma_input_send(TTObject& anInput, t_symbol *msg, long argc, const t_atom *argv)
563 {
564  TTValue v, none;
565 
566  if (anInput.valid()) {
567 
568  jamoma_ttvalue_from_Atom(v, msg, argc, argv);
569 
570  return anInput.send(kTTSym_Send, v, none);
571  }
572 
573  return kTTErrGeneric;
574 }
575 
576 
577 // Method to deal with TTOutput
578 ///////////////////////////////////////////////////////////////////////
579 
580 /** Create an output object for signal */
581 TTErr jamoma_output_create(t_object *x, TTObject& returnedOutput)
582 {
583  TTValue baton;
584  TTObject signalOutCallback;
585 
586  // prepare arguments
587  signalOutCallback = TTObject("callback");
588  baton = TTValue(TTPtr(x), TTPtr(jps_return_signal));
589  signalOutCallback.set(kTTSym_baton, baton);
590  signalOutCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value_typed));
591 
592  returnedOutput = TTObject(kTTSym_Output, signalOutCallback);
593  returnedOutput.set("type", TTSymbol("control"));
594  return kTTErrNone;
595 }
596 
597 /** Create an output object for audio signal */
598 TTErr jamoma_output_create_audio(t_object *x, TTObject& returnedOutput)
599 {
600  // prepare arguments
601  returnedOutput = TTObject("Output.audio");
602  return kTTErrNone;
603 }
604 
605 /** Send any signal to an output object */
606 TTErr jamoma_output_send(TTObject& anOutput, t_symbol *msg, long argc, const t_atom *argv)
607 {
608  TTValue v, none;
609 
610  if (anOutput.valid()) {
611 
612  jamoma_ttvalue_from_Atom(v, msg, argc, argv);
613 
614  return anOutput.send(kTTSym_Send, v, none);
615  }
616 
617  return kTTErrGeneric;
618 }
619 
620 
621 // Method to deal with TTMapper
622 ///////////////////////////////////////////////////////////////////////
623 
624 /** Create a mapper object */
625 TTErr jamoma_mapper_create(t_object *x, TTObject& returnedMapper)
626 {
627  TTValue args, baton, none;
628  TTObject returnValueCallback, returnInputGoingDownCallback, returnInputGoingUpCallback, returnOutputGoingDownCallback, returnOutputGoingUpCallback;
629 
630  // prepare arguments
631  returnValueCallback = TTObject("callback");
632  returnValueCallback.set(kTTSym_baton, TTPtr(x));
633  returnValueCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value));
634  args.append(returnValueCallback);
635 
636  returnInputGoingDownCallback = TTObject("callback");
637  baton = TTValue(TTPtr(x), TTPtr(gensym("return_input_going_down")));
638  returnInputGoingDownCallback.set(kTTSym_baton, baton);
639  returnInputGoingDownCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value));
640  args.append(returnInputGoingDownCallback);
641 
642  returnInputGoingUpCallback = TTObject("callback");
643  baton = TTValue(TTPtr(x), TTPtr(gensym("return_input_going_up")));
644  returnInputGoingUpCallback.set(kTTSym_baton, baton);
645  returnInputGoingUpCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value));
646  args.append(returnInputGoingUpCallback);
647 
648  returnOutputGoingDownCallback = TTObject("callback");
649  baton = TTValue(TTPtr(x), TTPtr(gensym("return_output_going_down")));
650  returnOutputGoingDownCallback.set(kTTSym_baton, baton);
651  returnOutputGoingDownCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value));
652  args.append(returnOutputGoingDownCallback);
653 
654  returnOutputGoingUpCallback = TTObject("callback");
655  baton = TTValue(TTPtr(x), TTPtr(gensym("return_output_going_up")));
656  returnOutputGoingUpCallback.set(kTTSym_baton, baton);
657  returnOutputGoingUpCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value));
658  args.append(returnOutputGoingUpCallback);
659 
660  returnedMapper = TTObject(kTTSym_Mapper, args);
661 
662  return kTTErrNone;
663 }
664 
665 
666 // Method to deal with TTViewer
667 ///////////////////////////////////////////////////////////////////////
668 
669 /** Create a viewer object */
670 TTErr jamoma_viewer_create(t_object *x, TTObject& returnedViewer)
671 {
672  returnedViewer = TTObject(kTTSym_Viewer);
673 
674  returnedViewer.set(kTTSym_baton, TTPtr(x));
675  returnedViewer.set(kTTSym_function, TTPtr(&jamoma_callback_return_value_typed));
676 
677  return kTTErrNone;
678 }
679 
680 /** Send Max data using a viewer object */
681 TTErr jamoma_viewer_send(TTObject& aViewer, t_symbol *msg, long argc, const t_atom *argv)
682 {
683  TTValue v, none;
684 
685  if (aViewer.valid()) {
686 
687  jamoma_ttvalue_from_Atom(v, msg, argc, argv);
688 
689  return aViewer.send(kTTSym_Send, v, none);
690  }
691 
692  return kTTErrGeneric;
693 }
694 
695 
696 // Method to deal with TTExplorer
697 ///////////////////////////////////////////////////////////////////////
698 
699 /** Create an explorer object */
700 TTErr jamoma_explorer_create(t_object *x, TTObject& returnedExplorer)
701 {
702  TTValue args, baton;
703  TTObject returnValueCallback, returnSelectionCallback;
704 
705  // prepare arguments
706  returnValueCallback = TTObject("callback");
707  returnValueCallback.set(kTTSym_baton, TTPtr(x));
708  returnValueCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value));
709  args.append(returnValueCallback);
710 
712 
713  returnSelectionCallback = TTObject("callback");
714  baton = TTValue(TTPtr(x), (TTPtr)gensym("return_selection"));
715  returnSelectionCallback.set(kTTSym_baton, baton);
716  returnSelectionCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value));
717  args.append(returnSelectionCallback);
718 
719  returnedExplorer = TTObject(kTTSym_Explorer, args);
720 
721  return kTTErrNone;
722 }
723 
725 {
726  TTHashPtr defaultFilterBank = new TTHash();
727  TTDictionaryBasePtr aFilter;
728 
729  // Create some ready-made filters
730 
731  // to look for any data (parameter | message | return)
732  aFilter = new TTDictionaryBase;
733  aFilter->setSchema(kTTSym_filter);
734  aFilter->append(kTTSym_object, kTTSym_Data);
735  aFilter->append(kTTSym_mode, kTTSym_restrict);
736  defaultFilterBank->append(TTSymbol("data"), (TTPtr)aFilter);
737 
738  // to look for j.parameter
739  aFilter = new TTDictionaryBase;
740  aFilter->setSchema(kTTSym_filter);
741  aFilter->append(kTTSym_object, kTTSym_Data);
742  aFilter->append(kTTSym_attribute, kTTSym_service);
743  aFilter->append(kTTSym_value, kTTSym_parameter);
744  aFilter->append(kTTSym_mode, kTTSym_restrict);
745  defaultFilterBank->append(TTSymbol("parameter"), (TTPtr)aFilter);
746 
747  // to look for j.message
748  aFilter = new TTDictionaryBase;
749  aFilter->setSchema(kTTSym_filter);
750  aFilter->append(kTTSym_object, kTTSym_Data);
751  aFilter->append(kTTSym_attribute, kTTSym_service);
752  aFilter->append(kTTSym_value, kTTSym_message);
753  aFilter->append(kTTSym_mode, kTTSym_restrict);
754  defaultFilterBank->append(TTSymbol("message"), (TTPtr)aFilter);
755 
756  // to look for j.return
757  aFilter = new TTDictionaryBase;
758  aFilter->setSchema(kTTSym_filter);
759  aFilter->append(kTTSym_object, kTTSym_Data);
760  aFilter->append(kTTSym_attribute, kTTSym_service);
761  aFilter->append(kTTSym_value, kTTSym_return);
762  aFilter->append(kTTSym_mode, kTTSym_restrict);
763  defaultFilterBank->append(TTSymbol("return"), (TTPtr)aFilter);
764 
765  // to look for j.model
766  aFilter = new TTDictionaryBase;
767  aFilter->setSchema(kTTSym_filter);
768  aFilter->append(kTTSym_object, kTTSym_Container);
769  aFilter->append(kTTSym_attribute, kTTSym_service);
770  aFilter->append(kTTSym_value, kTTSym_model);
771  aFilter->append(kTTSym_mode, kTTSym_restrict);
772  defaultFilterBank->append(TTSymbol("model"), (TTPtr)aFilter);
773 
774  // to look for j.view
775  aFilter = new TTDictionaryBase;
776  aFilter->setSchema(kTTSym_filter);
777  aFilter->append(kTTSym_object, kTTSym_Container);
778  aFilter->append(kTTSym_attribute, kTTSym_service);
779  aFilter->append(kTTSym_value, kTTSym_view);
780  aFilter->append(kTTSym_mode, kTTSym_restrict);
781  defaultFilterBank->append(TTSymbol("view"), (TTPtr)aFilter);
782 
783  // to look for empty nodes
784  aFilter = new TTDictionaryBase;
785  aFilter->setSchema(kTTSym_filter);
786  aFilter->append(kTTSym_object, TTSymbol("none"));
787  aFilter->append(kTTSym_mode, kTTSym_restrict);
788  defaultFilterBank->append(TTSymbol("none"), (TTPtr)aFilter);
789 
790  // to look for j.remote
791  aFilter = new TTDictionaryBase;
792  aFilter->setSchema(kTTSym_filter);
793  aFilter->append(kTTSym_object, kTTSym_Viewer);
794  aFilter->append(kTTSym_mode, kTTSym_restrict);
795  defaultFilterBank->append(TTSymbol("remote"), (TTPtr)aFilter);
796 
797  // to look for user-defined object
798  aFilter = new TTDictionaryBase;
799  aFilter->setSchema(kTTSym_filter);
800  aFilter->append(kTTSym_attribute, kTTSym_tags);
801  aFilter->append(kTTSym_value, kTTSym_generic);
802  aFilter->append(kTTSym_mode, kTTSym_exclude);
803  defaultFilterBank->append(TTSymbol("noGenericTag"), (TTPtr)aFilter);
804 
805  // to look for generic tagged object
806  aFilter = new TTDictionaryBase;
807  aFilter->setSchema(kTTSym_filter);
808  aFilter->append(kTTSym_attribute, kTTSym_tags);
809  aFilter->append(kTTSym_value, kTTSym_generic);
810  aFilter->append(kTTSym_mode, kTTSym_restrict);
811  defaultFilterBank->append(TTSymbol("genericTag"), (TTPtr)aFilter);
812 
813  return defaultFilterBank;
814 }
815 
816 
817 // Method to deal with TTRamp
818 ///////////////////////////////////////////////////////////////////////
819 TTErr jamoma_ramp_create(t_object *x, TTObject& returnedRamp)
820 {
821  TTValue args;
822 
823  // prepare arguments
825  args.append((TTPtr)x);
826 
827  returnedRamp = TTObject(kTTSym_Ramp, args);
828  return kTTErrNone;
829 }
830 
831 void JAMOMA_EXPORT jamoma_callback_return_ramped_value(void *o, TTUInt32 n, TTFloat64 *v)
832 {
833  t_object *x = (t_object*)o;
834  long i, argc = n;
835  t_atom *argv = NULL;
836 
837  if (!argc)
838  return;
839 
840  // copy the array of ramped float value into an atom
841  argv = (t_atom*)sysmem_newptr(sizeof(t_atom) * argc);
842 
843  for (i = 0; i < argc; i++)
844  atom_setfloat(argv+i, v[i]);
845 
846  // send the atom to the object using return_value method
847  if (argc == 1)
848  object_method(x, jps_return_value, _sym_float, argc, argv);
849  else
850  object_method(x, jps_return_value, _sym_list, argc, argv);
851 
852  sysmem_freeptr(argv);
853 }
854 
855 // Method to return data
856 ///////////////////////////////////////////////////////////////////////
857 
858 void jamoma_callback_return_address(const TTValue& baton, const TTValue& v)
859 {
860  t_object *x;
861  TTSymbol address;
862 
863  // unpack baton (a t_object *and the name of the method to call)
864  x = (t_object*)((TTPtr)baton[0]);
865 
866  if (v.size() == 1) {
867 
868  if (v[0].type() == kTypeSymbol) {
869 
870  // unpack data (address)
871  address = v[0];
872 
873  // send data to a data using the return_value method
874  object_method(x, jps_return_address, SymbolGen(address.c_str()), 0, 0);
875  }
876  }
877 }
878 
879 /** Return the value to a j. external as _sym_nothing, argc, argv */
880 void jamoma_callback_return_value(const TTValue& baton, const TTValue& v)
881 {
882  t_object *x;
883  t_symbol *s_method;
884  TTBoolean deferlow = NO;
885  long argc = 0;
886  t_atom *argv = NULL;
887  method p_method = NULL;
888 
889  // unpack baton (a t_object *and the name of the method to call (default : jps_return_value))
890 
891  // get object
892  x = (t_object*)((TTPtr)baton[0]);
893 
894  // get method
895  if (baton.size() >= 2) {
896 
897  s_method = (t_symbol*)((TTPtr)baton[1]);
898 
899  if (s_method == NULL || s_method == _sym_nothing)
900  return;
901 
902  // do we need to deferlow it ?
903  if (baton.size() == 3)
904  deferlow = baton[2];
905  }
906  else
907  s_method = jps_return_value;
908 
909  jamoma_ttvalue_to_Atom(v, &argc, &argv);
910 
911  // send data to an external
912  if (!deferlow)
913  object_method(x, s_method, _sym_nothing, argc, argv);
914 
915  else {
916 
917  p_method = object_getmethod(x, s_method);
918 
919  if (p_method)
920  defer_low(x, (method)p_method, _sym_nothing, argc, argv);
921  }
922 
923  sysmem_freeptr(argv);
924 }
925 
926 /** Return the value to a j. external as msg, argc, argv */
927 // TODO #556 : merge this function into jamoma_callback_return_value
928 // TODO : why don't we pass a #TTDictionary into the baton
930 {
931  t_object *x;
932  t_symbol *msg, *s_method;
933  TTBoolean deferlow = NO;
934  long argc = 0;
935  t_atom *argv = NULL;
936  method p_method = NULL;
937  TTBoolean shifted = false;
938 
939  // unpack baton (a t_object *and the name of the method to call (default : jps_return_value))
940 
941  // get Max wrapper object that was passed in
942  x = (t_object*)((TTPtr)baton[0]);
943 
944  // get name of the method to call
945  if (baton.size() >= 2) {
946 
947  s_method = (t_symbol*)((TTPtr)baton[1]);
948 
949  if (s_method == NULL || s_method == _sym_nothing)
950  return;
951 
952  // do we need to deferlow it ?
953  if (baton.size() == 3)
954  deferlow = baton[2];
955  }
956  // by default we call "return_value" method
957  else
958  s_method = jps_return_value;
959 
960  // convert TTValue into a typed atom array
961  jamoma_ttvalue_to_typed_Atom(v, &msg, &argc, &argv, shifted);
962 
963  // send data to an external
964  if (!deferlow)
965  object_method(x, s_method, msg, argc, argv);
966 
967  else {
968 
969  p_method = object_getmethod(x, s_method);
970 
971  if (p_method)
972  defer_low(x, (method)p_method, msg, argc, argv);
973  }
974 
975  if (shifted)
976  argv--;
977  sysmem_freeptr(argv);
978 }
979 
980 /** Return any signal */
981 void jamoma_callback_return_signal(const TTValue& baton, const TTValue& v)
982 {
983  t_object *x;
984  long argc = 0;
985  t_atom *argv = NULL;
986 
987  // unpack baton (a t_object*)
988  x = (t_object*)((TTPtr)baton[0]);
989 
990  jamoma_ttvalue_to_Atom(v, &argc, &argv);
991 
992  // send signal using the return_signal method
993  object_method(x, jps_return_signal, _sym_nothing, argc, argv);
994 
995  sysmem_freeptr(argv);
996 }
997 
998 /** Return audio signal */
1000 {
1001  t_object *x;
1002  TTPtr signal;
1003  long i, argc = 0;
1004  t_atom *argv = NULL;
1005 
1006  // unpack baton (a t_object*)
1007  x = (t_object*)((TTPtr)baton[0]);
1008 
1009  // unpack data (signal)
1010  argc = v.size();
1011  argv = (t_atom*)sysmem_newptr(sizeof(t_atom) * argc);
1012  for (i = 0; i < argc; i++) {
1013  signal = v[i];
1014  atom_setobj(argv+i, signal);
1015  }
1016 
1017  // send signal using the return_signal method
1018  object_method(x, jps_return_signal, _sym_nothing, argc, argv);
1019 
1020  sysmem_freeptr(argv);
1021 }
1022 
1023 // Method to deal with TTValue
1024 /////////////////////////////////////////
1025 
1026 /** Make a typed Atom array from a TTValue (!!! this method allocate memory for the Atom array ! free it after ! */
1027 void jamoma_ttvalue_to_typed_Atom(const TTValue& v, t_symbol **msg, long *argc, t_atom **argv, TTBoolean& shifted)
1028 {
1029  long i;
1030  TTFloat64 f;
1031  TTSymbol s;
1032  TTInt32 t;
1033 
1034  *msg = _sym_nothing;
1035  *argc = v.size();
1036 
1037  if (!(*argv)) // otherwise use memory passed in
1038  *argv = (t_atom*)sysmem_newptr(sizeof(t_atom) * (*argc));
1039 
1040  if (*argc && v.size() > 0) {
1041 
1042  for (i = 0; i < *argc; i++) {
1043 
1044  if(v[i].type() == kTypeFloat32 || v[i].type() == kTypeFloat64){
1045  f = v[i];
1046  atom_setfloat((*argv)+i, f);
1047  *msg = _sym_float;
1048  }
1049  else if(v[i].type() == kTypeSymbol){
1050  s = v[i];
1051  if (s == kTTSymEmpty || s == kTTAdrsEmpty)
1052  atom_setsym((*argv)+i, _sym_bang);
1053  else
1054  atom_setsym((*argv)+i, gensym((char*)s.c_str()));
1055  //*msg = _sym_symbol;
1056  }
1057  else{ // assume int
1058  t = v[i];
1059  atom_setlong((*argv)+i, t);
1060  *msg = _sym_int;
1061  }
1062  }
1063 
1064  if (i>0) {
1065 
1066  if (atom_gettype(*argv) == A_SYM) {
1067 
1068  *msg = atom_getsym(*argv);
1069  *argc = (*argc)-1;
1070  *argv = (*argv)+1;
1071  shifted = true;
1072  }
1073  else if (i>1)
1074  *msg = _sym_list;
1075  }
1076  }
1077  else {
1078 
1079  *msg = _sym_bang;
1080  *argc = 0;
1081  *argv = NULL;
1082  }
1083 }
1084 
1085 /** Make an Atom array from a TTValue (!!! this method allocate memory for the Atom array ! free it after ! */
1086 void jamoma_ttvalue_to_Atom(const TTValue& v, long *argc, t_atom **argv)
1087 {
1088  long i;
1089  TTFloat64 f;
1090  TTSymbol s;
1091  TTInt32 t;
1092 
1093  *argc = v.size();
1094 
1095  if (*argc == 0 || v.size() == 0)
1096  return;
1097 
1098  if (!(*argv)) // otherwise use memory passed in
1099  *argv = (t_atom*)sysmem_newptr(sizeof(t_atom) * (*argc));
1100 
1101  for (i = 0; i < v.size(); i++)
1102  {
1103  if (v[i].type() == kTypeFloat32 || v[i].type() == kTypeFloat64)
1104  {
1105  f = v[i];
1106  atom_setfloat((*argv)+i, f);
1107  }
1108  else if (v[i].type() == kTypeSymbol)
1109  {
1110  s = v[i];
1111  if (s == kTTSymEmpty)
1112  atom_setsym((*argv)+i, _sym_bang); // because empty symbol can't be filtered in Max
1113  else
1114  atom_setsym((*argv)+i, gensym((char*)s.c_str()));
1115  }
1116  else
1117  { // assume int
1118  t = v[i];
1119  atom_setlong((*argv)+i, t);
1120  }
1121  }
1122 }
1123 
1124 /** Make a TTValue from Atom array */
1125 void jamoma_ttvalue_from_Atom(TTValue& v, t_symbol *msg, long argc, const t_atom *argv)
1126 {
1127  long i, start;
1128 
1129  if ((msg == _sym_bang || msg == _sym_nothing) && argc == 0)
1130  v.clear();
1131  else
1132  {
1133  // add msg to the value
1134  if (msg != _sym_nothing && msg != _sym_int && msg != _sym_float && msg != _sym_symbol && msg != _sym_list)
1135  {
1136  v.resize(argc+1);
1137  v[0] = TTSymbol(msg->s_name);
1138  start = 1;
1139  }
1140  else
1141  {
1142  v.resize(argc);
1143  start = 0;
1144  }
1145 
1146  // convert Atom to TTValue
1147  for (i = 0; i < argc; i++)
1148  {
1149  if (atom_gettype(argv+i) == A_LONG)
1150  v[i+start] = (int)atom_getlong(argv+i);
1151  else if (atom_gettype(argv+i) == A_FLOAT)
1152  v[i+start] = (TTFloat64)atom_getfloat(argv+i);
1153  else if (atom_gettype(argv+i) == A_SYM)
1154  v[i+start] = TTSymbol(atom_getsym(argv+i)->s_name);
1155  }
1156  }
1157 }
1158 
1159 /** Convert a TTSymbol "MyObjectMessage" into a t_symbol *"my/object/message"
1160  or return NULL if the TTSymbol doesn't begin by an uppercase letter */
1162 {
1163  TTSymbol AppName;
1164  TTAddress anAddress;
1165  TTErr err;
1166 
1167  AppName = ToAppName(TTName);
1168 
1169  if (AppName == kTTSymEmpty)
1170  err = convertUpperCasedNameInAddress(TTName, anAddress);
1171  else
1172  err = convertUpperCasedNameInAddress(AppName, anAddress);
1173 
1174  if (!err)
1175  return gensym((char*)anAddress.c_str());
1176  else
1177  return NULL;
1178 }
1179 
1180 /** Load an external for internal use. Returns true if successful */
1181 TTBoolean jamoma_extern_load(t_symbol *objectname, long argc, t_atom *argv, t_object **object)
1182 {
1183  t_class *c = NULL;
1184  t_object *p = NULL;
1185 
1186  c = class_findbyname(jps_box, objectname);
1187  if (!c) {
1188  p = (t_object *)newinstance(objectname, 0, NULL);
1189  if (p) {
1190  c = class_findbyname(jps_box, objectname);
1191  freeobject(p);
1192  p = NULL;
1193  }
1194  else {
1195  error("jamoma: could not load extern (%s) within the core", objectname->s_name);
1196  return false;
1197  }
1198  }
1199 
1200  if (*object != NULL) { // if there was an object set previously, free it first...
1201  object_free(*object);
1202  *object = NULL;
1203  }
1204 
1205  *object = (t_object*)object_new_typed(CLASS_BOX, objectname, argc, argv);
1206  return true;
1207 }
1208 
1209 // Don't pass memory in for this function! It will allocate what it needs
1210 // -- then the caller is responsible for freeing
1211 void jamoma_patcher_get_args(t_object *patcher, long *argc, t_atom **argv)
1212 {
1213  t_symbol *hierarchy = jamoma_patcher_get_hierarchy(patcher);
1214  t_object *box = object_attr_getobj(patcher, _sym_box);
1215  t_object *textfield = NULL;
1216  t_object *assoc = NULL;
1217  char *text = NULL;
1218  unsigned long textlen = 0;
1219 
1220  if (hierarchy == _sym_bpatcher)
1221  object_attr_getvalueof(box, SymbolGen("args"), argc, argv);
1222 
1223  else if (hierarchy == _sym_subpatcher) {
1224  textfield = object_attr_getobj(box, SymbolGen("textfield"));
1225  object_method(textfield, SymbolGen("gettextptr"), &text, &textlen);
1226  atom_setparse(argc, argv, text);
1227  }
1228  else if (hierarchy == gensym("poly")){
1229 
1230  object_method(patcher, gensym("getassoc"), &assoc);
1231  if (assoc)
1232  object_attr_getvalueof(assoc, SymbolGen("args"), argc, argv);
1233  }
1234  else {
1235  *argc = 0;
1236  *argv = NULL;
1237  }
1238 }
1239 
1240 /** Get the context from the upper j.model|view in the patcher or from patcher's name */
1241 void jamoma_patcher_get_context(t_object **patcher, TTSymbol& returnedContext)
1242 {
1243  t_symbol *hierarchy, *_sym_j_model, *_sym_j_view, *_sym_context;
1244  t_object *obj, *upperPatcher;
1245  TTBoolean found = NO;
1246 
1247  // Look for j.model|view in the patcher
1248  obj = object_attr_getobj(*patcher, _sym_firstobject);
1249 
1250  // TODO : cache those t_symbol else where ...
1251  _sym_j_model = gensym("j.model");
1252  _sym_j_view = gensym("j.view");
1253 
1254  while (obj) {
1255 
1256  _sym_context = object_attr_getsym(obj, _sym_maxclass);
1257 
1258  if (_sym_context == _sym_j_model) {
1259 
1260  returnedContext = kTTSym_model;
1261  found = YES;
1262  break;
1263 
1264  } else if (_sym_context == _sym_j_view) {
1265 
1266  returnedContext = kTTSym_view;
1267  found = YES;
1268  break;
1269  }
1270 
1271  obj = object_attr_getobj(obj, _sym_nextobject);
1272  }
1273 
1274  // if no context
1275  if (!found) {
1276 
1277  // in subpatcher look upper
1278  hierarchy = jamoma_patcher_get_hierarchy(*patcher);
1279  if (hierarchy == _sym_subpatcher || hierarchy == _sym_bpatcher || hierarchy == SymbolGen("poly")) {
1280 
1281  // get the patcher where is the patcher to look for the context one step upper
1282  upperPatcher = jamoma_patcher_get(*patcher);
1283 
1284  jamoma_patcher_get_context(&upperPatcher, returnedContext);
1285 
1286  // if the context is still NULL and there is a j.model|view at this level
1287  // the default case would be to set it as a model patcher by default
1288  // AV : this is never reach since found is FALSE as it's check in the if statement above
1289  // TODO : fixme
1290  if (returnedContext == kTTSymEmpty && found)
1291  returnedContext = kTTSym_model;
1292  // keep the upperPatcher if no j.model|view around
1293  // because it is where the context is defined
1294  else if (!found)
1295  *patcher = upperPatcher;
1296  }
1297  // default case : a patcher has no type
1298  else if (hierarchy == _sym_topmost)
1299  returnedContext = kTTSymEmpty;
1300  }
1301 }
1302 
1303 /** Get the class of the patcher from the file name (removing .model and .view convention name if they exist) */
1304 void jamoma_patcher_get_class(t_object *patcher, TTSymbol context, TTSymbol& returnedClass)
1305 {
1306  t_symbol *patcherName, *hierarchy;
1307  t_object *upperPatcher;
1308  TTString s_toParse;
1309  TTStringIter begin, end;
1310  TTBoolean intoHelp = NO;
1311 
1312  // extract class from the file name
1313  patcherName = object_attr_getsym(patcher, _sym_filename);
1314 
1315  if (patcherName != _sym_nothing) {
1316 
1317  s_toParse = patcherName->s_name;
1318 
1319  begin = s_toParse.begin();
1320  end = s_toParse.end();
1321 
1322  // parse .maxpat
1323  if (!ttRegexForMaxpat->parse(begin, end)) {
1324  s_toParse = TTString(begin, ttRegexForMaxpat->begin());
1325  begin = s_toParse.begin();
1326  end = s_toParse.end();
1327  }
1328  // parse .maxhelp
1329  else if (!ttRegexForMaxhelp->parse(begin, end)) {
1330  s_toParse = TTString(begin, ttRegexForMaxhelp->begin());
1331  begin = s_toParse.begin();
1332  end = s_toParse.end();
1333 
1334  intoHelp = YES;
1335  }
1336 
1337  // parse jmod.
1338  if (!ttRegexForJmod->parse(begin, end)) {
1339 
1340  object_error(patcher, "jmod. prefix in %s is a 0.5 convention. Please use .module suffix instead", patcherName->s_name);
1341 
1342  s_toParse = TTString(ttRegexForJmod->end(), end);
1343  begin = s_toParse.begin();
1344  end = s_toParse.end();
1345  }
1346  // parse j.
1347  else if (!ttRegexForJcom->parse(begin, end)) {
1348 
1349  s_toParse = TTString(ttRegexForJcom->end(), end);
1350  begin = s_toParse.begin();
1351  end = s_toParse.end();
1352  }
1353 
1354  // parse .module or if not parse context (model or view)
1355  if (!ttRegexForModule->parse(begin, end)) {
1356  s_toParse = TTString(begin, ttRegexForModule->begin());
1357  begin = s_toParse.begin();
1358  end = s_toParse.end();
1359  }
1360  else if (context == kTTSym_model) {
1361 
1362  if (!ttRegexForModel->parse(begin, end)) {
1363  s_toParse = TTString(begin, ttRegexForModel->begin());
1364  begin = s_toParse.begin();
1365  end = s_toParse.end();
1366  }
1367  }
1368  else if (context == kTTSym_view) {
1369 
1370  if (!ttRegexForView->parse(begin, end)) {
1371  s_toParse = TTString(begin, ttRegexForView->begin());
1372  begin = s_toParse.begin();
1373  end = s_toParse.end();
1374  }
1375  }
1376 
1377  // in help patcher : append _help to the class to clarify the namespace
1378  if (intoHelp)
1379  s_toParse += "_help";
1380 
1381  returnedClass = TTSymbol(s_toParse);
1382  }
1383  else {
1384 
1385  // in subpatcher : look to the name else look upper
1386  hierarchy = jamoma_patcher_get_hierarchy(patcher);
1387  if (hierarchy == _sym_subpatcher) {
1388 
1389  long ac = 0;
1390  t_atom *av = NULL;
1391 
1392  jamoma_patcher_get_args(patcher, &ac, &av);
1393 
1394  // remove first 'p' or 'patcher'
1395  if (ac > 0 && av) {
1396  if (atom_getsym(av) == _sym_p || atom_getsym(av) == _sym_patcher) {
1397  ac--;
1398  av++;
1399  }
1400  }
1401 
1402  // is there still arguments ?
1403  if (ac > 0 && av) {
1404 
1405  // the first argument is the class
1406  returnedClass = TTSymbol(atom_getsym(av)->s_name);
1407  }
1408  else {
1409 
1410  // get the patcher where is the patcher to look for the class one step upper
1411  upperPatcher = jamoma_patcher_get(patcher);
1412 
1413  jamoma_patcher_get_class(upperPatcher, context, returnedClass);
1414  }
1415  }
1416  // in bpatcher : look upper
1417  else if (hierarchy == _sym_bpatcher) {
1418 
1419  // get the patcher where is the patcher to look for the class one step upper
1420  upperPatcher = jamoma_patcher_get(patcher);
1421 
1422  jamoma_patcher_get_class(upperPatcher, context, returnedClass);
1423  }
1424  // default case : a patcher has no class
1425  else if (hierarchy == _sym_topmost)
1426  returnedClass = kTTSymEmpty;
1427  }
1428 }
1429 
1430 /** Get the name of the patcher from his arguments */
1431 void jamoma_patcher_get_name(t_object *patcher, TTSymbol context, TTSymbol& returnedName)
1432 {
1433  long ac = 0;
1434  t_atom *av = NULL;
1435  t_symbol *hierarchy, *argName = _sym_nothing;
1436 
1437  returnedName = kTTSymEmpty;
1438 
1439  // try to get context name from the patcher arguments
1440  hierarchy = jamoma_patcher_get_hierarchy(patcher);
1441  jamoma_patcher_get_args(patcher, &ac, &av);
1442 
1443  // for subpatcher :
1444  if (hierarchy == _sym_subpatcher) {
1445 
1446  // remove first 'p' or 'patcher'
1447  if (ac > 0 && av) {
1448  if (atom_getsym(av) == _sym_p || atom_getsym(av) == _sym_patcher) {
1449  ac--;
1450  av++;
1451  }
1452  }
1453 
1454  // remove the next argument because it is the class
1455  ac--;
1456  av++;
1457  }
1458 
1459  // is there still arguments ?
1460  if (ac > 0 && av) {
1461 
1462  // notice we have to test view case before model case
1463  // because a j.view can be in subpatcher too
1464 
1465  // for view : the second argument is the name
1466  // (the first is reserved for the model:address)
1467  if (context == kTTSym_view) {
1468  if (ac > 1)
1469  argName = atom_getsym(av+1);
1470 
1471  // for model : the first argument is the name
1472  } else if (context == kTTSym_model || hierarchy == _sym_subpatcher)
1473  argName = atom_getsym(av);
1474 
1475  // if the argname begin by a @ ignore it
1476  if (argName->s_name[0] == '@')
1477  argName = _sym_nothing;
1478 
1479  if (argName != _sym_nothing)
1480  returnedName = TTSymbol(jamoma_parse_dieze(patcher, argName)->s_name);
1481  }
1482 }
1483 
1484 /** Get all context info from the root j.model|view in the patcher */
1485 void jamoma_patcher_share_info(t_object *patcher, t_object **returnedPatcher, TTSymbol& returnedContext, TTSymbol& returnedClass, TTSymbol& returnedName)
1486 {
1487  TTValue patcherInfo;
1488  t_object *obj;
1489  t_symbol *_sym_j_model, *_sym_j_view, *_sym_j_context, *_sym_share;
1490 
1491  obj = object_attr_getobj(patcher, _sym_firstobject);
1492 
1493  // TODO : cache those t_symbol else where ...
1494  _sym_j_model = gensym("j.model");
1495  _sym_j_view = gensym("j.view");
1496  _sym_share = gensym("share_patcher_info");
1497  while (obj) {
1498  _sym_j_context = object_attr_getsym(obj, _sym_maxclass);
1499  if (_sym_j_context == _sym_j_model || _sym_j_context == _sym_j_view) {
1500 
1501  // ask it patcher info
1502  object_method(object_attr_getobj(obj, _sym_object), _sym_share, &patcherInfo);
1503 
1504  if (patcherInfo.size() == 4) {
1505  *returnedPatcher = (t_object*)((TTPtr)patcherInfo[0]);
1506  returnedContext = patcherInfo[1];
1507  returnedClass = patcherInfo[2];
1508  returnedName = patcherInfo[3];
1509  break;
1510  }
1511  }
1512  obj = object_attr_getobj(obj, _sym_nextobject);
1513  }
1514 }
1515 
1516 /** Get j.model or j.view of a patcher */
1517 void jamoma_patcher_get_model_or_view(t_object *patcher, t_object **returnedModelOrView)
1518 {
1519  TTValue patcherInfo;
1520  t_object *obj;
1521  t_symbol *_sym_j_model, *_sym_j_view, *_sym_j_context;
1522 
1523  *returnedModelOrView = NULL;
1524 
1525  obj = object_attr_getobj(patcher, _sym_firstobject);
1526 
1527  // TODO : cache those t_symbol else where ...
1528  _sym_j_model = gensym("j.model");
1529  _sym_j_view = gensym("j.view");
1530  while (obj) {
1531  _sym_j_context = object_attr_getsym(obj, _sym_maxclass);
1532  if (_sym_j_context == _sym_j_model || _sym_j_context == _sym_j_view) {
1533 
1534  *returnedModelOrView = object_attr_getobj(obj, _sym_object);
1535  break;
1536  }
1537  obj = object_attr_getobj(obj, _sym_nextobject);
1538  }
1539 }
1540 
1541 /** Look for input and output (data and audio) */
1542 void jamoma_patcher_get_input_output(t_object *patcher, TTBoolean& dataInput, TTBoolean& dataOutput, TTBoolean& audioInput, TTBoolean& audioOutput)
1543 {
1544  TTValue patcherInfo;
1545  t_object *obj;
1546  t_symbol *_sym_jcomcontext, *_sym_jin, *_sym_jout, *_sym_jintilda, *_sym_jouttilda;
1547 
1548  dataInput = NO;
1549  dataOutput = NO;
1550  audioInput = NO;
1551  audioOutput = NO;
1552 
1553  obj = object_attr_getobj(patcher, _sym_firstobject);
1554 
1555  // TODO : cache those t_symbol else where ...
1556  _sym_jin = gensym("j.in");
1557  _sym_jout = gensym("j.out");
1558  _sym_jintilda = gensym("j.in~");
1559  _sym_jouttilda = gensym("j.out~");
1560  while (obj) {
1561  _sym_jcomcontext = object_attr_getsym(obj, _sym_maxclass);
1562 
1563  dataInput = dataInput || _sym_jcomcontext == _sym_jin;
1564  dataOutput = dataOutput || _sym_jcomcontext == _sym_jout;
1565  audioInput = audioInput || _sym_jcomcontext == _sym_jintilda;
1566  audioOutput = audioOutput || _sym_jcomcontext == _sym_jouttilda;
1567 
1568  obj = object_attr_getobj(obj, _sym_nextobject);
1569  }
1570 }
1571 
1572 /** Is there a j.ui object */
1574 {
1575  TTValue patcherInfo;
1576  t_object *obj;
1577  t_symbol *_sym_jcomcontext, *_sym_jui;
1578  TTBoolean uiObject = NO;
1579 
1580  obj = object_attr_getobj(patcher, _sym_firstobject);
1581 
1582  // TODO : cache this t_symbol else where ...
1583  _sym_jui = gensym("j.ui");
1584  while (obj) {
1585  _sym_jcomcontext = object_attr_getsym(obj, _sym_maxclass);
1586 
1587  uiObject = _sym_jcomcontext == _sym_jui;
1588  if (uiObject)
1589  break;
1590 
1591  obj = object_attr_getobj(obj, _sym_nextobject);
1592  }
1593 
1594  return uiObject;
1595 }
1596 
1597 /** Get the "aClass.model" external in the patcher */
1598 void jamoma_patcher_get_model_patcher(t_object *patcher, TTSymbol modelClass, t_object **returnedModelPatcher)
1599 {
1600  t_object *obj;
1601  t_symbol *_sym_modelfilename, *_sym_objmaxclass, *_sym_objfilename;
1602 
1603  jamoma_edit_filename(*ModelPatcherFormat, modelClass, &_sym_modelfilename);
1604 
1605  obj = object_attr_getobj(patcher, _sym_firstobject);
1606 
1607  *returnedModelPatcher = NULL;
1608 
1609  while (obj) {
1610 
1611  // look for jpatcher
1612  _sym_objmaxclass = object_attr_getsym(obj, _sym_maxclass);
1613  if (_sym_objmaxclass == _sym_jpatcher) {
1614 
1615  // look for _sym_modelfilename
1616  _sym_objfilename = object_attr_getsym(obj, _sym_filename);
1617  if (_sym_objfilename == _sym_modelfilename) {
1618 
1619  *returnedModelPatcher = object_attr_getobj(obj, _sym_object);
1620  break;
1621  }
1622  }
1623  obj = object_attr_getobj(obj, _sym_nextobject);
1624  }
1625 }
1626 
1627 /** Get patcher's node from the root j.model|view in the patcher */
1628 void jamoma_patcher_share_node(t_object *patcher, TTNodePtr *patcherNode)
1629 {
1630  t_object *obj;
1631  t_symbol *_sym_j_model, *_sym_j_view, *_sym_j_context, *_sym_share;
1632 
1633  *patcherNode = NULL;
1634 
1635  obj = object_attr_getobj(patcher, _sym_firstobject);
1636 
1637  // TODO : cache those t_symbol else where ...
1638  _sym_j_model = gensym("j.model");
1639  _sym_j_view = gensym("j.view");
1640  _sym_share = gensym("share_patcher_node");
1641  while (obj) {
1642  _sym_j_context = object_attr_getsym(obj, _sym_maxclass);
1643  if (_sym_j_context == _sym_j_model || _sym_j_context == _sym_j_view) {
1644 
1645  // ask it patcher info
1646  object_method(object_attr_getobj(obj, _sym_object), _sym_share, patcherNode);
1647 
1648  if (*patcherNode)
1649  break;
1650  }
1651  obj = object_attr_getobj(obj, _sym_nextobject);
1652  }
1653 }
1654 
1655 /** Get all context info from an object (his patcher and the context, the class and the name of his patcher) */
1656 TTErr jamoma_patcher_get_info(t_object *obj, t_object **returnedPatcher, TTSymbol& returnedContext, TTSymbol& returnedClass, TTSymbol& returnedName)
1657 {
1658  TTBoolean canShare;
1659  t_symbol *_sym_j_context;
1660  TTString viewName;
1661  t_object *patcher;
1662  t_object *sharedPatcher = NULL;
1663  TTSymbol sharedContext;
1664  TTSymbol sharedClass;
1665  TTSymbol sharedName;
1666 
1667  *returnedPatcher = jamoma_patcher_get(obj);
1668 
1669  _sym_j_context = object_classname(obj);
1670  canShare = _sym_j_context == gensym("j.model") || _sym_j_context == gensym("j.view");
1671 
1672  patcher = *returnedPatcher;
1673 
1674  // Get the context, the class and the name of the patcher
1675  if (*returnedPatcher) {
1676 
1677  // try to get them from a j.model|view around to go faster (except for j.model|view of course)
1678  if (!canShare) {
1679 
1680  jamoma_patcher_share_info(*returnedPatcher, &sharedPatcher, sharedContext, sharedClass, sharedName);
1681 
1682  if (sharedPatcher && sharedContext && sharedClass && sharedName) {
1683 
1684  *returnedPatcher = sharedPatcher;
1685  returnedContext = sharedContext;
1686  returnedClass = sharedClass;
1687  returnedName = sharedName;
1688  return kTTErrNone;
1689  }
1690  }
1691 
1692  // get the context looking for a j.model|view in the patcher
1693  // it will also return a patcher above where a j.model|view has been found
1694  jamoma_patcher_get_context(returnedPatcher, returnedContext);
1695 
1696  // if still no context : stop the subscription process
1697  if (returnedContext == kTTSymEmpty) {
1698 
1699  returnedName = S_SEPARATOR;
1700  returnedClass = kTTSymEmpty;
1701 
1702  // can't find any j.model|view with a correct context attribute in the patcher
1703  // so this means the object have to be registered under the root
1704  return kTTErrGeneric;
1705  }
1706 
1707  // get the class from the patcher filename
1708  jamoma_patcher_get_class(*returnedPatcher, returnedContext, returnedClass);
1709 
1710  // if no class : set it as "Untitled" to continue the process
1711  if (returnedClass == kTTSymEmpty)
1712  returnedClass = TTSymbol("Untitled");
1713 
1714  // for j.model|view object, use the patcher where it is to get the name
1715  if (canShare)
1716  jamoma_patcher_get_name(patcher, returnedContext, returnedName);
1717  // else get the name from the argument of the patcher
1718  else
1719  jamoma_patcher_get_name(*returnedPatcher, returnedContext, returnedName);
1720 
1721  // if no name
1722  if (returnedName == kTTSymEmpty) {
1723 
1724  // for model : used "class"
1725  if (returnedContext == kTTSym_model)
1726  returnedName = returnedClass;
1727 
1728  // for view : used "class(view)"
1729  else if (returnedContext == kTTSym_view) {
1730  viewName = returnedClass.c_str();
1731  viewName += "(view)";
1732  returnedName = TTSymbol(viewName.data());
1733  }
1734 
1735  // format name coming from class name replacing '.' and ' ' by '_'
1736  TTString s_toParse = returnedName.c_str();
1737  std::replace(s_toParse.begin(), s_toParse.end(), '.', '_');
1738  std::replace(s_toParse.begin(), s_toParse.end(), ' ', '_');
1739 
1740  // in poly case, the index is used to edit an instance
1741  // according to the voice index of the poly~
1742  if (jamoma_patcher_get_hierarchy(patcher) == gensym("poly")) {
1743 
1744  t_object *assoc = NULL;
1745  method m = NULL;
1746 
1747  object_method(patcher, gensym("getassoc"), &assoc);
1748  if (assoc) {
1749 
1750  m = zgetfn(assoc, gensym("getindex"));
1751  if(m) {
1752 
1753  char *s_num;
1754  long index = (long)(*m)(assoc, patcher);
1755  TTInt32 len;
1756 
1757  s_toParse += ".%d";
1758  len = s_toParse.size() + (TTInt32)log10((TTFloat32)index); // note : %d (lenght = 2) is replaced by 1 character (0::9), 2 charecters (10 :: 99), 3 char...
1759  s_num = (char *)malloc(sizeof(char)*len);
1760  snprintf(s_num, len, s_toParse.c_str(), index);
1761  s_toParse = s_num;
1762  free(s_num);
1763  }
1764  }
1765  }
1766 
1767  returnedName = TTSymbol(s_toParse);
1768  }
1769  }
1770  // if no patcher : stop the subscription process
1771  else {
1772  object_error(obj, "Can't get the patcher. Subscription failed");
1773  return kTTErrGeneric;
1774  }
1775 
1776  return kTTErrNone;
1777 }
1778 
1779 /** returned the N inside "pp/xx.[N]/yyy" and a format string as "pp/xx.%d/yy" and a format string as "pp/xx.%s/yy" */
1780 TTUInt32 jamoma_parse_bracket(t_symbol *s, TTString& si_format, TTString& ss_format)
1781 {
1782  long number = 0;
1783  TTString s_toParse = s->s_name;
1784  TTString s_number;
1785  TTString s_before;
1786  TTString s_after;
1787  TTStringIter begin, end;
1788  TTStringIter beginNumber, endNumber;
1789 
1790  begin = s_toParse.begin();
1791  end = s_toParse.end();
1792 
1793  // parse braket
1794  if (!ttRegexForBracket->parse(begin, end))
1795  {
1796  beginNumber = ttRegexForBracket->begin();
1797  endNumber = ttRegexForBracket->end();
1798 
1799  s_before = TTString(begin, ttRegexForBracket->begin()-1);
1800  s_number = TTString(ttRegexForBracket->begin(), ttRegexForBracket->end());
1801  s_after = TTString(ttRegexForBracket->end()+1, end);
1802 
1803  sscanf(s_number.c_str(), "%ld", &number);
1804 
1805  si_format = s_before;
1806  si_format += "%d";
1807  si_format += s_after;
1808 
1809  ss_format = s_before;
1810  ss_format += "%s";
1811  ss_format += s_after;
1812  }
1813  else {
1814  si_format = "";
1815  ss_format = "";
1816  }
1817 
1818  return number;
1819 }
1820 
1821 /** edit a new instance of the given format address using interger */
1822 void jamoma_edit_numeric_instance(TTString format, t_symbol** returnedName, long i)
1823 {
1824  char *s_num;
1825  TTInt32 len;
1826 
1827  if (i > 0) {
1828  len = format.size() + (TTInt32)log10((TTFloat32)i); // note : %d (lenght = 2) is replaced by 1 character (0::9), 2 charecters (10 :: 99), 3 char...
1829  s_num = (char *)malloc(sizeof(char)*len);
1830  snprintf(s_num, len, format.c_str(), i);
1831  *returnedName = gensym(s_num);
1832  free(s_num);
1833  }
1834 }
1835 
1836 /** edit a new instance of the given format address using string */
1837 void jamoma_edit_string_instance(TTString format, t_symbol** returnedName, TTString s)
1838 {
1839  char *s_str;
1840  long len;
1841 
1842  len = format.size() + s.size();
1843  s_str = (char *)malloc(sizeof(char)*len);
1844  snprintf(s_str, len, format.c_str(), s.c_str());
1845  *returnedName = gensym(s_str);
1846  free(s_str);
1847 }
1848 
1849 /** edit a file name from a given file format and a class name */
1850 void jamoma_edit_filename(TTString format, TTSymbol className, t_symbol **returnedFileName)
1851 {
1852  char *s_str;
1853  long len;
1854 
1855  len = format.size() + className.string().size();
1856  s_str = (char *)malloc(sizeof(char)*len);
1857  snprintf(s_str, len, format.c_str(), className.c_str());
1858  *returnedFileName = gensym(s_str);
1859  free(s_str);
1860 }
1861 
1862 
1863 // Files
1864 ///////////////////////////////////////////////
1865 
1866 
1867 /** Get BOOT style filepath from args or, if no args open a dialog to write a file */
1868 TTSymbol jamoma_file_write(t_object *x, long argc, const t_atom *argv, char* default_filename)
1869 {
1870  char fullpath[MAX_PATH_CHARS]; // for storing the absolute path of the file
1871  short err, path; // pathID#, error number
1872  t_filehandle file_handle; // a reference to our file (for opening it, closing it, etc.)
1873  t_fourcc filetype = 'TEXT', outtype; // the file type that is actually true
1874  t_symbol *userpath;
1875  TTSymbol result = kTTSymEmpty;
1876 
1877  // Give a path ...
1878  if (argc && argv) {
1879  if (atom_gettype(argv) == A_SYM) {
1880  userpath = atom_getsym(argv);
1881 
1882  if (userpath != _sym_nothing && userpath != _sym_bang) {
1883  // Use BOOT style path
1884  path = 0;
1885  path_nameconform(userpath->s_name, fullpath, PATH_STYLE_NATIVE, PATH_TYPE_BOOT);// Copy symbol argument to a local string
1886 
1887  // Create a file using Max API
1888  path_createsysfile(fullpath, path, filetype, &file_handle);
1889 
1890  result = TTSymbol(fullpath);
1891  }
1892  }
1893  }
1894 
1895  // ... or open a dialog
1896  if (result == kTTSymEmpty) {
1897 
1898  saveas_promptset("Save Preset..."); // Instructional Text in the dialog
1899  err = saveasdialog_extended(default_filename, &path, &outtype, &filetype, 1); // Returns 0 if successful
1900  if (!err) { // User Cancelled
1901  char posixpath[MAX_PATH_CHARS];
1902 
1903  // Create a file using Max API
1904  path_createsysfile(default_filename, path, filetype, &file_handle);
1905 
1906  // Use BOOT style path
1907  path_topathname(path, default_filename, fullpath);
1908  path_nameconform(fullpath, posixpath, PATH_STYLE_NATIVE, PATH_TYPE_BOOT);
1909 
1910  result = TTSymbol(posixpath);
1911  }
1912  }
1913 
1914  return result;
1915 }
1916 
1917 /** Get BOOT style filepath from args or, if no args open a dialog to read a file */
1918 TTSymbol jamoma_file_read(t_object *x, long argc, const t_atom *argv, t_fourcc filetype)
1919 {
1920  char filepath[MAX_FILENAME_CHARS]; // for storing the name of the file locally
1921  char fullpath[MAX_PATH_CHARS]; // path and name passed on to the xml parser
1922  char posixpath[MAX_PATH_CHARS];
1923  short path = 0; // pathID#
1924  t_fourcc outtype;
1925  t_symbol *userpath;
1926  TTSymbol result = kTTSymEmpty;
1927 
1928  // Give a path ...
1929  if (argc && argv) {
1930  if (atom_gettype(argv) == A_SYM) {
1931  userpath = atom_getsym(argv);
1932 
1933  if (userpath != _sym_nothing && userpath != _sym_bang) {
1934 
1935  strncpy_zero(filepath, userpath->s_name, MAX_FILENAME_CHARS); // must copy symbol before calling locatefile_extended
1936  if (locatefile_extended(filepath, &path, &outtype, &filetype, 1)) { // Returns 0 if successful
1937 
1938  object_error(x, "%s : not found", filepath);
1939  return result;
1940  }
1941  }
1942  }
1943  }
1944 
1945  // ... or open a dialog
1946  if (!path)
1947  open_dialog(filepath, &path, &outtype, &filetype, 1);
1948 
1949  if (path) {
1950 
1951  path_topathname(path, filepath, fullpath);
1952  path_nameconform(fullpath, posixpath, PATH_STYLE_NATIVE, PATH_TYPE_BOOT);
1953  result = TTSymbol(posixpath);
1954  }
1955 
1956  return result;
1957 }
1958 
void jamoma_patcher_get_class(t_object *patcher, TTSymbol context, TTSymbol &returnedClass)
Get the class of the patcher from the file name (removing .model and .view convention name if they ex...
TTErr setSchema(const TTSymbol schemaName)
TODO: Add documentation schemaName TODO: Add documentation.
JAMOMA_EXPORT TTRegex * ttRegexForJmod
A global regex to parse jmod. (usefull to detect a 0.5 module)
void jamoma_patcher_get_model_or_view(t_object *patcher, t_object **returnedModelOrView)
Get j.model or j.view of a patcher.
void jamoma_ttvalue_to_Atom(const TTValue &v, long *argc, t_atom **argv)
Make an Atom array from a TTValue (!!! this method allocate memory for the Atom array ! free it after...
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
Definition: TTBase.h:167
TTHashPtr jamoma_explorer_default_filter_bank(void)
TTSymbol jamoma_file_write(t_object *x, long argc, const t_atom *argv, char *default_filename)
Get BOOT style filepath from args or, if no args open a dialog to write a file.
TTErr jamoma_patcher_get_info(t_object *obj, t_object **returnedPatcher, TTSymbol &returnedContext, TTSymbol &returnedClass, TTSymbol &returnedName)
Get all context info from an object (his patcher and the context, the class and the name of his patch...
TTUInt32 jamoma_parse_bracket(t_symbol *s, TTString &si_format, TTString &ss_format)
returned the N inside "pp/xx.[N]/yyy" and a format string as "pp/xx.%d/yy" and a format string as "pp...
TTErr send(const TTSymbol aName)
Send a message to this object with no arguments.
Definition: TTObject.cpp:135
TTAddress appendAttribute(TTSymbol anAttribute)
Return a new TTAddress with attribute part.
Definition: TTAddress.h:161
TTBoolean jamoma_extern_load(t_symbol *objectname, long argc, t_atom *argv, t_object **object)
Load an external for internal use.
TTErr jamoma_viewer_create(t_object *x, TTObject &returnedViewer)
Create a viewer object.
TTErr jamoma_output_create(t_object *x, TTObject &returnedOutput)
Create an output object for signal.
We build a directory of TTNodes, and you can request a pointer for any TTNode, or add an observer to ...
Definition: TTNode.h:59
A type that contains a key and a value.
void jamoma_patcher_share_node(t_object *patcher, TTNodePtr *patcherNode)
Get patcher's node from the root j.model|view in the patcher.
TTErr jamoma_sender_create_audio(t_object *x, TTObject &returnedSender)
Create a sender object for audio signal.
TTErr jamoma_presetManager_create(t_object *x, TTObject &returnedPresetManager)
Create a preset manager object.
TTAddress getParent()
Get a pointer to the parent address.
Definition: TTAddress.h:112
void jamoma_subscriber_get_patcher_list(t_object *x, TTList &aContextListToFill)
Get the list above an external.
t_symbol * jamoma_TTName_To_MaxName(TTSymbol TTName)
Convert a TTSymbol "MyObjectMessage" into a t_symbol *"my/object/message" or return NULL if the TTSym...
const char * c_str() const
Return a pointer to the internal C-string.
Definition: TTString.h:83
JamomaModular For Max Shared Library.
TTErr jamoma_container_send(TTObject &aContainer, t_symbol *relativeAddressAndAttribute, long argc, const t_atom *argv)
Send Max data to a node (e.g., a j.parameter object) using a container object.
The TTAddress class is used to represent a string and efficiently pass and compare that string...
Definition: TTAddress.h:29
Create and use Jamoma object instances.
Definition: TTObject.h:29
size_type size() const noexcept
Return the number of elements.
JAMOMA_EXPORT TTRegex * ttRegexForJcom
A global regex to parse j.
TTErr jamoma_explorer_create(t_object *x, TTObject &returnedExplorer)
Create an explorer object.
this flag means that an address have no leading slash
Definition: TTAddressBase.h:64
void jamoma_edit_string_instance(TTString format, t_symbol **returnedName, TTString s)
edit a new instance of the given format address using string
t_symbol * jamoma_parse_dieze(t_object *x, t_symbol *address)
Parse #N inside address and replace them by parent patcher arguments if there are.
void jamoma_callback_return_signal(const TTValue &baton, const TTValue &v)
Return any signal.
void jamoma_patcher_get_args(t_object *patcher, long *argc, t_atom **argv)
Convenient method to get the patcher argument easily.
void jamoma_ttvalue_to_typed_Atom(const TTValue &v, t_symbol **msg, long *argc, t_atom **argv, TTBoolean &shifted)
Make a typed Atom array from a TTValue (!!! this method allocate memory for the Atom array ! free it ...
TTErr jamoma_input_create_audio(t_object *x, TTObject &returnedInput)
Create an input object for audio signal.
Maintain a collection of TTValue objects indexed by TTSymbol pointers.
Definition: TTHash.h:36
Symbol type.
Definition: TTBase.h:282
double TTFloat64
64 bit floating point number
Definition: TTBase.h:188
void jamoma_patcher_share_info(t_object *patcher, t_object **returnedPatcher, TTSymbol &returnedContext, TTSymbol &returnedClass, TTSymbol &returnedName)
Get all context info from the root j.model|view in the patcher.
#define ToAppName(ttName)
Convert a local application TTSymbol into a tt name.
JAMOMA_EXPORT TTRegex * ttRegexForModel
A global regex to parse .model.
void jamoma_edit_filename(TTString format, TTSymbol className, t_symbol **returnedFileName)
edit a file name from a given file format and a class name
TTErr jamoma_input_send(TTObject &anInput, t_symbol *msg, long argc, const t_atom *argv)
Send any signal to an input object.
void jamoma_patcher_get_context(t_object **patcher, TTSymbol &returnedContext)
Get the context from the upper j.model|view in the patcher or from patcher's name.
void append(const T &anElementValueToAppend)
Insert a single TTElement at the end.
Definition: TTValue.h:243
void * TTPtr
A generic pointer.
Definition: TTBase.h:248
TTBoolean jamoma_patcher_get_ui(t_object *patcher)
Is there a j.ui object.
TTErr get(const TTSymbol aName, T &aReturnedValue) const
Get an attribute value for an object.
TTErr JAMOMA_EXPORT jamoma_node_info_create(t_object *x, TTObject &returnedNodeInfo)
Create a TTNodeInfo object.
void jamoma_patcher_get_name(t_object *patcher, TTSymbol context, TTSymbol &returnedName)
Get the name of the patcher from his arguments.
void jamoma_edit_numeric_instance(TTString format, t_symbol **returnedName, long i)
edit a new instance of the given format address using interger
void jamoma_callback_return_value(const TTValue &baton, const TTValue &v)
Return the value to a j.
64-bit floating point
Definition: TTBase.h:272
TTErr jamoma_output_create_audio(t_object *x, TTObject &returnedOutput)
Create an output object for audio signal.
TTErr set(const TTSymbol aName, T aValue)
Set an attribute value for an object.
The TTSymbol class is used to represent a string and efficiently pass and compare that string...
Definition: TTSymbol.h:26
TTErr append(const TTSymbol key, const TTValue &value)
Insert an item into the hash table.
Definition: TTHash.cpp:70
TTErr jamoma_viewer_send(TTObject &aViewer, t_symbol *msg, long argc, const t_atom *argv)
Send Max data using a viewer object.
void jamoma_ttvalue_from_Atom(TTValue &v, t_symbol *msg, long argc, const t_atom *argv)
Make a TTValue from Atom array.
float TTFloat32
32 bit floating point number
Definition: TTBase.h:187
#define ToTTName(appName)
Convert a tt name TTSymbol into a local application name.
JAMOMA_EXPORT TTRegex * ttRegexForMaxpat
A global regex to parse .maxpat.
TTErr jamoma_output_send(TTObject &anOutput, t_symbol *msg, long argc, const t_atom *argv)
Send any signal to an output object.
void jamoma_patcher_get_model_patcher(t_object *patcher, TTSymbol modelClass, t_object **returnedModelPatcher)
Get the "aClass.model" external in the patcher.
JAMOMA_EXPORT TTRegex * ttRegexForModule
A global regex to parse .module.
TTSymbol & getAttribute()
Get the attribute part.
Definition: TTAddress.h:130
TTSymbol getNameInstance()
Get the name.instance part.
Definition: TTAddress.h:142
const char * c_str() const
Return a pointer to the internal string as a C-string.
Definition: TTSymbol.h:77
std::int32_t TTInt32
32 bit signed integer
Definition: TTBase.h:177
JAMOMA_EXPORT TTRegex * ttRegexForBracket
A global regex to parse [ and ].
TTErr jamoma_data_create(t_object *x, TTObject &returnedData, TTSymbol service)
Create a data object.
JAMOMA_EXPORT TTRegex * ttRegexForMaxhelp
A global regex to parse .maxhelp.
void jamoma_callback_return_signal_audio(const TTValue &baton, const TTValue &v)
Return audio signal.
void jamoma_callback_return_address(const TTValue &baton, const TTValue &v)
Return an address to a j.
32-bit floating point
Definition: TTBase.h:271
void clear()
Clear all values from the vector, leaving with size of 0.
Definition: TTValue.h:131
TTErr jamoma_sender_create(t_object *x, TTObject &returnedSender)
Create a sender object.
Something went wrong, but what exactly is not known. Typically used for context-specific problems...
Definition: TTBase.h:344
TTAddressType getType()
Get the type.
Definition: TTAddress.h:136
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
TTErr append(const TTSymbol key, const TTValue &value)
Insert an item into the hash table.
void JAMOMA_EXPORT jamoma_callback_return_ramped_value(void *o, TTUInt32 n, TTFloat64 *v)
std::uint32_t TTUInt32
32 bit unsigned integer
Definition: TTBase.h:178
TTErr jamoma_receiver_create(t_object *x, TTObject &returnedReceiver)
Create a receiver object.
TTErr jamoma_cueManager_create(t_object *x, TTObject &returnedCueManager)
Create a cue manager object.
size_t size() const
Find out the length of a string.
Definition: TTString.h:144
TTErr jamoma_container_create(t_object *x, TTObject &returnedContainer)
Create a container object.
JAMOMA_EXPORT TTRegex * ttRegexForView
A global regex to parse .view.
TTSymbol jamoma_file_read(t_object *x, long argc, const t_atom *argv, t_fourcc filetype)
Get BOOT style filepath from args or, if no args open a dialog to read a file.
TTErr jamoma_receiver_create_audio(t_object *x, TTObject &returnedReceiver)
Create a receiver object for audio signal.
TTErr jamoma_subscriber_create(t_object *x, TTObject &anObject, TTAddress relativeAddress, TTObject &returnedSubscriber, TTSymbol &returnedAddress, TTNodePtr *returnedNode, TTNodePtr *returnedContextNode)
Create a #TTSubscriber object and register a TTObject into the tree or, if aTTObject is NULL...
TTErr jamoma_sender_send(TTObject &aSender, t_symbol *msg, long argc, const t_atom *argv)
Send Max data using a sender object.
No Error.
Definition: TTBase.h:343
The TTString class is used to represent a string.
Definition: TTString.h:34
TTErr jamoma_data_command(TTObject &aData, t_symbol *msg, long argc, const t_atom *argv)
Send Max data command.
t_symbol * jamoma_patcher_get_hierarchy(t_object *patcher)
Get the hierarchy of the patcher : bpatcher, subpatcher or top level one.
TTBoolean valid() const
Determine if the object contained by this TTObject is truly ready for use.
Definition: TTObject.cpp:179
TTErr jamoma_mapper_create(t_object *x, TTObject &returnedMapper)
Create a mapper object.
void jamoma_patcher_get_input_output(t_object *patcher, TTBoolean &dataInput, TTBoolean &dataOutput, TTBoolean &audioInput, TTBoolean &audioOutput)
Look for input and output (data and audio)
void resize(size_type n)
Change the number of elements.
void jamoma_callback_return_value_typed(const TTValue &baton, const TTValue &v)
Return the value to a j.
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
TTErr jamoma_ramp_create(t_object *x, TTObject &returnedRamp)
Create a TTRamp object.
TTErr jamoma_input_create(t_object *x, TTObject &returnedInput)
Create an input object for any signal.
t_object * jamoma_patcher_get(t_object *obj)
Convenient method to get the patcher easily.