CSL 5.2

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

OSC_support.cpp
Go to the documentation of this file.
1 //
2 // OSC_support.cpp -- CSL support functions for use with OSC input.
3 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
4 //
5 // This file has a bunch of the "glue" code necessary to use OSC simply from within CSL.
6 // For an example, see OSC_main.cpp (which uses CSL instruymkents) GestureSensorTests.cpp,
7 // which interfaces to the CREATE gesture sensors using OSC, or Server_Tests.cpp, which
8 // adds a few simple OSC commands for controlling the random bell textures.
9 //
10 // To use this in your own main, add the following:
11 // // setup call for OSC addr space mgmnt
12 // initOSCAddrSpace();
13 // // add an OSC command callback
14 // addOSCMethod(mCmd, callback);
15 //
16 // // or use an instrument library
17 // setupOSCInstrLibrary(vector<Instrument *> library);
18 //
19 // // Run the main loop function (doesn't return)
20 // mainOSCLoop(udp_port);
21 //
22 // Functions
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27
28 #include "lo/lo.h"
29
30 #include "BasicFMInstrument.h"
31 //#include "SndFileInstrument.h"
32 //#include "OSC_cpp.h"
33
34 int done = 0;
35
36 void error(int num, const char *m, const char *path);
37 int generic_handler(const char *path, const char *types, lo_arg **argv,
38 int argc, void *data, void *user_data);
39 int foo_handler(const char *path, const char *types, lo_arg **argv, int argc,
40 void *data, void *user_data);
41 int quit_handler(const char *path, const char *types, lo_arg **argv, int argc,
42 void *data, void *user_data);
43
44 #define MAX_ACCESSORS 64 // max number of instrument accessors
45
46 using namespace csl;
47
48 // Prototypes for "glue" code
49
50 extern "C" void initOSCReceive();
51 extern "C" void initOSCAddrSpace();
52 extern "C" void setupOSCInstrLibrary(std::vector<Instrument *> library);
53 #define addOSCMethod(name, nfunction) \
54 lo_server_thread_add_method(sSrvThrd, nname, NULL, nfunction, NULL)
55
56 extern "C" void addOSCMethod2(name, nfunction, void * user_data);
57
58 /* add method that will match the path /foo/bar, with two numbers, coerced
59 * to float and int */
60 lo_server_thread_add_method(sSrvThrd, "/foo/bar", "fi", foo_handler, NULL);
61
62
63 extern "C" void mainOSCLoop(int port);
64 extern "C" void quitCSL();
65
66 // OSC globals
67
68 static lo_server_thread sSrvThrd;
69
70 void error(int num, const char *msg, const char *path)
71 {
72 printf("liblo server error %d in path %s: %s\n", num, path, msg);
73 fflush(stdout);
74 }
75
76 /* catch any incoming messages and display them. returning 1 means that the
77 * message has not been fully handled and the server should try other methods */
78 int generic_handler(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) {
79 int i;
80 printf("path: <%s>\n", path);
81 for (i=0; i<argc; i++) {
82 printf("arg %d '%c' ", i, types[i]);
83 lo_arg_pp(types[i], argv[i]);
84 printf("\n");
85 }
86 printf("\n");
87 fflush(stdout);
88
89 return 1;
90 }
91
92 int foo_handler(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) {
93 /* example showing pulling the argument values out of the argv array */
94 printf("%s <- f:%f, i:%d\n\n", path, argv[0]->f, argv[1]->i);
95 fflush(stdout);
96
97 return 0;
98 }
99
100 int quit_handler(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) {
101 done = 1;
102 printf("quiting\n\n");
103 fflush(stdout);
104 // Shut down and quit
105 logMsg("OSC server exiting.");
106 lo_server_thread_stop(sSrvThrd);
107 IO * io = IO :: theInstance();
108 io->stop(); // stop it
109 io->close();
110 exit(0);
111 }
112
113 // OSC support functions
114
115 // Set up the receive Q
116
117 extern "C" void initOSCReceive() {
118
119 /* start a new server on port 7770 */
120 sSrvThrd = lo_server_thread_new("7770", error);
121 }
122
123 // Main OSC loop -- select - read - dispatch
124
125 extern "C" void mainOSCLoop(int port) {
126 /* add method that will match any path and args */
127 lo_server_thread_add_method(sSrvThrd, NULL, NULL, generic_handler, NULL);
128 /* add method that will match the path /quit with no args */
129 lo_server_thread_add_method(sSrvThrd, "/quit", "", quit_handler, NULL);
130 // start lo!
131 lo_server_thread_start(st);
132
133 while (!done) {
134 #ifdef WIN32
135 Sleep(1);
136 #else
137 usleep(1000);
138 #endif
139 }
140 quit:
141 quitCSL();
142 return 0;
143 }
144
145 /////////////////////////// OSC Helper Functions /////////////////////////////
146
147 // Structure passed to OSC to hold a UGEN reference and a parameter selector
148
149 typedef struct {
150 Instrument * instr;
151 unsigned num;
152 unsigned selector;
153 } Inst_Context;
154
155 // General-purpose type-checking parameter-setter methods for Instruments
156
157 void floatParamSetter(void * con, int arglen, const void * vargs, OSCTimeTag when, NetworkReturnAddressPtr ra) {
158 char * error;
159 Inst_Context * context = (Inst_Context *) con;
160 char * typeString = (char *) vargs;
161 void * otherArgs = (void *) OSCDataAfterAlignedString(typeString, typeString+arglen, &error);
162 if (strcmp(typeString, ",f")) {
163 logMsg(kLogError, "ERROR: Invalid type string in OSC message, expected \",f\" got \"%s\"", typeString);
164 fflush(stdout);
165 return;
166 }
167 logMsg("OSC set float param %d/%d to %g", (context->num + 1), context->selector, ((float *) otherArgs)[0]);
168 fflush(stdout);
169 context->instr->setParameter(context->selector, otherArgs);
170 }
171
172 void intParamSetter(void * con, int arglen, const void * vargs, OSCTimeTag when, NetworkReturnAddressPtr ra) {
173 char * error;
174 Inst_Context * context = (Inst_Context *) con;
175 char * typeString = (char *) vargs;
176 void * otherArgs = (void *) OSCDataAfterAlignedString(typeString, typeString+arglen, &error);
177 if (strcmp(typeString, ",i")) {
178 logMsg(kLogError, "ERROR: Invalid type string in OSC message, expected \",i\" got \"%s\"", typeString);
179 return;
180 }
181 logMsg("OSC set int param %d/%d to %d", (context->num + 1), context->selector, ((int *) otherArgs)[0]);
182 fflush(stdout);
183 context->instr->setParameter(context->selector, otherArgs);
184 }
185
186 void stringParamSetter(void * con, int arglen, const void * vargs, OSCTimeTag when, NetworkReturnAddressPtr ra) {
187 char * error;
188 Inst_Context * context = (Inst_Context *) con;
189 char * typeString = (char *) vargs;
190 void * otherArgs = (void *) OSCDataAfterAlignedString(typeString, typeString+arglen, &error);
191 if (strcmp(typeString, ",s")) {
192 logMsg(kLogError, "ERROR: Invalid type string in OSC message, expected \",s\" got \"%s\"", typeString);
193 return;
194 }
195 logMsg("OSC set string param %d/%d to %s", (context->num + 1), context->selector, (char *) otherArgs);
196 context->instr->setParameter(context->selector, otherArgs);
197 }
198
199 // Play a note by re-triggering the main envelope
200
201 void playNote(void * con, int arglen, const void * vargs, OSCTimeTag when, NetworkReturnAddressPtr ra) {
202 Inst_Context * context = (Inst_Context *) con;
203 logMsg("OSC play_note on instr %d", (context->num + 1));
204 context->instr->play();
205 }
206
207 // Play a note with arguments (passed to the instrument as a void *)
208
209 void playWithArgs(void * con, int arglen, const void * vargs, OSCTimeTag when, NetworkReturnAddressPtr ra) {
210 Inst_Context * context = (Inst_Context *) con;
211 char * error;
212 char * typeString = (char *) vargs;
213 char * endOfArgs = (char *) vargs + arglen;
214 void * otherArgs = OSCDataAfterAlignedString(typeString, typeString+arglen, &error);
215 logMsg("OSC play_with_args on instr %d %s", (context->num + 1), typeString);
216 context->instr->playOSC(typeString, otherArgs, endOfArgs);
217 }
218
219
220 // IOSC setup methods
221
222 extern "C" void initOSCAddrSpace() {
223 }
224
225 extern "C" void addOSCMethod(char * name, OSC_CALL_BACK function ) {
226 }
227
228 extern "C" void addOSCMethod2(char * name, OSC_CALL_BACK function, void * user_data) {
229 }
230
231 // Set up the OSC address space for an instrument library
232
233 extern "C" void setupOSCInstrLibrary(std::vector<Instrument *> library) {
234 char * iname = NULL;
235 Inst_Context * the_context = NULL;
236 unsigned num_instruments = library.size();
237 logMsg("Setting up OSC address space for %d instruments\n", num_instruments);
238
239 // Instrument reader loop
240 for (unsigned i = 0; i < num_instruments; i++) {
241 iname = (char *) malloc(8);
242 sprintf(iname, "i%d", i+1); // create container for instrument
243 temp_cont = OSCNewContainer(iname, OSCTopLevelContainer, &cqinfo);
244 Instrument * instr = library[i]; // get the instrument and its accessors
245 unsigned num_accessors = instr->numAccessors();
246 AccessorVector accs = instr->getAccessors();
247 logMsg("Adding instrument \"%s\" (%s); %d accessors", iname, instr->name().c_str(), num_accessors);
248
249 // Accessor method creation loop
250 for (unsigned j = 0; j < num_accessors; j++) {
251 the_context = (Inst_Context *) malloc(sizeof(Inst_Context));
252 the_context->instr = instr;
253 the_context->num = i;
254 the_context->selector = accs[j]->mSelector;
255 // if (i == 0)
256 // printf("\tAdding OSC method for %s (%d)\n", accessors[j]->name, accessors[j]->selector);
257 switch(accs[j]->mType) {
258 case CSL_INT_TYPE:
259 OSCNewMethod(accs[j]->mName.c_str(), temp_cont, intParamSetter, the_context, &QueryResponseInfo);
260 break;
261 case CSL_FLOAT_TYPE:
262 OSCNewMethod(accs[j]->mName.c_str(), temp_cont, floatParamSetter, the_context, &QueryResponseInfo);
263 break;
264 case CSL_STRING_TYPE:
265 OSCNewMethod(accs[j]->mName.c_str(), temp_cont, stringParamSetter, the_context, &QueryResponseInfo);
266 }
267 }
268 OSCNewMethod("p", temp_cont, playNote, the_context, &QueryResponseInfo);
269 OSCNewMethod("pn", temp_cont, playWithArgs, the_context, &QueryResponseInfo);
270 }
271 fflush(stdout);
272 //Debugging
273 // printf("\nPrinting whole address space as published\n");
274 // OSCPrintWholeAddressSpace();
275 }