1 /*----------------------------------------------------------------------------
2 ChucK Concurrent, On-the-fly Audio Programming Language
3 Compiler and Virtual Machine
5 Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6 http://chuck.cs.princeton.edu/
7 http://soundlab.cs.princeton.edu/
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
26 // file: ulib_opsc.cpp
29 // author: Philip L. Davidson (philipd@alumni.princeton.edu)
30 // Ge Wang (gewang@cs.princeton.edu)
31 // Perry R. Cook (prc@cs.princeton.edu)
33 //-----------------------------------------------------------------------------
34 #include "ulib_opsc.h"
35 #include "chuck_type.h"
38 #include "util_opsc.h"
39 #include "chuck_instr.h"
41 static t_CKUINT osc_send_offset_data
= 0;
42 static t_CKUINT osc_recv_offset_data
= 0;
43 static t_CKUINT osc_address_offset_data
= 0;
44 static Chuck_Type
* osc_addr_type_ptr
= 0;
46 DLL_QUERY
opensoundcontrol_query ( Chuck_DL_Query
* query
) {
49 Chuck_Env
* env
= Chuck_Env::instance();
50 Chuck_DL_Func
* func
= NULL
;
53 if( !type_engine_import_class_begin( env
, "OscSend", "Object",
54 env
->global(), osc_send_ctor
,
58 // add member variable - OSCTransmitter object
59 osc_send_offset_data
= type_engine_import_mvar( env
, "int", "@OscSend_data", FALSE
);
60 if( osc_send_offset_data
== CK_INVALID_OFFSET
) goto error
;
62 func
= make_new_mfun( "int", "setHost", osc_send_setHost
);
63 func
->add_arg( "string", "address" );
64 func
->add_arg( "int", "port" );
65 if( !type_engine_import_mfun( env
, func
) ) goto error
;
67 func
= make_new_mfun( "int", "startMsg", osc_send_startMesg
);
68 func
->add_arg( "string", "address" );
69 func
->add_arg( "string", "args" );
70 if( !type_engine_import_mfun( env
, func
) ) goto error
;
72 func
= make_new_mfun( "int", "startMsg", osc_send_startMesg_spec
);
73 func
->add_arg( "string", "spec" );
74 if( !type_engine_import_mfun( env
, func
) ) goto error
;
76 func
= make_new_mfun( "int", "addInt", osc_send_addInt
);
77 func
->add_arg( "int", "value" );
78 if( !type_engine_import_mfun( env
, func
) ) goto error
;
80 func
= make_new_mfun( "float", "addFloat", osc_send_addFloat
);
81 func
->add_arg( "float", "value" );
82 if( !type_engine_import_mfun( env
, func
) ) goto error
;
84 func
= make_new_mfun( "string", "addString", osc_send_addString
);
85 func
->add_arg( "string", "value" );
86 if( !type_engine_import_mfun( env
, func
) ) goto error
;
88 func
= make_new_mfun( "int", "openBundle", osc_send_openBundle
);
89 func
->add_arg( "time", "value" );
90 if( !type_engine_import_mfun( env
, func
) ) goto error
;
92 func
= make_new_mfun( "int", "closeBundle", osc_send_closeBundle
);
93 if( !type_engine_import_mfun( env
, func
) ) goto error
;
95 func
= make_new_mfun( "int", "hold", osc_send_holdMesg
);
96 func
->add_arg( "int", "on" );
97 if( !type_engine_import_mfun( env
, func
) ) goto error
;
99 func
= make_new_mfun( "int", "kick", osc_send_kickMesg
);
100 if( !type_engine_import_mfun( env
, func
) ) goto error
;
102 type_engine_import_class_end( env
);
105 if( !type_engine_import_class_begin( env
, "OscEvent", "Event",
106 env
->global(), osc_address_ctor
,
110 // add member variable - OSCAddress object
112 osc_address_offset_data
= type_engine_import_mvar( env
, "int", "@OscEvent_Data", FALSE
);
113 if( osc_recv_offset_data
== CK_INVALID_OFFSET
) goto error
;
115 // keep type around for initialization ( so other classes can return it )
117 osc_addr_type_ptr
= env
->class_def
;
119 func
= make_new_mfun( "int", "set", osc_address_set
);
120 func
->add_arg( "string" , "addr" );
121 if( !type_engine_import_mfun( env
, func
) ) goto error
;
123 func
= make_new_mfun( "int", "hasMsg", osc_address_has_mesg
);
124 if( !type_engine_import_mfun( env
, func
) ) goto error
;
126 func
= make_new_mfun( "int", "nextMsg", osc_address_next_mesg
);
127 if( !type_engine_import_mfun( env
, func
) ) goto error
;
129 func
= make_new_mfun( "int", "getInt", osc_address_next_int
);
130 if( !type_engine_import_mfun( env
, func
) ) goto error
;
132 func
= make_new_mfun( "float", "getFloat", osc_address_next_float
);
133 if( !type_engine_import_mfun( env
, func
) ) goto error
;
135 func
= make_new_mfun( "string", "getString", osc_address_next_string
);
136 if( !type_engine_import_mfun( env
, func
) ) goto error
;
138 func
= make_new_mfun( "int", "can_wait", osc_address_can_wait
);
139 if( !type_engine_import_mfun( env
, func
) ) goto error
;
141 type_engine_import_class_end( env
);
144 if( !type_engine_import_class_begin( env
, "OscRecv", "Object",
145 env
->global(), osc_recv_ctor
,
149 // add member variable - OSCReceiver object
150 osc_recv_offset_data
= type_engine_import_mvar( env
, "int", "@OscRecv_data", FALSE
);
151 if( osc_recv_offset_data
== CK_INVALID_OFFSET
) goto error
;
153 func
= make_new_mfun( "int", "port", osc_recv_port
);
154 func
->add_arg( "int" , "port" );
155 if( !type_engine_import_mfun( env
, func
) ) goto error
;
157 func
= make_new_mfun( "int", "listen", osc_recv_listen_port
);
158 func
->add_arg( "int" , "port" );
159 if( !type_engine_import_mfun( env
, func
) ) goto error
;
161 func
= make_new_mfun( "int", "listen", osc_recv_listen
);
162 if( !type_engine_import_mfun( env
, func
) ) goto error
;
164 func
= make_new_mfun( "int", "stop", osc_recv_listen_stop
);
165 if( !type_engine_import_mfun( env
, func
) ) goto error
;
167 func
= make_new_mfun( "int", "add_address", osc_recv_add_address
);
168 func
->add_arg( "OscEvent" , "addr" );
169 if( !type_engine_import_mfun( env
, func
) ) goto error
;
171 func
= make_new_mfun( "int", "remove_address", osc_recv_remove_address
);
172 func
->add_arg( "OscEvent" , "addr" );
173 if( !type_engine_import_mfun( env
, func
) ) goto error
;
175 func
= make_new_mfun( "OscEvent", "event", osc_recv_new_address
);
176 func
->add_arg( "string" , "spec" );
177 if( !type_engine_import_mfun( env
, func
) ) goto error
;
179 func
= make_new_mfun( "OscEvent", "event", osc_recv_new_address_type
);
180 func
->add_arg( "string" , "address" );
181 func
->add_arg( "string" , "type" );
182 if( !type_engine_import_mfun( env
, func
) ) goto error
;
184 func
= make_new_mfun( "OscEvent", "address", osc_recv_new_address
);
185 func
->add_arg( "string" , "spec" );
186 if( !type_engine_import_mfun( env
, func
) ) goto error
;
188 func
= make_new_mfun( "OscEvent", "address", osc_recv_new_address_type
);
189 func
->add_arg( "string" , "address" );
190 func
->add_arg( "string" , "type" );
191 if( !type_engine_import_mfun( env
, func
) ) goto error
;
193 type_engine_import_class_end( env
);
198 fprintf( stderr
, "class import error!\n" );
199 // end the class import
200 type_engine_import_class_end( env
);
204 //----------------------------------------------
205 // name : osc_send_ctor
206 // desc : CTOR function
207 //-----------------------------------------------
208 CK_DLL_CTOR( osc_send_ctor
) {
209 OSC_Transmitter
* xmit
= new OSC_Transmitter();
210 OBJ_MEMBER_INT( SELF
, osc_send_offset_data
) = (t_CKINT
)xmit
;
213 //----------------------------------------------
214 // name : osc_send_dtor
215 // desc : DTOR function
216 //-----------------------------------------------
217 CK_DLL_DTOR( osc_send_dtor
) {
218 OSC_Transmitter
* xmit
= (OSC_Transmitter
*)OBJ_MEMBER_INT(SELF
, osc_send_offset_data
);
220 OBJ_MEMBER_UINT(SELF
, osc_send_offset_data
) = 0;
223 //----------------------------------------------
224 // name : osc_send_setHost
225 // desc : MFUN function
226 //-----------------------------------------------
227 CK_DLL_MFUN( osc_send_setHost
) {
228 OSC_Transmitter
* xmit
= (OSC_Transmitter
*)OBJ_MEMBER_INT(SELF
, osc_send_offset_data
);
229 Chuck_String
* host
= GET_NEXT_STRING(ARGS
);
230 t_CKINT port
= GET_NEXT_INT(ARGS
);
231 xmit
->setHost( (char*) host
->str
.c_str(), port
);
234 //----------------------------------------------
235 // name : osc_send_startMesg
236 // desc : MFUN function
237 //-----------------------------------------------
238 CK_DLL_MFUN( osc_send_startMesg
) {
239 OSC_Transmitter
* xmit
= (OSC_Transmitter
*)OBJ_MEMBER_INT(SELF
, osc_send_offset_data
);
240 Chuck_String
* address
= GET_NEXT_STRING(ARGS
);
241 Chuck_String
* args
= GET_NEXT_STRING(ARGS
);
242 xmit
->startMessage( (char*) address
->str
.c_str(), (char*) args
->str
.c_str() );
245 //----------------------------------------------
246 // name : osc_send_startMesg
247 // desc : MFUN function
248 //-----------------------------------------------
249 CK_DLL_MFUN( osc_send_startMesg_spec
) {
250 OSC_Transmitter
* xmit
= (OSC_Transmitter
*)OBJ_MEMBER_INT(SELF
, osc_send_offset_data
);
251 Chuck_String
* spec
= GET_NEXT_STRING(ARGS
);
252 xmit
->startMessage( (char*) spec
->str
.c_str() );
255 //----------------------------------------------
256 // name : osc_send_addInt
257 // desc : MFUN function
258 //-----------------------------------------------
259 CK_DLL_MFUN( osc_send_addInt
) {
260 OSC_Transmitter
* xmit
= (OSC_Transmitter
*)OBJ_MEMBER_INT(SELF
, osc_send_offset_data
);
261 xmit
->addInt( GET_NEXT_INT(ARGS
) );
264 //----------------------------------------------
265 // name : osc_send_addFloat
266 // desc : MFUN function
267 //-----------------------------------------------
268 CK_DLL_MFUN( osc_send_addFloat
) {
269 OSC_Transmitter
* xmit
= (OSC_Transmitter
*)OBJ_MEMBER_INT(SELF
, osc_send_offset_data
);
270 xmit
->addFloat( (float)(GET_NEXT_FLOAT(ARGS
)) );
273 //----------------------------------------------
274 // name : osc_send_addString
275 // desc : MFUN function
276 //-----------------------------------------------
277 CK_DLL_MFUN( osc_send_addString
) {
278 OSC_Transmitter
* xmit
= (OSC_Transmitter
*)OBJ_MEMBER_INT(SELF
, osc_send_offset_data
);
279 xmit
->addString( (char*)(GET_NEXT_STRING(ARGS
))->str
.c_str() );
282 //----------------------------------------------
283 // name : osc_send_openBundle
284 // desc : MFUN function
285 //-----------------------------------------------
286 CK_DLL_MFUN( osc_send_openBundle
) {
287 OSC_Transmitter
* xmit
= (OSC_Transmitter
*)OBJ_MEMBER_INT(SELF
, osc_send_offset_data
);
288 // we should add in an option to translate from chuck-time to current time to timetag.
289 // but for now let's just spec. immediately.
290 xmit
->openBundle(OSCTT_Immediately());
293 //----------------------------------------------
294 // name : osc_send_closeBundle
295 // desc : MFUN function
296 //-----------------------------------------------
297 CK_DLL_MFUN( osc_send_closeBundle
) {
298 OSC_Transmitter
* xmit
= (OSC_Transmitter
*)OBJ_MEMBER_INT(SELF
, osc_send_offset_data
);
302 //----------------------------------------------
303 // name : osc_send_holdMesg
304 // desc : MFUN function
305 //-----------------------------------------------
306 CK_DLL_MFUN( osc_send_holdMesg
) {
307 OSC_Transmitter
* xmit
= (OSC_Transmitter
*)OBJ_MEMBER_INT(SELF
, osc_send_offset_data
);
308 xmit
->holdMessage( GET_NEXT_INT(ARGS
) != 0 );
311 //----------------------------------------------
312 // name : osc_send_kickMesg
313 // desc : MFUN function
314 //-----------------------------------------------
315 CK_DLL_MFUN( osc_send_kickMesg
) {
316 OSC_Transmitter
* xmit
= (OSC_Transmitter
*)OBJ_MEMBER_INT(SELF
, osc_send_offset_data
);
320 //----------------------------------------------
321 // name : osc_address_ctor
322 // desc : CTOR function
323 //-----------------------------------------------
324 CK_DLL_CTOR( osc_address_ctor
) {
325 OSC_Address_Space
* addr
= new OSC_Address_Space();
327 // fprintf(stderr,"address:ptr %x\n", (uint)addr);
328 // fprintf(stderr,"self:ptr %x\n", (uint)SELF);
329 OBJ_MEMBER_INT(SELF
, osc_address_offset_data
) = (t_CKINT
)addr
;
332 CK_DLL_DTOR( osc_address_dtor
) {
333 delete (OSC_Address_Space
*)OBJ_MEMBER_UINT(SELF
, osc_address_offset_data
);
334 OBJ_MEMBER_UINT(SELF
, osc_address_offset_data
) = 0;
337 CK_DLL_MFUN( osc_address_set
) {
338 OSC_Address_Space
* addr
= (OSC_Address_Space
*)OBJ_MEMBER_INT( SELF
, osc_address_offset_data
);
339 addr
->setSpec ( (char*)(GET_NEXT_STRING(ARGS
))->str
.c_str() );
343 //----------------------------------------------
344 // name : osc_address_can_wait
345 // desc : MFUN function
346 //-----------------------------------------------
347 CK_DLL_MFUN( osc_address_can_wait
) {
348 OSC_Address_Space
* addr
= (OSC_Address_Space
*)OBJ_MEMBER_INT( SELF
, osc_address_offset_data
);
349 RETURN
->v_int
= ( addr
->has_mesg() ) ? 0 : 1;
352 //----------------------------------------------
353 // name : osc_address_has_mesg
354 // desc : MFUN function
355 //-----------------------------------------------
356 CK_DLL_MFUN( osc_address_has_mesg
) {
357 OSC_Address_Space
* addr
= (OSC_Address_Space
*)OBJ_MEMBER_INT( SELF
, osc_address_offset_data
);
358 RETURN
->v_int
= ( addr
->has_mesg() ) ? 1 : 0 ;
361 //----------------------------------------------
362 // name : osc_address_next_mesg
363 // desc : MFUN function
364 //-----------------------------------------------
365 CK_DLL_MFUN( osc_address_next_mesg
) {
366 OSC_Address_Space
* addr
= (OSC_Address_Space
*)OBJ_MEMBER_INT( SELF
, osc_address_offset_data
);
367 RETURN
->v_int
= ( addr
->next_mesg() ) ? 1 : 0 ;
370 //----------------------------------------------
371 // name : osc_address_next_int
372 // desc : MFUN function
373 //-----------------------------------------------
374 CK_DLL_MFUN( osc_address_next_int
) {
375 OSC_Address_Space
* addr
= (OSC_Address_Space
*)OBJ_MEMBER_INT( SELF
, osc_address_offset_data
);
376 RETURN
->v_int
= addr
->next_int();
379 //----------------------------------------------
380 // name : osc_address_next_float
381 // desc : MFUN function
382 //-----------------------------------------------
383 CK_DLL_MFUN( osc_address_next_float
) {
384 OSC_Address_Space
* addr
= (OSC_Address_Space
*)OBJ_MEMBER_INT( SELF
, osc_address_offset_data
);
385 RETURN
->v_float
= addr
->next_float();
388 //----------------------------------------------
389 // name : osc_address_next_string
390 // desc : MFUN function
391 //-----------------------------------------------
392 CK_DLL_MFUN( osc_address_next_string
) {
393 OSC_Address_Space
* addr
= (OSC_Address_Space
*)OBJ_MEMBER_INT( SELF
, osc_address_offset_data
);
394 char * cs
= addr
->next_string();
395 Chuck_String
* ckstr
= ( cs
) ? new Chuck_String ( cs
) : new Chuck_String("");
396 initialize_object( ckstr
, &t_string
);
397 RETURN
->v_string
= ckstr
;
403 //----------------------------------------------
404 // name : osc_recv_ctor
405 // desc : CTOR function
406 //-----------------------------------------------
407 CK_DLL_CTOR( osc_recv_ctor
) {
408 OSC_Receiver
* recv
= new OSC_Receiver();
409 OBJ_MEMBER_INT( SELF
, osc_send_offset_data
) = (t_CKINT
)recv
;
412 //----------------------------------------------
413 // name : osc_recv_dtor
414 // desc : DTOR function
415 //-----------------------------------------------
416 CK_DLL_DTOR( osc_recv_dtor
) {
417 OSC_Receiver
* recv
= (OSC_Receiver
*)OBJ_MEMBER_INT(SELF
, osc_recv_offset_data
);
419 OBJ_MEMBER_INT(SELF
, osc_recv_offset_data
) = 0;
422 //----------------------------------------------
423 // name : osc_recv_port
424 // desc : specify port to listen on
425 //-----------------------------------------------
426 CK_DLL_MFUN( osc_recv_port
) {
428 OSC_Receiver
* recv
= (OSC_Receiver
*)OBJ_MEMBER_INT(SELF
, osc_recv_offset_data
);
429 recv
->bind_to_port( (int)GET_NEXT_INT(ARGS
) );
432 // need to add a listen function in Receiver which opens up a recv loop on another thread.
433 // address then subscribe to a receiver to take in events.
435 //----------------------------------------------
436 // name : osc_recv_listen
437 // desc : start listening
438 //-----------------------------------------------
439 CK_DLL_MFUN( osc_recv_listen
) {
440 OSC_Receiver
* recv
= (OSC_Receiver
*)OBJ_MEMBER_INT(SELF
, osc_recv_offset_data
);
444 //----------------------------------------------
445 // name : osc_recv_listen_port
446 // desc : listen to a given port ( disconnects from current )
447 //-----------------------------------------------
448 CK_DLL_MFUN( osc_recv_listen_port
) {
449 OSC_Receiver
* recv
= (OSC_Receiver
*)OBJ_MEMBER_INT(SELF
, osc_recv_offset_data
);
450 recv
->listen((int)GET_NEXT_INT(ARGS
));
453 //----------------------------------------------
454 // name : osc_recv_listen_port
455 // desc : listen to a given port ( disconnects from current )
456 //-----------------------------------------------
457 CK_DLL_MFUN( osc_recv_listen_stop
) {
458 OSC_Receiver
* recv
= (OSC_Receiver
*)OBJ_MEMBER_INT(SELF
, osc_recv_offset_data
);
459 recv
->stopListening();
462 //----------------------------------------------
463 // name : osc_recv_add_listener
464 // desc : MFUN function
465 //-----------------------------------------------
466 CK_DLL_MFUN( osc_recv_add_address
) {
467 OSC_Receiver
* recv
= (OSC_Receiver
*)OBJ_MEMBER_INT(SELF
, osc_recv_offset_data
);
468 Chuck_Object
* addr_obj
= GET_NEXT_OBJECT(ARGS
); //address object class...
469 OSC_Address_Space
* addr
= (OSC_Address_Space
*)OBJ_MEMBER_INT( addr_obj
, osc_address_offset_data
);
470 recv
->add_address( addr
);
473 //----------------------------------------------
474 // name : osc_recv_remove_listener
475 // desc : MFUN function
476 //-----------------------------------------------
477 CK_DLL_MFUN( osc_recv_remove_address
) {
478 OSC_Receiver
* recv
= (OSC_Receiver
*)OBJ_MEMBER_INT(SELF
, osc_recv_offset_data
);
479 Chuck_Object
* addr_obj
= GET_NEXT_OBJECT(ARGS
); //listener object class...
480 OSC_Address_Space
* addr
= (OSC_Address_Space
*)OBJ_MEMBER_INT( addr_obj
, osc_address_offset_data
);
481 recv
->remove_address( addr
);
484 //----------------------------------------------
485 // name : osc_recv_new_address
486 // desc : MFUN function
487 //-----------------------------------------------
488 CK_DLL_MFUN( osc_recv_new_address
) {
489 OSC_Receiver
* recv
= (OSC_Receiver
*)OBJ_MEMBER_INT(SELF
, osc_recv_offset_data
);
490 Chuck_String
* spec_obj
= (Chuck_String
*) GET_NEXT_STRING(ARGS
); //listener object class...
492 OSC_Address_Space
* new_addr_obj
= recv
->new_event ( (char*)spec_obj
->str
.c_str() );
494 /* wolf in sheep's clothing
495 initialize_object( new_addr_obj , osc_addr_type_ptr ); //initialize in vm
496 new_addr_obj->SELF = new_addr_obj;
497 OBJ_MEMBER_INT( new_addr_obj, osc_address_offset_data ) = (t_CKINT)new_addr_obj;
501 Chuck_Event
* new_event_obj
= new Chuck_Event();
502 initialize_object( new_event_obj
, osc_addr_type_ptr
);
503 new_addr_obj
->SELF
= new_event_obj
;
504 OBJ_MEMBER_INT( new_event_obj
, osc_address_offset_data
) = (t_CKINT
)new_addr_obj
;
506 RETURN
->v_object
= new_event_obj
;
511 //----------------------------------------------
512 // name : osc_recv_new_address
513 // desc : MFUN function
514 //-----------------------------------------------
515 CK_DLL_MFUN( osc_recv_new_address_type
) {
516 OSC_Receiver
* recv
= (OSC_Receiver
*)OBJ_MEMBER_INT(SELF
, osc_recv_offset_data
);
517 Chuck_String
* addr_obj
= (Chuck_String
*) GET_NEXT_STRING(ARGS
); //listener object class...
518 Chuck_String
* type_obj
= (Chuck_String
*) GET_NEXT_STRING(ARGS
); //listener object class...
520 OSC_Address_Space
* new_addr_obj
= recv
->new_event ( (char*)addr_obj
->str
.c_str(), (char*)type_obj
->str
.c_str() );
522 /* wolf in sheep's clothing
523 initialize_object( new_addr_obj , osc_addr_type_ptr ); //initialize in vm
524 new_addr_obj->SELF = new_addr_obj;
525 OBJ_MEMBER_INT( new_addr_obj, osc_address_offset_data ) = (t_CKINT)new_addr_obj;
529 Chuck_Event
* new_event_obj
= new Chuck_Event();
530 initialize_object( new_event_obj
, osc_addr_type_ptr
);
531 new_addr_obj
->SELF
= new_event_obj
;
532 OBJ_MEMBER_INT( new_event_obj
, osc_address_offset_data
) = (t_CKINT
)new_addr_obj
;
534 RETURN
->v_object
= new_event_obj
;