Jamoma API  0.6.0.a19
j.send~.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationMaxLibrary
4  *
5  * @brief Jamoma For Max Shared Library
6  *
7  * @details Send remote audio signals
8  *
9  * @authors Tim Place, Trond Lossius
10  *
11  * @copyright Copyright © 2007, 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 "Jamoma.h"
18 
19 /*
20  The way this should work is that we have a j.send object with N inlets and one outlet (dumpout)
21  When the object receives a 'gettargets' message then it fills a menu via dumpout with all of the targets.
22  The target is the OSC name of the target module.
23 
24  There is then an @target attribute, which is the j.in~ that this sends to.
25 
26  The number of inlets are defined by an argument. We need to check at the time that dsp is started to
27  make sure the target actually has the number of audio signals we are sending though...
28 
29  QUESTION:
30  What about Jitter or other 'signals'? Should they be implemented via a special mode or additions to
31  the plain vanilla j.send?
32 
33  Argument in that case will need to be type-checked: int = number of inputs, symbol = OSCname
34 */
35 
36 typedef struct _audiosend{
37  t_pxobject obj;
38  void *dumpout; ///< dumpout outlet
39 
40  t_symbol *attr_target; ///< name of the module we are sending to
41  t_object *obj_target; ///< the hub of the module we are sending to
42  t_object *obj_direct_target; ///< the j.in~ object in the module we are sending to
43 
44  long num_inputs; ///< spec'd as an argument
45  float *audio_in[MAX_NUM_CHANNELS]; ///< pointers to the audio vectors
46 } t_audiosend;
47 
48 
49 // Prototypes
50 
51 /** Called at object instantiation.
52  @param s Pointer to symbol bassed as message argument to the object.
53  @param argc The number of arguments passed to the object.
54  @param argv Pointer to arguments as an array of atoms.
55  @return Pointer to the newly created object.
56  */
57 void *audiosend_new(t_symbol *s, long argc, t_atom *argv);
58 
59 
60 /** Free up and dispose of the object.
61  @param x Pointer to this object.
62  */
63 void audiosend_free(t_audiosend *x);
64 
65 
66 /** Method for displaying assist strings for inlets and outlets.
67  @param x Pointer to this object.
68  @param b
69  @param msg
70  @param argc
71  @param argv
72  */
73 void audiosend_assist(t_audiosend *x, void *b, long msg, long arg, char *dst);
74 
75 
76 /** When banged, fill a menu with potential targets.
77  @param x Pointer to this class.
78  */
79 void audiosend_bang(t_audiosend *x);
80 
81 
82 /** Audio perform method for the object.
83  */
84 t_int* audiosend_perform(t_int *w);
85 
86 
87 /** The DSP method for the object, called when compiling the audio chain.
88  @param x
89  @param sp
90  @param count
91  */
92 void audiosend_dsp(t_audiosend *x, t_signal **sp, short *count);
93 
94 
95 /** Set the hub of the module we are sending to as an attribute.
96  @param x Pointer to this object
97  @param attr Pointer to the attribute
98  @param argc
99  @param argv
100 */
101 t_max_err audiosend_attr_settarget(t_audiosend *x, void *attr, long argc, t_atom *argv);
102 
103 
104 // Globals
105 static t_class *s_audiosend_class; ///< Required: Global pointer for our class
106 
107 
108 /************************************************************************************/
109 
110 void send_tilde_initclass(void)
111 {
112  long attrflags = 0;
113  t_class *c;
114  t_object *attr;
115 
116  // Define our class
117  c = class_new("j.send~", (method)audiosend_new, (method)audiosend_free,
118  sizeof(t_audiosend), (method)NULL, A_GIMME, 0);
119 
120  // Make methods accessible for our class:
121  class_addmethod(c, (method)audiosend_bang, "bang", 0);
122  class_addmethod(c, (method)audiosend_dsp, "dsp", A_CANT, 0);
123  class_addmethod(c, (method)audiosend_assist, "assist", A_CANT, 0);
124  class_addmethod(c, (method)object_obex_dumpout, "dumpout", A_CANT,0);
125 
126  // ATTRIBUTE: name
127  attr = attr_offset_new("target", _sym_symbol, attrflags,
128  (method)0, (method)audiosend_attr_settarget, calcoffset(t_audiosend, attr_target));
129  class_addattr(c, attr);
130 
131  // Setup our class to work with MSP
132  class_dspinit(c);
133 
134  // Finalize our class
135  class_register(CLASS_BOX, c);
136  s_audiosend_class = c;
137 }
138 
139 
140 /************************************************************************************/
141 // Object Life
142 
143 // Create
144 void *audiosend_new(t_symbol *s, long argc, t_atom *argv)
145 {
146  long attrstart = attr_args_offset(argc, argv); // support normal arguments
147  t_audiosend *x = (t_audiosend *)object_alloc(s_audiosend_class);
148  short i;
149 
150  if (x) {
151  x->dumpout = outlet_new(x, NULL);
152  object_obex_store(x, _sym_dumpout, (t_object *)x->dumpout);
153 
154  x->attr_target = _sym_nothing;
155  x->num_inputs = 2; // TODO: make this dynamic from args
156 
157  for (i=0; i<attrstart; i++) {
158  if (argv[i].a_type == A_LONG)
159  x->num_inputs = atom_getlong(argv+i);
160  else if (argv[i].a_type == A_SYM)
161  x->attr_target = atom_getsym(argv+i);
162  }
163 
164  dsp_setup((t_pxobject *)x, x->num_inputs);
165  x->obj.z_misc = Z_NO_INPLACE;
166  attr_args_process(x, argc, argv); // handle attribute args
167  }
168  return x;
169 }
170 
171 
172 void audiosend_free(t_audiosend *x)
173 {
174  dsp_free((t_pxobject *)x);
175 }
176 
177 
178 /************************************************************************************/
179 // Methods bound to input/inlets
180 
181 // Method for Assistance Messages
182 void audiosend_assist(t_audiosend *x, void *b, long msg, long arg, char *dst)
183 {
184  if (msg==1) // Inlets
185  strcpy(dst, "input to send to a named module");
186  else if (msg==2) // Outlets
187  strcpy(dst, "dumpout");
188 }
189 
190 
191 void audiosend_bang(t_audiosend *x)
192 {
193  t_atom a[2];
194  t_symbol **moduleNames = NULL;
195  long numModules = 0;
196  long i;
197 
198  jamoma_get_all_module_names(&numModules, &moduleNames);
199 
200  atom_setsym(a+0, SymbolGen("clear"));
201  outlet_anything(x->dumpout, SymbolGen("menu"), 1, a);
202 
203  atom_setsym(a+0, SymbolGen("append"));
204  for (i=0; i<numModules; i++) {
205  atom_setsym(a+1, moduleNames[i]);
206  outlet_anything(x->dumpout, SymbolGen("menu"), 2, a);
207  }
208  if (moduleNames)
209  sysmem_freeptr(moduleNames);
210 }
211 
212 
213 t_int* audiosend_perform(t_int *w)
214 {
215  t_audiosend *x = (t_audiosend*)(w[1]);
216 
217  object_method(x->obj_direct_target, SymbolGen("remoteaudio"), x->audio_in, (long)(w[2]));
218  return(w+3);
219 }
220 
221 
222 void audiosend_dsp(t_audiosend *x, t_signal **sp, short *count)
223 {
224  long numInputs = x->num_inputs;
225  short i, j;
226  t_object *hub;
227 
228  if (x->attr_target && x->attr_target != _sym_nothing) {
229  hub = jamoma_get_hub_for_module_named(x->attr_target);
230  if (hub != x->obj_target) {
231  if (hub) {
232  x->obj_target = hub;
233  // we could attach to the hub here to listen for free notifications
234  // but freeing it will restart the dsp anyway, so I don't think there is any need [tap]
235  x->obj_direct_target = (t_object*)object_method(hub, SymbolGen("getobj_audioin"));
236  }
237  }
238  if (x->obj_target) {
239  for (i=0, j=0; i<numInputs; i++) {
240  if (count[i])
241  j=i;
242  x->audio_in[i] = (t_float*)sp[i]->s_vec;
243  }
244  numInputs = j+1;
245 
246  dsp_add(audiosend_perform, 2, x, numInputs);
247  }
248  }
249 }
250 
251 
252 /************************************************************************************/
253 
254 t_max_err audiosend_attr_settarget(t_audiosend *x, void *attr, long argc, t_atom *argv)
255 {
256  t_object *hub;
257 
258  x->attr_target = atom_getsym(argv);
259  hub = jamoma_get_hub_for_module_named(x->attr_target);
260  if (hub) {
261  x->obj_target = hub;
262  x->obj_direct_target = (t_object*)object_method(hub, SymbolGen("getobj_audioin"));
263  }
264  return MAX_ERR_NONE;
265 }
void audiosend_free(t_audiosend *x)
Free up and dispose of the object.
Definition: j.send~.cpp:172
void audiosend_bang(t_audiosend *x)
When banged, fill a menu with potential targets.
Definition: j.send~.cpp:191
void audiosend_assist(t_audiosend *x, void *b, long msg, long arg, char *dst)
Method for displaying assist strings for inlets and outlets.
Definition: j.send~.cpp:182
t_max_err audiosend_attr_settarget(t_audiosend *x, void *attr, long argc, t_atom *argv)
Set the hub of the module we are sending to as an attribute.
Definition: j.send~.cpp:254
void * audiosend_new(t_symbol *s, long argc, t_atom *argv)
Called at object instantiation.
Definition: j.send~.cpp:144
t_int * audiosend_perform(t_int *w)
Audio perform method for the object.
Definition: j.send~.cpp:213
void audiosend_dsp(t_audiosend *x, t_signal **sp, short *count)
The DSP method for the object, called when compiling the audio chain.
Definition: j.send~.cpp:222