Jamoma API  0.6.0.a19
j.route.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationMaxExternals
4  *
5  * @brief j.route : Route messages to an outlet if they meet our criteria
6  *
7  * @details
8  *
9  * @authors Tim Place, Trond Lossius
10  *
11  * @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 MAX_LIST_LENGTH 100
20 
21 typedef struct _route{ // Data Structure for this object
22  t_object ob; // REQUIRED: Our object
23  void *my_outlet[2]; // my outlet array -- NOTE: the attribute dump outlet is handled automagically
24 
25  t_symbol *searchlist[MAX_LIST_LENGTH]; // ATTRIBUTE: storage of which inlets tigger output from the object (essentially an array of toggles)
26  long searchlistlen;
27  long searchpositions[MAX_LIST_LENGTH];
28  long searchpositionslen;
29 // long stripmatch; // ATTRIBUTE: toggle strip_match
30  long partialmatch;
31  t_symbol *searchsymbol;
32 } t_route;
33 
34 // Prototypes for our methods:
35 void *route_new(t_symbol *s, long argc, t_atom *argv);
36 void route_assist(t_route *x, void *b, long msg, long arg, char *dst);
37 void route_symbol(t_route *x, t_symbol *msg, long argc, t_atom *argv);
38 void route_list(t_route *x, t_symbol *msg, long argc, t_atom *argv);
39 void route_bang(t_route *x);
40 char find_match(t_route *x, t_symbol *input, short position);
41 
42 // Globals
43 t_class *route_class; // Required: Global pointer for our class
44 
45 /************************************************************************************/
46 // Main() Function
47 
48 int JAMOMA_EXPORT_MAXOBJ main(void)
49 {
50  long attrflags = 0;
51  t_class *c;
52  t_object *attr;
53 
54  common_symbols_init();
55 
56  // Define our class
57  c = class_new("j.route",(method)route_new, (method)0L, sizeof(t_route), (method)0L, A_GIMME, 0);
58 
59  // Make methods accessible for our class:
60  class_addmethod(c, (method)route_bang, "bang", 0L);
61  class_addmethod(c, (method)route_list, "list", A_GIMME, 0L);
62  class_addmethod(c, (method)route_symbol, "anything", A_GIMME, 0L);
63  class_addmethod(c, (method)route_assist, "assist", A_CANT, 0L);
64  class_addmethod(c, (method)object_obex_dumpout, "dumpout", A_CANT,0);
65 
66  // ATTRIBUTE: searchstring
67  attr = attr_offset_array_new("searchstring", _sym_symbol, MAX_LIST_LENGTH, attrflags,
68  (method)0, (method)0, calcoffset(t_route, searchlistlen), calcoffset(t_route, searchlist));
69  class_addattr(c, attr);
70 
71  // ATTRIBUTE: searchpositions
72  attr = attr_offset_array_new("searchpositions", _sym_long, MAX_LIST_LENGTH, attrflags,
73  (method)0, (method)0, calcoffset(t_route, searchpositionslen), calcoffset(t_route, searchpositions));
74  class_addattr(c, attr);
75 
76  // ATTRIBUTE: partialmatch
77  attr = attr_offset_new("partialmatch", _sym_long, attrflags,
78  (method)0, (method)0, calcoffset(t_route, partialmatch));
79  class_addattr(c, attr);
80 
81  // ATTRIBUTE: stripmatch
82 // attr = attr_offset_new("stripmatch", _sym_long, attrflags,
83 // (method)0, (method)0, calcoffset(t_route, stripmatch));
84 // class_addattr(c, attr);
85 
86 
87  // Finalize our class
88  class_register(CLASS_BOX, c);
89  route_class = c;
90  return 0;
91 }
92 
93 
94 /************************************************************************************/
95 // Object Life
96 
97 void *route_new(t_symbol *s, long argc, t_atom *argv)
98 {
99  t_route *x = (t_route *)object_alloc(route_class);
100  if (x) {
101  object_obex_store((void *)x, _sym_dumpout, (object *)outlet_new(x,NULL)); // dumpout
102 
103  // Create Outlets
104  x->my_outlet[1] = outlet_new(x, 0);
105  x->my_outlet[0] = outlet_new(x, 0);
106 
107  // Set defaults before I go loading in values from the attributes
108  x->searchlist[0] = gensym("default");
109  x->searchlistlen = 1;
110  x->searchpositions[0] = 1;
111  x->searchpositionslen = 1;
112  // x->stripmatch = 0;
113  x->partialmatch = 0;
114 
115  attr_args_process(x,argc,argv); //handle attribute args
116  }
117  return (x); // return the pointer to our new instantiation
118 }
119 
120 
121 /************************************************************************************/
122 // Methods bound to input/inlets
123 
124 // Method for Assistance Messages
125 void route_assist(t_route *x, void *b, long msg, long arg, char *dst)
126 {
127  if (msg==1) // Inlet
128  strcpy(dst, "Input");
129  else if (msg==2) { // Outlets
130  switch(arg) {
131  case 0: strcpy(dst, "Matching Output"); break;
132  case 1: strcpy(dst, "Unmatching Output"); break;
133  case 2: strcpy(dst, "Dumpout"); break;
134  }
135  }
136 }
137 
138 
139 // generate a single symbol out of the multiple symbols given in the attribute
140 void route_bang(t_route *x)
141 {
142  short i;
143  char newstring[500];
144 
145  newstring[0] = 0;
146  for (i=0; i< (x->searchlistlen); i++) {
147  strcat(newstring, x->searchlist[i]->s_name);
148  strcat(newstring, " ");
149  }
150  // knock out the last space
151  newstring[strlen(newstring) - 1] = 0;
152 
153  x->searchsymbol = gensym(newstring);
154 }
155 
156 
157 // utility function to help out the methods
158 char find_match(t_route *x, t_symbol *input, short position)
159 {
160  short i;
161  char matched = 0;
162  short len;
163 
164  for (i=0; i<MAX_LIST_LENGTH ;i++) {
165  matched += (x->searchpositions[i] == position);
166  }
167 
168  if (matched > 0) {
169  if (x->partialmatch) {
170  len = strlen(x->searchsymbol->s_name);
171  for (i=0; i<len; i++) {
172  if (input->s_name[i] != x->searchsymbol->s_name[i])
173  return 0;
174  }
175  return 1;
176  }
177  else
178  return (input == x->searchsymbol);
179  }
180  else
181  return 0;
182 }
183 
184 
185 // SYMBOL INPUT
186 void route_symbol(t_route *x, t_symbol *msg, long argc, t_atom *argv)
187 {
188  short i;
189  char matched;
190  char tempstring[50];
191  t_symbol *tempsym;
192 
193  route_bang(x);
194  matched = 0;
195 
196  // match the symbol
197  matched += find_match(x, msg, 1);
198 
199  // match the arguments
200  for (i=0; i<argc; i++) {
201  switch(argv[i].a_type) {
202  case A_LONG:
203  snprintf(tempstring, 50, "%ld", argv[i].a_w.w_long);
204  tempsym = gensym(tempstring);
205  break;
206  case A_FLOAT:
207  snprintf(tempstring, 50, "%f", argv[i].a_w.w_float);
208  tempsym = gensym(tempstring);
209  break;
210  case A_SYM:
211  tempsym = argv[i].a_w.w_sym;
212  break;
213  }
214  matched += find_match(x, tempsym, i+2);
215  }
216 
217  // Output
218  if (matched > 0)
219  outlet_anything(x->my_outlet[0], msg, argc , argv);
220  else
221  outlet_anything(x->my_outlet[1], msg, argc, argv);
222 }
223 
224 
225 
226 // LIST INPUT
227 void route_list(t_route *x, t_symbol *msg, long argc, t_atom *argv)
228 {
229  short i;
230  char matched;
231  char tempstring[50];
232  t_symbol *tempsym;
233 
234  route_bang(x);
235  matched = 0;
236 
237  // match the arguments
238  for (i=0; i<argc; i++) {
239  switch(argv[i].a_type) {
240  case A_LONG:
241  snprintf(tempstring, 50, "%ld", argv[i].a_w.w_long);
242  tempsym = gensym(tempstring);
243  break;
244  case A_FLOAT:
245  snprintf(tempstring, 50, "%f", argv[i].a_w.w_float);
246  tempsym = gensym(tempstring);
247  break;
248  case A_SYM:
249  tempsym = argv[i].a_w.w_sym;
250  break;
251  }
252  matched += find_match(x, tempsym, i+1); // NOTE THE DIFFERENCE HERE COMPARED TO ABOVE
253  }
254 
255  // Output
256  if (matched > 0)
257  outlet_anything(x->my_outlet[0], msg, argc , argv);
258  else
259  outlet_anything(x->my_outlet[1], msg, argc, argv);
260 
261 }
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.route.cpp:48
Various utilities for interfacing with Max that are not specific to JamomaModular as such...