Jamoma API  0.6.0.a19
j.unit~.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationMaxExternals
4  *
5  * @brief j.unit - Max external that converts values from one kind of unit to another kind of unit
6  *
7  * @details The convertions make use of the DataspaceLib
8  *
9  * @authors Tim Place, Trond Lossius
10  *
11  * @copyright Copyright © 2007 Tim Place, Trond Lossius @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 "TTClassWrapperMax.h"
18 
19 
20 // Data Structure for this object
21 typedef struct _unit {
22  t_pxobject ob;
23  TTPtr outlet;
24  TTObjectBasePtr dataspace;
25  t_symbol* attr_dataspace; // name of the dataspace -- e.g. "temperature"
26  t_symbol* attr_unit_active; // name of the current unit within the dataspace -- e.g. "celsius"
27  t_symbol* attr_unit_native; // name of the desired native unit within the dataspace -- e.g. "celsius"
28 } t_unit;
29 
30 
31 // Prototypes for methods
32 void* unit_new(t_symbol *name, long argc, t_atom *argv);
33 void unit_free(t_unit *self);
34 void unit_assist(t_unit *self, void *b, long m, long a, char *s);
35 void unit_getDataspaces(t_unit *self);
36 void unit_getUnits(t_unit *self);
37 void unit_perform64(t_unit *self, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam);
38 void unit_dsp64(t_unit *self, t_object *dsp64, short *count, double samplerate, long maxvectorsize, long flags);
39 t_max_err unit_setDataspace(t_unit *self, void *attr, long argc, t_atom *argv);
40 t_max_err unit_setDataspaceActive(t_unit *self, void *attr, long argc, t_atom *argv);
41 t_max_err unit_setDataspaceNative(t_unit *self, void *attr, long argc, t_atom *argv);
42 
43 
44 // Globals
45 static t_class* unit_class;
46 static TTSymbol kTTSym_convert("convert");
47 
48 
49 #pragma mark -
50 #pragma mark main
51 /************************************************************************************/
52 // Main() Function
53 
54 int C74_EXPORT main(void)
55 {
56  t_class* c;
57 
58  TTFoundationInit();
59  common_symbols_init();
60 
61  // Define our class
62  c = class_new("j.unit~",(method)unit_new, (method)unit_free, sizeof(t_unit), (method)0L, A_GIMME, 0);
63 
64  // Make methods accessible for our class:
65  class_addmethod(c, (method)unit_getDataspaces, "dataspaces.get", 0);
66  class_addmethod(c, (method)unit_getUnits, "units.get", A_GIMME, 0);
67  class_addmethod(c, (method)unit_assist, "assist", A_CANT, 0);
68  class_addmethod(c, (method)object_obex_dumpout, "dumpout", A_CANT, 0);
69  class_addmethod(c, (method)unit_dsp64, "dsp64", A_CANT, 0);
70 
71  class_addattr(c, attr_offset_new("dataspace", _sym_symbol, 0, (method)0, (method)unit_setDataspace, calcoffset(t_unit, attr_dataspace)));
72 
73  CLASS_ATTR_SYM(c, "input", 0, t_unit, attr_unit_active);
74  CLASS_ATTR_ACCESSORS(c, "input", NULL, unit_setDataspaceActive);
75 
76  CLASS_ATTR_SYM(c, "output", 0, t_unit, attr_unit_native);
77  CLASS_ATTR_ACCESSORS(c, "output", NULL, unit_setDataspaceNative);
78 
79  // Finalize our class
80  class_dspinit(c);
81  class_register(CLASS_BOX, c);
82  unit_class = c;
83  return 0;
84 }
85 
86 
87 #pragma mark -
88 #pragma mark life cycle
89 /************************************************************************************/
90 // Object Life
91 
92 void *unit_new(t_symbol *name, long argc, t_atom *argv)
93 {
94  t_unit *self;
95  TTValue none;
96 
97  self = (t_unit *)object_alloc(unit_class);
98  if (self) {
99  object_obex_store((void*)self, _sym_dumpout, (object*)outlet_new(self, NULL));
100 
101  // Make sure that environment sample rate is set correctly at instantiated,
102  // as it is used by time dataspace for conversions to and from sample
103  TTValue sr(sys_getsr());
104  ttEnvironment->setAttributeValue(kTTSym_sampleRate, sr);
105 
106  dsp_setup((t_pxobject*)self, 1);
107 
108  self->outlet = outlet_new(self, "signal");
109  TTObjectBaseInstantiate(TT("dataspace"), &self->dataspace, none);
110 
111  attr_args_process(self, argc, argv);
112  if (!self->dataspace)
113  object_attr_setsym(self, gensym("dataspace"), gensym("temperature"));
114  }
115  return self;
116 }
117 
118 
119 void unit_free(t_unit *self)
120 {
121  TTObjectBaseRelease(&self->dataspace);
122 }
123 
124 
125 
126 #pragma mark -
127 #pragma mark methods
128 /************************************************************************************/
129 // Methods bound to input/inlets
130 
131 // Method for Assistance Messages
132 void unit_assist(t_unit *self, void *b, long msg, long arg, char *dst)
133 {
134  if (msg==1) // Inlets
135  strcpy(dst, "x");
136  else if (msg==2) { // Outlets
137  switch(arg) {
138  case 0: strcpy(dst, "y=f(x)"); break;
139  default: strcpy(dst, "dumpout"); break;
140  }
141  }
142 }
143 
144 /*
145 void unit_int(t_unit *self, long x)
146 {
147  unit_float(self, (double)x);
148 }
149 
150 
151 void unit_float(t_unit *self, double x)
152 {
153  TTValue v(x);
154 
155  self->dataspace->sendMessage(TT("convert"), v, v);
156  outlet_float(self->outlet_native, v.getFloat64(0));
157 }
158 
159 
160 void unit_list(t_unit *self, t_symbol *msg, long argc, t_atom *argv)
161 {
162  TTValue v;
163 
164  v.resize(argc);
165  for (int i=0; i<argc; i++)
166  v.set(i, atom_getfloat(argv+i));
167 
168  //TODO: add dataspace support for lists of single dimensional data conversion #42
169  self->dataspace->sendMessage(TT("convert"), v, v);
170 
171  argc = v.getSize(); // in case the output list is longer than the input list (e.g. quaternions)
172  t_atom* rv = new t_atom[argc];
173 
174  for (int i=0; i<argc; i++)
175  atom_setfloat(rv+i, v.getFloat64(i));
176 
177  outlet_anything(self->outlet_native, _sym_list, argc, rv);
178 }
179 */
180 
181 
182 void unit_getDataspaces(t_unit *self)
183 {
184  t_atom a[2];
185  TTValue v;
186 
187  atom_setsym(a+0, gensym("clear"));
188  object_obex_dumpout(self, gensym("DataspacesMenu"), 1, a);
189 
190  self->dataspace->sendMessage(TT("getAvailableDataspaces"), v, v);
191  for (TTUInt32 i=0; i < v.size(); i++) {
192  TTSymbol name = v[i];
193 
194  atom_setsym(a+0, gensym("append"));
195  atom_setsym(a+1, gensym(name.c_str()));
196  object_obex_dumpout(self, gensym("DataspacesMenu"), 2, a);
197  }
198 }
199 
200 
201 void unit_getUnits(t_unit *self)
202 {
203  t_atom a[2];
204  TTValue v;
205 
206  atom_setsym(a+0, gensym("clear"));
207  object_obex_dumpout(self, gensym("UnitMenu"), 1, a);
208 
209  self->dataspace->sendMessage(TT("getAvailableUnits"), v, v);
210  for (TTUInt32 i=0; i < v.size(); i++) {
211  TTSymbol name = v[i];
212 
213  atom_setsym(a+0, gensym("append"));
214  atom_setsym(a+1, gensym(name.c_str()));
215  object_obex_dumpout(self, gensym("UnitMenu"), 2, a);
216  }
217 }
218 
219 
220 void unit_perform64(t_unit *self, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam)
221 {
222  double *in = ins[0];
223  double *out = outs[0];
224  TTValue v;
225 
226  while (sampleframes--){
227  v = *in++;
228  self->dataspace->sendMessage(kTTSym_convert, v, v);
229  *out++ = v;
230  }
231 }
232 
233 
234 void unit_dsp64(t_unit *self, t_object *dsp64, short *count, double samplerate, long maxvectorsize, long flags)
235 {
236  object_method(dsp64, gensym("dsp_add64"), (t_object*)self, unit_perform64, 0, NULL);
237 }
238 
239 
240 #pragma mark -
241 #pragma mark attributes
242 
243 t_max_err unit_setDataspace(t_unit *self, void *attr, long argc, t_atom *argv)
244 {
245  TTValue v;
246  TTSymbol s;
247 
248  self->attr_dataspace = atom_getsym(argv);
249  self->dataspace->setAttributeValue(TT("dataspace"), TT(self->attr_dataspace->s_name));
250 
251  self->dataspace->getAttributeValue(TT("inputUnit"), v);
252  s = v[0];
253  self->attr_unit_active = gensym(s.c_str());
254 
255  self->dataspace->getAttributeValue(TT("outputUnit"), v);
256  s = v[0];
257  self->attr_unit_native = gensym(s.c_str());
258 
259  return MAX_ERR_NONE;
260 }
261 
262 
263 t_max_err unit_setDataspaceActive(t_unit *self, void *attr, long argc, t_atom *argv)
264 {
265  self->attr_unit_active = atom_getsym(argv);
266  self->dataspace->setAttributeValue(TT("inputUnit"), TT(self->attr_unit_active->s_name));
267  return MAX_ERR_NONE;
268 }
269 
270 
271 t_max_err unit_setDataspaceNative(t_unit *self, void *attr, long argc, t_atom *argv)
272 {
273  self->attr_unit_native = atom_getsym(argv);
274  self->dataspace->setAttributeValue(TT("outputUnit"), TT(self->attr_unit_native->s_name));
275  return MAX_ERR_NONE;
276 }
277 
TTErr TTObjectBaseRelease(TTObjectBasePtr *anObject)
DEPRECATED.
TTFOUNDATION_EXPORT TTEnvironment * ttEnvironment
The environment object has one instance, which is global in scope.
size_type size() const noexcept
Return the number of elements.
Base class for all first-class Jamoma objects.
Definition: TTObjectBase.h:109
TTErr setAttributeValue(const TTSymbol name, TTValue &value)
Set an attribute value for an object.
#define TT
This macro is defined as a shortcut for doing a lookup in the symbol table.
Definition: TTSymbol.h:155
void * TTPtr
A generic pointer.
Definition: TTBase.h:248
The TTSymbol class is used to represent a string and efficiently pass and compare that string...
Definition: TTSymbol.h:26
TTErr TTObjectBaseInstantiate(const TTSymbol className, TTObjectBasePtr *returnedObjectPtr, const TTValue arguments)
DEPRECATED.
const char * c_str() const
Return a pointer to the internal string as a C-string.
Definition: TTSymbol.h:77
int C74_EXPORT main(void)
Set up this class as a Max external the first time an object of this kind is instantiated.
Definition: j.unit~.cpp:54
std::uint32_t TTUInt32
32 bit unsigned integer
Definition: TTBase.h:178
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34