Jamoma API  0.6.0.a19
j.gang.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationMaxExternals
4  *
5  * @brief j.gang - Gang multiple objects together
6  *
7  * @details
8  *
9  * @authors Tim Place, Trond Lossius
10  *
11  * @copyright Copyright © 2005 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 "JamomaForMax.h"
18 
19 #define NUM_INLETS 4
20 #define NUM_OUTLETS 4
21 #define MAX_LIST_LENGTH 256
22 
23 
24 // Data Structure for this object
25 typedef struct _gang{
26  t_object ob;
27  void *outlets[NUM_OUTLETS];
28  void *inlets[NUM_INLETS]; // for proxy inlets
29  bool type_is_list; // flag for the data type (false=float, true=list)
30  bool set_by_pp; // flag: if true, the value was set by pp, which takes precedance
31  float parameter_value; // FLOAT INPUT
32  float parameter_value_pp;
33  t_atom argv[MAX_LIST_LENGTH]; // LIST INPUT: stored atoms for output
34  short argc; // LIST INPUT: len
35  void *qelem_send_pp; // queue element
36  void *qelem_send_ui; // queue element
37  void *qelem_send_pattr; // queue element
38  void *qelem_send_scope; // queue element
39 } t_gang;
40 
41 // Prototypes for methods: need a method for each incoming message type:
42 void *gang_new(t_symbol *msg, long argc, t_atom *argv);
43 void gang_free(t_gang *x);
44 void gang_assist(t_gang *x, void *b, long msg, long arg, char *dst);
45 void gang_int(t_gang *x, long value);
46 void gang_float(t_gang *x, double value);
47 void gang_list(t_gang *x, t_symbol *msg, long argc, t_atom *argv);
48 void gang_qfn_send_pp(t_gang *x);
49 void gang_qfn_send_ui(t_gang *x);
50 void gang_qfn_send_pattr(t_gang *x);
51 void gang_qfn_send_scope(t_gang *x);
52 float gang_bitsafe(double in);
53 
54 // Class Globals
55 t_class *gang_class; // Required. Global pointing to this class
56 
57 
58 /************************************************************************************/
59 // Main() Function
60 
61 int JAMOMA_EXPORT_MAXOBJ main(void)
62 {
63  t_class *c;
64 
65  common_symbols_init();
66 
67  c = class_new("j.gang",(method)gang_new, (method)gang_free, sizeof(t_gang), (method)0L, A_GIMME, 0);
68 
69  class_addmethod(c, (method)gang_float, "float", 0L);
70  class_addmethod(c, (method)gang_int, "int", 0L);
71  class_addmethod(c, (method)gang_list, "list", A_GIMME, 0L);
72  class_addmethod(c, (method)gang_assist, "assist", A_CANT, 0L);
73 
74  // Finalize our class
75  class_register(CLASS_BOX, c);
76  gang_class = c;
77 
78  return 0;
79 }
80 
81 
82 /************************************************************************************/
83 // Object Creation Method
84 
85 void *gang_new(t_symbol *msg, long argc, t_atom *argv)
86 {
87  t_gang *x;
88  short i;
89 
90  x = (t_gang *)object_alloc(gang_class);
91  if (x) {
92  // outlets
93  object_obex_store((void *)x, _sym_dumpout, (object *)outlet_new(x,NULL));
94  for (i = NUM_OUTLETS-1; i>=0; i--)
95  x->outlets[i] = floatout(x);
96 
97  // Create Inlets (inlets beyond the default (num 0) inlet)
98  for (i = NUM_INLETS-1; i >= 1; i--)
99  x->inlets[i] = proxy_new(x, i, 0L);
100 
101  // defaults
102  x->parameter_value = -2000000;
103  x->argc = 0;
104  x->set_by_pp = false;
105 
106  // qelem
107  x->qelem_send_ui = qelem_new(x, (method)gang_qfn_send_ui);
108  x->qelem_send_pp = qelem_new(x, (method)gang_qfn_send_pp);
109  x->qelem_send_pattr = qelem_new(x, (method)gang_qfn_send_pattr);
110  x->qelem_send_scope = qelem_new(x, (method)gang_qfn_send_scope);
111 
112  //handle attribute args
113  attr_args_process(x, argc, argv);
114  }
115  return (x);
116 }
117 
118 void gang_free(t_gang *x)
119 {
120  short i;
121 
122  qelem_free(x->qelem_send_ui);
123  qelem_free(x->qelem_send_pp);
124  qelem_free(x->qelem_send_pattr);
125  qelem_free(x->qelem_send_scope);
126 
127  for (i = NUM_INLETS-1; i >= 1; i--)
128  freeobject((t_object *)x->inlets[i]);
129 }
130 
131 /************************************************************************************/
132 // Methods bound to input/inlets
133 
134 // Method for Assistance Messages
135 void gang_assist(t_gang *x, void *b, long msg, long arg, char *dst)
136 {
137  if (msg==1) { // Inlets
138  switch(arg) {
139  case 0: strcpy(dst, "connect to ui object"); break;
140  case 1: strcpy(dst, "connect to pp"); break;
141  case 2: strcpy(dst, "aux object 1"); break;
142  case 3: strcpy(dst, "aux object 2"); break;
143  }
144  }
145  else if (msg==2) { // Outlets
146  switch(arg) {
147  case 0: strcpy(dst, "connect to ui object"); break;
148  case 1: strcpy(dst, "connect to pp"); break;
149  case 2: strcpy(dst, "aux object 1"); break;
150  case 3: strcpy(dst, "aux object 2"); break;
151  default: strcpy(dst, "dumpout"); break;
152  }
153  }
154 }
155 
156 
157 // METHOD: int conversion
158 void gang_int(t_gang *x, long value)
159 {
160  gang_float(x, value);
161 }
162 
163 
164 // METHOD: float input
165 void gang_float(t_gang *x, double value)
166 {
167  long inletnum = proxy_getinlet((object *)x);
168 
169  if (value == x->parameter_value) return;
170  //x->parameter_value = value;
171  x->parameter_value = gang_bitsafe(value);
172  x->type_is_list = false;
173 
174  switch(inletnum) {
175  case 0: // UI Input
176  qelem_set(x->qelem_send_pp);
177  qelem_set(x->qelem_send_pattr);
178  qelem_set(x->qelem_send_scope);
179  break;
180  case 1: // PP Input
181  x->set_by_pp = true;
182  x->parameter_value_pp = x->parameter_value;
183  qelem_set(x->qelem_send_ui);
184  qelem_set(x->qelem_send_pattr);
185  qelem_set(x->qelem_send_scope);
186  break;
187  case 2: // Pattr Input
188  qelem_set(x->qelem_send_pp);
189  qelem_set(x->qelem_send_ui);
190  qelem_set(x->qelem_send_scope);
191  break;
192  case 3: // Scope Input
193  qelem_set(x->qelem_send_pp);
194  qelem_set(x->qelem_send_ui);
195  qelem_set(x->qelem_send_pattr);
196  break;
197  }
198 }
199 
200 
201 // METHOD: list input
202 void gang_list(t_gang *x, t_symbol *msg, long argc, t_atom *argv)
203 {
204  long inletnum = proxy_getinlet((object *)x);
205  short i,n;
206  t_atom *ap;
207 
208 // if (x->set_by_pp == false) return; // this has already been set by pp, which takes precedance
209 
210  n = MIN(MAX_LIST_LENGTH, argc);
211  ap = x->argv;
212  x->type_is_list = true;
213 
214  // check to see if the list has changed
215  for (i=0; i<n; i++) {
216  if (atom_getfloat(ap+i) != atom_getfloat(argv+i)) goto process;
217  }
218  return;
219 
220 process:
221  // copy input to our private copy
222  for (i=0; i < n; i++, argv++, ap++) {
223 // *ap = *argv;
224  atom_setfloat(ap, gang_bitsafe(atom_getfloat(argv)));
225 
226  }
227  x->argc = n;
228 
229  switch(inletnum) {
230  case 0: // UI Input
231  qelem_set(x->qelem_send_pp);
232  qelem_set(x->qelem_send_pattr);
233  qelem_set(x->qelem_send_scope);
234  break;
235  case 1: // PP Input
236  qelem_set(x->qelem_send_ui);
237  qelem_set(x->qelem_send_pattr);
238  qelem_set(x->qelem_send_scope);
239  break;
240  case 2: // Pattr Input
241  qelem_set(x->qelem_send_pp);
242  qelem_set(x->qelem_send_ui);
243  qelem_set(x->qelem_send_scope);
244  break;
245  case 3: // Scope Input
246  qelem_set(x->qelem_send_pp);
247  qelem_set(x->qelem_send_ui);
248  qelem_set(x->qelem_send_pattr);
249  break;
250  }
251 }
252 
253 
254 // METHOD: Queue Function
255 void gang_qfn_send_ui(t_gang *x)
256 {
257  if (x->type_is_list)
258  outlet_list(x->outlets[0], _sym_list, x->argc, x->argv);
259  else {
260  if (x->set_by_pp) outlet_float(x->outlets[0], x->parameter_value_pp);
261  else outlet_float(x->outlets[0], x->parameter_value);
262  }
263  x->set_by_pp = false;
264 }
265 
266 // METHOD: Queue Function
267 void gang_qfn_send_pp(t_gang *x)
268 {
269  if (x->type_is_list)
270  outlet_list(x->outlets[1], _sym_list, x->argc, x->argv);
271  else {
272  if (x->set_by_pp) outlet_float(x->outlets[1], x->parameter_value_pp);
273  else outlet_float(x->outlets[1], x->parameter_value);
274  }
275  x->set_by_pp = false;
276 }
277 
278 // METHOD: Queue Function
279 void gang_qfn_send_pattr(t_gang *x)
280 {
281  if (x->type_is_list)
282  outlet_list(x->outlets[2], _sym_list, x->argc, x->argv);
283  else {
284  if (x->set_by_pp) outlet_float(x->outlets[2], x->parameter_value_pp);
285  else outlet_float(x->outlets[2], x->parameter_value);
286  }
287  x->set_by_pp = false;
288 }
289 
290 // METHOD: Queue Function
291 void gang_qfn_send_scope(t_gang *x)
292 {
293  if (x->type_is_list)
294  outlet_list(x->outlets[3], _sym_list, x->argc, x->argv);
295  else {
296  if (x->set_by_pp) outlet_float(x->outlets[3], x->parameter_value_pp);
297  else outlet_float(x->outlets[3], x->parameter_value);
298  }
299  x->set_by_pp = false;
300 }
301 
302 
303 // FILTER OUT NANs
304 float gang_bitsafe(double in)
305 {
306  double temp = in;
307  if (temp != in) // nan does not equal itself
308  temp = 0;
309  return(temp);
310 }
Various utilities for interfacing with Max that are not specific to JamomaModular as such...
int JAMOMA_EXPORT_MAXOBJ main(void)
Set up this class as a Max external the first time an object of this kind is instantiated.
Definition: j.gang.cpp:61