Jamoma API  0.6.0.a19
j.remote_array.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationMaxExternals
4  *
5  * @brief j.remote_array : An array of j.remote objects
6  *
7  * @details Useful when designing views and more.
8  *
9  * @authors Théo de la Hogue, Trond Lossius
10  *
11  * @copyright © 2011 by Théo de la Hogue @n
12  * This code is licensed under the terms of the "New BSD License" @n
13  * http://creativecommons.org/licenses/BSD/
14  */
15 
16 
18 
19 #define set_out 0
20 #define data_out 1
21 #define index_out 2
22 #define dump_out 3
23 
24 
25 // This is used to store extra data
26 typedef struct extra {
27 
28  TTObject *modelAddressReceiver; // the internal model:address receiver (not registered inside internals)
29  TTBoolean changingAddress; // a flag to protect from succession of address changes
30  TTPtr ui_qelem; // to output "qlim'd" data for ui object
31  TTListPtr ui_qelem_list; // a list of defered value to output
32  TTUInt32 countSubscription; // to count how many time we try to subscribe
33  TTListPtr values; // store all values in a list for array format
34  TTBoolean setting; // a flag to know if the remote array is updated by a set message
35  TTBoolean lock; // a flag to lock
36 } t_extra;
37 #define EXTRA ((t_extra*)x->extra)
38 
39 // Definitions
40 void WrapTTViewerClass(WrappedClassPtr c);
41 void WrappedViewerClass_new(TTPtr self, long argc, t_atom *argv);
42 void WrappedViewerClass_free(TTPtr self);
43 
44 void remote_assist(TTPtr self, TTPtr b, long msg, long arg, char *dst);
45 
46 void remote_new_address(TTPtr self, t_symbol *address);
47 void remote_array_create(TTPtr self, TTObject& returnedViewer, TTUInt32 index);
48 void remote_array_subscribe(TTPtr self, t_symbol *address);
49 void remote_array_select(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
50 void remote_address(TTPtr self, t_symbol *name);
51 
52 void remote_array_return_value(const TTValue& baton, const TTValue& v);
53 
54 void remote_create_model_address_receiver(TTPtr self);
55 void remote_free_model_address_receiver(TTPtr self);
56 void remote_return_model_address(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
57 
58 void WrappedViewerClass_anything(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
59 void remote_bang(TTPtr self);
60 void remote_int(TTPtr self, long value);
61 void remote_float(TTPtr self, double value);
62 TTErr remote_list(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
63 
64 TTErr remote_array(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
65 
66 void remote_set(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
67 void remote_set_array(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
68 
69 void remote_ui_queuefn(TTPtr self);
70 
71 int C74_EXPORT main(void)
72 {
73  ModularSpec *spec = new ModularSpec;
74  spec->_wrap = &WrapTTViewerClass;
75  spec->_new = &WrappedViewerClass_new;
76  spec->_free = &WrappedViewerClass_free;
77  spec->_any = &WrappedViewerClass_anything;
78 
79  return wrapTTModularClassAsMaxClass(kTTSym_Viewer, "j.remote_array", NULL, spec);
80 }
81 
82 void WrapTTViewerClass(WrappedClassPtr c)
83 {
84  class_addmethod(c->maxClass, (method)remote_assist, "assist", A_CANT, 0L);
85  class_addmethod(c->maxClass, (method)remote_return_model_address, "return_model_address", A_CANT, 0);
86 
87  class_addmethod(c->maxClass, (method)remote_bang, "bang", 0L);
88  class_addmethod(c->maxClass, (method)remote_int, "int", A_LONG, 0);
89  class_addmethod(c->maxClass, (method)remote_float, "float", A_FLOAT, 0);
90  class_addmethod(c->maxClass, (method)remote_list, "list", A_GIMME, 0);
91 
92  class_addmethod(c->maxClass, (method)remote_array, "array", A_GIMME, 0);
93 
94  class_addmethod(c->maxClass, (method)remote_set, "set", A_GIMME, 0);
95  class_addmethod(c->maxClass, (method)remote_set_array, "setArray", A_GIMME, 0);
96 
97  class_addmethod(c->maxClass, (method)remote_address, "address", A_SYM,0);
98 }
99 
100 void WrappedViewerClass_new(TTPtr self, long argc, t_atom *argv)
101 {
103  long attrstart = attr_args_offset(argc, argv); // support normal arguments
104  t_symbol *address;
105  TTValue none;
106 
107  // check address argument
108  address = _sym_nothing;
109  if (attrstart && argv)
110  if (atom_gettype(argv) == A_SYM)
111  address = atom_getsym(argv);
112 
113  // add an inlet for the index
114  x->inlets = (TTHandle)sysmem_newptr(sizeof(TTPtr) * 1);
115  x->inlets[0] = proxy_new(x, 1, &x->index);
116 
117  // Make outlets (before attr_args_process)
118  /////////////////////////////////////////////////////////////////////////////////
119 
120  // Don't create outlets during dynamic changes
121  x->outlets = (TTHandle)sysmem_newptr(sizeof(TTPtr) * 3);
122  x->outlets[index_out] = outlet_new(x, NULL); // long outlet to output view index
123  x->outlets[data_out] = outlet_new(x, NULL); // anything outlet to output data
124  x->outlets[set_out] = outlet_new(x, NULL); // anything outlet to output defered data prepend with a 'set'
125 
126  x->useInternals = YES;
127  x->internals->setThreadProtection(YES);
128 
129  x->arraySize = 0;
130  x->arrayIndex = 0;
131  x->arrayAddress = kTTAdrsEmpty;
132  x->arrayArgs = none;
133  x->arrayAttrFormat = gensym("single");
134 
135  // Prepare extra data for parameters and messages
136  x->extra = (t_extra*)malloc(sizeof(t_extra));
137 
138  EXTRA->modelAddressReceiver = NULL;
139  EXTRA->changingAddress = NO;
140  EXTRA->ui_qelem = qelem_new(x, (method)remote_ui_queuefn);
141  EXTRA->ui_qelem_list = new TTList();
142  EXTRA->countSubscription = 0;
143  EXTRA->values = new TTList();
144  EXTRA->lock = NO;
145 
146  // create model:address receiver
147  remote_create_model_address_receiver(self);
148 
149  // handle args
150  if (argc && argv) {
151 
152  // set the external attribute
153  attr_args_process(x, argc, argv);
154 
155  // keep args to set the wrapped object attributes
156  if (argc > 1)
157  jamoma_ttvalue_from_Atom(x->arrayArgs, _sym_list, argc--, argv++);
158  }
159 
160  // The following must be deferred because we have to interrogate our box,
161  // and our box is not yet valid until we have finished instantiating the object.
162  // Trying to use a loadbang method instead is also not fully successful (as of Max 5.0.6)
163  defer_low((t_object*)x, (method)remote_new_address, address, 0, NULL);
164 }
165 
166 void WrappedViewerClass_free(TTPtr self)
167 {
169 
170  if (EXTRA) {
171 
172  // delete model:address receiver
173  remote_free_model_address_receiver(self);
174 
175  qelem_free(EXTRA->ui_qelem);
176 
177  delete EXTRA->ui_qelem_list;
178 
179  delete EXTRA->values;
180 
181  free(EXTRA);
182  }
183 }
184 
185 void remote_new_address(TTPtr self, t_symbol *address)
186 {
188  long argc = 0;
189  t_atom* argv = NULL;
190  TTUInt32 number;
191  TTUInt32 i;
192  TTAddress newAddress = TTAddress(address->s_name);
193  t_symbol *instanceAddress;
194  TTObject anObject, empty;
195  TTValue v;
196 
197  x->cursor = kTTSymEmpty;
198  x->arrayAddress = newAddress;
199 
200  number = jamoma_parse_bracket(address, x->arrayFormatInteger, x->arrayFormatString);
201 
202  // don't resize to 0
203  if (number && number <= MAX_ARRAY_SIZE) {
204 
205  // Starts iteration on internals
206  x->iterateInternals = YES;
207 
208  x->arraySize = number;
209 
210  EXTRA->values->clear();
211 
212  for (i = 1; i <= x->arraySize; i++) {
213 
214  jamoma_edit_numeric_instance(x->arrayFormatInteger, &instanceAddress, i);
215 
216  remote_array_create(x, anObject, i);
217 
218  // append the viewer to the internals table
219  v = TTValue(anObject);
220  v.append(TTSymbol(instanceAddress->s_name));
221  v.append(empty);
222 
223  x->internals->append(TTSymbol(instanceAddress->s_name), v);
224 
225  // inverse values order for iteration purpose (see in remote_array_return_value : array mode)
226  v.clear();
227  EXTRA->values->insert(0, v);
228  }
229 
230  // Ends iteration on internals
231  x->iterateInternals = NO;
232 
233  // clear the list used by qelem
234  qelem_unset(EXTRA->ui_qelem);
235  EXTRA->ui_qelem_list->clear();
236 
237  // handle args
238  jamoma_ttvalue_to_Atom(x->arrayArgs, &argc, &argv);
239  if (argc && argv)
240  attr_args_process(x, argc, argv);
241 
242  // try to subscribe the entire array
243  remote_array_subscribe(self, address);
244 
245  // attach the j.remote to connected ui object
246  //remote_attach(self);
247  }
248  else if (number > MAX_ARRAY_SIZE)
249  object_error((t_object*)x, "the size is greater than the maximum array size (%d)", MAX_ARRAY_SIZE);
250 }
251 
252 void remote_array_create(TTPtr self, TTObject& returnedViewer, TTUInt32 index)
253 {
255  t_symbol *iAdrs;
256  TTValue baton;
257 
258  returnedViewer = TTObject(kTTSym_Viewer);
259 
260  jamoma_edit_numeric_instance(x->arrayFormatInteger, &iAdrs, index);
261 
262  baton = TTValue(self, index, TTSymbol(iAdrs->s_name));
263  returnedViewer.set(kTTSym_baton, baton);
264  returnedViewer.set(kTTSym_function, TTPtr(&remote_array_return_value));
265 }
266 
267 void remote_array_subscribe(TTPtr self, t_symbol *address)
268 {
270  t_symbol *instanceAddress;
271  TTAddress contextAddress = kTTAdrsEmpty;
272  TTAddress absoluteAddress, returnedAddress;
273  TTNodePtr returnedNode = NULL;
274  TTNodePtr returnedContextNode = NULL;
275  TTObject toSubscribe, empty;
276  TTBoolean subscribe;
277  TTObject aSubscriber;
278  TTUInt32 i;
279  TTValue v;
280  t_atom a[1];
281 
282  // for absolute address
283  if (TTAddress(address->s_name).getType() == kAddressAbsolute) {
284 
285  // Starts iteration on internals
286  x->iterateInternals = YES;
287 
288  for (i = 1; i <= x->arraySize; i++) {
289  jamoma_edit_numeric_instance(x->arrayFormatInteger, &instanceAddress, i);
290  x->cursor = TTSymbol(instanceAddress->s_name);
291 
292  selectedObject->setAttributeValue(kTTSym_address, x->cursor);
293  }
294 
295  // Ends iteration on internals
296  x->iterateInternals = NO;
297  return;
298  }
299 
300  // for relative address
302 
303  // Do we subscribe all Viewers ?
304  // View patcher case :
305  if (x->patcherContext == kTTSym_view)
306  subscribe = YES;
307 
308  // Model patcher case :
309  // try to binds on the parameter|message|return of the model without subscribing the Viewer
310  else if (x->patcherContext == kTTSym_model)
311  subscribe = NO;
312 
313  // Any other case : no subscription
314  else
315  subscribe = NO;
316 
317  // Starts iteration on internals
318  x->iterateInternals = YES;
319 
320  for (i = 1; i <= x->arraySize; i++) {
321 
322  jamoma_edit_numeric_instance(x->arrayFormatInteger, &instanceAddress, i);
323  x->cursor = TTSymbol(instanceAddress->s_name);
324 
325  if (subscribe)
326  toSubscribe = selectedObject;
327  else
328  toSubscribe = TTObject();
329 
330  if (!jamoma_subscriber_create((t_object*)x, toSubscribe, TTAddress(instanceAddress->s_name), aSubscriber, returnedAddress, &returnedNode, &returnedContextNode)) {
331 
332  // get the context address to make
333  // a viewer on the contextAddress/model:address attribute
334  aSubscriber.get("contextAddress", v);
335  contextAddress = v[0];
336 
337  // append the subscriber to the internal
338  if (aSubscriber.valid()) {
339 
340  v = TTObject(selectedObject);
341  v.append(x->cursor);
342  v.append(aSubscriber);
343 
344  // replace the internal
345  x->internals->remove(x->cursor);
346  x->internals->append(x->cursor, v);
347  }
348  }
349 
350  // else, if no context, set address directly
351  else if (x->patcherContext == kTTSymEmpty) {
352  contextAddress = kTTAdrsRoot;
353  absoluteAddress = contextAddress.appendAddress(TTAddress(instanceAddress->s_name));
354  selectedObject->setAttributeValue(kTTSym_address, absoluteAddress);
355 
356  atom_setsym(a, gensym((char*)absoluteAddress.c_str()));
357  object_obex_dumpout((t_object*)x, gensym("address"), 1, a);
358  continue;
359  }
360 
361  // if an object can't subscribe, the other objects will fail too
362  break;
363  }
364 
365  // Ends iteration on internals
366  x->iterateInternals = NO;
367 
368  // if the subscription success
369  if (contextAddress != kTTAdrsEmpty) {
370 
371  // make the model:address receiver binds on the model:address attribute
372  EXTRA->modelAddressReceiver->set(kTTSym_address, contextAddress.appendAddress(TTAddress("model:address")));
373 
374  return;
375  }
376 
377  // otherwise while the context node is not registered : try to binds again :(
378  // (to -- this is not a good way todo. For binding we should make a subscription
379  // to a notification mechanism and each time an TTObjet subscribes to the namespace
380  // using jamoma_subscriber_create we notify all the externals which have used
381  // jamoma_subscriber_create with NULL object to bind)
382 
383  // Starts iteration on internals
384  x->iterateInternals = YES;
385 
386  for (i = 1; i <= x->arraySize; i++) {
387 
388  jamoma_edit_numeric_instance(x->arrayFormatInteger, &instanceAddress, i);
389  x->cursor = TTSymbol(instanceAddress->s_name);
390 
391  if (!x->internals->lookup(x->cursor, v)) {
392 
393  aSubscriber = v[2];
394 
395  // release the subscriber
396  if (aSubscriber.valid())
397  aSubscriber = TTObject();
398 
399  // keep only the viewer object and his address
400 
401  v.set(2, empty);
402 
403  // replace the internal
404  x->internals->remove(x->cursor);
405  x->internals->append(x->cursor, v);
406  }
407  }
408 
409  // Ends iteration on internals
410  x->iterateInternals = NO;
411 
412  EXTRA->countSubscription++; // the index member is usefull to count how many time the external tries to bind
413  if (EXTRA->countSubscription > 100) {
414  object_error((t_object*)x, "tries to bind too many times on %s", address->s_name);
415  object_obex_dumpout((t_object*)x, gensym("error"), 0, NULL);
416  return;
417  }
418 
419  // The following must be deferred because we have to interrogate our box,
420  // and our box is not yet valid until we have finished instantiating the object.
421  // Trying to use a loadbang method instead is also not fully successful (as of Max 5.0.6)
422  defer_low((t_object*)x, (method)remote_array_subscribe, address, 0, NULL);
423 }
424 
425 void remote_address(TTPtr self, t_symbol *address)
426 {
428  t_symbol *instanceAddress;
429  TTValue v;
430  TTUInt32 i;
431 
432  // Avoid succession of address changes
433  if (!EXTRA->changingAddress) {
434 
435  EXTRA->changingAddress = YES;
436 
437  // filter repetitions
438  if (!(x->arrayAddress == TTAddress(address->s_name))) {
439 
440  // unregister all internals viewers
441  if (!x->iterateInternals) {
442 
443  // Starts iteration on internals
444  x->iterateInternals = YES;
445 
446  for (i = 1; i <= x->arraySize; i++) {
447 
448  jamoma_edit_numeric_instance(x->arrayFormatInteger, &instanceAddress, i);
449  x->cursor = TTSymbol(instanceAddress->s_name);
450 
451  if (!x->internals->lookup(x->cursor, v)) {
452 
453  TTObject o = v[0];
454  o.set(kTTSym_address, kTTAdrsEmpty);
455 
456  x->internals->remove(x->cursor);
457  }
458  }
459 
460  // Ends iteration on internals
461  x->iterateInternals = NO;
462 
463  x->arraySize = 0;
464 
465  // rebuild internals
466  EXTRA->countSubscription = 0;
467  x->internals->clear();
468  defer(self,(method)remote_new_address, address, 0, NULL);
469  }
470  }
471 
472  EXTRA->changingAddress = NO;
473  return;
474  }
475 
476  object_error((t_object*)x, "can't change to %s address. Please defer low", address->s_name);
477 }
478 
479 // Method for Assistance Messages
480 void remote_assist(TTPtr self, TTPtr b, long msg, long arg, char *dst)
481 {
482  if (msg==1) { // Inlet
483  switch(arg) {
484  case 0 :
485  strcpy(dst, "set the value of the selected instance(s)");
486  break;
487  case 1 :
488  strcpy(dst, "index (use * to bind all instances)");
489  break;
490  }
491  }
492  else { // Outlets
493  switch(arg) {
494  case set_out:
495  strcpy(dst, "set: connect to ui object");
496  break;
497  case data_out:
498  strcpy(dst, "direct: values");
499  break;
500  case index_out:
501  strcpy(dst, "index");
502  break;
503  case dump_out:
504  strcpy(dst, "dumpout");
505  break;
506  }
507  }
508 }
509 
510 void remote_bang(TTPtr self)
511 {
513 
514  if (x->arraySize > 0)
515  remote_list(self, _sym_bang, 0, NULL);
516  else
517  object_error((t_object*)x, "bang : the array is empty");
518 }
519 
520 void remote_int(TTPtr self, long value)
521 {
523  t_atom a;
524 
525  if (proxy_getinlet((t_object*)x)) {
526  atom_setlong(&a, value);
527  wrappedModularClass_ArraySelect(self, _sym_nothing, 1, &a);
528  }
529  else {
530  if (x->arraySize > 0) {
531  atom_setlong(&a, value);
532  remote_list(self, _sym_int, 1, &a);
533  }
534  else
535  object_error((t_object*)x, "int : the array is empty");
536  }
537 }
538 
539 void remote_float(TTPtr self, double value)
540 {
542  t_atom a;
543 
544  if (x->arraySize > 0) {
545 
546  atom_setfloat(&a, value);
547  remote_list(self, _sym_float, 1, &a);
548  }
549  else
550  object_error((t_object*)x, "float : the array is empty");
551 }
552 
553 TTErr remote_list(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
554 {
556  TTErr err = kTTErrNone;
557  TTObject o;
558 
559  if (x->arraySize > 0) {
560 
561  // send to each view
562  if (x->arrayIndex == 0) {
563 
564  TTValue keys;
565 
566  if (!x->internals->isEmpty()) {
567  x->internals->getKeys(keys);
568  for (int i = 0; i < keys.size(); i++) {
569 
570  x->cursor = keys[i];
571  o = selectedObject;
572  if (jamoma_viewer_send(o, msg, argc, argv))
573 
574  err = kTTErrGeneric;
575  }
576  }
577 
578  // watching the first instance by default
579  x->cursor = keys[0];
580 
581  return err;
582  }
583  else {
584  o = selectedObject;
585  jamoma_viewer_send(o, msg, argc, argv);
586  }
587  }
588  else
589  object_error((t_object*)x, "list : the array is empty");
590 
591  return kTTErrGeneric;
592 }
593 
594 void WrappedViewerClass_anything(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
595 {
597  TTObject o;
598 
599  if (proxy_getinlet((t_object*)x))
600  wrappedModularClass_ArraySelect(self, msg, argc, argv);
601  else
602  remote_list(self, msg, argc, argv);
603 }
604 
605 TTErr remote_array(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
606 {
608  TTInt32 d, i;
609  t_symbol *instanceAddress;
610  TTSymbol memoCursor;
611  TTErr err = kTTErrNone;
612 
613  if (x->arraySize > 0) {
614 
615  // is the incoming data size is a multiple of the array size ?
616  d = argc / x->arraySize;
617  if ((d * x->arraySize) == argc) {
618 
619  memoCursor = x->cursor;
620 
621  if (!x->internals->isEmpty()) {
622 
623  for (i = 1; i <= x->arraySize; i++) {
624 
625  jamoma_edit_numeric_instance(x->arrayFormatInteger, &instanceAddress, i);
626  x->cursor = TTSymbol(instanceAddress->s_name);
627  TTObject o = selectedObject;
628  if (jamoma_viewer_send(o, _sym_nothing, d, argv+((i-1)*d)))
629 
630  err = kTTErrGeneric;
631  }
632  }
633 
634  x->cursor = memoCursor;
635 
636  return err;
637  }
638  else
639  object_error((t_object*)x, "array : the array message size have to be a multiple of the array size");
640 
641  }
642  else
643  object_error((t_object*)x, "array : the array is empty");
644 
645  return kTTErrGeneric;
646 }
647 
648 void remote_set(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
649 {
651 
652  EXTRA->setting = YES;
653 
654  if (remote_list(self, _sym_nothing, argc, argv))
655 
656  EXTRA->setting = NO;
657 }
658 
659 void remote_set_array(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
660 {
662 
663  EXTRA->setting = YES;
664 
665  if (remote_array(self, _sym_nothing, argc, argv))
666 
667  EXTRA->setting = NO;
668 }
669 
670 void remote_array_return_value(const TTValue& baton, const TTValue& v)
671 {
673  TTValue array;
674  t_symbol *msg;
675  long argc = 0;
676  TTUInt32 i, j;
677  t_atom* argv = NULL;
678  TTBoolean shifted = NO;
679 
680  // unpack baton (a t_object, the index of the value and the instance symbol)
681  x = WrappedModularInstancePtr((TTPtr)baton[0]);
682  i = baton[1];
683 
684  // a gate to not output the value if it have been set by this j.remote_array
685  if (EXTRA->setting)
686  {
687  EXTRA->setting = NO;
688  return;
689  }
690 
691  // output index
692  if (x->arrayIndex == 0)
693  x->cursor = baton[2];
694 
695  outlet_int(x->outlets[index_out], i);
696 
697  // in array output mode
698  // edit an array containing all values
699  if (x->arrayAttrFormat == gensym("array"))
700  {
701  // don't output array when changing address
702  if (EXTRA->changingAddress)
703  return;
704 
705  if (!EXTRA->lock)
706  {
707  EXTRA->lock = YES;
708 
709  TTListPtr vlist = EXTRA->values;
710 
711  // get each values in reverse order
712  j = vlist->getSize();
713 
714  for (vlist->begin();
715  vlist->end();
716  vlist->next())
717  {
718  // store the incoming value at the right index
719  if (j == i)
720  vlist->current() = v;
721 
722  // prepare array to output
723  TTValue prepend = vlist->current();
724  TTUInt32 size = prepend.size();
725  if (size > 0)
726  array.prepend(prepend);
727 
728  // use 0. as default value
729  else
730  array.prepend(0.);
731 
732  j--;
733  }
734 
735  // output array value
736  jamoma_ttvalue_to_typed_Atom(array, &msg, &argc, &argv, shifted);
737 
738  // append to the list used by qelem
739  EXTRA->ui_qelem_list->append(array);
740 
741  EXTRA->lock = NO;
742  }
743  else
744  return;
745  }
746  else
747  {
748  // output single value
749  jamoma_ttvalue_to_typed_Atom(v, &msg, &argc, &argv, shifted);
750 
751  // append to the list used by qelem
752  EXTRA->ui_qelem_list->append(v);
753  }
754 
755  // avoid blank before data
756  if (msg == _sym_nothing)
757  outlet_atoms(x->outlets[data_out], argc, argv);
758  else
759  outlet_anything(x->outlets[data_out], msg, argc, argv);
760 
761  // call the queue function
762  qelem_set(EXTRA->ui_qelem);
763 
764  if (shifted)
765  argv--;
766  sysmem_freeptr(argv);
767 }
768 
769 void remote_ui_queuefn(TTPtr self)
770 {
772  long argc;
773  t_atom* argv;
774  TTValue v;
775 
776  for (EXTRA->ui_qelem_list->begin();
777  EXTRA->ui_qelem_list->end();
778  EXTRA->ui_qelem_list->next()) {
779 
780  argc = 0;
781  argv = NULL;
782  jamoma_ttvalue_to_Atom(EXTRA->ui_qelem_list->current(), &argc, &argv);
783 
784  if (x->arrayAttrFormat == gensym("array"))
785  outlet_anything(x->outlets[set_out], gensym("setlist"), argc, argv);
786  else
787  outlet_anything(x->outlets[set_out], _sym_set, argc, argv);
788 
789  sysmem_freeptr(argv);
790  }
791 
792  EXTRA->ui_qelem_list->clear();
793 }
794 
795 void remote_create_model_address_receiver(TTPtr self)
796 {
798  TTValue args, baton, none;
799  TTObject returnValueCallback, empty;
800 
801  // don't need to get the receiver address back
802  args.append(empty);
803 
804  returnValueCallback = TTObject("callback");
805 
806  baton = TTValue(TTPtr(x), TTPtr(gensym("return_model_address")), YES); // YES : we want to deferlow this method
807  returnValueCallback.set(kTTSym_baton, baton);
808  returnValueCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value_typed));
809  args.append(returnValueCallback);
810 
811  EXTRA->modelAddressReceiver = new TTObject(kTTSym_Receiver, args);
812 }
813 
814 void remote_free_model_address_receiver(TTPtr self)
815 {
817 
818  EXTRA->modelAddressReceiver->set(kTTSym_address, kTTAdrsEmpty);
819 
820  delete EXTRA->modelAddressReceiver;
821 }
822 
823 void remote_return_model_address(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
824 {
826  t_symbol *instanceAddress;
827  TTAddress address;
828  TTSymbol service;
829  TTList returnedNodes;
830  TTUInt32 i;
831  TTValue v;
832 
833  if (msg) {
834 
835  // Starts iteration on internals
836  x->iterateInternals = YES;
837 
838  for (i = 1; i <= x->arraySize; i++) {
839 
840  jamoma_edit_numeric_instance(x->arrayFormatInteger, &instanceAddress, i);
841  x->cursor = TTSymbol(instanceAddress->s_name);
842 
843  // set address attribute of the internal Viewer object
844  address = TTAddress(msg->s_name).appendAddress(TTAddress(instanceAddress->s_name));
845  selectedObject->setAttributeValue(kTTSym_address, address);
846 
847  JamomaDebug object_post((t_object*)x, "binds on %s", address.c_str());
848  }
849 
850  // Ends iteration on internals
851  x->iterateInternals = NO;
852 
853  EXTRA->countSubscription = 0;
854  }
855 }
TTErr JAMOMA_EXPORT 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...
TTAddress appendAddress(const TTAddress &toAppend)
Return a new TTAddress with the appended part.
Definition: TTAddress.h:167
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
Definition: TTBase.h:167
void JAMOMA_EXPORT jamoma_edit_numeric_instance(TTString format, t_symbol **returnedName, long i)
Edit a new instance of the given format address using interger.
TTHandle outlets
an array of outlet
TTErr wrapTTModularClassAsMaxClass(TTSymbol &ttblueClassName, const char *maxClassName, WrappedClassPtr *c, ModularSpec *specificities)
Wrap a Jamoma class as a Max class.
TTErr lookup(const TTSymbol key, TTValue &value)
Find the value for the given key.
Definition: TTHash.cpp:76
We build a directory of TTNodes, and you can request a pointer for any TTNode, or add an observer to ...
Definition: TTNode.h:59
TTSymbol patcherClass
the patcher class in which the external is
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.
Data structure for storing extra data.
void * extra
used to keep very specific things
t_object * patcherPtr
the patcher in which the external is (ignoring subpatcher)
TTErr getKeys(TTValue &hashKeys)
Get an array of all of the keys for the hash table.
Definition: TTHash.cpp:126
TTHashPtr internals
An hash table to store any internal TTObjectBases (like TTData, TTViewer, ...)
void prepend(const TTValue &aValueToPrepend)
Insert another TTValue before the first element.
Definition: TTValue.h:162
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
TTErr get(const TTSymbol aName, T &aReturnedValue) const
Get an attribute value for an object.
void JAMOMA_EXPORT jamoma_ttvalue_to_Atom(const TTValue &v, long *argc, t_atom **argv)
Make an Atom array from a TTValue.
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
TTHandle inlets
an array of inlets
TTBoolean iterateInternals
The flag is true when an iteration is done on the internals.
TTBoolean isEmpty()
Return true if the hash has nothing stored in it.
Definition: TTHash.cpp:205
void JAMOMA_EXPORT 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 flag means that an address have a leading slash
Definition: TTAddressBase.h:65
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
TTErr clear()
Remove all items from the hash table.
Definition: TTHash.cpp:117
void JAMOMA_EXPORT jamoma_ttvalue_from_Atom(TTValue &v, t_symbol *msg, long argc, const t_atom *argv)
Make a TTValue from Atom array.
void JAMOMA_EXPORT jamoma_callback_return_value_typed(const TTValue &baton, const TTValue &v)
Return the value to a j.
void clear()
Clear all values from the vector, leaving with size of 0.
Definition: TTValue.h:131
void set(const TTUInt16 index, const T &anElementValue)
DEPRECATED.
Definition: TTValue.h:569
Data Structure for this object.
Something went wrong, but what exactly is not known. Typically used for context-specific problems...
Definition: TTBase.h:344
int C74_EXPORT main(void)
Set up this class as a Max external the first time an object of this kind is instantiated.
TTAddressType getType()
Get the type.
Definition: TTAddress.h:136
TTErr remove(const TTSymbol key)
Remove an item from the hash table.
Definition: TTHash.cpp:108
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
Wraps Jamoma Core classes as objects for Max/MSP.
std::uint32_t TTUInt32
32 bit unsigned integer
Definition: TTBase.h:178
TTSymbol patcherContext
the patcher context in which the external is (model, view)
TTBoolean useInternals
The hash table can be used as an array of wrappedObject.
TTSymbol patcherName
the patcher name in which the external is
No Error.
Definition: TTBase.h:343
TTErr JAMOMA_EXPORT 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...
TTUInt32 JAMOMA_EXPORT 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...
long index
index of the inlet used
TTSymbol cursor
to select an entry in x->internals
TTBoolean valid() const
Determine if the object contained by this TTObject is truly ready for use.
Definition: TTObject.cpp:179
TTErr JAMOMA_EXPORT jamoma_viewer_send(TTObject &aViewer, t_symbol *msg, long argc, const t_atom *argv)
Send Max data using a #TTViewer object.
WrappedModularInstance * WrappedModularInstancePtr
Pointer to a wrapped instance of our object.
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34