Jamoma API  0.6.0.a19
PureData/source/j.modular/j.modular.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationPdExternals
4  *
5  * @brief j.modular - external to manage local and distant application
6  *
7  * @details
8  *
9  * @authors Théo de la Hogue, Trond Lossius, Antoine Villeret
10  *
11  * @copyright Copyright © 2010 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 
19 
20 #define dump_out 0
21 
22 // This is used to store extra data
23 typedef struct extra {
24 
25  TTSymbol protocolName; // remember the handled protocol
26 
27 } t_extra;
28 #define EXTRA ((t_extra*)x->extra)
29 
30 
31 // Definitions
32 void WrapTTApplicationClass(WrappedClassPtr c);
33 void WrappedApplicationClass_new(TTPtr self, long argc, t_atom *argv);
34 void WrappedApplicationClass_free(TTPtr self);
35 
36 void modular_assist(TTPtr self, void *b, long msg, long arg, char *dst);
37 
38 void modular_protocol_setup(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
39 void modular_protocol_scan(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
40 
41 void modular_namespace_read(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
42 void modular_namespace_doread(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
43 
44 void modular_namespace_write(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
45 void modular_namespace_dowrite(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
46 
47 extern "C" void JAMOMA_EXPORT_MAXOBJ setup_j0x2emodular(void)
48 {
49  ModularSpec *spec = new ModularSpec;
50  spec->_wrap = &WrapTTApplicationClass;
51  spec->_new = &WrappedApplicationClass_new;
52  spec->_any = NULL;
53  spec->_free = &WrappedApplicationClass_free;
54  spec->_notify = NULL;
55 
56  return (void)wrapTTModularClassAsPdClass(kTTSym_Application, "j.modular", NULL, spec);
57 }
58 
59 void WrapTTApplicationClass(WrappedClassPtr c)
60 {
61  eclass_addmethod(c->pdClass, (method)modular_assist, "assist", A_CANT, 0L);
62 
63  eclass_addmethod(c->pdClass, (method)modular_protocol_setup, "protocol/setup", A_GIMME, 0);
64 
65  eclass_addmethod(c->pdClass, (method)modular_protocol_scan, "protocol/scan", A_GIMME, 0);
66 
67  eclass_addmethod(c->pdClass, (method)modular_namespace_read, "namespace/read", A_GIMME, 0);
68 
69  eclass_addmethod(c->pdClass, (method)modular_namespace_write, "namespace/write", A_GIMME, 0);
70 }
71 
72 void WrappedApplicationClass_new(TTPtr self, long argc, t_atom *argv)
73 {
75  TTSymbol applicationName;
76  TTSymbol protocolName;
77  TTObject protocol, anXmlHandler;
78  TTValue v, args, out;
79  long attrstart = attr_args_offset(argc, argv); // support normal arguments
80 
81  // j.modular can handle the local application (1 argument to declare a protocol to use)
82  if (attrstart <= 1) {
83 
84  // our wrapped object is the local application
86  x->wrappedObject.get("name", applicationName);
87 
88  if (attrstart == 1)
89  protocolName = TTSymbol(atom_getsym(argv)->s_name);
90 
91  }
92  // or it can handle a distant application (2 arguments to declare the name of the distant application and the protocol to use)
93  else if (attrstart == 2) {
94 
95  // our wrapped object is a distant application
96  applicationName = TTSymbol(atom_getsym(argv)->s_name);
97  x->wrappedObject = accessApplication(applicationName);
98 
99  // if the application doesn't exists
100  if (!x->wrappedObject.valid()) {
101 
102  // create the application
103  TTModularApplicationManager->sendMessage("ApplicationInstantiateDistant", applicationName, out);
104  x->wrappedObject = out[0];
105  }
106 
107  protocolName = TTSymbol(atom_getsym(argv+1)->s_name);
108 
109  // set the type of the application depending on the plugin
110  if (protocolName == TTSymbol("Minuit"))
111  x->wrappedObject.set(kTTSym_type, TTSymbol("mirror"));
112  else
113  x->wrappedObject.set(kTTSym_type, TTSymbol("proxy"));
114  }
115 
116  // j.modular handle only one protocol per application
117  if (protocolName != kTTSymEmpty) {
118 
119  protocol = accessProtocol(protocolName);
120 
121  // check if the protocol has been loaded
122  if (!protocol.valid()) {
123  try {
124  TTModularApplicationManager->sendMessage("ProtocolInstantiate", protocolName, out);
125  } catch ( TTException & e )
126  {
127  pd_error((t_object*)x, "Can't instantiate protocole %s. Reason : %s", protocolName.c_str(),e.getReason());
128  return;
129  }
130 
131  protocol = out[0];
132  }
133 
134  // register the application to the protocol
135  protocol.send("ApplicationRegister", applicationName, out);
136 
137  // run this protocol
138  protocol.send("Run");
139  }
140 
141  // Prepare extra data
142  x->extra = (t_extra*)malloc(sizeof(t_extra));
143  EXTRA->protocolName = protocolName;
144 
145  // create internal TTXmlHandler
146  anXmlHandler = TTObject(kTTSym_XmlHandler);
147  x->internals->append(kTTSym_XmlHandler, anXmlHandler);
148  anXmlHandler.set(kTTSym_object, x->wrappedObject);
149 
150  if (attrstart && argv) attr_args_process(x, argc, argv);
151 }
152 
153 void WrappedApplicationClass_free(TTPtr self)
154 {
156  TTObject localApplication = accessApplicationLocal;
157  TTObject protocol;
158  TTSymbol applicationName;
159 
160  // get application name
161  x->wrappedObject.get(kTTSym_name, applicationName);
162 
163  // the xmlhandler have to forget the application object
164  TTValue o;
165  x->internals->lookup(kTTSym_XmlHandler, o);
166  TTObject empty, anXmlHandler = o[0];
167  anXmlHandler.set(kTTSym_object, empty);
168 
169  // unregister the application to the protocol
170  if (EXTRA->protocolName != kTTSymEmpty) {
171 
172  TTValue out;
173  protocol = accessProtocol(EXTRA->protocolName);
174  protocol.send("ApplicationUnregister", applicationName, out);
175  }
176 
177  // don't release the local application
178  if (!(x->wrappedObject == localApplication)) {
179 
180  TTValue out;
181  x->wrappedObject = TTObject();
182  TTModularApplicationManager->sendMessage("ApplicationRelease", applicationName, out);
183  }
184 
185  free(EXTRA);
186 }
187 
188 // Method for Assistance Messages
189 void modular_assist(TTPtr self, void *b, long msg, long arg, char *dst)
190 {
191  if (msg==1) // Inlet
192  strcpy(dst, "input");
193  else { // Outlets
194  switch(arg) {
195  case dump_out:
196  strcpy(dst, "dumpout");
197  break;
198  }
199  }
200 }
201 
202 void modular_protocol_setup(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
203 {
205  TTSymbol applicationName, parameterName;
206  TTObject aProtocol;
207  TTValue v, out, parameterValue;
208  long ac;
209  t_atom *av;
210 
211  // get the protocol object
212  aProtocol = accessProtocol(EXTRA->protocolName);
213  if (aProtocol.valid()) {
214 
215  if (x->wrappedObject.valid()) {
216 
217  if (argc && argv) {
218 
219  // stop protocol
220  aProtocol.send("Stop");
221 
222  // select this application
223  x->wrappedObject.get(kTTSym_name, applicationName);
224  if (aProtocol.send("ApplicationSelect", applicationName, out))
225  pd_error((t_object*)x, "%s is not registered to the %s protocol", applicationName.c_str(), EXTRA->protocolName.c_str());
226 
227  // set parameters
228  parameterName = TTSymbol(atom_getsym(argv)->s_name);
229  jamoma_ttvalue_from_Atom(parameterValue, _sym_nothing, argc-1, argv+1);
230  if (aProtocol.set(parameterName, parameterValue))
231  pd_error((t_object*)x, "%s is not a parameter of %s protocol", parameterName.c_str(), EXTRA->protocolName.c_str());
232 
233  // run protocol
234  aProtocol.send("Run");
235  }
236  // or if no arg : dumpout the current setup
237  else {
238 
239  // select this application
240  x->wrappedObject.get(kTTSym_name, applicationName);
241  if (aProtocol.send("ApplicationSelect", applicationName, out))
242  pd_error((t_object*)x, "%s is not registered to the %s protocol", applicationName.c_str(), EXTRA->protocolName.c_str());
243 
244  aProtocol.get("parameterNames", out);
245  for (TTElementIter it = out.begin() ; it != out.end() ; it++) {
246 
247  TTSymbol name = TTElement(*it);
248  aProtocol.get(parameterName, parameterValue);
249  parameterValue.prepend(name);
250  ac = 0;
251  av = NULL;
252  jamoma_ttvalue_to_Atom(parameterValue, &ac, &av);
253  outlet_anything(x->dumpOut, gensym("protocol/setup"), ac, av);
254  }
255  }
256  }
257  else
258  pd_error((t_object*)x, "doesn't handle any application");
259  }
260 }
261 
262 void modular_protocol_scan(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
263 {
265  TTObject aProtocol;
266  TTValue args, out;
267  long ac = 0;
268  t_atom *av = NULL;
269 
270  // get the protocol object
271  aProtocol = accessProtocol(EXTRA->protocolName);
272  if (aProtocol.valid()) {
273 
274  jamoma_ttvalue_from_Atom(args, _sym_nothing, argc, argv);
275 
276  aProtocol.send("Scan", args, out);
277 
278  // add "inputs" or "outputs" symbol before
279  out.prepend(args);
280 
281  jamoma_ttvalue_to_Atom(out, &ac, &av);
282  outlet_anything((t_outlet*)x->dumpOut, gensym("protocol/scan"), ac, av);
283  }
284 }
285 
286 void modular_namespace_read(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
287 {
288  modular_namespace_doread((t_object*)self, msg, argc, argv);
289 // defer(self, (method)modular_namespace_doread, msg, argc, argv);
290 }
291 
292 void modular_namespace_doread(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
293 {
295  TTValue o, v, none;
296  TTSymbol fullpath;
297  TTObject anXmlHandler;
298  TTErr tterr;
299 
300  if (x->wrappedObject.valid()) {
301 
302  fullpath = jamoma_file_read((t_object*)x, argc, argv, (t_fourcc)'TEXT');
303  v.append(fullpath);
304 
305  tterr = x->internals->lookup(kTTSym_XmlHandler, o);
306 
307  if (!tterr) {
308 
309  anXmlHandler = o[0];
310 
311 // critical_enter(0);
312  tterr = anXmlHandler.send(kTTSym_Read, v, none);
313 // critical_exit(0);
314 
315  if (!tterr)
316  outlet_anything(x->dumpOut, _sym_read, argc, argv);
317  else
318  outlet_anything(x->dumpOut, _sym_error, 0, NULL);
319  }
320  }
321 }
322 
323 void modular_namespace_write(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
324 {
325  modular_namespace_dowrite((t_object*)self, msg, argc, argv);
326 // defer(self, (method)modular_namespace_dowrite, msg, argc, argv);
327 }
328 
329 void modular_namespace_dowrite(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
330 {
332  char filename[MAX_FILENAME_CHARS];
333  TTSymbol fullpath;
334  TTValue o, v, none;
335  TTObject anXmlHandler;
336  TTErr tterr;
337 
338  if (x->wrappedObject.valid()) {
339 
340  // Default XML File Name
341  snprintf(filename, MAX_FILENAME_CHARS, "namespace.xml");
342  fullpath = jamoma_file_write((t_object*)x, argc, argv, filename);
343  v.append(fullpath);
344 
345  tterr = x->internals->lookup(kTTSym_XmlHandler, o);
346 
347  if (!tterr) {
348  anXmlHandler = o[0];
349 
350 // critical_enter(0);
351  tterr = anXmlHandler.send(kTTSym_Write, v, none);
352 // critical_exit(0);
353 
354  if (!tterr)
355  object_obex_dumpout(self, _sym_write, argc, argv);
356  else
357  object_obex_dumpout(self, _sym_error, 0, NULL);
358  }
359  }
360 }
TTErr sendMessage(const TTSymbol name)
TODO: Document this function.
TTErr send(const TTSymbol aName)
Send a message to this object with no arguments.
Definition: TTObject.cpp:135
TTErr lookup(const TTSymbol key, TTValue &value)
Find the value for the given key.
Definition: TTHash.cpp:76
Create and use Jamoma object instances.
Definition: TTObject.h:29
Data structure for storing extra data.
void * extra
used to keep very specific things
TTSymbol JAMOMA_EXPORT 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.
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.
TTMODULAR_EXPORT TTApplicationManagerPtr TTModularApplicationManager
Export a pointer to a TTApplicationManager instance.
Definition: TTModular.cpp:34
A TTBlue exception is thown with this object.
Definition: TTBase.h:368
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
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.
#define accessApplication(applicationName)
Access to an application by name.
TTErr append(const TTSymbol key, const TTValue &value)
Insert an item into the hash table.
Definition: TTHash.cpp:70
#define accessApplicationLocal
Access to local application.
TTObject wrappedObject
The instance of the Jamoma object we are wrapping.
Individual items found in a TTValue.
Definition: TTElement.h:89
const char * c_str() const
Return a pointer to the internal string as a C-string.
Definition: TTSymbol.h:77
void JAMOMA_EXPORT jamoma_ttvalue_from_Atom(TTValue &v, t_symbol *msg, long argc, const t_atom *argv)
Make a TTValue from Atom array.
Wraps Jamoma Core classes as objects for PureData.
Data Structure for this object.
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
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 accessProtocol(protocolName)
Access to a protocol by name.
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
TTErr wrapTTModularClassAsPdClass(TTSymbol &ttblueClassName, const char *pdClassName, WrappedClassPtr *c, ModularSpec *specificities)
Wrap a Jamoma class as a Pd class.