Jamoma API  0.6.0.a19
PureData/source/j.init/j.init.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationPdExternals
4  *
5  * @brief j.init - Send bang to initialize something.
6  *
7  * @details Bang source may be global or for just one module
8  *
9  * @authors Tim Place, Trond Lossius, Antoine Villeret
10  *
11  * @copyright Copyright © 2006 by Tim Place @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 "JamomaForPd.h"
19 
20 
21 #define start_out 0
22 #define end_out 1
23 
24 // Data Structure for this object
25 typedef struct _init{
26  t_object obj;
27  TTNodePtr patcherNode;
28  TTObject initReceiver;
29  TTObject subscriberObject;
30  TTAddress address;
31  TTHandle outlets;
32 } t_init;
33 
34 // Prototypes for methods
35 void *init_new(t_symbol* s, long argc, t_atom* argv); // New Object Creation Method
36 void init_free(t_init *x);
37 void init_assist(t_init *x, void *b, long m, long a, char *s); // Assistance Method
38 void init_subscribe(t_init *x);
39 void init_return_address(t_init *x, t_symbol *msg, long argc, t_atom *argv);
40 void init_return_value(t_init *x, t_symbol *msg, long argc, t_atom *argv);
41 //void init_bang(t_init *x);
42 
43 // Globals
44 t_eclass *g_init_class; // Required. Global pointing to this class
45 
46 
47 /************************************************************************************/
48 // Main() Function
49 
50 extern "C" void JAMOMA_EXPORT_MAXOBJ setup_j0x2einit(void)
51 {
52  t_eclass *c;
53 
54  // Define our class
55  c = eclass_new("j.init",(method)init_new, (method)init_free, sizeof(t_init), 0, A_GIMME, 0);
56 
57  // Make methods accessible for our class:
58  //class_addmethod(c, (method)init_bang, "bang", 0L);
59  eclass_addmethod(c, (method)init_return_address, "return_address", A_CANT, 0);
60  eclass_addmethod(c, (method)init_return_value, "return_value", A_CANT, 0);
61  eclass_addmethod(c, (method)init_assist, "assist", A_CANT, 0L);
62 
63  // Finalize our class
64  eclass_register(CLASS_BOX, c);
65  g_init_class = c;
66 
67 }
68 
69 
70 /************************************************************************************/
71 // Object Life
72 
73 // Create
74 void *init_new(t_symbol *s, long argc, t_atom *argv)
75 {
76  long attrstart = attr_args_offset(argc, argv); // support normal arguments
77  t_init *x = (t_init *)eobj_new(g_init_class);
78  t_symbol *relativeAddress = _sym_nothing; // could be used to binds on a sub level j.hub
79 
80  if (argc && argv[0].a_type == A_SYMBOL)
81  relativeAddress = atom_getsymbol(argv);
82 
83  if (x) {
84 
85  x->outlets = (TTHandle)sysmem_newptr(sizeof(TTPtr) * 2);
86  x->outlets[end_out] = bangout(x);
87  x->outlets[start_out] = bangout(x);
88 
89  x->patcherNode = NULL;
90  x->address = TTAddress(relativeAddress->s_name);
91 
92  attr_args_process(x, argc, argv); // handle attribute args
93 
94  // The following must be deferred because we have to interrogate our box,
95  // and our box is not yet valid until we have finished instantiating the object.
96  // Trying to use a loadbang method instead is also not fully successful (as of Max 5.0.6)
97  init_subscribe(x);
98  // defer_low((t_object*)x, (method)init_subscribe, NULL, 0, 0);
99  }
100 
101  return (x); // Return the pointer
102 }
103 
104 void init_free(t_init *x)
105 {
106  // release the receiver
107  x->initReceiver.set(kTTSym_address, kTTAdrsEmpty);
108  x->initReceiver = TTObject();
109 
110  // release the subscriber
111  x->subscriberObject = TTObject();
112 }
113 
114 
115 
116 /************************************************************************************/
117 // Methods bound to input/inlets
118 
119 // Method for Assistance Messages
120 void init_assist(t_init *x, void *b, long msg, long arg, char *dst)
121 {
122  if (msg==1) // Inlets
123  strcpy(dst, "");
124  else if (msg==2) { // Outlets
125  if (arg == 0)
126  strcpy(dst, "bang when initialization starts");
127  else
128  strcpy(dst, "bang when initilization is done");
129  }
130 }
131 
132 void init_subscribe(t_init *x)
133 {
134  TTValue v, args, none;
135  TTAddress contextAddress = kTTAdrsEmpty;
136  TTAddress returnedAddress;
137  TTNodePtr returnedNode = NULL;
138  TTNodePtr returnedContextNode = NULL;
139  TTObject returnAddressCallback, returnValueCallback, empty;
140 
141  // for relative address
142  if (x->address.getType() == kAddressRelative) {
143 
144  if (!jamoma_subscriber_create((t_eobj*)x, empty, x->address, x->subscriberObject, returnedAddress, &returnedNode, &returnedContextNode)) {
145 
146  // get the context address to make
147  // a receiver on the contextAddress:initialized attribute
148  x->subscriberObject.get("contextAddress", v);
149  contextAddress = v[0];
150  }
151 
152  // bind on the /model:address parameter (view patch) or return (model patch)
153  if (contextAddress != kTTAdrsEmpty) {
154 
155  // Make a TTReceiver object
156  returnAddressCallback = TTObject("callback");
157  returnAddressCallback.set(kTTSym_baton, TTPtr(x));
158  returnAddressCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_address));
159  args.append(returnAddressCallback);
160 
161  returnValueCallback = TTObject("callback");
162  returnValueCallback.set(kTTSym_baton, TTPtr(x));
163  returnValueCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value));
164  args.append(returnValueCallback);
165 
166  x->initReceiver = TTObject(kTTSym_Receiver, args);
167 
168  x->initReceiver.set(kTTSym_address, contextAddress.appendAttribute(kTTSym_initialized));
169  }
170 
171  // while the context node is not registered : try to binds again :(
172  // (to -- this is not a good way todo. For binding we should make a subscription
173  // to a notification mechanism and each time an TTObjet subscribes to the namespace
174  // using jamoma_subscriber_create we notify all the externals which have used
175  // jamoma_subscriber_create with NULL object to bind)
176  else {
177 
178  // release the subscriber
179  x->subscriberObject = TTObject();
180 
181  // The following must be deferred because we have to interrogate our box,
182  // and our box is not yet valid until we have finished instantiating the object.
183  // Trying to use a loadbang method instead is also not fully successful (as of Max 5.0.6)
184  init_subscribe(x);
185 // defer_low((t_object*)x, (method)init_subscribe, NULL, 0, 0);
186  }
187  }
188  else
189  pd_error((t_object*)x, "can't bind because %s is not a relative address", x->address.c_str());
190 }
191 
192 void init_return_address(t_init *x, t_symbol *msg, long argc, t_atom *argv)
193 {
194  ;
195 }
196 
197 // GO !
198 void init_return_value(t_init *x, t_symbol *msg, long argc, t_atom *argv)
199 {
200  if (atom_gettype(argv) == A_LONG) {
201 
202  if (atom_getlong(argv) == 0)
203  outlet_bang((t_outlet*)x->outlets[start_out]);
204  else
205  outlet_bang((t_outlet*)x->outlets[end_out]);
206 
207  }
208 }
209 
210 /*
211 // BANG !
212 void init_bang(t_init *x)
213 {
214  if (x->contextNode)
215  if (x->contextNode->getObject().valid())
216  x->contextNode->getObject().send("Init");
217 }
218  */
TTAddress appendAttribute(TTSymbol anAttribute)
Return a new TTAddress with attribute part.
Definition: TTAddress.h:161
We build a directory of TTNodes, and you can request a pointer for any TTNode, or add an observer to ...
Definition: TTNode.h:59
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 JAMOMA_EXPORT jamoma_callback_return_value(const TTValue &baton, const TTValue &v)
Return the value to a j.
Various utilities for interfacing with Pd that are not specific to JamomaModular as such...
this flag means that an address have no leading slash
Definition: TTAddressBase.h:64
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.
TTErr set(const TTSymbol aName, T aValue)
Set an attribute value for an object.
void JAMOMA_EXPORT jamoma_callback_return_address(const TTValue &baton, const TTValue &v)
Return an address to a j.
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...
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34