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 via LibLo
3 //
4 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
5 //
6 // This file has a bunch of the "glue" code necessary to use OSC simply from within CSL.
7 // For an example, see OSC_main.cpp (which uses CSL instruymkents) GestureSensorTests.cpp,
8 // which interfaces to the CREATE gesture sensors using OSC, or Server_Tests.cpp, which
9 // adds a few simple OSC commands for controlling the random bell textures.
10 //
11
12
13 #include "OSC_support.h"
14
15 #ifdef USE_LOSC // liblo for OSC
16
17 #include "lo/lo.h"
18
19 // OSC globals
20
21 static int done = 0; // running flag
22 static lo_server_thread sSrvThrd; // the liblo thread guy
23
24 // error logger
25
26 void osc_error(int num, const char *msg, const char *path) {
27 logMsg(kLogError, "OSC server error %d in path %s: %s\n", num, path, msg);
28 }
29
30 // Shut down and quit
31
32 void quitCSL() {
33 done = 1;
34 logMsg("OSC server exiting.");
35 lo_server_thread_stop(sSrvThrd);
36 }
37
38 int quit_handler(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) {
39 quitCSL();
40 return 0;
41 }
42
43 // catch any incoming messages and display them
44
45 int generic_handler(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) {
46 logMsg("OSC message: <%s>", path);
47 for (unsigned i=0; i<argc; i++) {
48 printf("\t\targ %d '%c' ", i, types[i]);
49 lo_arg_pp((lo_type)types[i], argv[i]);
50 printf("\n");
51 }
52 printf("\n");
53 fflush(stdout);
54 return 1;
55 }
56
57 // Set up the LibLo OSC thread
58
59 extern "C" void initOSC(const char * thePort) {
60 logMsg("initOSC");
61 sSrvThrd = lo_server_thread_new(thePort, osc_error);
62 #ifdef CSL_DEBUG // add method that will match any path and args
63 lo_server_thread_add_method(sSrvThrd, NULL, NULL, generic_handler, NULL);
64 #endif // add method that will match the path /q with no args and exit
65 lo_server_thread_add_method(sSrvThrd, "/q", "", quit_handler, NULL);
66 }
67
68 // Main OSC loop -- select - read - dispatch
69
70 extern "C" void * mainOSCLoop(void * arg) {
71 logMsg("mainOSCLoop starting");
72 lo_server_thread_start(sSrvThrd); // start lo!
73 done = 0;
74 while (!done)
75 sleepSec(0.5);
76 logMsg("mainOSCLoop returning");
77 return NULL;
78 }
79
80 // Structure passed to OSC to hold a UGEN reference and a parameter selector
81
82 typedef struct {
83 Instrument * instr;
84 unsigned num;
85 unsigned selector;
86 } Inst_Context;
87
88 // General-purpose type-checking parameter-setter methods for Instruments
89
90 int paramSetter(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) {
91 Inst_Context * context = (Inst_Context *) user_data;
92 // logMsg("OSC set %d/%d to (%d : %s) %g", (context->num + 1), context->selector, argc, types, ((float *) argv)[0]);
93 context->instr->setParameter(context->selector, argc, (void **)argv, types);
94 return 0;
95 }
96
97 // Play a note by re-triggering the main envelope
98
99 int playNote(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) {
100 Inst_Context * context = (Inst_Context *) user_data;
101 logMsg("OSC playNote on instr %d", (context->num + 1));
102 context->instr->play();
103 return 0;
104 }
105
106 // Play a note with arguments (passed to the instrument as a void *)
107
108 int playWithArgs(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) {
109 Inst_Context * context = (Inst_Context *) user_data;
110 // logMsg("OSC play_with_args on instr %d %s", (context->num + 1), types);
111 context->instr->playOSC(argc, (void **) argv, types);
112 return 0;
113 }
114
115 // Set up the OSC address space for an instrument library
116
117 extern "C" void setupOSCInstrLibrary(InstrumentVector library) {
118 char iname[16];
119 Inst_Context * the_context = NULL;
120 unsigned num_instruments = library.size();
121 logMsg("Setting up OSC address space for %d instruments", num_instruments);
122 // Instrument reader loop
123 for (unsigned i = 0; i < num_instruments; i++) {
124 Instrument * instr = library[i]; // get the instrument and its accessors
125 unsigned num_accessors = instr->numAccessors();
126 AccessorVector accs = instr->getAccessors();
127 // logMsg("Adding instrument %d (%s) %d accessors", i + 1, instr->name().c_str(), num_accessors);
128 // Accessor method creation loop
129 for (unsigned j = 0; j < num_accessors; j++) {
130 the_context = (Inst_Context *) malloc(sizeof(Inst_Context));
131 the_context->instr = instr;
132 the_context->num = i;
133 the_context->selector = accs[j]->mSelector;
134 sprintf(iname, "/i%d/%s", i+1, accs[j]->mName.c_str()); // create address
135 #ifdef CSL_DEBUG
136 if (i == 0)
137 logMsg("\t\tAdding OSC method for %s (%d)", iname, accs[j]->mSelector);
138 #endif
139 lo_server_thread_add_method(sSrvThrd, iname, NULL, paramSetter, the_context); // float handles all other formats
140 }
141 sprintf(iname, "/i%d/p", i + 1); // now add play commands
142 lo_server_thread_add_method(sSrvThrd, iname, "", playNote, the_context);
143 sprintf(iname, "/i%d/pn", i + 1);
144 lo_server_thread_add_method(sSrvThrd, iname, NULL, playWithArgs, the_context);
145 }
146 }
147
148 #endif