Jamoma API  0.6.0.a19
JamomaForPd.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationPdLibrary
4  *
5  * @brief Jamoma For Max Shared Library
6  *
7  * @details Functions and resources used by Max objects.
8  *
9  * @authors Tim Place, Théo de la Hogue, Trond Lossius, Antoine Villeret
10  *
11  * @copyright Copyright © 2013, Tim Place & 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 #include "JamomaForPd.h"
18 #if defined(TT_PLATFORM_WIN)
19  #include <shlobj.h>
20 #else
21  #include <dlfcn.h>
22 #endif
23 #include <map>
24 
25 // statics and globals
26 static long initialized = false; ///< Global variabel indicating whether Jamoma has been initiated or not.
27 static std::map<std::string,std::string> *map_modules = NULL; ///< A hashtab of all modules (j.hubs) currently instantiated
28 //t_object *obj_jamoma_clock = NULL; // there is only one master clock for the whole system
29 //t_object *obj_jamoma_scheduler = NULL; // a shared global instance of the scheduler class (there may be others too)
30 
31 TTSymbol kTTSym_Jamoma;
32 TTObject JamomaApplicationManager;
33 TTObject JamomaApplication;
34 
35 TTRegex* ttRegexForJmod = NULL;
36 TTRegex* ttRegexForJcom = NULL;
37 TTRegex* ttRegexForModel = NULL;
38 TTRegex* ttRegexForModule = NULL;
39 TTRegex* ttRegexForView = NULL;
40 TTRegex* ttRegexForPdpat = NULL;
41 TTRegex* ttRegexForPdhelp = NULL;
42 TTRegex* ttRegexForBracket = NULL;
43 
44 TTString* ModelPatcherFormat = NULL;
45 TTString* ModelPresetFormat = NULL;
46 TTString* ViewPresetFormat = NULL;
47 TTString* HelpPatcherFormat = NULL;
48 TTString* RefpageFormat = NULL;
49 TTString* DocumentationFormat = NULL;
50 
51 /************************************************************************************/
52 // Init the framework
53 
54 void jamoma_init(void)
55 {
56  short outvol = 0;
57  t_fourcc outtype, filetype = 'TEXT';
58  char name[MAX_PATH_CHARS];
59  //char fullpath[MAX_PATH_CHARS];
60 
61  if (!initialized) {
62 
63  t_object *pd_obj = (t_object *) SymbolGen("pd")->s_thing;
64  TTString JamomaConfigurationFilePath;
65  t_atom a[4];
66  TTValue v, out;
67  TTErr err;
68 
69  // Init the Modular library
70 
71  char mainBundleStr[4096];
72  mainBundleStr[0]='\0';
73 
74 #if defined(TT_PLATFORM_WIN)
75  TTString fullpath{};
76  char temppath[4096];
77  LONG lRes;
78 
79  LPCSTR moduleName = "JamomaFoundation.dll";
80  HMODULE hmodule = GetModuleHandle(moduleName);
81  // get the path
82  GetModuleFileName(hmodule, (LPSTR)temppath, 4096);
83 
84  if (!FAILED(hmodule) && temppath[0])
85  {
86  fullpath = temppath;
87 
88  // get support folder path
89  fullpath = fullpath.substr(0, fullpath.length() - (strlen(moduleName) + 1));
90  lRes = SHCreateDirectory(NULL, (LPCWSTR)fullpath.c_str());
91  }
92 
93  strncpy(mainBundleStr, fullpath.c_str(), 4095);
94 #else
95  Dl_info info;
96  // Use the path of JamomaFoundation
97  if (dladdr((const void*)jamoma_init, &info))
98  {
99  char *c = 0;
100 
101  strncpy(mainBundleStr, info.dli_fname, 4095);
102  c = strrchr(mainBundleStr, '/');
103  if (c)
104  *c = 0; // chop the filename off of the path
105  strcat(mainBundleStr,"/../support");
106  }
107 #endif
108  TTLogError("support folder : %s \n", mainBundleStr);
109  TTModularInit(mainBundleStr);
110 
111  // prepare a symbol for Jamoma
112  kTTSym_Jamoma = TTSymbol(JAMOMA);
113 
114  // Create an application manager
115  JamomaApplicationManager = TTObject("ApplicationManager");
116 
117  // Create a local application called "Jamoma" and get it back
118  err = JamomaApplicationManager.send("ApplicationInstantiateLocal", kTTSym_Jamoma, out);
119 
120  if (err) {
121  TTLogError("Error : can't create Jamoma application \n");
122  return;
123  }
124  else
125  JamomaApplication = out[0];
126 
127  // Edit the path to the JamomaConfiguration.xml file
128  long size = TTFoundationBinaryPath.size() - std::string("support").size();
129  size = size > 0 ? size : 0;
130  JamomaConfigurationFilePath = TTFoundationBinaryPath.substr(0,size);
131  JamomaConfigurationFilePath += "misc/JamomaConfiguration.xml";
132 
133  // check if the JamomaConfiguration.xml file exists
134  //if (locatefile_extended(name, &outvol, &outtype, &filetype, 1))
135  //return error("Jamoma not loaded : can't find %s", JamomaConfigurationFilePath.data());
136 
137  // JamomaApplication have to read JamomaConfiguration.xml
138  TTObject anXmlHandler(kTTSym_XmlHandler);
139  anXmlHandler.set(kTTSym_object, JamomaApplication);
140  err = anXmlHandler.send(kTTSym_Read, TTSymbol(JamomaConfigurationFilePath));
141  if ( err )
142  post("error %d : can't load configuration file \"%s\"", err, JamomaConfigurationFilePath.c_str() );
143 
144  // Initialize common symbols
145  common_symbols_init();
146  jamomaSymbolsInit();
147 
148  // Initialize common regex
149  ttRegexForJmod = new TTRegex("(jmod.)");
150  ttRegexForJcom = new TTRegex("(j\\.)");
151  ttRegexForModel = new TTRegex("(.model)");
152  ttRegexForModule = new TTRegex("(.module)");
153  ttRegexForView = new TTRegex("(.view)");
154  ttRegexForPdpat = new TTRegex("(.pd)");
155  ttRegexForPdhelp = new TTRegex("(-help.pd)");
156  ttRegexForBracket = new TTRegex("\\[(\\d|\\d\\d|\\d\\d\\d)\\]"); // parse until 999
157 
158  ModelPatcherFormat = new TTString("%s.model.pd");
159  ModelPresetFormat = new TTString("%s.model.presets.txt");
160  ViewPresetFormat = new TTString("%s.view.presets.txt");
161  HelpPatcherFormat = new TTString("%s.model");
162  RefpageFormat = new TTString("%s.model");
163  DocumentationFormat = new TTString("%s.model.html");
164 
166 
167  post("Jamoma for Pd version %s - %s | jamoma.org",JAMOMA_PD_VERSION, JAMOMA_PD_REV);
168 
169  initialized = true;
170  }
171 }
172 
173 #pragma mark -
174 #pragma mark Utilities
175 
176 // Copying all of the elements should be faster than branching and copying one element
177 // (that's the theory anyway...)
178 void jamoma_atom_copy(t_atom *dst, t_atom *src)
179 {
180  // memcpy(dst, src, sizeof(t_atom));
181  memcpy(src, dst, sizeof(t_atom));
182 }
183 
184 bool jamoma_atom_compare(t_symbol *type, t_atom *a1, t_atom *a2)
185 {
186  if (!a1 || !a2)
187  return 0;
188 
189  if (type == jps_decimal) { // float is first so that it gets process the most quickly
190  if (atom_getfloat(a1) == atom_getfloat(a2))
191  return 1;
192  }
193  else if ((type == jps_integer) || (type == jps_boolean)) {
194  if (atom_getint(a1) == atom_getint(a2))
195  return 1;
196  }
197  else if (type == jps_string) {
198  if (atom_getsymbol(a1) == atom_getsymbol(a2))
199  return 1;
200  }
201  // type array should be checked here as well. If type == array and this function is called
202  // it means we are dealing with a list of length 1, so we only need to compare one atom anyway.
203  else if ((type == jps_decimalArray) || (type == jps_array)) {
204  if (a1->a_w.w_float == a2->a_w.w_float)
205  return 1;
206  }
207  /*
208  else if (type == jps_integerArray) {
209  if (a1->a_w.w_long == a2->a_w.w_long)
210  return 1;
211  }
212  */
213  else if (type == jps_generic){
214  // note that if the two are of different types, then they are obviously not the same
215  /*
216  if ((a1->a_type == A_LONG) && (a2->a_type == A_LONG)) {
217  if (a1->a_w.w_long == a2->a_w.w_long)
218  return 1;
219  }
220  else */ if ((a1->a_type == A_FLOAT) && (a2->a_type == A_FLOAT)) {
221  if (a1->a_w.w_float == a2->a_w.w_float)
222  return 1;
223  }
224  else if ((a1->a_type == A_SYMBOL) && (a2->a_type == A_SYMBOL)) {
225  if (a1->a_w.w_symbol == a2->a_w.w_symbol)
226  return 1;
227  }
228  }
229  else
230  error("atom_compare: cannot do comparison on this data type");
231  return 0;
232 }
233 
234 // Compare Strings: Is s2 after s1 in alphabetical order?
235 bool jamoma_string_compare(char *s1, char *s2)
236 {
237  short i;
238  short len1 = strlen(s1);
239  short len2 = strlen(s2);
240  bool result = false;
241  bool keepgoing = true;
242 
243  if (len2 < len1)
244  len1 = len2; // only compare the characters of the short string
245 
246  for (i =0 ; i < len1 && keepgoing; i++) {
247  if (s1[i] < s2[i]) {
248  result = true;
249  keepgoing = false;
250  }
251  else if (s1[i] > s2[i])
252  keepgoing = false;
253  }
254  return result;
255 }
256 
257 // Load an external for internal use
258 // returns true if successful
259 /*
260 bool jamoma_loadextern(t_symbol *objectname, long argc, t_atom *argv, t_object **object)
261 {
262  t_class *c = NULL;
263  t_object *p = NULL;
264 
265  c = class_findbyname(jps_box, objectname);
266  if (!c) {
267  p = (t_object *)newinstance(objectname, 0, NULL);
268  if (p) {
269  c = class_findbyname(jps_box, objectname);
270  freeobject(p);
271  p = NULL;
272  }
273  else {
274  error("jamoma: could not load extern (%s) within the core", objectname->s_name);
275  return false;
276  }
277  }
278 
279  if (*object != NULL) { // if there was an object set previously, free it first...
280  object_free(*object);
281  *object = NULL;
282  }
283 
284  *object = (t_object *)object_new_typed(CLASS_BOX, objectname, argc, argv);
285  return true;
286 }
287 */
288 
289 t_symbol *object_attr_getsym(void *x, t_symbol *s){
290  int argc=0;
291  t_atom *argv=NULL;
292  t_symbol*retsym = _sym_nothing;
293  eclass_attr_getter((t_object *) x, s, &argc, &argv);
294  if ( argv && argv[0].a_type == A_SYMBOL){
295  retsym = argv[0].a_w.w_symbol;
296  free(argv);
297  }
298  return retsym;
299 }
300 
301 void* object_attr_getobj(void *x, t_symbol *attrname){
302 
303  if ( attrname == _sym_parentpatcher ){
304  return ((t_canvas*)x)->gl_owner;
305  }
306  else if ( attrname == _sym_firstobject )
307  {
308  return ((t_canvas*)x)->gl_list;
309  }
310 
311  return NULL;
312 }
313 
314 /*
315 void attr_args_process(void *x, short ac, t_atom *av)
316 {
317  long index = atoms_get_attributes_offset(ac,av);
318  if (index == ac) return; // no argument
319  long next = atoms_get_attributes_offset(ac-index,av+index);
320 
321  object_attr_setvalueof((t_object*)x,atom_getsym(av+index),next-index,av+index+1);
322 
323  //loop to process other arguments
324  attr_args_process(x,ac-next,av+next);
325 
326 }
327 */
328 
329 method object_getmethod(void* x, t_symbol* s)
330 {
331  return (method)zgetfn((t_pd *)x, s);
332 }
333 
334 void* object_method_typed(void* x, t_symbol* method, t_symbol* s, long argc, t_atom* argv)
335 {
336  t_ret_method nrmethod = (t_ret_method)zgetfn((t_pd *)x, method);
337  return nrmethod(x, s, argc, argv);
338 }
339 
340 void* object_method(void *x, t_symbol *s)
341 {
342  t_ret_method nrmethod = (t_ret_method)zgetfn((t_pd *)x, s);
343  return nrmethod(x);
344 }
345 
346 short locatefile_extended(char *name, short *outvol, t_fourcc *outtype, const t_fourcc *filetypelist, short numtypes)
347 {
348  int fd = -1;
349  int bin;
350  char realname[MAXPDSTRING], dirbuf[MAXPDSTRING], *basename;
351  fd = open_via_path("", name, "", dirbuf, &basename, MAXPDSTRING, 0);
352  return fd < 0;
353 }
354 
355 short path_topathname(const short path, const char *file, char *name)
356 {
357  int fd = -1;
358  int bin;
359  char realname[MAXPDSTRING], dirbuf[MAXPDSTRING], *basename;
360  fd = open_via_path(NULL, file, "", name, &basename, MAXPDSTRING, 0);
361  strcat(name,basename);
362  return fd < 0;
363 }
JAMOMA_EXPORT t_symbol * jps_generic
Pointer to the symbol "generic", one of the parameter and message data types.
JAMOMA_EXPORT t_symbol * jps_decimal
Pointer to the symbol "decimal", one of the parameter and message data types.
TTRegex * ttRegexForView
A global regex to parse .view.
Definition: JamomaForPd.cpp:39
TTErr send(const TTSymbol aName)
Send a message to this object with no arguments.
Definition: TTObject.cpp:135
TTRegex * ttRegexForJcom
A global regex to parse j.
Definition: JamomaForPd.cpp:36
const char * c_str() const
Return a pointer to the internal C-string.
Definition: TTString.h:83
Create and use Jamoma object instances.
Definition: TTObject.h:29
Various utilities for interfacing with Pd that are not specific to JamomaModular as such...
void jamoma_object_initclass(void)
Set up the class.
bool jamoma_string_compare(char *s1, char *s2)
Compare two strings.
void jamoma_atom_copy(t_atom *dst, t_atom *src)
Utility function to perform an atom copy.
JAMOMA_EXPORT t_symbol * jps_string
Pointer to the symbol "string", one of the parameter and message data types.
JAMOMA_EXPORT t_symbol * jps_integer
Pointer to the symbol "integer", one of the parameter and message data types.
TTRegex * ttRegexForModel
A global regex to parse .model.
Definition: JamomaForPd.cpp:37
TTRegex * ttRegexForJmod
A global regex to parse jmod. (usefull to detect a 0.5 module)
Definition: JamomaForPd.cpp:35
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
void TTFOUNDATION_EXPORT TTLogError(TTImmutableCString message,...)
Platform and host independent method for posting errors.
Definition: TTBase.cpp:572
JAMOMA_EXPORT t_symbol * jps_boolean
Pointer to the symbol "boolean", one of the parameter and message data types.
bool jamoma_atom_compare(t_symbol *type, t_atom *a1, t_atom *a2)
Utility function to compare two t_atoms.
TTString substr(size_t pos=0, size_t n=1) const
Returns a string object with its contents initialized to a substring of the current object...
Definition: TTString.h:342
TTRegex * ttRegexForPdpat
A global regex to parse .maxpat.
Definition: JamomaForPd.cpp:40
TTRegex * ttRegexForModule
A global regex to parse .module.
Definition: JamomaForPd.cpp:38
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
size_t size() const
Find out the length of a string.
Definition: TTString.h:144
void TTMODULAR_EXPORT TTModularInit(const char *binaries=nullptr, bool loadFromBuiltinPaths=false)
Initialize the Modular library and intanciate the TTModular object.
Definition: TTModular.cpp:45
The TTString class is used to represent a string.
Definition: TTString.h:34
JAMOMA_EXPORT t_symbol * jps_array
This is deprecated, please use #jps_list, jps_decimalArray or jps_integerArray instead.
TTRegex * ttRegexForBracket
A global regex to parse [ and ].
Definition: JamomaForPd.cpp:42
TTRegex * ttRegexForPdhelp
A global regex to parse .maxhelp.
Definition: JamomaForPd.cpp:41
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
JAMOMA_EXPORT t_symbol * jps_decimalArray
Pointer to the symbol "decimalArray", one of the parameter and message data types. Used for arrays of decimal values.