diff --git a/mixer/src/Mixer.C b/mixer/src/Mixer.C index d2a1033..4bffbdc 100644 --- a/mixer/src/Mixer.C +++ b/mixer/src/Mixer.C @@ -48,6 +48,8 @@ #include #include "FL/Fl_Blinker.H" +#include "OSC/Endpoint.H" + const double STATUS_UPDATE_FREQ = 0.2f; const double OSC_INTERVAL = 1.0 / 20.0; /* 20 hz */ @@ -679,6 +681,22 @@ 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 e8eeb8f..721845f 100644 --- a/mixer/src/Mixer.H +++ b/mixer/src/Mixer.H @@ -29,8 +29,8 @@ class Fl_Blinker; class Fl_Flowpack; class Fl_Menu_Bar; - -#include "OSC/Endpoint.H" +namespace OSC { class Endpoint; } +#include class Mixer : public Fl_Group { @@ -105,6 +105,8 @@ public: void say_hello ( void ); + void discover_peers ( void ); + public: bool command_save ( void ); diff --git a/mixer/src/Module.C b/mixer/src/Module.C index 453f6f9..1b88b86 100644 --- a/mixer/src/Module.C +++ b/mixer/src/Module.C @@ -39,6 +39,8 @@ #include "FL/menu_popup.H" #include "Mixer.H" +#include "OSC/Endpoint.H" + Module *Module::_copied_module_empty = 0; @@ -226,7 +228,7 @@ Module::Port::generate_osc_path () char *path = NULL; - // /mixer/STRIPNAME/MODULENAME/CONTROLNAME + // /strip/STRIPNAME/MODULENAME/CONTROLNAME if ( ! module()->allows_external_control() ) { @@ -237,9 +239,9 @@ Module::Port::generate_osc_path () int n = module()->chain()->get_module_instance_number( module() ); if ( n > 0 ) - asprintf( &path, "/mixer/%s/%s.%i/%s", module()->chain()->name(), p->module()->label(), n, p->name() ); + asprintf( &path, "/strip/%s/%s.%i/%s", module()->chain()->name(), p->module()->label(), n, p->name() ); else - asprintf( &path, "/mixer/%s/%s/%s", module()->chain()->name(), p->module()->label(), p->name() ); + asprintf( &path, "/strip/%s/%s/%s", module()->chain()->name(), p->module()->label(), p->name() ); // Hack to keep spaces out of OSC URL... Probably need to handle other special characters similarly. for ( int i = strlen( path ); i--; ) @@ -251,6 +253,12 @@ Module::Port::generate_osc_path () return path; } +void +Module::Port::handle_signal_connection_state_changed ( OSC::Signal *s ) +{ + module()->redraw(); +} + void Module::Port::change_osc_path ( char *path ) { @@ -261,20 +269,26 @@ Module::Port::change_osc_path ( char *path ) asprintf( &unscaled_path, "%s/unscaled", path ); - if ( ! ( _scaled_signal && _unscaled_signal ) ) + if ( NULL == _scaled_signal ) { _scaled_signal = mixer->osc_endpoint->add_signal( scaled_path, OSC::Signal::Input, &Module::Port::osc_control_change_cv, this ); - + + _scaled_signal->signal_connection_state_changed.connect( sigc::mem_fun( this, &Module::Port::handle_signal_connection_state_changed ) ); + _unscaled_signal = mixer->osc_endpoint->add_signal( unscaled_path, OSC::Signal::Input, &Module::Port::osc_control_change_exact, this ); } else { + DMESSAGE( "Renaming OSC signals" ); + _scaled_signal->rename( scaled_path ); _unscaled_signal->rename( unscaled_path ); + + return; } free( unscaled_path ); @@ -516,7 +530,7 @@ Module::draw_box ( void ) { fl_draw_box( FL_ROUNDED_BOX, tx + 4, ty + 4, 5, 5, is_being_controlled() ? FL_YELLOW : fl_inactive( FL_YELLOW ) ); - fl_draw_box( FL_ROUNDED_BOX, tx + 4, ty + 8, 5, 5, is_being_controlled_osc() ? FL_GREEN : fl_inactive( FL_GREEN ) ); + fl_draw_box( FL_ROUNDED_BOX, tx + 4, ty + th - 8, 5, 5, is_being_controlled_osc() ? FL_YELLOW : fl_inactive( FL_YELLOW ) ); } if ( control_output.size() ) diff --git a/mixer/src/Module.H b/mixer/src/Module.H index 0ed3483..51e24ca 100644 --- a/mixer/src/Module.H +++ b/mixer/src/Module.H @@ -170,13 +170,12 @@ public: void update_osc_port ( ) { - if ( INPUT == _direction ) - change_osc_path( generate_osc_path() ); +// if ( INPUT == _direction ) + change_osc_path( generate_osc_path() ); } void destroy_osc_port ( ) { - delete _unscaled_signal; delete _scaled_signal; @@ -256,8 +255,11 @@ public: nframes_t _nframes; Module *_module; + OSC::Signal *_scaled_signal; OSC::Signal *_unscaled_signal; + + void handle_signal_connection_state_changed ( OSC::Signal *s ); }; void bbox ( int &X, int &Y, int &W, int &H ) diff --git a/mixer/src/NSM.C b/mixer/src/NSM.C index e2d721f..cda7df7 100644 --- a/mixer/src/NSM.C +++ b/mixer/src/NSM.C @@ -23,6 +23,8 @@ #include "NSM.H" #include "Project.H" +#include "OSC/Endpoint.H" + extern char *instance_name; extern Mixer *mixer; @@ -101,6 +103,8 @@ NSM_Client::command_open ( const char *name, const char *display_name, const cha } } + mixer->discover_peers(); + Fl::unlock(); return r; diff --git a/nonlib/OSC/Endpoint.C b/nonlib/OSC/Endpoint.C index e07b0de..edbee91 100644 --- a/nonlib/OSC/Endpoint.C +++ b/nonlib/OSC/Endpoint.C @@ -70,30 +70,24 @@ namespace OSC void Signal::rename ( const char *path ) { - for ( std::list::const_iterator i = _incoming.begin(); - i != _incoming.end(); - ++i ) - { - _endpoint->send( (*i)->peer->addr, - "/signal/renamed", - (*i)->signal_id, - path ); + DMESSAGE( "Renaming signal %s to %s", this->path(), path ); - } free( _path ); _path = strdup( path ); + + _endpoint->send_signal_rename_notifications( this ); } bool Signal::is_connected_to ( const OSC::Signal *s ) const { - for ( std::list::const_iterator i = _outgoing.begin(); + for ( std::list::const_iterator i = _outgoing.begin(); i != _outgoing.end(); ++i ) { - if ( (*i)->peer == s->_peer && - (*i)->signal_id == s->id() ) + if ( (*i)->_peer == s->_peer && + (*i)->id() == s->id() ) return true; } @@ -103,31 +97,47 @@ namespace OSC void Signal::value ( float f ) { - for ( std::list::const_iterator i = _outgoing.begin(); + for ( std::list::const_iterator i = _outgoing.begin(); i != _outgoing.end(); ++i ) { - if ( (*i)->value != f ) + /* FIXME: won't work for loopback */ + if ( (*i)->_value != f ) { - (*i)->value = f; + (*i)->_value = f; - _endpoint->send( (*i)->peer->addr, + _endpoint->send( (*i)->_peer->addr, "/signal/change", - (*i)->signal_id, + id(), + (*i)->id(), f ); } } } - void - Signal::get_connected_peer_name_and_path ( char **peer_name, char **path ) + char * + Signal::get_output_connection_peer_name_and_path ( int n ) { - Target *t = _outgoing.back(); + Signal *t; - Signal *s = get_peer_signal_by_id( t->peer, t->signal_id ); + int j = 0; + for ( std::list::const_iterator i = _outgoing.begin(); + i != _outgoing.end(); + ++i, ++j ) + { + if ( j == n ) + { + t = *i; + break; + } + } - *peer_name = strdup( t->peer->name ); - *path = strdup( s->path() ); +// Signal *s = get_peer_signal_by_id( t->_peer, t->signal_id ); + + char *r; + asprintf( &r, "%s:%s", t->_peer->name, t->path() ); + + return r; } void @@ -154,13 +164,15 @@ namespace OSC } - add_method( "/signal/hello", "s", &Endpoint::osc_sig_hello, this, "" ); + add_method( "/signal/hello", "ss", &Endpoint::osc_sig_hello, this, "" ); add_method( "/signal/connect", "ii", &Endpoint::osc_sig_connect, this, "" ); add_method( "/signal/disconnect", "ii", &Endpoint::osc_sig_disconnect, this, "" ); add_method( "/signal/renamed", "is", &Endpoint::osc_sig_renamed, this, "" ); - add_method( "/signal/change", "if", &Endpoint::osc_sig_handler, this, "" ); - add_method( NULL, "", &Endpoint::osc_generic, this, "" ); + add_method( "/signal/removed", "i", &Endpoint::osc_sig_removed, this, "" ); + add_method( "/signal/created", "ssifff", &Endpoint::osc_sig_created, this, "" ); + add_method( "/signal/change", "iif", &Endpoint::osc_sig_handler, this, "" ); add_method( "/signal/list", NULL, &Endpoint::osc_signal_lister, this, "" ); + add_method( NULL, "", &Endpoint::osc_generic, this, "" ); add_method( "/reply", NULL, &Endpoint::osc_reply, this, "" ); return 0; @@ -173,15 +185,15 @@ namespace OSC lo_server_free( _server ); } - OSC::Target * - Endpoint::find_target_by_peer_address ( std::list *l, lo_address addr ) + OSC::Signal * + Endpoint::find_target_by_peer_address ( std::list *l, lo_address addr ) { - for ( std::list::iterator i = l->begin(); + for ( std::list::iterator i = l->begin(); i != l->end(); ++i ) { - if ( address_matches( addr, (*i)->peer->addr ) ) + if ( address_matches( addr, (*i)->_peer->addr ) ) { return *i; } @@ -237,8 +249,10 @@ namespace OSC { lo_address addr = lo_address_new_from_url ( url ); - send( addr, "/signal/hello", name() ); - + char *our_url = this->url(); + send( addr, "/signal/hello", name(), our_url ); + free( our_url ); + lo_address_free( addr ); } @@ -248,18 +262,15 @@ namespace OSC 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 ) ) { - char *url = lo_address_get_url( lo_message_get_source( msg )); + ep->scan_peer( peer_name, peer_url ); - ep->scan_peer( peer_name, url ); - - ep->send( lo_message_get_source( msg ), "/signal/hello", ep->name() ); - - free(url); + ep->hello( peer_url ); } return 0; @@ -290,21 +301,13 @@ namespace OSC if ( s->_direction == Signal::Input ) { - for ( std::list::iterator i = s->_incoming.begin(); - i != s->_incoming.end(); - ++i ) - { - if ( (*i)->peer == p && - (*i)->signal_id == ps->id() ) - { - DMESSAGE( "Peer %s has disconnected from signal %s", p->name, ps->path() ); + s->_incoming.remove( ps ); + + DMESSAGE( "Peer %s has disconnected from signal %s", p->name, ps->path() ); - delete *i; - i = s->_incoming.erase( i ); + s->signal_connection_state_changed( s ); - return 0; - } - } + return 0; } return 0; @@ -347,24 +350,109 @@ namespace OSC DMESSAGE( "Peer %s has connected to signal %s", p->name, s->path() ); - if ( s->_direction == Signal::Input ) + /* if ( s->_direction == Signal::Input ) */ + /* { */ + s->_incoming.push_back( ps ); + + /* make a record of it ourselves */ + ps->_outgoing.push_back( s ); + + s->signal_connection_state_changed( s ); + + /* return 0; */ + /* } */ + + return 0; + } + + int + Endpoint::osc_sig_removed ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) + { + int id = argv[0]->i; + + Endpoint *ep = (Endpoint*)user_data; + + Peer *p = ep->find_peer_by_address( lo_message_get_source( msg ) ); + + if ( ! p ) { - Target *t = new Target; - - t->peer = p; - t->signal_id = ps->id(); - - s->_incoming.push_back( t ); - + WARNING( "Got signal remove notification from unknown peer." ); return 0; } + Signal *o = ep->find_peer_signal_by_id( p, id ); + + if ( ! o ) + { + 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 ) + { + ep->disconnect_signal( o, *i ); + } + + for ( std::list::iterator i = o->_incoming.begin(); + i != o->_incoming.end(); + ++i ) + { + ep->disconnect_signal( *i, o ); + } + + p->_signals.remove( o ); + + delete o; + + return 0; + } + + int + 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; + + if ( ! argc ) + return -1; + + Peer *p = ep->find_peer_by_address( lo_message_get_source( msg ) ); + + if ( ! p ) + { + WARNING( "Got signal creation from unknown peer." ); + return 0; + } + + DMESSAGE( "Peer %s has created signal %s", p->name, &argv[0]->s ); + + int dir = 0; + + if ( !strcmp( &argv[1]->s, "in" ) ) + dir = Signal::Input; + else if ( !strcmp( &argv[1]->s, "out" ) ) + dir = Signal::Output; + + Signal *s = new Signal( &argv[0]->s, (Signal::Direction)dir ); + + s->_peer = p; + s->_id = argv[2]->i; + s->parameter_limits( argv[3]->f, argv[4]->f, argv[5]->f ); + + p->_signals.push_back( s ); + return 0; } int Endpoint::osc_sig_renamed ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) { + DMESSAGE( "Got renamed message." ); + int id = argv[0]->i; char *new_name = &argv[1]->s; @@ -386,7 +474,7 @@ namespace OSC return 0; } - DMESSAGE( "Signal %s was renamed to %s" ); + DMESSAGE( "Signal %s:%s was renamed to %s", o->_peer->name, o->_path, path ); free( o->_path ); o->_path = strdup( new_name ); @@ -399,13 +487,18 @@ namespace OSC { Signal *o; float f = 0.0; - - if ( !strcmp( path, "/signal/change" ) && !strcmp( types, "if" ) ) + Endpoint *ep = NULL; + + + if ( !strcmp( path, "/signal/change" ) && !strcmp( types, "iif" ) ) { /* accept a value for numbered signal */ - int id = argv[0]->i; - f = argv[1]->f; - o = ((Endpoint*)user_data)->find_signal_by_id( id ); + int id = argv[1]->i; + f = argv[2]->f; + ep = (Endpoint*)user_data; + + o = ep->find_signal_by_id( id ); + if ( ! o ) { WARNING( "Unknown signal id %i", id ); @@ -429,26 +522,44 @@ namespace OSC return -1; } - Target *t = NULL; + Peer *p = NULL; - if ( 0 == o->_incoming.size() || - ! ( t = find_target_by_peer_address( &o->_incoming, lo_message_get_source( msg ) ) ) ) + if ( ep ) + p = ep->find_peer_by_address( lo_message_get_source( msg ) ); + + if ( 0 == o->_incoming.size() ) + return 0; + + if ( !p ) { + DMESSAGE( "Signal change initiated by an unknown peer" ); /* message came from an unconnected peer, just set the value exactly */ } else { /* message is from a connected source, do mixing. */ - t->value = f; + /* remote signal */ + /* if ( t->_peer ) */ - f = 0.0; - - for ( std::list::const_iterator i = o->_incoming.begin(); + for ( std::list::const_iterator i = o->_incoming.begin(); i != o->_incoming.end(); ++i ) { - f += (*i)->value; + if ( (*i)->id() == argv[0]->i ) + { + (*i)->_value = f; + break; + } + } + + f = 0.0; + + for ( std::list::const_iterator i = o->_incoming.begin(); + i != o->_incoming.end(); + ++i ) + { + f += (*i)->_value; } } @@ -599,7 +710,25 @@ namespace OSC } bool - Endpoint::disconnect_signal( OSC::Signal *s, const char *peer_name, const char *signal_path ) + Endpoint::disconnect_signal ( OSC::Signal *s, OSC::Signal *d ) + { + if ( ! s->is_connected_to( d ) ) + return false; + + 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 ); + + return true; + } + + bool + Endpoint::disconnect_signal ( OSC::Signal *s, const char *peer_name, const char *signal_path ) { if ( s->_direction == Signal::Output ) { @@ -613,33 +742,53 @@ namespace OSC if ( ! ps ) return false; - MESSAGE( "Disconnecting signal output \"%s\" to %s:%i", s->path(), peer_name, ps->_id ); + if ( ! s->is_connected_to( ps ) ) + return false; - for ( std::list::iterator i = s->_outgoing.begin(); - i != s->_outgoing.end(); - ++i ) - { - if ( (*i)->peer == p && - (*i)->signal_id == ps->id() ) - { - send( p->addr, "/signal/disconnect", - s->_id, /* our signal id */ - (*i)->signal_id /* their signal id */ ); - - delete *i; - i = s->_outgoing.erase( i ); - - DMESSAGE( "Number of outgoing connections: %i", s->_outgoing.size() ); - return true; - } - } - + return disconnect_signal( s, ps ); } return false; } + bool + Endpoint::connect_signal( OSC::Signal *s, const char *peer_and_path ) + { + char peer[512]; + char path[1024]; + /* FIXME: use %a */ + if ( 2 == sscanf( peer_and_path, "%[^:]:%s", peer, path ) ) + { + return connect_signal( s, peer, path ); + } + else + return false; + } + + bool + Endpoint::connect_signal ( OSC::Signal *s, OSC::Signal *d ) + { + if ( s->is_connected_to( d ) ) + { + return false; + } + + MESSAGE( "Connecting signal output \"%s\" to %s:%s", s->path(), d->_peer->name, d->path() ); + + s->_outgoing.push_back( d ); + + /* make a record of it ourselves */ + d->_incoming.push_back( s ); + + send( d->_peer->addr, "/signal/connect", + s->_id, /* our signal id */ + d->_id /* their signal id */ ); + + return true; + } + + bool Endpoint::connect_signal( OSC::Signal *s, const char *peer_name, const char *signal_path ) { @@ -655,25 +804,7 @@ namespace OSC if ( ! ps ) return false; - if ( s->is_connected_to( ps ) ) - { - return false; - } - - MESSAGE( "Connecting signal output \"%s\" to %s:%i", s->path(), peer_name, ps->_id ); - - Target *t = new Target(); - - t->peer = p; - t->signal_id = ps->_id; - - s->_outgoing.push_back( t ); - - send( p->addr, "/signal/connect", - s->_id, /* our signal id */ - t->signal_id /* their signal id */ ); - - return true; + return connect_signal( s, ps ); } return false; @@ -688,24 +819,13 @@ namespace OSC if ( !p ) return false; - - MESSAGE( "Connecting signal output \"%s\" to %s:%i", s->path(), peer_name, signal_id ); - if ( p ) - { - Target *t = new Target(); - - t->peer = p; - t->signal_id = signal_id; - - s->_outgoing.push_back( t ); - - send( p->addr, "/signal/connect", - s->_id, /* our signal id */ - t->signal_id /* their signal id */ ); - - return true; - } + Signal *ps = find_peer_signal_by_id( p, signal_id ); + + if ( !ps ) + return false; + + return connect_signal( s, ps ); } return false; @@ -745,10 +865,12 @@ namespace OSC { p->_scanning = false; DMESSAGE( "Done scanning %s", p->name ); + + ep->signal_peer_scan_complete(); } - else if ( p->_scanning ) + else if ( argc == 7 && p->_scanning ) { - DMESSAGE( "Peer %s has signal %s", p->name, &argv[1]->s ); + DMESSAGE( "Peer %s has signal %s (%s)", p->name, &argv[1]->s, &argv[2]->s ); int dir = 0; @@ -761,9 +883,7 @@ namespace OSC s->_peer = p; s->_id = argv[3]->i; - s->parameter_limits().min = argv[4]->f; - s->parameter_limits().max = argv[5]->f; - s->parameter_limits().default_value = argv[6]->f; + s->parameter_limits( argv[4]->f, argv[5]->f, argv[6]->f ); p->_signals.push_back( s ); } @@ -790,9 +910,6 @@ namespace OSC if ( argument_description ) md->_documentation = strdup( argument_description ); - if ( typespec ) - md->_parameter_limits = new Parameter_Limits[strlen(typespec)]; - _methods.push_back( md ); return md; @@ -801,23 +918,39 @@ namespace OSC Signal * Endpoint::add_signal ( const char *path, Signal::Direction dir, signal_handler handler, void *user_data ) { - Signal *md = new Signal( path, dir ); + Signal *o = new Signal( path, dir ); if ( path ) - md->_path = strdup( path ); + o->_path = strdup( path ); - md->_handler = handler; - md->_user_data = user_data; - md->_endpoint = this; + o->_handler = handler; + o->_user_data = user_data; + o->_endpoint = this; - _signals.push_back( md ); + _signals.push_back( o ); if ( dir == Signal::Input ) { - lo_server_add_method( _server, path, NULL, osc_sig_handler, md ); + lo_server_add_method( _server, path, NULL, osc_sig_handler, o ); } - return md; + /* tell our peers about it */ + for ( std::list::iterator i = _peers.begin(); + i != _peers.end(); + ++i ) + { + send( (*i)->addr, + "/signal/created", + o->path(), + o->_direction == Signal::Input ? "in" : "out", + o->id(), + o->parameter_limits().min, + o->parameter_limits().max, + o->parameter_limits().default_value + ); + } + + return o; } void @@ -855,6 +988,21 @@ namespace OSC _methods.remove( meth ); } + void + Endpoint::send_signal_rename_notifications ( Signal *s ) + { + + for ( std::list::const_iterator i = _peers.begin(); + i != _peers.end(); + ++i ) + { + send( (*i)->addr, + "/signal/renamed", + s->id(), + s->path() ); + } + } + void Endpoint::del_signal ( Signal *o ) { @@ -862,6 +1010,17 @@ namespace OSC lo_server_del_method( _server, o->path(), "f" ); + /* tell our peers about it */ + for ( std::list::iterator i = _peers.begin(); + i != _peers.end(); + ++i ) + { + send( (*i)->addr, + "/signal/removed", + o->id() ); + } + + /* FIXME: clear loopback connections first! */ // delete o; _signals.remove( o ); @@ -1127,7 +1286,7 @@ namespace OSC int Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, const char *v3, int v4, float v5, float v6, float v7 ) { - return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sssifff", v1, v2, v3, v4, v5, v6, 7 ); + return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sssifff", v1, v2, v3, v4, v5, v6, v7 ); } int @@ -1147,4 +1306,16 @@ namespace OSC { return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "if", v1, v2 ); } + + int + Endpoint::send ( lo_address to, const char *path, const char *v1, int v2, int v3, float v4 ) + { + return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "siif", v1, v2, v3, v4 ); + } + + int + Endpoint::send ( lo_address to, const char *path, int v1, int v2, float v3 ) + { + return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "iif", v1, v2, v3 ); + } } diff --git a/nonlib/OSC/Endpoint.H b/nonlib/OSC/Endpoint.H index 74fcb78..a284e7a 100644 --- a/nonlib/OSC/Endpoint.H +++ b/nonlib/OSC/Endpoint.H @@ -25,6 +25,8 @@ #include #include +#include + namespace OSC { class OSC_Value @@ -125,13 +127,6 @@ namespace OSC std::list _signals; }; - struct Target - { - Peer *peer; - int signal_id; - float value; - }; - typedef int (*signal_handler) ( float value, void *user_data ); class Signal @@ -159,24 +154,17 @@ namespace OSC float _value; - std::list _outgoing; + std::list _outgoing; + std::list _incoming; Direction _direction; - /* FIXME: - In order to support signal mixing, the receiver must track - each connected signal channel separately, and add the - values together before invoking the handler. - */ - std::list _incoming; - signal_handler _handler; void *_user_data; + Parameter_Limits _parameter_limits; public: - Parameter_Limits _parameter_limits; - Signal ( const char *path, Direction dir ) { _direction = dir; @@ -187,12 +175,17 @@ namespace OSC _peer = NULL; } + sigc::signal signal_connection_state_changed; + ~Signal ( ); static Signal *get_peer_signal_by_id ( Peer *p, int signal_id ); + int noutput_connections() { return _outgoing.size(); } bool connected ( void ) { return _outgoing.size() + _incoming.size(); } - void get_connected_peer_name_and_path ( char **peer_name, char **path ); + + char * get_output_connection_peer_name_and_path ( int n ); + int id ( void ) const { return _id; } Direction direction ( void ) { return _direction; } @@ -205,7 +198,7 @@ namespace OSC _value = default_value; } - Parameter_Limits& parameter_limits ( void ) { return _parameter_limits; } + const Parameter_Limits& parameter_limits ( void ) const { return _parameter_limits; } const char *path ( void ) const { return _path; } @@ -226,7 +219,6 @@ namespace OSC char *_path; char *_typespec; char *_documentation; - struct Parameter_Limits *_parameter_limits; public: @@ -251,6 +243,8 @@ namespace OSC static int osc_generic ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); static int osc_sig_handler ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); static int osc_sig_renamed ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); + static int osc_sig_removed ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); + static int osc_sig_created ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); static int osc_sig_disconnect ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); 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 ); @@ -277,10 +271,13 @@ namespace OSC Peer *find_peer_by_address ( lo_address addr ); static bool address_matches ( lo_address addr1, lo_address addr2 ); - static Target *find_target_by_peer_address ( std::list *l, lo_address addr ); + static Signal *find_target_by_peer_address ( std::list *l, lo_address addr ); char *_name; + void del_signal ( Signal *signal ); + void send_signal_rename_notifications( Signal *s ); + public: void list_peers ( void (*callback) (const char *, const OSC::Signal *, void * ), void *v ); @@ -291,16 +288,20 @@ namespace OSC ~Endpoint ( ); - bool disconnect_signal( OSC::Signal *s, const char *peer_name, const char *signal_path ); - bool connect_signal( OSC::Signal *s, const char *peer_name, const char *signal_path ); - bool connect_signal( OSC::Signal *s, const char *peer_name, int signal_id ); + + + bool disconnect_signal ( OSC::Signal *s, OSC::Signal *d ); + bool disconnect_signal ( OSC::Signal *s, const char *peer_name, const char *signal_path ); + bool connect_signal ( OSC::Signal *s, OSC::Signal *d ); + bool connect_signal ( OSC::Signal *s, const char *peer_name, const char *signal_path ); + 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, 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 ); void del_method ( Method* method ); - void del_signal ( Signal *signal ); void start ( void ); void stop ( void ); int port ( void ) const; @@ -325,6 +326,7 @@ namespace OSC int send ( lo_address to, const char *path, long v ); int send ( lo_address to, const char *path, int v1, int v2 ); int send ( lo_address to, const char *path, int v1, float v2 ); + int send ( lo_address to, const char *path, int v1, int v2, float v3 ); int send ( lo_address to, const char *path, const char *v ); int send ( lo_address to, const char *path, const char *v1, float v2 ); int send ( lo_address to, const char *path, const char *v1, int v2, int v3 ); @@ -335,6 +337,7 @@ namespace OSC int send ( lo_address to, const char *path, const char *v1, int v2 ); int send ( lo_address to, const char *path, int v1, const char *v2 ); + int send ( lo_address to, const char *path, const char *v1, int v2, int v3, float v4 ); int send ( lo_address to, const char *path, const char *v1, const char *v2, const char *v3, int v4, int v5, int v6 ); int send ( lo_address to, const char *path, const char *v1, int v2, const char *v3 ); @@ -351,6 +354,11 @@ namespace OSC // can be used to point back to owning object. void *owner; + + sigc::signal signal_peer_scan_complete; + + friend Signal::~Signal(); + friend void Signal::rename ( const char *name ); }; }; diff --git a/timeline/src/Control_Sequence.C b/timeline/src/Control_Sequence.C index d3763aa..584180f 100644 --- a/timeline/src/Control_Sequence.C +++ b/timeline/src/Control_Sequence.C @@ -32,6 +32,8 @@ using std::list; #include "Transport.H" +#include "OSC/Endpoint.H" + bool Control_Sequence::draw_with_gradient = true; @@ -44,28 +46,15 @@ Control_Sequence::Control_Sequence ( Track *track ) : Sequence( 0 ) { init(); - _osc_connected_peer = _osc_connected_path = 0; - _track = track; - _output = new JACK::Port( engine, JACK::Port::Output, track->name(), track->ncontrols(), "cv" ); - - if ( ! _output->activate() ) - { - FATAL( "could not create JACK port" ); - } - - /* { */ - /* char *path; */ - /* asprintf( &path, "/non/daw/%s/control/%i", track->name(), track->ncontrols() ); */ - - /* _osc_output = timeline->osc->add_signal( path, OSC::Signal::Output, NULL, NULL ); */ - - /* free( path ); */ - /* } */ - _osc_output = 0; + _output = 0; + _mode = CV; + + mode( OSC ); + if ( track ) track->add( this ); @@ -90,25 +79,30 @@ Control_Sequence::~Control_Sequence ( ) engine->unlock(); - _output->shutdown(); + if ( _output ) + { + _output->shutdown(); - delete _output; - - _output = NULL; - - delete _osc_output; - - _osc_output = NULL; - - if ( _osc_connected_peer ) - free( _osc_connected_peer ); + delete _output; - _osc_connected_peer = NULL; + _output = NULL; + } - if ( _osc_connected_path ) - free( _osc_connected_path ); + if ( _osc_output ) + { + delete _osc_output; + + _osc_output = NULL; + } - _osc_connected_path = NULL; + for ( list::iterator i = _persistent_osc_connections.begin(); + i != _persistent_osc_connections.end(); + ++i ) + { + free( *i ); + } + + _persistent_osc_connections.clear(); Loggable::block_end(); } @@ -123,7 +117,6 @@ Control_Sequence::init ( void ) color( fl_darker( FL_YELLOW ) ); interpolation( Linear ); - frequency( 10 ); } @@ -139,21 +132,24 @@ void Control_Sequence::get_unjournaled ( Log_Entry &e ) const { e.add( ":interpolation", _interpolation ); - if ( _osc_output->connected() ) + + if ( _osc_output && _osc_output->connected() ) { - char *path; - char *peer; + DMESSAGE( "OSC Output connections: %i", _osc_output->noutput_connections() ); + + for ( int i = 0; i < _osc_output->noutput_connections(); ++i ) + { + char *s; + + s = _osc_output->get_output_connection_peer_name_and_path(i); + + e.add( ":osc-output", s ); - _osc_output->get_connected_peer_name_and_path( &peer, &path ); - - e.add( ":osc-peer", peer ); - - e.add( ":osc-path", path ); - - free( path ); - free( peer ); + free( s ); + } } - /* e.add( ":frequency", frequency() ); */ + + e.add( ":mode", mode() ); } void @@ -188,21 +184,67 @@ Control_Sequence::set ( Log_Entry &e ) } else if ( ! strcmp( ":interpolation", s ) ) { - interpolation( (curve_type_e)atoi( v ) ); + interpolation( (Curve_Type)atoi( v ) ); } - /* else if ( ! strcmp( ":frequency", s ) ) */ - /* frequency( atoi( v ) ); */ - else if ( ! strcmp( ":osc-peer", s ) ) + else if ( ! strcmp( ":mode", s ) ) + mode( (Mode)atoi( v ) ); + else if ( ! strcmp( ":osc-output", s ) ) { - _osc_connected_peer = strdup( v ); - } - else if ( !strcmp( ":osc-path", s ) ) - { - _osc_connected_path = strdup( v ); + _persistent_osc_connections.push_back( strdup( v ) ); } } } +void +Control_Sequence::mode ( Mode m ) +{ + if ( CV != m && mode() == CV ) + { + if ( _output ) + { + _output->shutdown(); + + delete _output; + + _output = NULL; + } + } + else if ( OSC != m && mode() == OSC ) + { + if ( _osc_output ) + { + delete _osc_output; + + _osc_output = NULL; + } + } + + if ( CV == m && mode() != CV ) + { + _output = new JACK::Port( engine, JACK::Port::Output, track()->name(), track()->ncontrols(), "cv" ); + + if ( ! _output->activate() ) + { + fl_alert( "Could not create JACK port for control output on %s", track()->name() ); + delete _output; + _output = NULL; + } + } + else if ( OSC == m && mode() != OSC ) + { + char *path; + asprintf( &path, "/track/%s/control/%i", track()->name(), track()->ncontrols() ); + + _osc_output = timeline->osc->add_signal( path, OSC::Signal::Output, NULL, NULL ); + + free( path ); + + connect_osc(); + } + + _mode = m; +} + void Control_Sequence::draw_curve ( bool flip, bool filled ) { @@ -284,31 +326,31 @@ Control_Sequence::draw ( void ) const Fl_Color selection_color = active ? this->selection_color() : fl_inactive( this->selection_color() ); - if ( draw_with_gradient ) - { + if ( draw_with_gradient ) + { /* const Fl_Color c2 = fl_color_average( selection_color, FL_WHITE, 0.90f ); */ /* const Fl_Color c1 = fl_color_average( color, c2, 0.60f ); */ - const Fl_Color c1 = fl_color_average( selection_color, FL_WHITE, 0.90f ); - const Fl_Color c2 = fl_color_average( color, c1, 0.60f ); + const Fl_Color c1 = fl_color_average( selection_color, FL_WHITE, 0.90f ); + const Fl_Color c2 = fl_color_average( color, c1, 0.60f ); - for ( int gy = 0; gy < bh; gy++ ) - { - fl_color( fl_color_average( c1, c2, gy / (float)bh) ); - fl_line( X, by + gy, X + W, by + gy ); - } - } - - if ( draw_with_grid ) + for ( int gy = 0; gy < bh; gy++ ) { - fl_color( fl_darker( color ) ); - - const int inc = bh / 10; - if ( inc ) - for ( int gy = 0; gy < bh; gy += inc ) - fl_line( X, by + gy, X + W, by + gy ); - + fl_color( fl_color_average( c1, c2, gy / (float)bh) ); + fl_line( X, by + gy, X + W, by + gy ); } + } + + if ( draw_with_grid ) + { + fl_color( fl_darker( color ) ); + + const int inc = bh / 10; + if ( inc ) + for ( int gy = 0; gy < bh; gy += inc ) + fl_line( X, by + gy, X + W, by + gy ); + + } if ( interpolation() != None ) { @@ -379,21 +421,34 @@ Control_Sequence::menu_cb ( const Fl_Menu_ *m ) *index( peer_name, '/' ) = 0; - _osc_connected_peer = strdup( peer_name ); + const char *path = ((OSC::Signal*)m->mvalue()->user_data())->path(); - _osc_connected_path = strdup( ((OSC::Signal*)m->mvalue()->user_data())->path() ); + char *peer_and_path; + asprintf( &peer_and_path, "%s:%s", peer_name, path ); if ( ! _osc_output->is_connected_to( ((OSC::Signal*)m->mvalue()->user_data()) ) ) { + _persistent_osc_connections.push_back( peer_and_path ); + connect_osc(); } else { - timeline->osc->disconnect_signal( _osc_output, _osc_connected_peer, _osc_connected_path ); - - free( _osc_connected_path ); - free( _osc_connected_peer ); - _osc_connected_peer = _osc_connected_path = NULL; + timeline->osc->disconnect_signal( _osc_output, peer_name, path ); + + for ( std::list::iterator i = _persistent_osc_connections.begin(); + i != _persistent_osc_connections.end(); + ++i ) + { + if ( !strcmp( *i, peer_and_path ) ) + { + free( *i ); + i = _persistent_osc_connections.erase( i ); + break; + } + } + + free( peer_and_path ); } } @@ -401,18 +456,10 @@ Control_Sequence::menu_cb ( const Fl_Menu_ *m ) interpolation( Linear ); else if ( ! strcmp( picked, "Interpolation/None" ) ) interpolation( None ); - /* else if ( ! strcmp( picked, "Frequency/1Hz" ) ) */ - /* frequency( 1 ); */ - /* else if ( ! strcmp( picked, "Frequency/5Hz" ) ) */ - /* frequency( 5 ); */ - /* else if ( ! strcmp( picked, "Frequency/10Hz" ) ) */ - /* frequency( 10 ); */ - /* else if ( ! strcmp( picked, "Frequency/20Hz" ) ) */ - /* frequency( 20 ); */ - /* else if ( ! strcmp( picked, "Frequency/30Hz" ) ) */ - /* frequency( 30 ); */ - /* else if ( ! strcmp( picked, "Frequency/60Hz" ) ) */ - /* frequency( 60 ); */ + else if ( ! strcmp( picked, "Mode/Control Signal (OSC)" )) + mode( OSC ); + else if ( ! strcmp( picked, "Mode/Control Voltage (JACK)" ) ) + mode( CV ); else if ( ! strcmp( picked, "/Rename" ) ) { @@ -431,31 +478,23 @@ Control_Sequence::menu_cb ( const Fl_Menu_ *m ) void Control_Sequence::connect_osc ( void ) - { - if ( ! _osc_output ) + if ( _persistent_osc_connections.size() ) { - char *path; - asprintf( &path, "/non/daw/%s/control/%i", track()->name(), track()->ncontrols() ); - - _osc_output = timeline->osc->add_signal( path, OSC::Signal::Output, NULL, NULL ); - - free( path ); - } - - if ( _osc_connected_peer && _osc_connected_path ) - { - if ( ! timeline->osc->connect_signal( _osc_output, _osc_connected_peer, _osc_connected_path ) ) + for ( std::list::iterator i = _persistent_osc_connections.begin(); + i != _persistent_osc_connections.end(); + ++i ) { - // MESSAGE( "Failed to connect output %s to %s:%s", _osc_output->path(), _osc_connected_peer, _osc_connected_path ); - } - else - { - tooltip( _osc_connected_path ); + if ( ! timeline->osc->connect_signal( _osc_output, *i ) ) + { +// MESSAGE( "Failed to connect output %s to ", _osc_output->path(), *i ); + } + else + { + MESSAGE( "Connected output %s to %s", _osc_output->path(), *i ); -// _osc_connected_peer = _osc_connected_path = - - MESSAGE( "Connected output %s to %s:%s", _osc_output->path(), _osc_connected_peer, _osc_connected_path ); +// tooltip( _osc_connected_path ); + } } } } @@ -492,10 +531,15 @@ Control_Sequence::peer_callback( const char *name, const OSC::Signal *sig ) { char *s; + /* only list CV signals for now */ + if ( ! ( sig->parameter_limits().min == 0.0 && + sig->parameter_limits().max == 1.0 ) ) + return; + asprintf( &s, "%s/%s%s", peer_prefix, name, sig->path() ); peer_menu->add( s, 0, NULL, (void*)( sig ), - FL_MENU_TOGGLE | + FL_MENU_TOGGLE | ( _osc_output->is_connected_to( sig ) ? FL_MENU_VALUE : 0 ) ); free( s ); @@ -506,10 +550,10 @@ Control_Sequence::peer_callback( const char *name, const OSC::Signal *sig ) void Control_Sequence::add_osc_peers_to_menu ( Fl_Menu_Button *m, const char *prefix ) { - peer_menu = m; - peer_prefix = prefix; + peer_menu = m; + peer_prefix = prefix; - timeline->osc->list_peers( &Control_Sequence::peer_callback, this ); + timeline->osc->list_peers( &Control_Sequence::peer_callback, this ); } int @@ -549,37 +593,25 @@ Control_Sequence::handle ( int m ) } else if ( Fl::event_button3() && ! ( Fl::event_state() & ( FL_ALT | FL_SHIFT | FL_CTRL ) ) ) { - timeline->discover_peers(); - - timeline->osc->wait( 500 ); Fl_Menu_Button menu( 0, 0, 0, 0, "Control Sequence" ); - /* Fl_Menu_Button *con = new Fl_Menu_Button( 0, 0, 0, 0 ); */ - -// con->callback( &Control_Sequence::menu_cb, (void*)this ); - menu.clear(); - add_osc_peers_to_menu( &menu, "Connect To" ); + if ( mode() == OSC ) + { + add_osc_peers_to_menu( &menu, "Connect To" ); + } - /* menu.add( "Connect To", 0, 0, 0); */ - /* menu.add( "Connect To", 0, 0, const_cast< Fl_Menu_Item *>( con->menu() ), FL_SUBMENU_POINTER ); */ menu.add( "Interpolation/None", 0, 0, 0, FL_MENU_RADIO | ( interpolation() == None ? FL_MENU_VALUE : 0 ) ); menu.add( "Interpolation/Linear", 0, 0, 0, FL_MENU_RADIO | ( interpolation() == Linear ? FL_MENU_VALUE : 0 ) ); - - /* menu.add( "Frequency/1Hz", 0, 0, 0, FL_MENU_RADIO | ( frequency() == 1 ? FL_MENU_VALUE : 0 ) ); */ - /* menu.add( "Frequency/5Hz", 0, 0, 0, FL_MENU_RADIO | ( frequency() == 5 ? FL_MENU_VALUE : 0 ) ); */ - /* menu.add( "Frequency/10Hz", 0, 0, 0, FL_MENU_RADIO | ( frequency() == 10 ? FL_MENU_VALUE : 0 ) ); */ - /* menu.add( "Frequency/20Hz", 0, 0, 0, FL_MENU_RADIO | ( frequency() == 20 ? FL_MENU_VALUE : 0 ) ); */ - /* menu.add( "Frequency/30Hz", 0, 0, 0, FL_MENU_RADIO | ( frequency() == 30 ? FL_MENU_VALUE : 0 ) ); */ - /* menu.add( "Frequency/60Hz", 0, 0, 0, FL_MENU_RADIO | ( frequency() == 60 ? FL_MENU_VALUE : 0 ) ); */ - + menu.add( "Mode/Control Voltage (JACK)", 0, 0, 0 ,FL_MENU_RADIO | ( mode() == CV ? FL_MENU_VALUE : 0 ) ); + menu.add( "Mode/Control Signal (OSC)", 0, 0, 0 , FL_MENU_RADIO | ( mode() == OSC ? FL_MENU_VALUE : 0 ) ); menu.add( "Rename", 0, 0, 0 ); menu.add( "Remove", 0, 0, 0 ); - menu.callback( &Control_Sequence::menu_cb, (void*)this); + menu.callback( &Control_Sequence::menu_cb, (void*)this); menu_popup( &menu, x(), y() ); diff --git a/timeline/src/Control_Sequence.H b/timeline/src/Control_Sequence.H index f51c866..39f8688 100644 --- a/timeline/src/Control_Sequence.H +++ b/timeline/src/Control_Sequence.H @@ -36,7 +36,14 @@ class Control_Sequence : public Sequence public: - enum curve_type_e { None, Linear, Quadratic }; + enum Curve_Type { None, Linear, Quadratic }; + + enum Mode { + CV, + OSC, + MIDI + }; + private: @@ -44,8 +51,7 @@ private: /* these are used to cache the saved osc connection until the * session is loaded, at which time we will reconnect */ - char *_osc_connected_peer; - char *_osc_connected_path; + std::list _persistent_osc_connections; /* osc output port */ OSC::Signal *_osc_output; @@ -55,9 +61,7 @@ private: bool _highlighted; - curve_type_e _interpolation; - int _frequency; - float _interval; + Curve_Type _interpolation; void init ( void ); @@ -66,6 +70,7 @@ private: static void menu_cb ( Fl_Widget *w, void *v ); void menu_cb ( const Fl_Menu_ *m ); + Mode _mode; float _rate; @@ -87,6 +92,7 @@ protected: public: + static void process_osc ( void *v ); void process_osc ( void ); @@ -103,10 +109,11 @@ public: Fl_Cursor cursor ( void ) const { return FL_CURSOR_CROSS; } - curve_type_e interpolation ( void ) const { return _interpolation; } - void interpolation ( curve_type_e v ) { _interpolation = v; } - int frequency ( void ) const { return _frequency; } - void frequency ( int v ) { _frequency = v; _interval = ( 1.0f / (float)v ) / 2; } + Curve_Type interpolation ( void ) const { return _interpolation; } + void interpolation ( Curve_Type v ) { _interpolation = v; } + + Mode mode ( void ) const { return _mode; } + void mode ( Mode v ); /* Engine */ void output ( JACK::Port *p ) { _output = p; } diff --git a/timeline/src/Engine/Control_Sequence.C b/timeline/src/Engine/Control_Sequence.C index 4b78602..7340c3d 100644 --- a/timeline/src/Engine/Control_Sequence.C +++ b/timeline/src/Engine/Control_Sequence.C @@ -97,7 +97,10 @@ nframes_t Control_Sequence::process ( nframes_t nframes ) { THREAD_ASSERT( RT ); - + + if ( ! _output ) + return nframes; + if ( _output->connected() ) /* don't waste CPU on disconnected ports */ { void *buf = _output->buffer( nframes ); diff --git a/timeline/src/NSM.C b/timeline/src/NSM.C index 23c1d0f..c16baa8 100644 --- a/timeline/src/NSM.C +++ b/timeline/src/NSM.C @@ -23,6 +23,7 @@ #include "TLE.H" #include "NSM.H" #include "Project.H" +#include "OSC/Endpoint.H" #define OSC_INTERVAL 0.2f @@ -60,28 +61,32 @@ NSM_Client::command_open ( const char *name, const char *display_name, const cha timeline->osc->name( client_id ); + int r = 0; + if ( Project::validate( name ) ) { if ( timeline->command_load( name, display_name ) ) - return ERR_OK; + r = ERR_OK; else { *out_msg = strdup( "Failed to load for unknown reason" ); - return ERR_GENERAL; + r = ERR_GENERAL; } } else { if ( timeline->command_new( name, display_name ) ) - return ERR_OK; + r =ERR_OK; else { *out_msg = strdup( "Failed to load for unknown reason" ); - return ERR_GENERAL; + r = ERR_GENERAL; } } - return 0; + timeline->discover_peers(); + + return r; } void diff --git a/timeline/src/Timeline.C b/timeline/src/Timeline.C index e6845f7..2a862f2 100644 --- a/timeline/src/Timeline.C +++ b/timeline/src/Timeline.C @@ -52,6 +52,7 @@ /* */ #include "OSC_Thread.H" +#include "OSC/Endpoint.H" #include "NSM.H" extern NSM_Client *nsm; @@ -1528,9 +1529,7 @@ Timeline::command_load ( const char *name, const char *display_name ) Project::set_name ( display_name ? display_name : name ); - // discover_peers(); - - return true; + return true; } bool @@ -1553,9 +1552,7 @@ Timeline::command_new ( const char *name, const char *display_name ) /* tle->main_window->redraw(); */ - // discover_peers(); - - return b; + return b; } const char * @@ -1597,6 +1594,8 @@ Timeline::init_osc ( const char *osc_port ) /* 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->signal_peer_scan_complete.connect( sigc::mem_fun( this, &Timeline::connect_osc ) ); + if ( ! osc_thread ) { osc_thread = new OSC_Thread(); @@ -1619,14 +1618,11 @@ Timeline::osc_non_hello ( const char *path, const char *types, lo_arg **argv, in const char *version = &argv[2]->s; const char *id = &argv[3]->s; - MESSAGE( "Discovered OSC peer %s (%s) @ %s with ID \"%s\"", name, version, url, id ); - - MESSAGE( "Scanning..." ); - -// timeline->osc->scan_peer( id, url ); + MESSAGE( "Discovered NON peer %s (%s) @ %s with ID \"%s\"", name, version, url, id ); + MESSAGE( "Registering Signals" ); timeline->osc->hello( url ); - + return 0; } @@ -1673,24 +1669,17 @@ Timeline::connect_osc ( void ) void Timeline::discover_peers ( void ) { - lo_message m = lo_message_new(); + if ( nsm->is_active() ) + { + lo_message m = lo_message_new(); + + lo_message_add_string( m, "/non/finger" ); + lo_message_add_string( m, osc->url() ); - lo_message_add_string( m, "/non/finger" ); - lo_message_add_string( m, osc->url() ); - - nsm->broadcast( m ); - - lo_message_free( m ); - - /* wait for responses and then autoconnect outputs */ - - MESSAGE( "Waiting for OSC peers..." ); - - osc->wait( 1000 ); - - MESSAGE( "Reconnecting signals." ); - - connect_osc(); + nsm->broadcast( m ); + + lo_message_free( m ); + } } diff --git a/timeline/src/Timeline.H b/timeline/src/Timeline.H index 2d73283..51a7e2f 100644 --- a/timeline/src/Timeline.H +++ b/timeline/src/Timeline.H @@ -31,7 +31,6 @@ #include #include -#include "OSC/Endpoint.H" #include "OSC_Thread.H" class Fl_Scroll; @@ -54,6 +53,10 @@ class Scalebar; class Sequence; class Sequence_Widget; +namespace OSC { class Endpoint; } + +#include + #ifndef USE_SINGLEBUFFERED_TIMELINE #include #else @@ -236,8 +239,6 @@ public: /* OSC */ - - void connect_osc ( void ); void discover_peers ( void );