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