diff --git a/mixer/src/Mixer.C b/mixer/src/Mixer.C index 7833177..7bc1632 100644 --- a/mixer/src/Mixer.C +++ b/mixer/src/Mixer.C @@ -92,28 +92,28 @@ OSC_HANDLER( add_strip ) return 0; } -OSC_HANDLER( finger ) -{ - OSC_DMSG(); +void +Mixer::reply_to_finger ( lo_message msg ) +{ + int argc = lo_message_get_argc( msg ); + lo_arg **argv = lo_message_get_argv( msg ); - OSC::Endpoint *ep = ((OSC::Endpoint*)user_data); - - lo_address reply = lo_address_new_from_url( &argv[0]->s ); - - ep->send( reply, - "/reply", - path, - ep->url(), - APP_NAME, - VERSION, - instance_name ); + if ( argc < 2 ) + return; - lo_address_free( reply ); + lo_address to = lo_address_new_from_url( &argv[1]->s ); - return 0; + osc_endpoint->send( to, + "/reply", + "/non/finger", + osc_endpoint->url(), + APP_NAME, + VERSION, + instance_name ); + + lo_address_free( to ); } - static @@ -383,13 +383,14 @@ Mixer::init_osc ( const char *osc_port ) printf( "OSC=%s\n", osc_endpoint->url() ); - osc_endpoint->add_method( "/non/finger", "s", OSC_NAME( finger ), osc_endpoint, "" ); osc_endpoint->add_method( "/non/mixer/add_strip", "", OSC_NAME( add_strip ), osc_endpoint, "" ); // osc_endpoint->start(); /* poll so we can keep OSC handlers running in the GUI thread and avoid extra sync */ Fl::add_timeout( OSC_INTERVAL, check_osc, this ); + + return 0; } void diff --git a/mixer/src/Mixer.H b/mixer/src/Mixer.H index c967799..9289dbc 100644 --- a/mixer/src/Mixer.H +++ b/mixer/src/Mixer.H @@ -95,6 +95,8 @@ public: static void check_osc ( void * v ); + void reply_to_finger ( lo_message msg ); + void announce ( const char *nash_url, const char *process_name ); int init_osc ( const char* osc_port ); diff --git a/mixer/src/NSM.C b/mixer/src/NSM.C index 081485d..733d2df 100644 --- a/mixer/src/NSM.C +++ b/mixer/src/NSM.C @@ -35,6 +35,22 @@ NSM_Client::NSM_Client ( ) int command_open ( const char *name, const char *display_name, const char *client_id, char **out_msg ); int command_save ( char **out_msg ); +int +NSM_Client::command_broadcast ( lo_message msg ) +{ + int argc = lo_message_get_argc( msg ); + lo_arg **argv = lo_message_get_argv( msg ); + + if ( argc > 1 && !strcmp( &argv[0]->s, "/non/finger" ) ) + { + mixer->reply_to_finger( msg ); + return 0; + } + else + return -1; + +} + int NSM_Client::command_save ( char **out_msg ) diff --git a/mixer/src/NSM.H b/mixer/src/NSM.H index bb62ae8..45942fa 100644 --- a/mixer/src/NSM.H +++ b/mixer/src/NSM.H @@ -35,4 +35,6 @@ protected: int command_save ( char **out_msg ); void command_active ( bool active ); + + int command_broadcast ( lo_message msg ); }; diff --git a/nonlib/NSM/Client.C b/nonlib/NSM/Client.C index ab51b7e..449b01a 100644 --- a/nonlib/NSM/Client.C +++ b/nonlib/NSM/Client.C @@ -121,6 +121,16 @@ namespace NSM } } + + void + Client::broadcast ( const char *path, const char *v1 ) + { + if ( nsm_is_active ) + { + lo_send_from( nsm_addr, _server, LO_TT_IMMEDIATE, "/nsm/server/broadcast", "ss", path, v1 ); + } + } + void Client::check ( int timeout ) { @@ -153,6 +163,8 @@ namespace NSM lo_server_add_method( _server, "/reply", "ssss", &Client::osc_announce_reply, this ); lo_server_add_method( _server, "/nsm/client/open", "sss", &Client::osc_open, this ); lo_server_add_method( _server, "/nsm/client/save", "", &Client::osc_save, this ); + lo_server_add_method( _server, "/nsm/client/session_is_loaded", "", &Client::osc_session_is_loaded, this ); + lo_server_add_method( _server, "/nsm/client/broadcast", NULL, &Client::osc_broadcast, this ); return 0; } @@ -170,7 +182,9 @@ namespace NSM lo_server_thread_add_method( _st, "/reply", "ssss", &Client::osc_announce_reply, this ); lo_server_thread_add_method( _st, "/nsm/client/open", "sss", &Client::osc_open, this ); lo_server_thread_add_method( _st, "/nsm/client/save", "", &Client::osc_save, this ); - + lo_server_thread_add_method( _st, "/nsm/client/session_is_loaded", "", &Client::osc_session_is_loaded, this ); + lo_server_thread_add_method( _st, "/nsm/client/broadcast", NULL, &Client::osc_broadcast, this ); + return 0; } @@ -178,6 +192,12 @@ namespace NSM /* OSC Message Handlers */ /************************/ + int + Client::osc_broadcast ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) + { + return ((NSM::Client*)user_data)->command_broadcast( msg ); + } + int Client::osc_save ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) { @@ -244,7 +264,7 @@ namespace NSM return 0; } - + int Client::osc_announce_reply ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) { diff --git a/nonlib/NSM/Client.H b/nonlib/NSM/Client.H index 870777f..299a9d6 100644 --- a/nonlib/NSM/Client.H +++ b/nonlib/NSM/Client.H @@ -65,7 +65,9 @@ namespace NSM void progress ( float f ); void message( int priority, const char *msg ); void announce ( const char *nsm_url, const char *appliction_name, const char *capabilities, const char *process_name ); - + + void broadcast ( const char *path, const char *v1 ); + /* init without threading */ int init ( void ); /* init with threading */ @@ -88,6 +90,9 @@ namespace NSM virtual void command_session_is_loaded ( void ) { } + /* invoked when an unrecognized message is received. Should return 0 if you handled it, -1 otherwise. */ + virtual int command_broadcast ( lo_message msg ) { return -1; } + private: /* osc handlers */ @@ -96,6 +101,7 @@ namespace NSM static int osc_announce_reply ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); static int osc_error ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); static int osc_session_is_loaded ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); + static int osc_broadcast ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); }; }; diff --git a/nonlib/OSC/Endpoint.C b/nonlib/OSC/Endpoint.C index adf4cf3..5c60d31 100644 --- a/nonlib/OSC/Endpoint.C +++ b/nonlib/OSC/Endpoint.C @@ -372,15 +372,15 @@ namespace OSC switch ( ov->type() ) { case 'f': - DMESSAGE( "Adding float %f", ((OSC_Float*)ov)->value() ); +// DMESSAGE( "Adding float %f", ((OSC_Float*)ov)->value() ); lo_message_add_float( m, ((OSC_Float*)ov)->value() ); break; case 'i': - DMESSAGE( "Adding int %i", ((OSC_Int*)ov)->value() ); +// DMESSAGE( "Adding int %i", ((OSC_Int*)ov)->value() ); lo_message_add_int32( m, ((OSC_Int*)ov)->value() ); break; case 's': - DMESSAGE( "Adding string %s", ((OSC_String*)ov)->value() ); +// DMESSAGE( "Adding string %s", ((OSC_String*)ov)->value() ); lo_message_add_string( m, ((OSC_String*)ov)->value() ); break; default: @@ -389,7 +389,7 @@ namespace OSC } } - DMESSAGE( "Path: %s", path ); +// DMESSAGE( "Path: %s", path ); lo_bundle b = lo_bundle_new( LO_TT_IMMEDIATE ); diff --git a/session/src/nsmd.C b/session/src/nsmd.C index 5d10eff..c6b2709 100644 --- a/session/src/nsmd.C +++ b/session/src/nsmd.C @@ -1451,15 +1451,23 @@ OSC_HANDLER( broadcast ) } } + char *sender_url = lo_address_get_url( lo_message_get_source( msg ) ); for ( std::list::iterator i = client.begin(); i != client.end(); ++i ) { - if ( (*i)->addr != lo_message_get_source( msg ) ) + if ( ! (*i)->addr ) + continue; + + char *url = lo_address_get_url( (*i)->addr ); + + if ( strcmp( sender_url, url ) ) { - osc_server->send( (*i)->addr, to_path, new_args ); + osc_server->send( (*i)->addr, "/nsm/client/broadcast", new_args ); } + + free( url ); } /* also relay to attached GUI so that the broadcast can be @@ -1471,6 +1479,8 @@ OSC_HANDLER( broadcast ) osc_server->send( gui_addr, path, new_args ); } + free( sender_url ); + return 0; } diff --git a/timeline/src/NSM.C b/timeline/src/NSM.C index aab2033..937a595 100644 --- a/timeline/src/NSM.C +++ b/timeline/src/NSM.C @@ -81,3 +81,27 @@ NSM_Client::command_open ( const char *name, const char *display_name, const cha return 0; } + +void +NSM_Client::command_session_is_loaded ( void ) +{ + MESSAGE( "NSM says session is loaded." ); + + timeline->discover_peers(); +} + +int +NSM_Client::command_broadcast ( lo_message msg ) +{ + int argc = lo_message_get_argc( msg ); + lo_arg **argv = lo_message_get_argv( msg ); + + if ( argc > 1 && !strcmp( &argv[0]->s, "/non/finger" ) ) + { + timeline->reply_to_finger( msg ); + return 0; + } + else + return -1; + +} diff --git a/timeline/src/NSM.H b/timeline/src/NSM.H index d0e6746..deb4ab8 100644 --- a/timeline/src/NSM.H +++ b/timeline/src/NSM.H @@ -33,4 +33,7 @@ protected: int command_open ( const char *name, const char *display_name, const char *client_id, char **out_msg ); int command_save ( char **out_msg ); + void command_session_is_loaded ( void ); + + int command_broadcast ( lo_message msg ); }; diff --git a/timeline/src/Timeline.C b/timeline/src/Timeline.C index 0395870..0a27811 100644 --- a/timeline/src/Timeline.C +++ b/timeline/src/Timeline.C @@ -1546,3 +1546,89 @@ Timeline::session_manager_name ( void ) { return nsm->session_manager_name(); } + + +/*******/ +/* OSC */ +/*******/ + +const double OSC_INTERVAL = 0.2f; + +void +Timeline::check_osc ( void * v ) +{ + ((Timeline*)v)->osc->check(); + Fl::repeat_timeout( OSC_INTERVAL, &Timeline::check_osc, v ); +} + +int +Timeline::init_osc ( const char *osc_port ) +{ + osc = new OSC::Endpoint(); + + if ( int r = osc->init( osc_port ) ) + return r; + + osc->owner = this; + + printf( "OSC=%s\n", osc->url() ); + + osc->add_method( "/reply", NULL, &Timeline::osc_reply, osc, "" ); + +// osc->start(); + + /* poll so we can keep OSC handlers running in the GUI thread and avoid extra sync */ + Fl::add_timeout( OSC_INTERVAL, &Timeline::check_osc, this ); + + return 0; +} + +int +Timeline::osc_reply ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) +{ + OSC_DMSG(); + + if ( argc >= 5 && !strcmp( &argv[0]->s, "/non/finger" ) ) + { + const char *url = &argv[1]->s; + const char *name = &argv[2]->s; + const char *version = &argv[3]->s; + const char *id = &argv[4]->s; + + MESSAGE( "Discovered OSC peer %s (%s) @ %s with ID \"%s\"", name, version, url, id ); + + return 0; + } + + return -1; +} + +void +Timeline::reply_to_finger ( lo_message msg ) +{ + int argc = lo_message_get_argc( msg ); + lo_arg **argv = lo_message_get_argv( msg ); + + if ( argc < 2 ) + return; + + lo_address reply = lo_address_new_from_url( &argv[1]->s ); + + osc->send( reply, + "/reply", + "/non/finger", + osc->url(), + APP_NAME, + VERSION, + instance_name ); + + lo_address_free( reply ); +} + + +void +Timeline::discover_peers ( void ) +{ + nsm->broadcast( "/non/finger", osc->url() ); +} + diff --git a/timeline/src/Timeline.H b/timeline/src/Timeline.H index a7e375b..baf1ed0 100644 --- a/timeline/src/Timeline.H +++ b/timeline/src/Timeline.H @@ -87,6 +87,8 @@ class Timeline : public Fl_Single_Window, public RWLock { static void draw_clip ( void * v, int X, int Y, int W, int H ); + OSC::Endpoint *osc; + int _old_xposition; int _old_yposition; @@ -228,6 +230,18 @@ public: bool command_save ( void ); void command_quit ( void ); + /* OSC */ + + void discover_peers ( void ); + + static void check_osc ( void * v ); + + int init_osc ( const char *osc_port ); + + static int osc_reply ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); + + void reply_to_finger ( lo_message msg ); + private: static void snapshot ( void *v ) { ((Timeline*)v)->snapshot(); } diff --git a/timeline/src/main.C b/timeline/src/main.C index e8719b0..059f6e3 100644 --- a/timeline/src/main.C +++ b/timeline/src/main.C @@ -201,6 +201,8 @@ main ( int argc, char **argv ) tle->run(); + timeline->init_osc( NULL ); + char *nsm_url = getenv( "NSM_URL" ); if ( nsm_url )