Jamoma API  0.6.0.a19
PureData/source/j.model/j.model.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationPdExternals
4  *
5  * @brief j.model / j.view - The main control center of Jamoma model and view patcher
6  *
7  * @details
8  *
9  * @authors Tim Place, Théo de la Hogue, Trond Lossius, Antoine Villeret
10  *
11  * @copyright Copyright © 2010 by Tim Place and Théo de la Hogue @n
12  * Copyright © 2015, Antoine Villeret@n
13  * This code is licensed under the terms of the "New BSD License" @n
14  * http://creativecommons.org/licenses/BSD/
15  */
16 
17 
18 #include "j.model.h"
19 
20 #if defined (JCOM_VIEW)
21 extern "C" void JAMOMA_EXPORT_MAXOBJ setup_j0x2eview(void)
22 #else
23 extern "C" void JAMOMA_EXPORT_MAXOBJ setup_j0x2emodel(void)
24 #endif
25 {
26  ModularSpec *spec = new ModularSpec;
27  spec->_wrap = &WrapTTContainerClass;
28  spec->_new = &WrappedContainerClass_new;
29  spec->_free = &WrappedContainerClass_free;
30  spec->_any = &WrappedContainerClass_anything;
31  spec->_notify = NULL;
32 
33  TTModelInfo::registerClass();
34 
35 #ifndef JCOM_VIEW
36  return (void) wrapTTModularClassAsPdClass(kTTSym_Container, "j.model", NULL, spec);
37 #else
38  return (void) wrapTTModularClassAsPdClass(kTTSym_Container, "j.view", NULL, spec);
39 #endif
40 }
41 
42 void WrapTTContainerClass(WrappedClassPtr c)
43 {
44  eclass_addmethod(c->pdClass, (method)model_assist, "assist", A_CANT, 0L);
45 
46  eclass_addmethod(c->pdClass, (method)model_share_patcher_info, "share_patcher_info", A_CANT, 0);
47  eclass_addmethod(c->pdClass, (method)model_share_patcher_node, "share_patcher_node", A_CANT, 0);
48 
49  eclass_addmethod(c->pdClass, (method)model_return_address, "return_address", A_CANT, 0);
50  eclass_addmethod(c->pdClass, (method)model_return_value, "return_value", A_CANT, 0);
51 
52  eclass_addmethod(c->pdClass, (method)model_return_upper_view_model_address,"return_upper_view_model_address", A_CANT, 0);
53 
54  eclass_addmethod(c->pdClass, (method)model_address, "model_address", A_CANT, 0);
55 
56  eclass_addmethod(c->pdClass, (method)model_reference_write, "reference_write", A_CANT, 0);
57 
58  eclass_addmethod(c->pdClass, (method)model_preset_return_names, "return_names", A_CANT, 0);
59  eclass_addmethod(c->pdClass, (method)model_preset_filechanged, "filechanged", A_CANT, 0);
60 
61  eclass_addmethod(c->pdClass, (method)model_preset_read, "preset_read", A_CANT, 0);
62  eclass_addmethod(c->pdClass, (method)model_preset_write, "preset_write", A_CANT, 0);
63 
64  eclass_addmethod(c->pdClass, (method)model_preset_read_again, "preset_read_again", A_CANT, 0);
65  eclass_addmethod(c->pdClass, (method)model_preset_write_again, "preset_write_again", A_CANT, 0);
66 
67  eclass_addmethod(c->pdClass, (method)model_preset_edit, "dblclick", A_CANT, 0);
68  eclass_addmethod(c->pdClass, (method)model_preset_edclose, "edclose", A_CANT, 0);
69 #ifndef JCOM_VIEW
70  eclass_addmethod(c->pdClass, (method)model_preset_read, "preset:read", A_GIMME, 0);
71  eclass_addmethod(c->pdClass, (method)model_preset_write, "preset:write", A_GIMME, 0);
72  eclass_addmethod(c->pdClass, (method)model_preset_edit, "preset:edit", A_GIMME, 0);
73 
74  eclass_addmethod(c->pdClass, (method)model_preset_read_again, "preset:read/again", A_CANT, 0);
75  eclass_addmethod(c->pdClass, (method)model_preset_write_again, "preset:write/again", A_CANT, 0);
76 #endif
77  eclass_addmethod(c->pdClass, (method)model_signal_amenities, "input_created", A_CANT, 0);
78  eclass_addmethod(c->pdClass, (method)model_signal_amenities, "output_created", A_CANT, 0);
79 
80  eclass_addmethod(c->pdClass, (method)model_signal_return_data_active, "return_data_active", A_CANT, 0);
81  eclass_addmethod(c->pdClass, (method)model_signal_return_data_bypass, "return_data_bypass", A_CANT, 0);
82 
83  eclass_addmethod(c->pdClass, (method)model_signal_return_audio_mute, "return_audio_mute", A_CANT, 0);
84  eclass_addmethod(c->pdClass, (method)model_signal_return_audio_bypass, "return_audio_bypass", A_CANT, 0);
85  eclass_addmethod(c->pdClass, (method)model_signal_return_audio_mix, "return_audio_mix", A_CANT, 0);
86  eclass_addmethod(c->pdClass, (method)model_signal_return_audio_gain, "return_audio_gain", A_CANT, 0);
87 
88  eclass_addmethod(c->pdClass, (method)model_subscribe, "loadbang", A_NULL, 0);
89 
90  CLASS_ATTR_ATOM(c->pdClass, "amenities", 0, WrappedModularInstance, extra);
91  CLASS_ATTR_DEFAULT(c->pdClass, "amenities", 0, "all");
92  CLASS_ATTR_ACCESSORS(c->pdClass, "amenities", model_get_amenities, model_set_amenities);
93  CLASS_ATTR_STYLE(c->pdClass, "amenities", 0, "text");
94 
95  CLASS_ATTR_ATOM(c->pdClass, "presets", 0, WrappedModularInstance, extra);
96  CLASS_ATTR_DEFAULT(c->pdClass, "presets", 0, "none");
97  CLASS_ATTR_ACCESSORS(c->pdClass, "presets", model_preset_get_presets, model_preset_set_presets);
98  CLASS_ATTR_STYLE(c->pdClass, "presets", 0, "text");
99 }
100 
101 void WrappedContainerClass_new(TTPtr self, long argc, t_atom *argv)
102 {
104  TTValue none;
105  t_object *aPatcher;
106 
107  // is there already a j.model or j.view in the patcher ?
108  jamoma_patcher_get_model_or_view(x->obj.o_canvas, &aPatcher);
109 
110  if (aPatcher) {
111  pd_error((t_object*)x, "can't have two models or views in the same patcher");
112  return;
113  }
114 
115  // create a container
116  jamoma_container_create((t_object*)x, x->wrappedObject);
117 
118 #ifndef JCOM_VIEW
119  x->patcherContext = kTTSym_model;
120  x->wrappedObject.set(kTTSym_service, kTTSym_model);
121 #else
122  x->patcherContext = kTTSym_view;
123  x->wrappedObject.set(kTTSym_service, kTTSym_view);
124 #endif
125 
126  // Make two outlets
127  x->outlets = (TTHandle)sysmem_newptr(sizeof(TTPtr) * 1);
128  x->outlets[data_out] = outlet_new((t_object*)x, NULL); // anything outlet to output data
129 
130  // Prepare extra data
131  x->extra = (t_extra*)malloc(sizeof(t_extra));
132  EXTRA->modelInfo = new TTObject();
133  EXTRA->containerAddress = kTTAdrsEmpty;
134  EXTRA->argAddress = kTTAdrsEmpty;
135  EXTRA->text = NULL;
136  EXTRA->textEditor = NULL;
137  EXTRA->presetManager = new TTObject();
138  EXTRA->attr_presets = kTTSym_none;
139  EXTRA->filewatcher = NULL;
140  EXTRA->toEdit = new TTObject();
141  *EXTRA->toEdit = x->wrappedObject;
142  EXTRA->presetName = kTTSymEmpty;
143  EXTRA->attr_amenities = new TTHash();
144  EXTRA->all_amenities = NO;
145  EXTRA->no_amenities = NO;
146 
147  EXTRA->attr_amenities->append(TTSymbol("all"), none);
148 
149  // handle attribute args
150  attr_args_process(x, argc, argv);
151 
152  // The following must be deferred because we have to interrogate our box,
153  // and our box is not yet valid until we have finished instantiating the object.
154  // Trying to use a loadbang method instead is also not fully successful (as of Max 5.0.6)
155  // defer_low((t_object*)x, (method)model_subscribe, NULL, 0, 0);
156  // model_subscribe((t_object*)x);
157 }
158 
160 {
162  TTAddress modelAddress, presetAddress;
163  TTValue v, none;
164 
165  if (!EXTRA)
166  return;
167 
168  if (EXTRA->modelInfo && EXTRA->modelInfo->valid()) {
169 
170  modelAddress = EXTRA->containerAddress.appendAddress(TTAddress("model"));
171 
172  // remove the model node
173  JamomaApplication.send("ObjectUnregister", modelAddress, none);
174  }
175  delete EXTRA->modelInfo;
176 
177  if (EXTRA->presetManager && EXTRA->presetManager->valid()) {
178 
179  presetAddress = EXTRA->containerAddress.appendAddress(TTAddress("preset"));
180 
181  // remove the preset node
182  JamomaApplication.send("ObjectUnregister", presetAddress, none);
183  }
184  delete EXTRA->presetManager;
185 
186  // delete filewatcher
187  /*
188  if (EXTRA->filewatcher) {
189  filewatcher_stop(EXTRA->filewatcher);
190  object_free(EXTRA->filewatcher);
191  }
192  */
193 
194  delete EXTRA->toEdit;
195 
196  // unbind the container
197  x->wrappedObject.set(kTTSym_address, kTTSymEmpty);
198 
199  free(EXTRA);
200 }
201 
203 {
205  TTValue v, args, none;
206  TTNodePtr returnedNode = NULL;
207  TTNodePtr returnedContextNode = NULL;
208  TTObject aReceiver;
209  TTObject aTextHandler;
210  TTBoolean isSubModel;
211  TTAddress returnedAddress, adrs;
212  TTSymbol description;
213  long ac;
214  t_atom* av;
215  t_atom a;
216  t_canvas* aPatcher = ((t_eobj*)x)->o_canvas;
217  TTAddress modelAddress, presetAddress;
218 
219  // unsubscribe before subscribing
220  if (EXTRA->modelInfo && EXTRA->modelInfo->valid()) {
221 
222  modelAddress = EXTRA->containerAddress.appendAddress(TTAddress("model"));
223 
224  // remove the model node
225  JamomaApplication.send("ObjectUnregister", modelAddress, none);
226  }
227 
228  if (EXTRA->presetManager && EXTRA->presetManager->valid()) {
229 
230  presetAddress = EXTRA->containerAddress.appendAddress(TTAddress("preset"));
231 
232  // remove the preset node
233  JamomaApplication.send("ObjectUnregister", presetAddress, none);
234  }
235 
236  // if the subscription is successful
237  if (!jamoma_subscriber_create((t_eobj*)x, x->wrappedObject, kTTAdrsEmpty, x->subscriberObject, returnedAddress, &returnedNode, &returnedContextNode)) {
238 
239  // get all info relative to our patcher
241  /*
242  post("j.model info :");
243  post("context : %s",x->patcherContext.c_str());
244  post("classe : %s",x->patcherClass.c_str());
245  post("name : %s",x->patcherName.c_str());
246  */
247  // set the address attribute of the Container
248  x->wrappedObject.set(kTTSym_address, returnedAddress);
249 
250  // keep the address for model_free (because the wrappedObject will be freed before)
251  EXTRA->containerAddress = returnedAddress;
252 
253  // set annotation attribute of the patcher using description attribute
254  /* AV TODO for PD ?
255  x->wrappedObject.get(kTTSym_description, v);
256  description = v[0];
257  atom_setsym(&a, gensym(description.c_str()));
258  object_attr_setvalueof(jpatcher_get_box(x->patcherPtr), _sym_annotation , 1, &a);
259  */
260 
261  // if the j.model|j.view is well subscribed
262  if (aPatcher == x->patcherPtr && x->patcherContext != kTTSymEmpty) {
263 
264  // create a model object (for j.view too !)
265  *EXTRA->modelInfo = TTObject("ModelInfo", (TTPtr)x);
266 
267  // set his class attribute
268  EXTRA->modelInfo->set("class", x->patcherClass);
269 
270  // suscribe it under a model node
271  adrs = returnedAddress.appendAddress(TTAddress("model"));
272  args = TTValue(adrs, *EXTRA->modelInfo, x->patcherPtr);
273 
274  if (JamomaApplication.send("ObjectRegister", args, none))
275  pd_error((t_object*)x, "can't subscribe model object");
276 
277  // In model patcher : set model:address with the model address
278  if (x->patcherContext == kTTSym_model) {
279 
280  EXTRA->modelInfo->set(kTTSym_address, returnedAddress);
281 
282  // then set the address attribute readOnly
283  TTModelInfoPtr(EXTRA->modelInfo->instance())->setAddressReadOnly(YES);
284  }
285 
286  // Get patcher arguments
287  ac = 0;
288  av = NULL;
289 
290  // If x is in a bpatcher, the patcher is NULL
291  // AV : the patcher can't be NULL since it is check in the if statement above
292  /*
293  if (!aPatcher)
294  aPatcher = (t_canvas*)object_attr_getobj(x, _sym_parentpatcher);
295  */
296 
297  jamoma_patcher_get_args(aPatcher, &ac, &av);
298 
299  // check if it's a sub model
300  if ( ac > 0 && av[0].a_type == A_SYMBOL )
301  isSubModel = atom_getsym(av) == _sym_pd;
302 
303  // in subpatcher :
304  if (jamoma_patcher_get_hierarchy(aPatcher) == _sym_subpatcher) {
305 
306  // remove first 'p' or 'patcher'
307  if (ac > 0 && av) {
308  if (atom_getsym(av) == _sym_pd) {
309  ac--;
310  av++;
311  }
312  }
313 
314  // remove the next argument because it is the class
315  ac--;
316  av++;
317  }
318 
319  // j.model case :
320  if (x->patcherContext == kTTSym_model) {
321 
322  // use patcher arguments to setup the model attributes (like @priority and @amenities)
323  if (ac && av)
324  attr_args_process(x, ac, av);
325 
326  // Create internal TTTextHandler (for documention and preset management)
327  aTextHandler = TTObject(kTTSym_TextHandler);
328  x->internals->append(kTTSym_TextHandler, aTextHandler);
329 
330  if (!EXTRA->attr_amenities->lookup(TTSymbol("all"), v))
331  EXTRA->all_amenities = YES;
332 
333  if (!EXTRA->attr_amenities->lookup(TTSymbol("none"), v))
334  EXTRA->no_amenities = YES;
335 
336  // Add amenities relative to preset informations
337  if (model_test_amenities(self, TTSymbol("preset")))
338 
339  // add preset managment features
341 
342  // Add amenities relative to signal informations
343  if (model_test_amenities(self, TTSymbol("data")) || model_test_amenities(self, TTSymbol("audio"))) {
344 
345  // look at model's content to create signal in/out datas
346  model_signal_amenities(self, _sym_nothing, 0, NULL);
347 
348  }
349  }
350 
351  // In view patcher : see in model_subscribe_view
352  if (x->patcherContext == kTTSym_view)
353  model_subscribe_view(self, _sym_nothing, ac, av);
354 
355  // output node address
356  t_atom a;
357  x->subscriberObject.get("nodeAddress", v);
358 
359  if (v.size() == 1) {
360  returnedAddress = v[0];
361  atom_setsym(&a, gensym((char*)returnedAddress.c_str()));
362  outlet_anything(x->dumpOut, gensym("address"),1,&a);
363 // object_obex_dumpout(self, gensym("address"), 1, &a);
364  }
365 
366  // init the model (but not subModel) or any model registered under the root
367  if (!isSubModel || returnedContextNode->getParent()->getContext() == accessApplicationLocalDirectory->getRoot()->getContext())
368  model_init(x);
369  }
370  }
371 }
372 
373 void model_subscribe_view(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
374 {
376  TTObject aReceiver;
377  t_symbol* hierarchy;
378  t_object* aPatcher;
379  TTList whereToSearch;
380  TTBoolean isThere;
381  TTNodePtr firstTTNode;
382  TTAddress modelAdrs, argAdrs, viewAdrs;
383  TTValue v;
384 
385  // look at hierarchy
387 
388  // if args exists, the first argument of the patcher is the model:address value
389  if (argc > 0 && atom_gettype(argv) == A_SYM) {
390 
391  argAdrs = TTAddress(atom_getsym(argv)->s_name);
392 
393  // in poly case : use the same instance as the container address
394  if (hierarchy == gensym("poly"))
395  if (argAdrs.getInstance() == kTTSymEmpty)
396  argAdrs = argAdrs.appendInstance(EXTRA->containerAddress.getInstance());
397 
398  // if the address is absolute : use it directly
399  if (argAdrs.getType() == kAddressAbsolute) {
400 
401  // set the model:address attribute to notify all observers
402  EXTRA->modelInfo->set(kTTSym_address, argAdrs);
403  return;
404  }
405 
406  // in case of relative address : try to use the upper view patcher model:address (else use root)
407  else {
408 
409  // if there is a parent view address : get the upper view address
410  if (EXTRA->containerAddress.getParent() != kTTAdrsRoot) {
411 
412  // keep the argument address
413  EXTRA->argAddress = argAdrs;
414 
415  // observe the selected view model:address attribute
416  makeInternals_receiver(self, EXTRA->containerAddress.getParent(), TTAddress("model:address"), gensym("return_upper_view_model_address"), aReceiver, YES); // we need to deferlow to avoid lock crash on TTContainer content
417  }
418  // use the argument address as an absolute address
419  else {
420 
421  // set the model:address attribute to notify all observers
422  EXTRA->modelInfo->set(kTTSym_address, kTTAdrsRoot.appendAddress(argAdrs));
423  return;
424  }
425  }
426  }
427  // else look around the patcher for model of the same class
428  else {
429 
430  // look for a model of the same class into the patcher of the bpatcher to get his model:address
432 
433  // if a model exists
434  if (aPatcher) {
435 
436  // is there a container (e.g. a j.model) registered with the same context in this model patcher ?
437  whereToSearch.append(accessApplicationLocalDirectory->getRoot());
438  accessApplicationLocalDirectory->IsThere(&whereToSearch, &testNodeContext, (TTPtr)aPatcher, &isThere, &firstTTNode);
439 
440  if (isThere) {
441 
442  firstTTNode->getAddress(modelAdrs);
443 
444  // set the model:address attribute to notify all observers
445  EXTRA->modelInfo->set(kTTSym_address, modelAdrs);
446  return;
447  }
448 
449  // deferlow to try another time because the model patcher is maybe not ready
450  else {
451 
452  // defer_low((t_object*)x, (method)model_subscribe_view, _sym_nothing, argc, argv);
453  model_subscribe_view(x, _sym_nothing, argc, argv);
454  return;
455  }
456  }
457  }
458 
459  // check if the model address have been filled or not (see in model_return_upper_view_model_address)
460  EXTRA->modelInfo->get(kTTSym_address, v);
461  modelAdrs = v[0];
462 
463  // if the model:address is still empty : the view is not binding a model for instant
464  if (modelAdrs == kTTSymEmpty)
465  modelAdrs = TTAddress("/no_model_address");
466 
467  // set the model:address attribute to notify all observers
468  EXTRA->modelInfo->set(kTTSym_address, modelAdrs);
469 }
470 
471 void model_return_upper_view_model_address(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
472 {
474  TTAddress upperViewModelAddress;
475  TTValue v, o, out;
476 
477  jamoma_ttvalue_from_Atom(v, msg, argc, argv);
478  upperViewModelAddress = v[0];
479 
480  // append argAddress stored in model_view_subscribe
481  if (upperViewModelAddress != kTTSymEmpty)
482  upperViewModelAddress = upperViewModelAddress.appendAddress(EXTRA->argAddress);
483  else
484  upperViewModelAddress = kTTAdrsRoot.appendAddress(EXTRA->argAddress);
485 
486  // set the model:address attribute to notify all observers
487  EXTRA->modelInfo->set(kTTSym_address, upperViewModelAddress);
488 }
489 
490 void model_init(TTPtr self)
491 {
493  TTBoolean initialized;
494  TTValue v;
495 
496  // Check if the model has not been initialized by a upper model
497  x->wrappedObject.get(kTTSym_initialized, v);
498  initialized = v[0];
499  if (!initialized)
500  x->wrappedObject.send(kTTSym_Init);
501 }
502 
503 // Method for Assistance Messages
504 void model_assist(TTPtr self, void *b, long msg, long arg, char *dst)
505 {
507 
508  if (msg==1) // Inlets
509  strcpy(dst, "");
510  else { // Outlets
511  switch(arg) {
512  case data_out:
513  if (x->patcherContext == kTTSym_model)
514  strcpy(dst, "model feeback");
515  else if (x->patcherContext == kTTSym_view)
516  strcpy(dst, "view feeback");
517  else
518  strcpy(dst, "feeback");
519  break;
520  case dump_out:
521  strcpy(dst, "dumpout");
522  break;
523  }
524  }
525 }
526 
528 {
530  patcherInfo->clear();
531 
532  if (x->patcherPtr && x->patcherContext != kTTSymEmpty && x->patcherClass != kTTSymEmpty && x->patcherName != kTTSymEmpty) {
533  patcherInfo->append((TTPtr)x->patcherPtr);
534  patcherInfo->append(x->patcherContext);
535  patcherInfo->append(x->patcherClass);
536  patcherInfo->append(x->patcherName);
537  }
538 }
539 
540 void model_share_patcher_node(TTPtr self, TTNodePtr *patcherNode)
541 {
543  TTValue v;
544 
545  if (x->subscriberObject.valid()) {
546  x->subscriberObject.get("contextNode", v);
547  *patcherNode = TTNodePtr((TTPtr)v[0]);
548  }
549 }
550 
551 void WrappedContainerClass_anything(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
552 {
554 
555  // the msg have to contains a relative address
556  jamoma_container_send(x->wrappedObject, msg, argc, argv);
557 }
558 
559 void model_return_address(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
560 {
562 
563  // store the address temporary into msg member to use it into model_return_value()
564  x->msg = msg;
565 }
566 
567 void model_return_value(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
568 {
570 
571  // using the temporay address stored previously into msg member in model_return_address()
572  outlet_anything((t_outlet*)x->outlets[data_out], x->msg, argc, argv);
573 }
574 
575 void model_reference_write(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
576 {
577 // defer(self, (method)model_reference_dowrite, msg, argc, argv);
578  model_reference_dowrite(self,msg,argc,argv);
579 }
580 
581 void model_reference_dowrite(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
582 {
584  char filename[MAX_FILENAME_CHARS];
585  TTSymbol fullpath;
586  TTValue o, v, none;
587  TTObject aTextHandler;
588  TTErr tterr;
589 
590  if (x->wrappedObject.valid()) {
591 
592  // Default HTML file name
593  snprintf(filename, MAX_FILENAME_CHARS, DocumentationFormat->data(), x->patcherClass.c_str());
594  fullpath = jamoma_file_write((t_object*)x, argc, argv, filename);
595  v.append(fullpath);
596 
597  tterr = x->internals->lookup(kTTSym_TextHandler, o);
598 
599  if (!tterr) {
600  aTextHandler = o[0];
601 
602  aTextHandler.set(kTTSym_object, x->wrappedObject);
603 
604 // critical_enter(0);
605  aTextHandler.send(kTTSym_Write, v, none);
606 // critical_exit(0);
607  }
608  }
609 }
610 
611 void model_address(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
612 {
614 
615  // In view patcher only
616  if (x->patcherContext == kTTSym_view) {
617 
618  if (atom_gettype(argv) == A_SYM) {
619 
620  TTAddress modelAdrs = TTAddress(atom_getsym(argv)->s_name);
621 
622  // set the model:address attribute to notify all observers
623  EXTRA->modelInfo->set(kTTSym_address, modelAdrs);
624  }
625  }
626 }
627 
628 t_max_err model_get_amenities(TTPtr self, TTPtr attr, long *ac, t_atom **av)
629 {
631  TTValue keys;
632 
633  EXTRA->attr_amenities->getKeysSorted(keys);
634 
635  if ((*ac)&&(*av)) {
636  //memory passed in, use it
637  } else {
638 
639  //otherwise allocate memory
640  *ac = keys.size();
641  if (!(*av = (t_atom*)getbytes(sizeof(t_atom)*(*ac)))) {
642  *ac = 0;
643  return -4; // MAX_ERR_OUT_OF_MEM;
644  }
645  }
646 
647  jamoma_ttvalue_to_Atom(keys, ac, av);
648 
649  return 0; // MAX_ERR_NONE;
650 }
651 
652 t_max_err model_set_amenities(TTPtr self, TTPtr attr, long ac, t_atom *av)
653 {
655  TTValue keys, none;
656  TTSymbol key;
657 
658  EXTRA->attr_amenities->clear();
659 
660  if (ac&&av) {
661 
662  jamoma_ttvalue_from_Atom(keys, _sym_nothing, ac, av);
663 
664  for (TTUInt8 i = 0; i < keys.size(); i++) {
665 
666  key = keys[i];
667  EXTRA->attr_amenities->append(key, none);
668  }
669  }
670  else
671  EXTRA->attr_amenities->append(TTSymbol("all"), none); // default all
672 
673  return 0; // MAX_ERR_NONE;
674 }
675 
677 {
679  TTValue v;
680 
681  return !EXTRA->no_amenities && (EXTRA->all_amenities || !EXTRA->attr_amenities->lookup(name, v));
682 }
void JAMOMA_EXPORT jamoma_patcher_get_args(t_object *patcher, long *argc, t_atom **argv)
Convenient method to get the patcher argument easily.
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...
void model_signal_return_audio_mix(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
TTAddress appendAddress(const TTAddress &toAppend)
Return a new TTAddress with the appended part.
Definition: TTAddress.h:167
t_max_err model_preset_set_presets(TTPtr self, TTPtr attr, long ac, const t_atom *av)
TTObject subscriberObject
The instance of a TTSubscriber object used to register the wrapped object in the tree structure...
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
Definition: TTBase.h:167
TTErr send(const TTSymbol aName)
Send a message to this object with no arguments.
Definition: TTObject.cpp:135
j.model / j.view - The main control center of Jamoma model and view patcher
TTSymbol & getInstance()
Get the instance part.
Definition: TTAddress.h:124
TTHandle outlets
an array of outlet
void model_preset_return_names(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
TTErr lookup(const TTSymbol key, TTValue &value)
Find the value for the given key.
Definition: TTHash.cpp:76
void model_signal_amenities(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
void model_subscribe_view(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
We build a directory of TTNodes, and you can request a pointer for any TTNode, or add an observer to ...
Definition: TTNode.h:59
void WrappedContainerClass_anything(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
t_max_err model_set_amenities(TTPtr self, TTPtr attr, long ac, t_atom *av)
TTSymbol patcherClass
the patcher class in which the external is
TTPtr getContext()
Get a pointer to the context of this node.
Definition: TTNode.cpp:473
void model_preset_amenities(TTPtr self)
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
void model_preset_edclose(TTPtr self, char **text, long size)
size_type size() const noexcept
Return the number of elements.
TTErr JAMOMA_EXPORT 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 TTContainer object.
Data structure for storing extra data.
void model_return_value(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
void model_return_address(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
void * extra
used to keep very specific things
TTAddress appendInstance(const TTSymbol anInstance)
Return a new TTAddress with a instance part.
Definition: TTAddress.h:173
t_object * patcherPtr
the patcher in which the external is (ignoring subpatcher)
void model_preset_edit(TTPtr self, t_symbol *msg, long argc, const t_atom *argv)
void model_signal_return_audio_mute(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
TTHashPtr internals
An hash table to store any internal TTObjectBases (like TTData, TTViewer, ...)
t_max_err model_get_amenities(TTPtr self, TTPtr attr, long *ac, t_atom **av)
void model_share_patcher_info(TTPtr self, TTValuePtr patcherInfo)
Maintain a collection of TTValue objects indexed by TTSymbol pointers.
Definition: TTHash.h:36
void model_share_patcher_node(TTPtr self, TTNodePtr *patcherNode)
void model_signal_return_audio_gain(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
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
void WrappedContainerClass_new(TTPtr self, long argc, t_atom *argv)
Constructor: Initiate the wrapped object instance.
TTErr get(const TTSymbol aName, T &aReturnedValue) const
Get an attribute value for an object.
TTBoolean model_test_amenities(TTPtr self, TTSymbol name)
void JAMOMA_EXPORT jamoma_ttvalue_to_Atom(const TTValue &v, long *argc, t_atom **argv)
Make an Atom array from a TTValue.
t_object obj
Max control object header.
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
TTSymbol JAMOMA_EXPORT 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.
void model_preset_write_again(TTPtr self)
TTObject wrappedObject
The instance of the Jamoma object we are wrapping.
void model_preset_read_again(TTPtr self)
void model_address(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
this flag means that an address have a leading slash
Definition: TTAddressBase.h:65
void model_reference_dowrite(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
TTErr JAMOMA_EXPORT jamoma_container_create(t_object *x, TTObject &returnedContainer)
Create a TTContainer object.
const char * c_str() const
Return a pointer to the internal string as a C-string.
Definition: TTSymbol.h:77
void model_return_upper_view_model_address(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
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 model_reference_write(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
void clear()
Clear all values from the vector, leaving with size of 0.
Definition: TTValue.h:131
void model_preset_filechanged(TTPtr self, char *filename, short path)
t_max_err model_preset_get_presets(TTPtr self, TTPtr attr, long *ac, t_atom **av)
void model_preset_write(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
TTErr getAddress(TTAddress &returnedAddress, TTAddress from=kTTAdrsEmpty)
Get the address of the node.
Definition: TTNode.cpp:478
Data Structure for this object.
TTAddressType getType()
Get the type.
Definition: TTAddress.h:136
void model_subscribe(TTPtr self)
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
void model_init(TTPtr self)
void WrappedContainerClass_free(TTPtr self)
Deconstructor: Destroy the object and free memory assigned to it.
TTSymbol patcherContext
the patcher context in which the external is (model, view)
A base class for Jamoma models.
void model_signal_return_data_active(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
void model_assist(TTPtr self, void *b, long msg, long arg, char *dst)
Display assist messages for inlets and outlets in Max.
void JAMOMA_EXPORT jamoma_patcher_get_model_patcher(t_object *patcher, TTSymbol modelClass, t_object **returnedModelPatcher)
Get the "aClass.model" external in the patcher.
t_symbol JAMOMA_EXPORT * jamoma_patcher_get_hierarchy(t_object *patcher)
Get the hierarchy of the patcher : bpatcher, subpatcher or toplevel.
TTSymbol patcherName
the patcher name in which the external is
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...
void model_signal_return_audio_bypass(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
void model_preset_read(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
void model_signal_return_data_bypass(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
TTBoolean valid() const
Determine if the object contained by this TTObject is truly ready for use.
Definition: TTObject.cpp:179
WrappedModularInstance * WrappedModularInstancePtr
Pointer to a wrapped instance of our object.
#define accessApplicationLocalDirectory
Access to the local application directory.
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
void WrapTTContainerClass(WrappedClassPtr c)
Set up what methods (Max messages) that the wrapped class is to respond to.
TTNodePtr getParent()
Get a pointer to the parent node of the node.
Definition: TTNode.cpp:296
TTErr wrapTTModularClassAsPdClass(TTSymbol &ttblueClassName, const char *pdClassName, WrappedClassPtr *c, ModularSpec *specificities)
Wrap a Jamoma class as a Pd class.
void JAMOMA_EXPORT jamoma_patcher_get_model_or_view(t_object *patcher, t_object **returnedModelOrView)
Get j.model or j.view of a patcher.
unsigned char TTUInt8
8 bit unsigned integer (char)
Definition: TTBase.h:174