Jamoma API  0.6.0.a19
JamomaForMax.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationMaxLibrary
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
10  *
11  * @copyright Copyright © 2013, Tim Place & 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 #include "JamomaForMax.h"
17 
18 // statics and globals
19 static long initialized = false; ///< Global variabel indicating whether Jamoma has been initiated or not.
20 static t_hashtab *hash_modules = NULL; ///< A hashtab of all modules (j.hubs) currently instantiated
21 //t_object *obj_jamoma_clock = NULL; // there is only one master clock for the whole system
22 //t_object *obj_jamoma_scheduler = NULL; // a shared global instance of the scheduler class (there may be others too)
23 bool max5 = false; ///< Is Jamoma currently running in Max 5 or newer?
24 bool max6 = false; ///< Is Jamoma currently running in Max 6 or newer?
25 
26 TTSymbol kTTSym_Jamoma;
27 TTObject JamomaApplicationManager;
28 TTObject JamomaApplication;
29 
30 TTRegex* ttRegexForJmod = NULL;
31 TTRegex* ttRegexForJcom = NULL;
32 TTRegex* ttRegexForModel = NULL;
33 TTRegex* ttRegexForModule = NULL;
34 TTRegex* ttRegexForView = NULL;
35 TTRegex* ttRegexForMaxpat = NULL;
36 TTRegex* ttRegexForMaxhelp = NULL;
37 TTRegex* ttRegexForBracket = NULL;
38 
39 TTString* ModelPatcherFormat = NULL;
40 TTString* ModelPresetFormat = NULL;
41 TTString* ViewPresetFormat = NULL;
42 TTString* HelpPatcherFormat = NULL;
43 TTString* RefpageFormat = NULL;
44 TTString* DocumentationFormat = NULL;
45 
46 /************************************************************************************/
47 // Init the framework
48 
49 void jamoma_init(void)
50 {
51  short outvol = 0;
52  t_fourcc outtype, filetype = 'TEXT';
53  char name[MAX_PATH_CHARS];
54  //char fullpath[MAX_PATH_CHARS];
55 
56  if (!initialized) {
57 
58  t_object *max = SymbolGen("max")->s_thing;
59  TTString JamomaConfigurationFilePath;
60  t_atom a[4];
61  TTValue v, out;
62  TTErr err;
63 
64  if (maxversion() >= 0x0519)
65  max5 = true;
66 
67  if (maxversion() >= 0x0600)
68  max6 = true;
69 
70  // Initialize the Modular library
71  TTModularInit();
72 
73 #ifdef TTSCORE_IMPORT
74  // Initialize the Score framework
75  TTScoreInit();
76 #endif
77 
78  // prepare a symbol for Jamoma
79  kTTSym_Jamoma = TTSymbol(JAMOMA);
80 
81  // Create an application manager
82  JamomaApplicationManager = TTObject("ApplicationManager");
83 
84  // Create a local application called "Jamoma" and get it back
85  err = JamomaApplicationManager.send("ApplicationInstantiateLocal", kTTSym_Jamoma, out);
86 
87  if (err) {
88  TTLogError("Error : can't create Jamoma application \n");
89  return;
90  }
91  else
92  JamomaApplication = out[0];
93 
94  // Edit the path to the JamomaConfiguration.xml file
95  strncpy_zero(name, TTFoundationBinaryPath.data(), TTFoundationBinaryPath.size()-6);
96  JamomaConfigurationFilePath = name;
97  JamomaConfigurationFilePath += "misc/JamomaConfiguration.xml";
98 
99  // check if the JamomaConfiguration.xml file exists
100  strncpy_zero(name, JamomaConfigurationFilePath.data(), MAX_PATH_CHARS);
101  if (locatefile_extended(name, &outvol, &outtype, &filetype, 1))
102  return error("Jamoma not loaded : can't find %s", JamomaConfigurationFilePath.data());
103 
104  // JamomaApplication have to read JamomaConfiguration.xml
105  TTObject anXmlHandler(kTTSym_XmlHandler);
106  anXmlHandler.set(kTTSym_object, JamomaApplication);
107  v = TTSymbol(JamomaConfigurationFilePath);
108  anXmlHandler.send(kTTSym_Read, v, out);
109 
110  // Initialize common symbols
111  common_symbols_init();
112  jamomaSymbolsInit();
113 
114  // Initialize common regex
115  ttRegexForJmod = new TTRegex("(jmod.)");
116  ttRegexForJcom = new TTRegex("(j\\.)");
117  ttRegexForModel = new TTRegex("(.model)");
118  ttRegexForModule = new TTRegex("(.module)");
119  ttRegexForView = new TTRegex("(.view)");
120  ttRegexForMaxpat = new TTRegex("(.maxpat)");
121  ttRegexForMaxhelp = new TTRegex("(.maxhelp)");
122  ttRegexForBracket = new TTRegex("\\[(\\d|\\d\\d|\\d\\d\\d)\\]"); // parse until 999
123 
124  ModelPatcherFormat = new TTString("%s.model.maxpat");
125  ModelPresetFormat = new TTString("%s.model.presets.txt");
126  ViewPresetFormat = new TTString("%s.view.presets.txt");
127  HelpPatcherFormat = new TTString("%s.model");
128  RefpageFormat = new TTString("%s.model");
129  DocumentationFormat = new TTString("%s.model.html");
130 
131  // Create Required Global Instances
132  hash_modules = (t_hashtab*)hashtab_new(0);
133  // TODO: Use quittask_install() to set up a destructor for this to free it before Max exits
134 
135  // Add Jamoma Key Commands
136 
137  // J -- Jamoma: a new object box with "j." in it
138  atom_setsym(a+0, SymbolGen("k"));
139  atom_setsym(a+1, SymbolGen("patcher"));
140  atom_setsym(a+2, SymbolGen("inserttextobj"));
141  atom_setsym(a+3, SymbolGen("j."));
142  object_method_typed(max, SymbolGen("definecommand"), 4, a, NULL);
143 
144 // // M -- Module: a new object box with ".model" in it
145 // atom_setsym(a+0, SymbolGen("M"));
146 // atom_setsym(a+1, SymbolGen("patcher"));
147 // atom_setsym(a+2, SymbolGen("inserttextobj"));
148 // atom_setsym(a+3, SymbolGen(".model"));
149 // object_method_typed(max, SymbolGen("definecommand"), 4, a, NULL);
150 //
151 
152 // // B -- BPatcher: a new module in a bpatcher
153 // object_method_parse(max, SymbolGen("definecommand"), (char*)"B patcher inserttextobj \"bpatcher @name .module @args myModule\"", NULL);
154 
155 // // D -- Demo: a new module in a bpatcher, but with the args reverse which is handy for super-fast demos when you don't care about the OSC name
156 // object_method_parse(max, SymbolGen("definecommand"), (char*)"D patcher inserttextobj \"bpatcher @name .module\"", NULL);
157 
158 // // X -- Continuous Mapper module
159 // object_method_parse(max, SymbolGen("definecommand"), (char*)"X patcher insertobj bpatcher @name mapper.module.maxpat @args mapper", NULL);
160 
161  // now the jamoma object
162  {
163  t_symbol *jamomaSymbol = SymbolGen("jamoma");
164 
166  jamomaSymbol->s_thing = jamoma_object_new();
167  }
168 
169  post("Jamoma (build %s) Version %s | jamoma.org", JAMOMA_MAX_REV, JAMOMA_MAX_VERSION);
170 
171  initialized = true;
172  }
173 }
174 
175 #pragma mark -
176 #pragma mark Utilities
177 
178 // Copying all of the elements should be faster than branching and copying one element
179 // (that's the theory anyway...)
180 void jamoma_atom_copy(t_atom *dst, t_atom *src)
181 {
182  // memcpy(dst, src, sizeof(t_atom));
183  sysmem_copyptr(src, dst, sizeof(t_atom));
184 }
185 
186 bool jamoma_atom_compare(t_symbol *type, t_atom *a1, t_atom *a2)
187 {
188  if (!a1 || !a2)
189  return 0;
190 
191  if (type == jps_decimal) { // float is first so that it gets process the most quickly
192  if (atom_getfloat(a1) == atom_getfloat(a2))
193  return 1;
194  }
195  else if ((type == jps_integer) || (type == jps_boolean)) {
196  if (atom_getlong(a1) == atom_getlong(a2))
197  return 1;
198  }
199  else if (type == jps_string) {
200  if (atom_getsym(a1) == atom_getsym(a2))
201  return 1;
202  }
203  // type array should be checked here as well. If type == array and this function is called
204  // it means we are dealing with a list of length 1, so we only need to compare one atom anyway.
205  else if ((type == jps_decimalArray) || (type == jps_array)) {
206  if (a1->a_w.w_float == a2->a_w.w_float)
207  return 1;
208  }
209  else if (type == jps_integerArray) {
210  if (a1->a_w.w_long == a2->a_w.w_long)
211  return 1;
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  if ((a1->a_type == A_LONG) && (a2->a_type == A_LONG)) {
216  if (a1->a_w.w_long == a2->a_w.w_long)
217  return 1;
218  }
219  else if ((a1->a_type == A_FLOAT) && (a2->a_type == A_FLOAT)) {
220  if (a1->a_w.w_float == a2->a_w.w_float)
221  return 1;
222  }
223  else if ((a1->a_type == A_SYM) && (a2->a_type == A_SYM)) {
224  if (a1->a_w.w_sym == a2->a_w.w_sym)
225  return 1;
226  }
227  }
228  else
229  error("atom_compare: cannot do comparison on this data type");
230  return 0;
231 }
232 
233 // Compare Strings: Is s2 after s1 in alphabetical order?
234 bool jamoma_string_compare(char *s1, char *s2)
235 {
236  short i;
237  short len1 = strlen(s1);
238  short len2 = strlen(s2);
239  bool result = false;
240  bool keepgoing = true;
241 
242  if (len2 < len1)
243  len1 = len2; // only compare the characters of the short string
244 
245  for (i =0 ; i < len1 && keepgoing; i++) {
246  if (s1[i] < s2[i]) {
247  result = true;
248  keepgoing = false;
249  }
250  else if (s1[i] > s2[i])
251  keepgoing = false;
252  }
253  return result;
254 }
255 
256 // Load an external for internal use
257 // returns true if successful
258 bool jamoma_loadextern(t_symbol *objectname, long argc, t_atom *argv, t_object **object)
259 {
260  t_class *c = NULL;
261  t_object *p = NULL;
262 
263  c = class_findbyname(jps_box, objectname);
264  if (!c) {
265  p = (t_object *)newinstance(objectname, 0, NULL);
266  if (p) {
267  c = class_findbyname(jps_box, objectname);
268  freeobject(p);
269  p = NULL;
270  }
271  else {
272  error("jamoma: could not load extern (%s) within the core", objectname->s_name);
273  return false;
274  }
275  }
276 
277  if (*object != NULL) { // if there was an object set previously, free it first...
278  object_free(*object);
279  *object = NULL;
280  }
281 
282  *object = (t_object *)object_new_typed(CLASS_BOX, objectname, argc, argv);
283  return true;
284 }
285 
286 
bool jamoma_string_compare(char *s1, char *s2)
Compare two strings.
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.
TTErr send(const TTSymbol aName)
Send a message to this object with no arguments.
Definition: TTObject.cpp:135
bool max5
Is Jamoma currently running in Max 5 or newer?
void jamoma_atom_copy(t_atom *dst, t_atom *src)
Utility function to perform an atom copy.
TTRegex * ttRegexForView
A global regex to parse .view.
Create and use Jamoma object instances.
Definition: TTObject.h:29
TTRegex * ttRegexForJmod
A global regex to parse jmod. (usefull to detect a 0.5 module)
bool jamoma_loadextern(t_symbol *objectname, long argc, t_atom *argv, t_object **object)
Load obex externals for use within other externals.
void jamoma_object_initclass(void)
Set up the class.
JAMOMA_EXPORT t_symbol * jps_string
Pointer to the symbol "string", one of the parameter and message data types.
TTRegex * ttRegexForJcom
A global regex to parse j.
JAMOMA_EXPORT t_symbol * jps_integer
Pointer to the symbol "integer", one of the parameter and message data types.
TTRegex * ttRegexForModule
A global regex to parse .module.
JAMOMA_EXPORT t_symbol * jps_integerArray
Pointer to the symbol "integerArray", one of the parameter and message data types. Used for arrays of decimal values.
t_object * jamoma_object_new()
Object instantiation.
TTRegex * ttRegexForModel
A global regex to parse .model.
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.
Various utilities for interfacing with Max that are not specific to JamomaModular as such...
TTRegex * ttRegexForMaxhelp
A global regex to parse .maxhelp.
TTRegex * ttRegexForBracket
A global regex to parse [ and ].
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
bool max6
Is Jamoma currently running in Max 6 or newer?
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
TTRegex * ttRegexForMaxpat
A global regex to parse .maxpat.
JAMOMA_EXPORT t_symbol * jps_array
This is deprecated, please use #jps_list, jps_decimalArray or jps_integerArray instead.
[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.
bool jamoma_atom_compare(t_symbol *type, t_atom *a1, t_atom *a2)
Utility function to compare two t_atoms.