Jamoma API  0.6.0.a19
PureData/source/j.ui/j.ui.internals.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationPdExternals
4  *
5  * @brief j.ui : Handling internal objects embedded in j.ui
6  *
7  * @details
8  *
9  * @authors Tim Place, Trond Lossius, Antoine Villeret
10  *
11  * @copyright © 2007 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 "j.ui.h"
19 
20 void ui_register_info(t_ui* obj)
21 {
22  TTObject anObject;
23  TTAddress returnedAddress;
24  TTNodePtr returnedNode = NULL;
25  TTNodePtr returnedContextNode = NULL;
26  TTValue v, args;
27 
28  // create a ui info object
29  obj->uiInfo = TTObject("UiInfo", (TTPtr)obj);
30 
31  // create a ui node with our patcher as context
32  if (!jamoma_subscriber_create((t_object*)obj, obj->uiInfo, TTAddress("ui"), obj->uiSubscriber, returnedAddress, &returnedNode, &returnedContextNode)) {
33 
34  // get info relative to our patcher
35  jamoma_patcher_get_info((t_object*)obj, &obj->patcherPtr, obj->patcherContext, obj->patcherClass, obj->patcherName);
36 
37  // get the view address from the ui address
38  obj->uiSubscriber.get("contextAddress", v);
39  obj->viewAddress = v[0];
40 
41  // make a receiver on contextAddress/model:address attribute
42  ui_receiver_create(obj, anObject, gensym("return_model_address"), TTSymbol("model:address"), obj->viewAddress, YES); // YES : we want to deferlow this method
43  }
44 }
45 
46 void ui_unregister_info(t_ui *obj)
47 {
48  // unregister the ui info object
49  if (obj->uiSubscriber.valid())
50  obj->uiSubscriber = TTObject();
51 
52  // delete the ui info object
53  if (obj->uiInfo.valid())
54  obj->uiInfo = TTObject();
55 }
56 
57 void ui_data_interface(t_ui *x, TTSymbol name)
58 {
59  char filename[MAX_FILENAME_CHARS];
60  short path;
61  t_fourcc type, filetype = 'JSON';
62  t_dictionary* d;
63  t_object* p;
64  TTAddress address;
65  t_atom a;
66 
67  strncpy_zero(filename, "j.reference_interface.maxpat", MAX_FILENAME_CHARS);
68  locatefile_extended(filename, &path, &type, &filetype, 1);
69  dictionary_read(filename, path, &d);
70 
71  atom_setobj(&a, d);
72  p = (t_object*)object_new_typed(_sym_nobox, _sym_jpatcher, 1, &a);
73  object_attr_setlong(p, _sym_locked, 1); // start out locked
74  object_attr_setchar(p, _sym_enablehscroll, 0); // turn off scroll bars
75  object_attr_setchar(p, _sym_enablevscroll, 0);
76  object_attr_setchar(p, _sym_openinpresentation, 1);
77  object_attr_setchar(p, _sym_toolbarvisible, 0);
78  object_attr_setsym(p, _sym_title, gensym("reference_interface"));
79  object_method_parse(p, _sym_window, "constrain 5 320 200 500", NULL);
80  object_attach_byptr_register(x, p, _sym_nobox);
81 
82  object_method(p, _sym_vis); // "vis" happens immediately, "front" is defer_lowed
83  object_attr_setobj(jpatcher_get_firstview(p), _sym_owner, (t_object*)x); // become the owner
84 
85  address = x->modelAddress.appendAddress(TTAddress(name.c_str()));
86 
87  OBJ_ATTR_SYM(p, "arguments", 0, gensym((char*)address.c_str())); // the patch needs a [j.interfaceArguments.js]
88 
89  object_method(p, _sym_loadbang);
90 }
91 
92 void ui_receiver_create(t_ui *obj, TTObject& returnedReceiver, t_symbol *aCallbackMethod, TTSymbol name, TTAddress address, TTBoolean deferlow, TTBoolean appendNameAsAttribute)
93 {
94  TTValue baton, args;
95  TTObject returnValueCallback, empty;
96  TTAddress adrs;
97 
98  // prepare arguments
99  args.append(empty);
100 
101  returnValueCallback = TTObject("callback");
102 
103  baton = TTValue(TTPtr(obj), TTPtr(aCallbackMethod), deferlow);
104  returnValueCallback.set(kTTSym_baton, baton);
105  returnValueCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value));
106  args.append(returnValueCallback);
107 
108  returnedReceiver = TTObject(kTTSym_Receiver, args);
109 
110  // edit address
111  if (appendNameAsAttribute)
112  adrs = address.appendAttribute(name);
113  else
114  adrs = address.appendAddress(TTAddress(name.c_str()));
115 
116  // store receiver
117  obj->hash_receivers->append(name, returnedReceiver);
118 
119  // set address attribute (after storing the receiver as the value can be updated in the same time)
120  returnedReceiver.set(kTTSym_address, adrs);
121 }
122 
123 void ui_receiver_destroy_all(t_ui *obj)
124 {
125  TTValue hk, v, none;
126  TTSymbol key, receiverAddress;
127  TTUInt8 i;
128 
129  // delete all receivers
130  if (obj->hash_receivers) {
131 
132  if (!obj->hash_receivers->isEmpty()) {
133 
134  obj->hash_receivers->getKeys(hk);
135 
136  for (i=0; i<obj->hash_receivers->getSize(); i++) {
137 
138  key = hk[i];
139  if (!obj->hash_receivers->lookup(key, v)) {
140 
141  TTObject receiver = v[0];
142  receiver.set(kTTSym_address, kTTAdrsEmpty);
143  }
144  }
145  }
146  obj->hash_receivers->clear();
147  }
148 }
149 
150 void ui_viewer_create(t_ui *obj, TTObject& returnedViewer, t_symbol *aCallbackMethod, TTSymbol name, TTAddress address, TTBoolean subscribe, TTBoolean deferlow)
151 {
152  TTValue v, baton, args, none;
153  TTAddress viewAddress, viewerAddress, adrs;
154 
155  returnedViewer = TTObject(kTTSym_Viewer);
156 
157  baton = TTValue(TTPtr(obj), TTPtr(aCallbackMethod), deferlow);
158  returnedViewer.set(kTTSym_baton, baton);
159  returnedViewer.set(kTTSym_function, TTPtr(&jamoma_callback_return_value));
160 
161  if (subscribe) {
162  // Register viewer
163  obj->uiSubscriber.get("contextAddress", v);
164  viewAddress = v[0];
165 
166  viewerAddress = viewAddress.appendAddress(TTAddress(name.c_str()));
167  args = TTValue(viewerAddress, returnedViewer, (TTPtr)obj->patcherPtr);
168  JamomaApplication.send("ObjectRegister", args, none);
169  }
170  else
171  viewerAddress = kTTAdrsEmpty;
172 
173  // edit address to bind
174  adrs = address.appendAddress(TTAddress(name.c_str()));
175 
176  // store viewer
177  args = TTValue(returnedViewer);
178  args.append(viewerAddress);
179  obj->hash_viewers->append(name, args);
180 
181  // set address attribute (after storing the receiver as the value can be updated in the same time)
182  returnedViewer.set(kTTSym_address, adrs);
183 }
184 
185 void ui_viewer_destroy(t_ui *obj, TTSymbol name)
186 {
187  TTValue v, none;
188  TTAddress viewerAddress;
189 
190  if (obj->hash_viewers)
191  if (!obj->hash_viewers->lookup(name, v)) {
192 
193  TTObject viewer = v[0];
194  viewer.set(kTTSym_address, kTTAdrsEmpty);
195 
196  // Unregister viewer
197  viewerAddress = v[1];
198  JamomaApplication.send("ObjectUnregister", viewerAddress, none);
199  obj->hash_viewers->remove(name);
200  }
201 }
202 
203 void ui_viewer_destroy_all(t_ui *obj)
204 {
205  TTValue hk, v, none;
206  TTSymbol key, viewerAddress;
207  TTUInt8 i;
208 
209  // delete all viewers
210  if (obj->hash_viewers) {
211 
212  if (!obj->hash_viewers->isEmpty()) {
213 
214  obj->hash_viewers->getKeys(hk);
215 
216  for (i=0; i<obj->hash_viewers->getSize(); i++) {
217 
218  key = hk[i];
219  if (!obj->hash_viewers->lookup(key, v)) {
220 
221  TTObject viewer = v[0];
222  viewer.set(kTTSym_address, kTTAdrsEmpty);
223 
224  // Unregister viewer
225  viewerAddress = v[1];
226  JamomaApplication.send("ObjectUnregister", viewerAddress, none);
227  }
228  }
229  }
230  delete obj->hash_viewers;
231  obj->hash_viewers = NULL;
232  }
233 }
234 
235 void ui_viewer_send(t_ui *obj, TTSymbol name, TTValue v)
236 {
237  TTValue storedObject, none;
238  TTObject anObject;
239  TTErr err;
240 
241  if (obj->hash_viewers) {
242  err = obj->hash_viewers->lookup(name, storedObject);
243 
244  if (!err) {
245  anObject = storedObject[0];
246  if (anObject.valid())
247  anObject.send(kTTSym_Send, v, none);
248  }
249  }
250 }
251 
252 void ui_viewer_highlight(t_ui *obj, TTSymbol name, TTBoolean s)
253 {
254  TTValue storedObject;
255  TTObject anObject;
256  TTErr err;
257 
258  if (obj->hash_viewers) {
259  err = obj->hash_viewers->lookup(name, storedObject);
260 
261  if (!err) {
262  anObject = storedObject[0];
263  if (anObject.valid())
264  anObject.set(kTTSym_highlight, s);
265  }
266  }
267 }
268 
269 void ui_viewer_freeze(t_ui *obj, TTSymbol name, TTBoolean f)
270 {
271  TTValue storedObject;
272  TTObject anObject;
273  TTErr err;
274 
275  if (obj->hash_viewers) {
276  err = obj->hash_viewers->lookup(name, storedObject);
277 
278  if (!err) {
279  anObject = storedObject[0];
280  if (anObject.valid())
281  anObject.set(kTTSym_freeze, f);
282  }
283  }
284 }
285 
286 #if 0
287 #pragma mark -
288 #pragma mark message handlers
289 #endif
290 
291 void ui_explorer_create(t_object *x, TTObject& returnedExplorer, t_symbol *method)
292 {
293  TTValue args, baton, none;
294  TTObject returnValueCallback;
295 
296  // prepare arguments
297  returnValueCallback = TTObject("callback");
298  baton = TTValue(TTPtr(x), TTPtr(method));
299  returnValueCallback.set(kTTSym_baton, baton);
300  returnValueCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value));
301  args.append(returnValueCallback);
302 
304 
305  returnedExplorer = TTObject(kTTSym_Explorer, args);
306 }
307 
308 void ui_modelParamExplorer_callback(TTPtr self, t_symbol *msg, long argc, t_atom* argv)
309 {
310  t_ui* obj = (t_ui*)self;
311  t_symobject *item = NULL;
312 
313  // model's message namespace observation
314  if (obj->modelAddress != kTTAdrsEmpty) {
315 
316  // fill item list
317  for (long i=0; i<argc; i++) {
318  item = (t_symobject *)symobject_new(atom_getsym(argv+i));
319  linklist_append(obj->refmenu_items, item);
320  }
321  }
322 }
323 
324 void ui_modelMessExplorer_callback(TTPtr self, t_symbol *msg, long argc, t_atom* argv)
325 {
326  t_ui* obj = (t_ui*)self;
327  t_symobject *item = NULL;
328 
329  // model's message namespace observation
330  if (obj->modelAddress != kTTAdrsEmpty) {
331 
332  // fill item list
333  for (long i=0; i<argc; i++) {
334  item = (t_symobject *)symobject_new(atom_getsym(argv+i));
335  linklist_append(obj->refmenu_items, item);
336  }
337  }
338 }
339 
340 void ui_modelRetExplorer_callback(TTPtr self, t_symbol *msg, long argc, t_atom* argv)
341 {
342  t_ui* obj = (t_ui*)self;
343  t_symobject *item = NULL;
344 
345  // model's message namespace observation
346  if (obj->modelAddress != kTTAdrsEmpty) {
347 
348  // fill item list
349  for (long i=0; i<argc; i++) {
350  item = (t_symobject *)symobject_new(atom_getsym(argv+i));
351  linklist_append(obj->refmenu_items, item);
352  }
353  }
354 }
355 
356 void ui_view_panel_attach(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
357 {
358  t_ui *obj = (t_ui*)self;
359  t_object *box;
360  t_outlet *myoutlet = NULL;
361  t_dll *connecteds = NULL;
362  t_object *o;
363  t_symbol *name;
364  TTValue v;
365 
366  // search through all connected objects for a patcher object
367  object_obex_lookup(obj, _sym_pound_B, &box);
368  myoutlet = (t_outlet*)jbox_getoutlet((t_jbox*)box, panel_out);
369  if (myoutlet)
370  connecteds = (t_dll*)myoutlet->o_dll;
371 
372  while (connecteds) {
373  o = (t_object*)connecteds->d_x1;
374  name = object_classname(o);
375  if (name == _sym_inlet) {
376  o = ((t_inlet *)connecteds->d_x1)->i_owner;
377  name = object_classname(o);
378  if (name == _sym_jpatcher) {
379 
380  obj->patcher_panel = o;
381  obj->has_panel = true;
382 
383  jbox_redraw(&obj->box);
384  return;
385  }
386  }
387  o = NULL;
388  name = NULL;
389  connecteds = connecteds->d_next;
390  }
391 }
392 
393 void ui_return_mute(TTPtr self, t_symbol *msg, long argc, t_atom* argv)
394 {
395  t_ui* obj = (t_ui*)self;
396 
397  obj->is_muted = atom_getlong(argv);
398  jbox_redraw(&obj->box);
399 }
400 
401 void ui_return_bypass(TTPtr self, t_symbol *msg, long argc, t_atom* argv)
402 {
403  t_ui* obj = (t_ui*)self;
404 
405  obj->is_bypassed = atom_getlong(argv);
406  jbox_redraw(&obj->box);
407 }
408 
409 void ui_return_mix(TTPtr self, t_symbol *msg, long argc, t_atom* argv)
410 {
411  t_ui* obj = (t_ui*)self;
412 
413  obj->mix = atom_getlong(argv);
414  jbox_redraw(&obj->box);
415 }
416 
417 void ui_return_gain(TTPtr self, t_symbol *msg, long argc, t_atom* argv)
418 {
419  t_ui* obj = (t_ui*)self;
420 
421  obj->gain = atom_getlong(argv);
422  jbox_redraw(&obj->box);
423 }
424 
425 void ui_return_freeze(TTPtr self, t_symbol *msg, long argc, t_atom* argv)
426 {
427  t_ui* obj = (t_ui*)self;
428 
429  obj->is_frozen = atom_getlong(argv);
430  jbox_redraw(&obj->box);
431 }
432 
433 void ui_return_active(TTPtr self, t_symbol *msg, long argc, t_atom* argv)
434 {
435  t_ui* obj = (t_ui*)self;
436 
437  obj->is_active = atom_getlong(argv);
438  jbox_redraw(&obj->box);
439 }
440 
441 void ui_return_model_address(TTPtr self, t_symbol *msg, long argc, t_atom* argv)
442 {
443  t_object *obj = (t_object*)self;
444 
445  // The following must be deferred because we have to interrogate our box,
446  // and our box is not yet valid until we have finished instantiating the object.
447  // Trying to use a loadbang method instead is also not fully successful (as of Max 5.0.6)
448  defer_low(obj, (method)ui_subscribe, atom_getsym(argv), 0, 0);
449 }
450 
451 void ui_return_model_init(TTPtr self, t_symbol *msg, long argc, t_atom* argv)
452 {
453  t_ui* obj = (t_ui*)self;
454  long init = atom_getlong(argv);
455  TTValue v;
456  TTObject aReceiver;
457 
458  // if the model is initialized and no content observer have been created
459  if (init) {
460 
461  if (obj->hash_receivers->lookup(kTTSym_content, v))
462 
463  // observe the content of the model
464  // by this way, the creation of any widgets depends on the existence of the data
465  ui_receiver_create(obj, aReceiver, gensym("return_model_content"), kTTSym_content, obj->modelAddress, NO, YES);
466 
467  else {
468 
469  // update address to get the content of the model
470  aReceiver = v[0];
471  aReceiver.set(kTTSym_address, obj->modelAddress.appendAttribute(kTTSym_content));
472  }
473  }
474 }
475 
476 void ui_return_model_content(TTPtr self, t_symbol *msg, long argc, t_atom* argv)
477 {
478  t_ui* obj = (t_ui*)self;
479  TTObject anObject;
480  TTBoolean gain = NO;
481  TTBoolean mix = NO;
482  TTBoolean bypass = NO;
483  TTBoolean freeze = NO;
484  TTBoolean active = NO;
485  TTBoolean mute = NO;
486  TTBoolean preset = NO; // is there a preset node in the model ?
487  TTBoolean model = NO; // is there a model node in the model ?
488  TTBoolean change = NO;
489  TTAddress relativeAddress;
490  TTBoolean dataInput = NO;
491  TTBoolean dataOutput = NO;
492  TTBoolean audioInput = NO;
493  TTBoolean audioOutput = NO;
494 
495  // the viewers table must be still available
496  if (!obj->hash_viewers)
497  return;
498 
499  // model namespace observation
500  if (obj->modelAddress != kTTAdrsEmpty) {
501 
502  // look the namelist to know which data exist
503  for (long i=0; i<argc; i++) {
504 
505  relativeAddress = TTAddress(atom_getsym(argv+i)->s_name);
506 
507  if (relativeAddress.getName() == TTSymbol("in")) {
508 
509  if (relativeAddress.getParent() == TTAddress("data"))
510  dataInput = YES;
511 
512  else if (relativeAddress.getParent() == TTAddress("audio"))
513  audioInput = YES;
514 
515  }
516  else if (relativeAddress.getName() == TTSymbol("out")) {
517 
518  if (relativeAddress.getParent() == TTAddress("data"))
519  dataOutput = YES;
520 
521  else if (relativeAddress.getParent() == TTAddress("audio"))
522  audioOutput = YES;
523  }
524  else if (relativeAddress.getName() == TTSymbol("preset"))
525  preset = true;
526 
527  else if (relativeAddress.getName() == TTSymbol("model"))
528  model = true;
529  }
530 
531  if (dataInput || dataOutput)
532  active = true;
533 
534  if (dataInput && dataOutput)
535  bypass = true;
536 
537  if (audioInput || audioOutput)
538  mute = true;
539 
540  if (audioInput && audioOutput) {
541  bypass = true;
542  mix = true;
543  }
544 
545  if (audioOutput)
546  gain = true;
547 
548  // if a data appears or disappears : create or remove the viewer
549 
550  // gain
551  if (gain != obj->has_gain) {
552  obj->has_gain = gain;
553  if (gain)
554  ui_viewer_create(obj, anObject, gensym("return_gain"), TTSymbol("audio/gain"), obj->modelAddress, NO); // don't subscribe this viewer
555  else
556  ui_viewer_destroy(obj, TTSymbol("audio/gain"));
557  }
558 
559  // mix
560  if (mix != obj->has_mix) {
561  obj->has_mix = mix;
562  if (mix)
563  ui_viewer_create(obj, anObject, gensym("return_mix"), TTSymbol("audio/mix"), obj->modelAddress, NO); // don't subscribe this viewer
564  else
565  ui_viewer_destroy(obj, TTSymbol("audio/mix"));
566 
567  change = true;
568  }
569 
570  // bypass
571  if (bypass != obj->has_bypass) {
572  obj->has_bypass = bypass;
573  if (bypass)
574  ui_viewer_create(obj, anObject, gensym("return_bypass"), TTSymbol("*.*/bypass"), obj->modelAddress, NO); // don't subscribe this viewer
575  else
576  ui_viewer_destroy(obj, TTSymbol("*.*/bypass"));
577 
578  change = true;
579  }
580 
581  // freeze
582  if (freeze != obj->has_freeze) {
583  obj->has_freeze = freeze;
584  if (freeze)
585  ui_viewer_create(obj, anObject, gensym("return_freeze"), TTSymbol("data/freeze"), obj->modelAddress, NO); // don't subscribe this viewer
586  else
587  ui_viewer_destroy(obj, TTSymbol("data/freeze"));
588 
589  change = true;
590  }
591 
592  // active
593  if (active != obj->has_active) {
594  obj->has_active = active;
595  if (active)
596  ui_viewer_create(obj, anObject, gensym("return_active"), TTSymbol("data/active"), obj->modelAddress, NO); // don't subscribe this viewer
597  else {
598  ui_viewer_destroy(obj, TTSymbol("data/active"));
599  obj->hash_viewers->remove(TTSymbol("data/active"));
600  }
601 
602  change = true;
603  }
604 
605  // mute
606  if (mute != obj->has_mute) {
607  obj->has_mute = mute;
608  if (mute)
609  ui_viewer_create(obj, anObject, gensym("return_mute"), TTSymbol("*.*/mute"), obj->modelAddress, NO); // don't subscribe this viewer
610  else
611  ui_viewer_destroy(obj, TTSymbol("*.*/mute"));
612 
613  change = true;
614  }
615 
616  // preset
617  if (preset != obj->has_preset) {
618  obj->has_preset = preset;
619  if (preset) {
620  ui_viewer_create(obj, anObject, gensym("return_preset_names"), TTSymbol("preset:names"), obj->modelAddress, NO); // don't subscribe this viewer
621  }
622  else {
623  ui_viewer_destroy(obj, TTSymbol("preset:names"));
624  }
625 
626  change = true;
627  }
628 
629  // model
630  if (model != obj->has_model)
631  obj->has_model = model;
632 
633  if (change)
634  jbox_redraw(&obj->box);
635 
636  }
637 }
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...
TTAddress appendAddress(const TTAddress &toAppend)
Return a new TTAddress with the appended part.
Definition: TTAddress.h:167
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
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
TTAddress getParent()
Get a pointer to the parent address.
Definition: TTAddress.h:112
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
TTHashPtr JAMOMA_EXPORT jamoma_explorer_default_filter_bank(void)
void JAMOMA_EXPORT jamoma_callback_return_value(const TTValue &baton, const TTValue &v)
Return the value to a j.
j.ui : Provide standard user interface component for modules
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 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
const char * c_str() const
Return a pointer to the internal string as a C-string.
Definition: TTSymbol.h:77
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
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...
TTBoolean valid() const
Determine if the object contained by this TTObject is truly ready for use.
Definition: TTObject.cpp:179
TTSymbol & getName()
Get the name part.
Definition: TTAddress.h:118
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
unsigned char TTUInt8
8 bit unsigned integer (char)
Definition: TTBase.h:174