From 9df0e9d665409fc8fa6428fdbfd4c1c8f3fe286c Mon Sep 17 00:00:00 2001 From: Jonathan Moore Liles Date: Mon, 8 Apr 2013 20:56:33 -0700 Subject: [PATCH] nonlib: Clean up signals handshaking. --- mixer/src/Mixer.C | 49 ++---- mixer/src/Mixer.H | 6 +- mixer/src/NSM.C | 4 +- mixer/src/main.C | 2 - nonlib/OSC/Endpoint.C | 263 ++++++++++++++++++++++++-------- nonlib/OSC/Endpoint.H | 27 +++- timeline/src/Control_Sequence.C | 84 +++++----- timeline/src/Control_Sequence.H | 5 +- timeline/src/NSM.C | 10 +- timeline/src/OSC_Thread.C | 15 +- timeline/src/Timeline.C | 110 +++++-------- timeline/src/Timeline.H | 6 +- timeline/src/Track.C | 10 ++ timeline/src/Track.H | 1 + 14 files changed, 366 insertions(+), 226 deletions(-) diff --git a/mixer/src/Mixer.C b/mixer/src/Mixer.C index cb3b9d3..481d421 100644 --- a/mixer/src/Mixer.C +++ b/mixer/src/Mixer.C @@ -94,34 +94,30 @@ static int osc_add_strip ( const char *path, const char *, lo_arg **, int , lo_m return 0; } + int +Mixer::osc_non_hello ( const char *, const char *, lo_arg **, int , lo_message msg, void * ) +{ + mixer->handle_hello( msg ); + return 0; +} + + void -Mixer::reply_to_finger ( lo_message msg ) +Mixer::handle_hello ( lo_message msg ) { int argc = lo_message_get_argc( msg ); lo_arg **argv = lo_message_get_argv( msg ); - + if ( argc >= 4 ) { const char *url = &argv[0]->s; const char *name = &argv[1]->s; const char *version = &argv[2]->s; const char *id = &argv[3]->s; - - MESSAGE( "Discovered NON peer %s (%s) @ %s with ID \"%s\"", name, version, url, id ); - MESSAGE( "Registering Signals" ); - - lo_address to = lo_address_new_from_url( &argv[0]->s ); - osc_endpoint->send( to, - "/non/hello", - osc_endpoint->url(), - APP_NAME, - VERSION, - instance_name ); - - mixer->osc_endpoint->hello( url ); - - lo_address_free( to ); + MESSAGE( "Got hello from NON peer %s (%s) @ %s with ID \"%s\"", name, version, url, id ); + + mixer->osc_endpoint->handle_hello( id, url ); } } @@ -450,6 +446,9 @@ Mixer::init_osc ( const char *osc_port ) printf( "OSC=%s\n", osc_endpoint->url() ); + osc_endpoint->add_method( "/non/hello", "ssss", &Mixer::osc_non_hello, osc_endpoint, "" ); + +// osc_endpoint->add_method( "/non/mixer/add_strip", "", osc_add_strip, osc_endpoint, "" ); osc_endpoint->start(); @@ -732,22 +731,6 @@ Mixer::handle ( int m ) -void -Mixer::discover_peers ( void ) -{ - if ( nsm->is_active() ) - { - lo_message m = lo_message_new(); - - lo_message_add_string( m, "/non/finger" ); - lo_message_add_string( m, osc_endpoint->url() ); - - nsm->broadcast( m ); - - lo_message_free( m ); - } -} - /************/ /* Commands */ /************/ diff --git a/mixer/src/Mixer.H b/mixer/src/Mixer.H index 5005960..a46ce15 100644 --- a/mixer/src/Mixer.H +++ b/mixer/src/Mixer.H @@ -71,6 +71,8 @@ private: static void handle_dirty ( int, void *v ); + static int osc_non_hello ( const char *, const char *, lo_arg **, int , lo_message msg, void * ); + protected: int handle ( int m ); @@ -100,7 +102,7 @@ public: Mixer ( int X, int Y, int W, int H, const char *L ); virtual ~Mixer(); - void reply_to_finger ( lo_message msg ); + void handle_hello ( lo_message msg ); void announce ( const char *nash_url, const char *process_name ); @@ -110,8 +112,6 @@ public: void say_hello ( void ); - void discover_peers ( void ); - public: bool command_save ( void ); diff --git a/mixer/src/NSM.C b/mixer/src/NSM.C index 491d177..b15385a 100644 --- a/mixer/src/NSM.C +++ b/mixer/src/NSM.C @@ -45,7 +45,7 @@ NSM_Client::command_broadcast ( const char *path, lo_message msg ) if ( !strcmp( path, "/non/hello" ) ) { - mixer->reply_to_finger( msg ); + mixer->handle_hello( msg ); return 0; } else @@ -103,7 +103,7 @@ NSM_Client::command_open ( const char *name, const char *display_name, const cha } } - mixer->discover_peers(); + mixer->say_hello(); Fl::unlock(); diff --git a/mixer/src/main.C b/mixer/src/main.C index 9c2c85a..abea660 100644 --- a/mixer/src/main.C +++ b/mixer/src/main.C @@ -305,8 +305,6 @@ main ( int argc, char **argv ) } } - mixer->say_hello(); - Fl::add_check( check_sigterm ); if ( ! no_ui ) diff --git a/nonlib/OSC/Endpoint.C b/nonlib/OSC/Endpoint.C index d0af9cc..4c532ee 100644 --- a/nonlib/OSC/Endpoint.C +++ b/nonlib/OSC/Endpoint.C @@ -60,7 +60,9 @@ namespace OSC Signal::Signal ( const char *path, Direction dir ) { _direction = dir; - _path = strdup( path ); + _path = NULL; + if ( path ) + _path = strdup( path ); _id = ++next_id; _value = 0.0f; _endpoint = NULL; @@ -77,8 +79,9 @@ namespace OSC { _endpoint->del_signal( this ); } - - free( _path ); + + if ( _path ) + free( _path ); _path = NULL; _endpoint = NULL; @@ -170,7 +173,9 @@ namespace OSC } Endpoint::Endpoint ( ) - { + { + _peer_signal_notification_callback = 0; + _peer_signal_notification_userdata = 0; _peer_scan_complete_callback = 0; _peer_scan_complete_userdata = 0; _server = 0; @@ -289,30 +294,62 @@ namespace OSC lo_address_free( addr ); } + void + Endpoint::handle_hello ( const char *peer_name, const char *peer_url ) + { + DMESSAGE( "Got hello from %s", peer_name ); + + Peer *p = find_peer_by_name( peer_name ); + + if ( ! p ) + { + scan_peer( peer_name, peer_url ); + } + else + { + /* maybe the peer has a new URL */ + + /* update address */ + lo_address addr = lo_address_new_from_url( peer_url ); + + if ( address_matches( addr, p->addr ) ) + { + free( addr ); + return; + } + + if ( p->addr ) + free( p->addr ); + + p->addr = addr; + + /* scan it while we're at it */ + p->_scanning = true; + + DMESSAGE( "Scanning peer %s", peer_name ); + + send( p->addr, "/signal/list" ); + } + + if ( name() ) + { + hello( peer_url ); + } + else + { + DMESSAGE( "Not sending hello because we don't have a name yet!" ); + } + } + int Endpoint::osc_sig_hello ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) { - Endpoint *ep = (Endpoint*)user_data; const char *peer_name = &argv[0]->s; const char *peer_url = &argv[1]->s; - DMESSAGE( "Got hello from %s", peer_name ); - - if ( ! ep->find_peer_by_name( peer_name ) ) - { - ep->scan_peer( peer_name, peer_url ); - - if ( ep->name() ) - { - ep->hello( peer_url ); - } - else - { - DMESSAGE( "Not sending hello because we don't have a name yet!" ); - } - } + ep->handle_hello( peer_name, peer_url ); return 0; } @@ -374,13 +411,24 @@ namespace OSC Signal *ps = ep->find_peer_signal_by_id( p, their_id ); + /* if ( ! ps ) */ + /* { */ + /* WARNING( "Unknown source signal" ); */ + /* WARNIN */ + /* return 0; */ + /* } */ + if ( ! ps ) { - WARNING( "Unknown source signal" ); + /* we don't know about this signal yet */ + /* just add a stub signal and fill in the blanks later */ + ps = new Signal( NULL, Signal::Output); + ps->_id = their_id; + ps->_peer = p; - return 0; + p->_signals.push_back( ps ); } - + Signal *s = ep->find_signal_by_id( our_id ); if ( ! s ) @@ -427,27 +475,44 @@ namespace OSC if ( ! o ) { - WARNING( "Unknown signal id %i", id ); + WARNING( "Unknown signal ID %i", id ); return 0; } DMESSAGE( "Signal %s:%s was removed", o->_peer->name, o->path() ); /* disconnect it */ - for ( std::list::iterator i = o->_outgoing.begin(); - i != o->_outgoing.end(); - ++i ) + if ( o->_outgoing.size() ) { - ep->disconnect_signal( o, *i ); + for ( std::list::iterator i = o->_outgoing.begin(); + i != o->_outgoing.end(); + ) + { + Signal *s = *i; + /* avoid messing up iterator */ + ++i; + + ep->disconnect_signal( o, s ); + } } - for ( std::list::iterator i = o->_incoming.begin(); + if ( o->_incoming.size() ) + { + for ( std::list::iterator i = o->_incoming.begin(); i != o->_incoming.end(); - ++i ) - { - ep->disconnect_signal( *i, o ); + ) + { + Signal *s = *i; + /* avoid messing up iterator */ + ++i; + + ep->disconnect_signal( s, o ); + } } + if ( ep->_peer_signal_notification_callback ) + ep->_peer_signal_notification_callback( o, Signal::Removed, ep->_peer_signal_notification_userdata ); + p->_signals.remove( o ); delete o; @@ -459,14 +524,6 @@ namespace OSC Endpoint::osc_sig_created ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) { Endpoint *ep = (Endpoint*)user_data; - - Peer *p = ep->find_peer_by_address( lo_message_get_source( msg ) ); - - if ( ! p ) - { - WARNING( "Got signal creation from unknown peer." ); - return 0; - } const char *name = &argv[0]->s; const char *direction = &argv[1]->s; @@ -475,9 +532,14 @@ namespace OSC const float max = argv[4]->f; const float default_value = argv[5]->f; - DMESSAGE( "Peer %s has created signal %s with id %i (%s %f %f %f)", p->name, - name, id, direction, min, max, default_value ); - + Peer *p = ep->find_peer_by_address( lo_message_get_source( msg ) ); + + if ( ! p ) + { + WARNING( "Got signal creation notification from unknown peer" ); + return 0; + } + Signal::Direction dir = Signal::Input; if ( !strcmp( direction, "in" ) ) @@ -492,6 +554,12 @@ namespace OSC s->parameter_limits( min, max, default_value ); p->_signals.push_back( s ); + + DMESSAGE( "Peer %s has created signal %s with id %i (%s %f %f %f)", p->name, + name, id, direction, min, max, default_value ); + + if ( ep->_peer_signal_notification_callback ) + ep->_peer_signal_notification_callback( s, Signal::Created, ep->_peer_signal_notification_userdata ); return 0; } @@ -652,6 +720,8 @@ namespace OSC Endpoint::osc_signal_lister ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) { // OSC_DMSG(); + + DMESSAGE( "Listing signals." ); const char *prefix = NULL; @@ -700,7 +770,7 @@ namespace OSC void - Endpoint::list_peer_signals ( void (*callback) (const char *, const OSC::Signal *, void * ), void *v ) + Endpoint::list_peer_signals ( void *v ) { for ( std::list::iterator i = _peers.begin(); i != _peers.end(); @@ -711,7 +781,8 @@ namespace OSC ++j ) { // DMESSAGE( "Running callback" ); - callback( (*i)->name, *j, v ); + if ( _peer_signal_notification_callback ) + _peer_signal_notification_callback( *j, OSC::Signal::Created, v ); } } } @@ -764,15 +835,22 @@ namespace OSC { if ( ! s->is_connected_to( d ) ) return false; + + if ( d->_peer ) + { + MESSAGE( "Disconnecting signal output \"%s\" from %s:%s", s->path(), d->_peer->name, d->_path ); + + send( d->_peer->addr, "/signal/disconnect", + s->_id, /* our signal id */ + d->_id /* their signal id */ ); + } + else + { + MESSAGE( "Disconnecting signal output \"%s\" to (unknown):%i", s->path(), d->_id ); + } - MESSAGE( "Disconnecting signal output \"%s\" to %s:%i", s->path(), d->_peer->name, d->_id ); - - send( d->_peer->addr, "/signal/disconnect", - s->_id, /* our signal id */ - d->_id /* their signal id */ ); - s->_outgoing.remove( d ); - s->_incoming.remove( d ); + d->_incoming.remove( s ); return true; } @@ -801,6 +879,9 @@ namespace OSC return false; } + /** Connect to name signal. If the destination doesn't currently * + exist, but appears at some later point, the connection will be made + then */ bool Endpoint::connect_signal( OSC::Signal *s, const char *peer_and_path ) { @@ -930,13 +1011,28 @@ namespace OSC else if ( !strcmp( &argv[2]->s, "out" ) ) dir = Signal::Output; - Signal *s = new Signal( &argv[1]->s, (Signal::Direction)dir ); + Signal *s = ep->find_peer_signal_by_id( p, argv[3]->i ); + + if ( s && s->id() == argv[3]->i ) + { + /* found a stub signal, fill in the blanks */ + s->_path = strdup(&argv[1]->s); + s->parameter_limits( argv[4]->f, argv[5]->f, argv[6]->f ); + } + else + { + + s = new Signal( &argv[1]->s, (Signal::Direction)dir ); s->_peer = p; s->_id = argv[3]->i; s->parameter_limits( argv[4]->f, argv[5]->f, argv[6]->f ); p->_signals.push_back( s ); + } + + if ( ep->_peer_signal_notification_callback ) + ep->_peer_signal_notification_callback( s, Signal::Created, ep->_peer_signal_notification_userdata ); } return 0; @@ -985,7 +1081,6 @@ namespace OSC lo_server_add_method( _server, path, NULL, osc_sig_handler, o ); } - o->parameter_limits( min, max, default_value ); /* tell our peers about it */ @@ -994,7 +1089,7 @@ namespace OSC ++i ) { send( (*i)->addr, - "/signal/created", + "/signal/created", o->path(), o->_direction == Signal::Input ? "in" : "out", o->id(), @@ -1074,24 +1169,66 @@ namespace OSC o->id() ); } + Endpoint *ep = this; + + /* disconnect it */ + if ( o->_outgoing.size() ) + { + for ( std::list::iterator i = o->_outgoing.begin(); + i != o->_outgoing.end(); + ) + { + Signal *s = *i; + /* avoid messing up iterator */ + ++i; + + ep->disconnect_signal( o, s ); + } + } + + if ( o->_incoming.size() ) + { + for ( std::list::iterator i = o->_incoming.begin(); + i != o->_incoming.end(); + ) + { + Signal *s = *i; + /* avoid messing up iterator */ + ++i; + + ep->disconnect_signal( s, o ); + } + } + /* FIXME: clear loopback connections first! */ // delete o; _signals.remove( o ); } - void - Endpoint::scan_peer ( const char *name, const char *url ) + Peer * + Endpoint::add_peer ( const char *name, const char *url ) { Peer *p = new Peer; - DMESSAGE( "Scanning peer %s @ %s...", name, url ); + DMESSAGE( "Adding peer %s @ %s...", name, url ); p->name = strdup( name ); p->addr = lo_address_new_from_url( url ); + + _peers.push_back( p ); + + return p; + } + + void + Endpoint::scan_peer ( const char *name, const char *url ) + { + Peer *p = add_peer(name,url); + p->_scanning = true; - _peers.push_back( p ); + DMESSAGE( "Scanning peer %s", name ); send( p->addr, "/signal/list" ); } @@ -1184,15 +1321,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: @@ -1201,7 +1338,7 @@ namespace OSC } } - DMESSAGE( "Path: %s", path ); +// DMESSAGE( "Path: %s", path ); lo_bundle b = lo_bundle_new( LO_TT_IMMEDIATE ); diff --git a/nonlib/OSC/Endpoint.H b/nonlib/OSC/Endpoint.H index ab2d984..ce5b082 100644 --- a/nonlib/OSC/Endpoint.H +++ b/nonlib/OSC/Endpoint.H @@ -133,6 +133,11 @@ namespace OSC public: + enum State { + Created = 0, + Removed = 1 + }; + enum Direction { Input, Output, @@ -166,6 +171,10 @@ namespace OSC public: + const char * peer_name ( void ) const { + return _peer->name; + } + Signal ( const char *path, Direction dir ); ~Signal ( ); @@ -259,6 +268,8 @@ namespace OSC static int osc_sig_connect ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); static int osc_sig_hello ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); + + Peer * add_peer ( const char *name, const char *url ); void scan_peer ( const char *name, const char *url ); private: @@ -279,12 +290,22 @@ namespace OSC void del_signal ( Signal *signal ); void send_signal_rename_notifications( Signal *s ); - public: + + void (*_peer_signal_notification_callback)( OSC::Signal *, OSC::Signal::State, void*); + void *_peer_signal_notification_userdata; + public: + + void peer_signal_notification_callback ( void (*cb)(OSC::Signal *, OSC::Signal::State, void*), void *userdata ) + { + _peer_signal_notification_callback = cb; + _peer_signal_notification_userdata = userdata; + } + // can be used to point back to owning object. void *owner; - void list_peer_signals ( void (*callback) (const char *, const OSC::Signal *, void * ), void *v ); + void list_peer_signals ( void *v ); int init ( int proto, const char *port = 0 ); @@ -299,7 +320,6 @@ namespace OSC bool connect_signal ( OSC::Signal *s, const char *peer_name, int signal_id ); bool connect_signal ( OSC::Signal *s, const char *peer_and_path ); - Signal * add_signal ( const char *path, Signal::Direction dir, float min, float max, float default_value, signal_handler handler, void *user_data ); Method *add_method ( const char *path, const char *typespec, lo_method_handler handler, void *user_data, const char *argument_description ); void del_method ( const char *path, const char *typespec ); @@ -317,6 +337,7 @@ namespace OSC const char *name ( void ) { return _name; } void hello ( const char *url ); + void handle_hello ( const char *peer_name, const char *peer_url ); int send ( lo_address to, const char *path, std::list< OSC_Value > values ); diff --git a/timeline/src/Control_Sequence.C b/timeline/src/Control_Sequence.C index 39fd776..4f84a63 100644 --- a/timeline/src/Control_Sequence.C +++ b/timeline/src/Control_Sequence.C @@ -66,10 +66,10 @@ Control_Sequence::Control_Sequence ( Track *track, const char *name ) : Sequence _track = track; - mode( OSC ); - this->name( name ); + mode( OSC ); + if ( track ) track->add( this ); @@ -198,6 +198,8 @@ Control_Sequence::cb_button ( Fl_Widget *w ) void Control_Sequence::init ( void ) { + timeline->osc->peer_signal_notification_callback( &Control_Sequence::peer_callback, NULL ); + labeltype( FL_NO_LABEL ); { Control_Sequence_Header *o = new Control_Sequence_Header( x(), y(), Track::width(), 52 ); @@ -332,7 +334,7 @@ Control_Sequence::mode ( Mode m ) { /* FIXME: use name here... */ char *path; - asprintf( &path, "/track/%s/control/%i", track()->name(), track()->ncontrols() ); + asprintf( &path, "/track/%s/%s", track()->name(), name() ); char *s = escape_url( path ); @@ -348,8 +350,6 @@ Control_Sequence::mode ( Mode m ) DMESSAGE( "osc_output: %p", _osc_output() ); - connect_osc(); - header()->outputs_indicator->label( "osc" ); } @@ -589,6 +589,8 @@ Control_Sequence::menu_cb ( const Fl_Menu_ *m ) void Control_Sequence::connect_osc ( void ) { + timeline->osc_thread->lock(); + if ( _persistent_osc_connections.size() ) { for ( std::list::iterator i = _persistent_osc_connections.begin(); @@ -597,7 +599,7 @@ Control_Sequence::connect_osc ( void ) { if ( ! timeline->osc->connect_signal( _osc_output(), *i ) ) { -// MESSAGE( "Failed to connect output %s to ", _osc_output->path(), *i ); + /* WARNING( "Failed to connect output %s to %s", _osc_output()->path(), *i ); */ } else { @@ -606,6 +608,10 @@ Control_Sequence::connect_osc ( void ) } } } + + header()->outputs_indicator->value( _osc_output() && _osc_output()->connected() ); + + timeline->osc_thread->unlock(); } void @@ -614,28 +620,26 @@ Control_Sequence::process_osc ( void ) if ( mode() != OSC ) return; - header()->outputs_indicator->value( _osc_output() && _osc_output()->connected() ); - if ( _osc_output() && _osc_output()->connected() ) { sample_t buf[1]; - + play( buf, (nframes_t)transport->frame, (nframes_t) 1 ); _osc_output()->value( (float)buf[0] ); } } -void -Control_Sequence::peer_callback( const char *name, const OSC::Signal *sig, void *v ) -{ - ((Control_Sequence*)v)->peer_callback( name, sig ); -} - static Fl_Menu_Button *peer_menu; static const char *peer_prefix; void -Control_Sequence::peer_callback( const char *name, const OSC::Signal *sig ) +Control_Sequence::update_osc_connection_state ( void ) +{ + header()->outputs_indicator->value( _osc_output() && _osc_output()->connected() ); +} + +void +Control_Sequence::peer_callback( OSC::Signal *sig, OSC::Signal::State state, void *v ) { char *s; @@ -647,34 +651,44 @@ Control_Sequence::peer_callback( const char *name, const OSC::Signal *sig ) if ( ! ( sig->parameter_limits().min == 0.0 && sig->parameter_limits().max == 1.0 ) ) return; + + if ( ! v ) + { + if( state == OSC::Signal::Created ) + timeline->connect_osc(); + else + timeline->update_osc_connection_state(); + } + else + { + /* building menu */ + const char *name = sig->peer_name(); + + assert( sig->path() ); + + char *path = strdup( sig->path() ); + + unescape_url( path ); + + asprintf( &s, "%s/%s%s", peer_prefix, name, path ); + + peer_menu->add( s, 0, NULL, (void*)( sig ), + FL_MENU_TOGGLE | + ( ((Control_Sequence*)v)->_osc_output()->is_connected_to( sig ) ? FL_MENU_VALUE : 0 ) ); + free( path ); - assert( sig->path() ); - - char *path = strdup( sig->path() ); - - unescape_url( path ); - - asprintf( &s, "%s/%s%s", peer_prefix, name, path ); - - peer_menu->add( s, 0, NULL, (void*)( sig ), - FL_MENU_TOGGLE | - ( _osc_output()->is_connected_to( sig ) ? FL_MENU_VALUE : 0 ) ); - - free( path ); - - free( s ); - - connect_osc(); + free( s ); + } } void Control_Sequence::add_osc_peers_to_menu ( Fl_Menu_Button *m, const char *prefix ) { - peer_menu = m; + peer_menu = m; peer_prefix = prefix; - timeline->osc->list_peer_signals( &Control_Sequence::peer_callback, this ); + timeline->osc->list_peer_signals( this ); } Fl_Menu_Button & diff --git a/timeline/src/Control_Sequence.H b/timeline/src/Control_Sequence.H index 7a3b9ed..ac0bc72 100644 --- a/timeline/src/Control_Sequence.H +++ b/timeline/src/Control_Sequence.H @@ -71,8 +71,8 @@ private: } - static void peer_callback( const char *name, const OSC::Signal *sig, void *v ); - void peer_callback( const char *name, const OSC::Signal *sig ); + static void peer_callback( OSC::Signal *sig, OSC::Signal::State state, void *v ); + void peer_callback( OSC::Signal *sig, OSC::Signal::State state ); void add_osc_peers_to_menu ( Fl_Menu_Button *m, const char *prefix ); static Fl_Widget *_highlighted; @@ -116,6 +116,7 @@ public: void process_osc ( void ); void connect_osc ( void ); + void update_osc_connection_state ( void ); static bool draw_with_polygon; static bool draw_with_grid; diff --git a/timeline/src/NSM.C b/timeline/src/NSM.C index 8613f84..28c702f 100644 --- a/timeline/src/NSM.C +++ b/timeline/src/NSM.C @@ -56,7 +56,7 @@ command_open ( const char *name, const char *display_name, const char *client_id instance_name = strdup( client_id ); timeline->osc->name( client_id ); - + int r = 0; if ( Project::validate( name ) ) @@ -79,8 +79,10 @@ command_open ( const char *name, const char *display_name, const char *client_id r = ERR_GENERAL; } } + + timeline->say_hello(); - timeline->discover_peers(); +// timeline->connect_osc(); return r; } @@ -89,8 +91,6 @@ static void command_session_is_loaded ( void *userdata ) { MESSAGE( "NSM says session is loaded." ); - - timeline->discover_peers(); } static int @@ -101,7 +101,7 @@ command_broadcast ( const char *path, lo_message msg, void *userdata ) if ( !strcmp( path, "/non/hello" ) ) { - timeline->reply_to_finger( msg ); + timeline->handle_hello( msg ); return 0; } else diff --git a/timeline/src/OSC_Thread.C b/timeline/src/OSC_Thread.C index 016dda5..50b1153 100644 --- a/timeline/src/OSC_Thread.C +++ b/timeline/src/OSC_Thread.C @@ -26,6 +26,8 @@ #include "debug.h" +#include "OSC/Endpoint.H" + extern Timeline *timeline; OSC_Thread::OSC_Thread ( ) @@ -61,14 +63,17 @@ OSC_Thread::process ( void ) _thread.name( "OSC" ); DMESSAGE( "OSC Thread starting" ); - + while ( !_shutdown ) { + if ( trylock() ) + { + timeline->osc->check(); + timeline->process_osc(); + unlock(); + } + usleep( 100 * 1000 ); - - /* lock(); */ - timeline->process_osc(); - /* unlock(); */ } DMESSAGE( "OSC Thread stopping." ); diff --git a/timeline/src/Timeline.C b/timeline/src/Timeline.C index 300ab5d..f74683a 100644 --- a/timeline/src/Timeline.C +++ b/timeline/src/Timeline.C @@ -2082,15 +2082,6 @@ Timeline::session_manager_name ( void ) /* 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 ) { @@ -2107,11 +2098,6 @@ Timeline::init_osc ( const char *osc_port ) // 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 ); - - osc->peer_scan_complete_callback( &Timeline::handle_peer_scan_complete, this ); - if ( ! osc_thread ) { osc_thread = new OSC_Thread(); @@ -2123,9 +2109,19 @@ Timeline::init_osc ( const char *osc_port ) } int -Timeline::osc_non_hello ( const char *path, const char *, lo_arg **argv, int argc, lo_message, void * ) +Timeline::osc_non_hello ( const char *, const char *, lo_arg **, int , lo_message msg, void * ) { - OSC_DMSG(); + THREAD_ASSERT( OSC ); + + timeline->handle_hello(msg); + return 0; +} + +void +Timeline::handle_hello ( lo_message msg ) +{ + int argc = lo_message_get_argc( msg ); + lo_arg **argv = lo_message_get_argv( msg ); if ( argc >= 4 ) { @@ -2134,64 +2130,14 @@ Timeline::osc_non_hello ( const char *path, const char *, lo_arg **argv, int arg const char *version = &argv[2]->s; const char *id = &argv[3]->s; - MESSAGE( "Discovered NON peer %s (%s) @ %s with ID \"%s\"", name, version, url, id ); - MESSAGE( "Registering Signals" ); - - timeline->osc->hello( url ); + MESSAGE( "Got hello from NON peer %s (%s) @ %s with ID \"%s\"", name, version, url, id ); - return 0; + osc->handle_hello( &argv[3]->s, &argv[0]->s ); } - - 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 < 1 ) - return; - - lo_address reply = lo_address_new_from_url( &argv[0]->s ); - - osc->send( reply, - "/non/hello", - osc->url(), - APP_NAME, - VERSION, - instance_name ); - - osc->hello( &argv[0]->s ); - - lo_address_free( reply ); -} - -void -Timeline::handle_peer_scan_complete ( void *o ) -{ - ((Timeline*)o)->connect_osc(); -} - -void -Timeline::connect_osc ( void ) -{ -// rdlock(); - - /* try to (re)connect OSC signals */ - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - t->connect_osc(); - } - -// unlock(); -} - -void -Timeline::discover_peers ( void ) +Timeline::say_hello ( void ) { if ( nsm_is_active( nsm ) ) { @@ -2208,6 +2154,28 @@ Timeline::discover_peers ( void ) } } +void +Timeline::connect_osc ( void ) +{ + /* reconnect OSC signals */ + for ( int i = tracks->children(); i-- ; ) + { + Track *t = (Track*)tracks->child( i ); + + t->connect_osc(); + } +} +void +Timeline::update_osc_connection_state ( void ) +{ + /* reconnect OSC signals */ + for ( int i = tracks->children(); i-- ; ) + { + Track *t = (Track*)tracks->child( i ); + + t->update_osc_connection_state(); + } +} /* runs in the OSC thread... */ void @@ -2215,7 +2183,7 @@ Timeline::process_osc ( void ) { THREAD_ASSERT( OSC ); - rdlock(); + /* rdlock(); */ /* reconnect OSC signals */ for ( int i = tracks->children(); i-- ; ) @@ -2225,6 +2193,6 @@ Timeline::process_osc ( void ) t->process_osc(); } - unlock(); + /* unlock(); */ } diff --git a/timeline/src/Timeline.H b/timeline/src/Timeline.H index 14de37b..c6c59e4 100644 --- a/timeline/src/Timeline.H +++ b/timeline/src/Timeline.H @@ -294,7 +294,9 @@ public: void connect_osc ( void ); - void discover_peers ( void ); + void update_osc_connection_state ( void ); + + void say_hello ( void ); static void check_osc ( void * v ); @@ -304,7 +306,7 @@ public: static int osc_non_hello ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); - void reply_to_finger ( lo_message msg ); + void handle_hello ( lo_message msg ); void add_cursor ( Cursor_Region *o ); void add_cursor ( Cursor_Point *o ); diff --git a/timeline/src/Track.C b/timeline/src/Track.C index 29cdd63..4613fee 100644 --- a/timeline/src/Track.C +++ b/timeline/src/Track.C @@ -1095,6 +1095,16 @@ Track::connect_osc ( void ) } } +void +Track::update_osc_connection_state ( void ) +{ + for ( int j = control->children(); j--; ) + { + Control_Sequence *c = (Control_Sequence*)control->child( j ); + c->update_osc_connection_state(); + } +} + void Track::process_osc ( void ) { diff --git a/timeline/src/Track.H b/timeline/src/Track.H index 1c16566..49bf812 100644 --- a/timeline/src/Track.H +++ b/timeline/src/Track.H @@ -242,6 +242,7 @@ public: void process_osc ( void ); void connect_osc ( void ); + void update_osc_connection_state ( void ); /* Engine */ const Audio_Region *capture_region ( void ) const;