| @@ -48,6 +48,8 @@ | |||||
| #include <lo/lo.h> | #include <lo/lo.h> | ||||
| #include "FL/Fl_Blinker.H" | #include "FL/Fl_Blinker.H" | ||||
| #include "OSC/Endpoint.H" | |||||
| const double STATUS_UPDATE_FREQ = 0.2f; | const double STATUS_UPDATE_FREQ = 0.2f; | ||||
| const double OSC_INTERVAL = 1.0 / 20.0; /* 20 hz */ | 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 */ | /* Commands */ | ||||
| /************/ | /************/ | ||||
| @@ -29,8 +29,8 @@ | |||||
| class Fl_Blinker; | class Fl_Blinker; | ||||
| class Fl_Flowpack; | class Fl_Flowpack; | ||||
| class Fl_Menu_Bar; | class Fl_Menu_Bar; | ||||
| #include "OSC/Endpoint.H" | |||||
| namespace OSC { class Endpoint; } | |||||
| #include <lo/lo.h> | |||||
| class Mixer : public Fl_Group | class Mixer : public Fl_Group | ||||
| { | { | ||||
| @@ -105,6 +105,8 @@ public: | |||||
| void say_hello ( void ); | void say_hello ( void ); | ||||
| void discover_peers ( void ); | |||||
| public: | public: | ||||
| bool command_save ( void ); | bool command_save ( void ); | ||||
| @@ -39,6 +39,8 @@ | |||||
| #include "FL/menu_popup.H" | #include "FL/menu_popup.H" | ||||
| #include "Mixer.H" | #include "Mixer.H" | ||||
| #include "OSC/Endpoint.H" | |||||
| Module *Module::_copied_module_empty = 0; | Module *Module::_copied_module_empty = 0; | ||||
| @@ -226,7 +228,7 @@ Module::Port::generate_osc_path () | |||||
| char *path = NULL; | char *path = NULL; | ||||
| // /mixer/STRIPNAME/MODULENAME/CONTROLNAME | |||||
| // /strip/STRIPNAME/MODULENAME/CONTROLNAME | |||||
| if ( ! module()->allows_external_control() ) | if ( ! module()->allows_external_control() ) | ||||
| { | { | ||||
| @@ -237,9 +239,9 @@ Module::Port::generate_osc_path () | |||||
| int n = module()->chain()->get_module_instance_number( module() ); | int n = module()->chain()->get_module_instance_number( module() ); | ||||
| if ( n > 0 ) | 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 | 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. | // Hack to keep spaces out of OSC URL... Probably need to handle other special characters similarly. | ||||
| for ( int i = strlen( path ); i--; ) | for ( int i = strlen( path ); i--; ) | ||||
| @@ -251,6 +253,12 @@ Module::Port::generate_osc_path () | |||||
| return path; | return path; | ||||
| } | } | ||||
| void | |||||
| Module::Port::handle_signal_connection_state_changed ( OSC::Signal *s ) | |||||
| { | |||||
| module()->redraw(); | |||||
| } | |||||
| void | void | ||||
| Module::Port::change_osc_path ( char *path ) | Module::Port::change_osc_path ( char *path ) | ||||
| { | { | ||||
| @@ -261,20 +269,26 @@ Module::Port::change_osc_path ( char *path ) | |||||
| asprintf( &unscaled_path, "%s/unscaled", path ); | asprintf( &unscaled_path, "%s/unscaled", path ); | ||||
| if ( ! ( _scaled_signal && _unscaled_signal ) ) | |||||
| if ( NULL == _scaled_signal ) | |||||
| { | { | ||||
| _scaled_signal = | _scaled_signal = | ||||
| mixer->osc_endpoint->add_signal( scaled_path, | mixer->osc_endpoint->add_signal( scaled_path, | ||||
| OSC::Signal::Input, &Module::Port::osc_control_change_cv, this ); | 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 = | _unscaled_signal = | ||||
| mixer->osc_endpoint->add_signal( unscaled_path, | mixer->osc_endpoint->add_signal( unscaled_path, | ||||
| OSC::Signal::Input, &Module::Port::osc_control_change_exact, this ); | OSC::Signal::Input, &Module::Port::osc_control_change_exact, this ); | ||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| DMESSAGE( "Renaming OSC signals" ); | |||||
| _scaled_signal->rename( scaled_path ); | _scaled_signal->rename( scaled_path ); | ||||
| _unscaled_signal->rename( unscaled_path ); | _unscaled_signal->rename( unscaled_path ); | ||||
| return; | |||||
| } | } | ||||
| free( unscaled_path ); | 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 + 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() ) | if ( control_output.size() ) | ||||
| @@ -170,13 +170,12 @@ public: | |||||
| void update_osc_port ( ) | 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 ( ) | void destroy_osc_port ( ) | ||||
| { | { | ||||
| delete _unscaled_signal; | delete _unscaled_signal; | ||||
| delete _scaled_signal; | delete _scaled_signal; | ||||
| @@ -256,8 +255,11 @@ public: | |||||
| nframes_t _nframes; | nframes_t _nframes; | ||||
| Module *_module; | Module *_module; | ||||
| OSC::Signal *_scaled_signal; | OSC::Signal *_scaled_signal; | ||||
| OSC::Signal *_unscaled_signal; | OSC::Signal *_unscaled_signal; | ||||
| void handle_signal_connection_state_changed ( OSC::Signal *s ); | |||||
| }; | }; | ||||
| void bbox ( int &X, int &Y, int &W, int &H ) | void bbox ( int &X, int &Y, int &W, int &H ) | ||||
| @@ -23,6 +23,8 @@ | |||||
| #include "NSM.H" | #include "NSM.H" | ||||
| #include "Project.H" | #include "Project.H" | ||||
| #include "OSC/Endpoint.H" | |||||
| extern char *instance_name; | extern char *instance_name; | ||||
| extern Mixer *mixer; | 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(); | Fl::unlock(); | ||||
| return r; | return r; | ||||
| @@ -70,30 +70,24 @@ namespace OSC | |||||
| void | void | ||||
| Signal::rename ( const char *path ) | Signal::rename ( const char *path ) | ||||
| { | { | ||||
| for ( std::list<Target*>::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 ); | free( _path ); | ||||
| _path = strdup( path ); | _path = strdup( path ); | ||||
| _endpoint->send_signal_rename_notifications( this ); | |||||
| } | } | ||||
| bool | bool | ||||
| Signal::is_connected_to ( const OSC::Signal *s ) const | Signal::is_connected_to ( const OSC::Signal *s ) const | ||||
| { | { | ||||
| for ( std::list<Target*>::const_iterator i = _outgoing.begin(); | |||||
| for ( std::list<Signal*>::const_iterator i = _outgoing.begin(); | |||||
| i != _outgoing.end(); | i != _outgoing.end(); | ||||
| ++i ) | ++i ) | ||||
| { | { | ||||
| if ( (*i)->peer == s->_peer && | |||||
| (*i)->signal_id == s->id() ) | |||||
| if ( (*i)->_peer == s->_peer && | |||||
| (*i)->id() == s->id() ) | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -103,31 +97,47 @@ namespace OSC | |||||
| void | void | ||||
| Signal::value ( float f ) | Signal::value ( float f ) | ||||
| { | { | ||||
| for ( std::list<Target*>::const_iterator i = _outgoing.begin(); | |||||
| for ( std::list<Signal*>::const_iterator i = _outgoing.begin(); | |||||
| i != _outgoing.end(); | i != _outgoing.end(); | ||||
| ++i ) | ++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", | "/signal/change", | ||||
| (*i)->signal_id, | |||||
| id(), | |||||
| (*i)->id(), | |||||
| f ); | 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; | |||||
| int j = 0; | |||||
| for ( std::list<Signal*>::const_iterator i = _outgoing.begin(); | |||||
| i != _outgoing.end(); | |||||
| ++i, ++j ) | |||||
| { | |||||
| if ( j == n ) | |||||
| { | |||||
| t = *i; | |||||
| break; | |||||
| } | |||||
| } | |||||
| // Signal *s = get_peer_signal_by_id( t->_peer, t->signal_id ); | |||||
| Signal *s = get_peer_signal_by_id( t->peer, t->signal_id ); | |||||
| char *r; | |||||
| asprintf( &r, "%s:%s", t->_peer->name, t->path() ); | |||||
| *peer_name = strdup( t->peer->name ); | |||||
| *path = strdup( s->path() ); | |||||
| return r; | |||||
| } | } | ||||
| void | 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/connect", "ii", &Endpoint::osc_sig_connect, this, "" ); | ||||
| add_method( "/signal/disconnect", "ii", &Endpoint::osc_sig_disconnect, this, "" ); | add_method( "/signal/disconnect", "ii", &Endpoint::osc_sig_disconnect, this, "" ); | ||||
| add_method( "/signal/renamed", "is", &Endpoint::osc_sig_renamed, 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( "/signal/list", NULL, &Endpoint::osc_signal_lister, this, "" ); | ||||
| add_method( NULL, "", &Endpoint::osc_generic, this, "" ); | |||||
| add_method( "/reply", NULL, &Endpoint::osc_reply, this, "" ); | add_method( "/reply", NULL, &Endpoint::osc_reply, this, "" ); | ||||
| return 0; | return 0; | ||||
| @@ -173,15 +185,15 @@ namespace OSC | |||||
| lo_server_free( _server ); | lo_server_free( _server ); | ||||
| } | } | ||||
| OSC::Target * | |||||
| Endpoint::find_target_by_peer_address ( std::list<Target*> *l, lo_address addr ) | |||||
| OSC::Signal * | |||||
| Endpoint::find_target_by_peer_address ( std::list<Signal*> *l, lo_address addr ) | |||||
| { | { | ||||
| for ( std::list<Target*>::iterator i = l->begin(); | |||||
| for ( std::list<Signal*>::iterator i = l->begin(); | |||||
| i != l->end(); | i != l->end(); | ||||
| ++i ) | ++i ) | ||||
| { | { | ||||
| if ( address_matches( addr, (*i)->peer->addr ) ) | |||||
| if ( address_matches( addr, (*i)->_peer->addr ) ) | |||||
| { | { | ||||
| return *i; | return *i; | ||||
| } | } | ||||
| @@ -237,8 +249,10 @@ namespace OSC | |||||
| { | { | ||||
| lo_address addr = lo_address_new_from_url ( url ); | 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 ); | lo_address_free( addr ); | ||||
| } | } | ||||
| @@ -248,18 +262,15 @@ namespace OSC | |||||
| Endpoint *ep = (Endpoint*)user_data; | Endpoint *ep = (Endpoint*)user_data; | ||||
| const char *peer_name = &argv[0]->s; | const char *peer_name = &argv[0]->s; | ||||
| const char *peer_url = &argv[1]->s; | |||||
| DMESSAGE( "Got hello from %s", peer_name ); | DMESSAGE( "Got hello from %s", peer_name ); | ||||
| if ( ! ep->find_peer_by_name( 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, url ); | |||||
| ep->send( lo_message_get_source( msg ), "/signal/hello", ep->name() ); | |||||
| ep->scan_peer( peer_name, peer_url ); | |||||
| free(url); | |||||
| ep->hello( peer_url ); | |||||
| } | } | ||||
| return 0; | return 0; | ||||
| @@ -290,21 +301,13 @@ namespace OSC | |||||
| if ( s->_direction == Signal::Input ) | if ( s->_direction == Signal::Input ) | ||||
| { | { | ||||
| for ( std::list<Target*>::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; | return 0; | ||||
| @@ -347,24 +350,109 @@ namespace OSC | |||||
| DMESSAGE( "Peer %s has connected to signal %s", p->name, s->path() ); | 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; | |||||
| WARNING( "Got signal remove notification from unknown peer." ); | |||||
| return 0; | |||||
| } | |||||
| t->peer = p; | |||||
| t->signal_id = ps->id(); | |||||
| Signal *o = ep->find_peer_signal_by_id( p, id ); | |||||
| s->_incoming.push_back( t ); | |||||
| if ( ! o ) | |||||
| { | |||||
| WARNING( "Unknown signal id %i", id ); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| DMESSAGE( "Signal %s:%s was removed", o->_peer->name, o->path() ); | |||||
| /* disconnect it */ | |||||
| for ( std::list<Signal*>::iterator i = o->_outgoing.begin(); | |||||
| i != o->_outgoing.end(); | |||||
| ++i ) | |||||
| { | |||||
| ep->disconnect_signal( o, *i ); | |||||
| } | |||||
| for ( std::list<Signal*>::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; | return 0; | ||||
| } | } | ||||
| int | int | ||||
| Endpoint::osc_sig_renamed ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) | 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; | int id = argv[0]->i; | ||||
| char *new_name = &argv[1]->s; | char *new_name = &argv[1]->s; | ||||
| @@ -386,7 +474,7 @@ namespace OSC | |||||
| return 0; | 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 ); | free( o->_path ); | ||||
| o->_path = strdup( new_name ); | o->_path = strdup( new_name ); | ||||
| @@ -399,13 +487,18 @@ namespace OSC | |||||
| { | { | ||||
| Signal *o; | Signal *o; | ||||
| float f = 0.0; | 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 */ | /* 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 ) | if ( ! o ) | ||||
| { | { | ||||
| WARNING( "Unknown signal id %i", id ); | WARNING( "Unknown signal id %i", id ); | ||||
| @@ -429,26 +522,44 @@ namespace OSC | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| Target *t = NULL; | |||||
| Peer *p = NULL; | |||||
| if ( ep ) | |||||
| p = ep->find_peer_by_address( lo_message_get_source( msg ) ); | |||||
| if ( 0 == o->_incoming.size() ) | |||||
| return 0; | |||||
| if ( 0 == o->_incoming.size() || | |||||
| ! ( t = find_target_by_peer_address( &o->_incoming, lo_message_get_source( msg ) ) ) ) | |||||
| if ( !p ) | |||||
| { | { | ||||
| DMESSAGE( "Signal change initiated by an unknown peer" ); | |||||
| /* message came from an unconnected peer, just set the value exactly */ | /* message came from an unconnected peer, just set the value exactly */ | ||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| /* message is from a connected source, do mixing. */ | /* message is from a connected source, do mixing. */ | ||||
| t->value = f; | |||||
| /* remote signal */ | |||||
| /* if ( t->_peer ) */ | |||||
| for ( std::list<Signal*>::const_iterator i = o->_incoming.begin(); | |||||
| i != o->_incoming.end(); | |||||
| ++i ) | |||||
| { | |||||
| if ( (*i)->id() == argv[0]->i ) | |||||
| { | |||||
| (*i)->_value = f; | |||||
| break; | |||||
| } | |||||
| } | |||||
| f = 0.0; | f = 0.0; | ||||
| for ( std::list<Target*>::const_iterator i = o->_incoming.begin(); | |||||
| for ( std::list<Signal*>::const_iterator i = o->_incoming.begin(); | |||||
| i != o->_incoming.end(); | i != o->_incoming.end(); | ||||
| ++i ) | ++i ) | ||||
| { | { | ||||
| f += (*i)->value; | |||||
| f += (*i)->_value; | |||||
| } | } | ||||
| } | } | ||||
| @@ -599,7 +710,25 @@ namespace OSC | |||||
| } | } | ||||
| bool | 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 ) | if ( s->_direction == Signal::Output ) | ||||
| { | { | ||||
| @@ -613,33 +742,53 @@ namespace OSC | |||||
| if ( ! ps ) | if ( ! ps ) | ||||
| return false; | return false; | ||||
| MESSAGE( "Disconnecting signal output \"%s\" to %s:%i", s->path(), peer_name, ps->_id ); | |||||
| for ( std::list<Target*>::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 ); | |||||
| if ( ! s->is_connected_to( ps ) ) | |||||
| return false; | |||||
| DMESSAGE( "Number of outgoing connections: %i", s->_outgoing.size() ); | |||||
| return true; | |||||
| } | |||||
| } | |||||
| return disconnect_signal( s, ps ); | |||||
| } | } | ||||
| return false; | 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 | bool | ||||
| Endpoint::connect_signal( OSC::Signal *s, const char *peer_name, const char *signal_path ) | Endpoint::connect_signal( OSC::Signal *s, const char *peer_name, const char *signal_path ) | ||||
| { | { | ||||
| @@ -655,25 +804,7 @@ namespace OSC | |||||
| if ( ! ps ) | if ( ! ps ) | ||||
| return false; | 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; | return false; | ||||
| @@ -688,24 +819,13 @@ namespace OSC | |||||
| if ( !p ) | if ( !p ) | ||||
| return false; | 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; | return false; | ||||
| @@ -745,10 +865,12 @@ namespace OSC | |||||
| { | { | ||||
| p->_scanning = false; | p->_scanning = false; | ||||
| DMESSAGE( "Done scanning %s", p->name ); | 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; | int dir = 0; | ||||
| @@ -761,9 +883,7 @@ namespace OSC | |||||
| s->_peer = p; | s->_peer = p; | ||||
| s->_id = argv[3]->i; | 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 ); | p->_signals.push_back( s ); | ||||
| } | } | ||||
| @@ -790,9 +910,6 @@ namespace OSC | |||||
| if ( argument_description ) | if ( argument_description ) | ||||
| md->_documentation = strdup( argument_description ); | md->_documentation = strdup( argument_description ); | ||||
| if ( typespec ) | |||||
| md->_parameter_limits = new Parameter_Limits[strlen(typespec)]; | |||||
| _methods.push_back( md ); | _methods.push_back( md ); | ||||
| return md; | return md; | ||||
| @@ -801,23 +918,39 @@ namespace OSC | |||||
| Signal * | Signal * | ||||
| Endpoint::add_signal ( const char *path, Signal::Direction dir, signal_handler handler, void *user_data ) | 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 ) | 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 ) | 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<Peer*>::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 | void | ||||
| @@ -855,6 +988,21 @@ namespace OSC | |||||
| _methods.remove( meth ); | _methods.remove( meth ); | ||||
| } | } | ||||
| void | |||||
| Endpoint::send_signal_rename_notifications ( Signal *s ) | |||||
| { | |||||
| for ( std::list<Peer*>::const_iterator i = _peers.begin(); | |||||
| i != _peers.end(); | |||||
| ++i ) | |||||
| { | |||||
| send( (*i)->addr, | |||||
| "/signal/renamed", | |||||
| s->id(), | |||||
| s->path() ); | |||||
| } | |||||
| } | |||||
| void | void | ||||
| Endpoint::del_signal ( Signal *o ) | Endpoint::del_signal ( Signal *o ) | ||||
| { | { | ||||
| @@ -862,6 +1010,17 @@ namespace OSC | |||||
| lo_server_del_method( _server, o->path(), "f" ); | lo_server_del_method( _server, o->path(), "f" ); | ||||
| /* tell our peers about it */ | |||||
| for ( std::list<Peer*>::iterator i = _peers.begin(); | |||||
| i != _peers.end(); | |||||
| ++i ) | |||||
| { | |||||
| send( (*i)->addr, | |||||
| "/signal/removed", | |||||
| o->id() ); | |||||
| } | |||||
| /* FIXME: clear loopback connections first! */ | |||||
| // delete o; | // delete o; | ||||
| _signals.remove( o ); | _signals.remove( o ); | ||||
| @@ -1127,7 +1286,7 @@ namespace OSC | |||||
| int | 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 ) | 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 | int | ||||
| @@ -1147,4 +1306,16 @@ namespace OSC | |||||
| { | { | ||||
| return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "if", v1, v2 ); | 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 ); | |||||
| } | |||||
| } | } | ||||
| @@ -25,6 +25,8 @@ | |||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| #include <sigc++/sigc++.h> | |||||
| namespace OSC | namespace OSC | ||||
| { | { | ||||
| class OSC_Value | class OSC_Value | ||||
| @@ -125,13 +127,6 @@ namespace OSC | |||||
| std::list<Signal*> _signals; | std::list<Signal*> _signals; | ||||
| }; | }; | ||||
| struct Target | |||||
| { | |||||
| Peer *peer; | |||||
| int signal_id; | |||||
| float value; | |||||
| }; | |||||
| typedef int (*signal_handler) ( float value, void *user_data ); | typedef int (*signal_handler) ( float value, void *user_data ); | ||||
| class Signal | class Signal | ||||
| @@ -159,24 +154,17 @@ namespace OSC | |||||
| float _value; | float _value; | ||||
| std::list<Target*> _outgoing; | |||||
| std::list<Signal*> _outgoing; | |||||
| std::list<Signal*> _incoming; | |||||
| Direction _direction; | 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<Target*> _incoming; | |||||
| signal_handler _handler; | signal_handler _handler; | ||||
| void *_user_data; | void *_user_data; | ||||
| Parameter_Limits _parameter_limits; | |||||
| public: | public: | ||||
| Parameter_Limits _parameter_limits; | |||||
| Signal ( const char *path, Direction dir ) | Signal ( const char *path, Direction dir ) | ||||
| { | { | ||||
| _direction = dir; | _direction = dir; | ||||
| @@ -187,12 +175,17 @@ namespace OSC | |||||
| _peer = NULL; | _peer = NULL; | ||||
| } | } | ||||
| sigc::signal <void,Signal*> signal_connection_state_changed; | |||||
| ~Signal ( ); | ~Signal ( ); | ||||
| static Signal *get_peer_signal_by_id ( Peer *p, int signal_id ); | 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(); } | 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; } | int id ( void ) const { return _id; } | ||||
| Direction direction ( void ) { return _direction; } | Direction direction ( void ) { return _direction; } | ||||
| @@ -205,7 +198,7 @@ namespace OSC | |||||
| _value = default_value; | _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; } | const char *path ( void ) const { return _path; } | ||||
| @@ -226,7 +219,6 @@ namespace OSC | |||||
| char *_path; | char *_path; | ||||
| char *_typespec; | char *_typespec; | ||||
| char *_documentation; | char *_documentation; | ||||
| struct Parameter_Limits *_parameter_limits; | |||||
| public: | 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_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_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_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_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_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 ); | 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 ); | Peer *find_peer_by_address ( lo_address addr ); | ||||
| static bool address_matches ( lo_address addr1, lo_address addr2 ); | static bool address_matches ( lo_address addr1, lo_address addr2 ); | ||||
| static Target *find_target_by_peer_address ( std::list<Target*> *l, lo_address addr ); | |||||
| static Signal *find_target_by_peer_address ( std::list<Signal*> *l, lo_address addr ); | |||||
| char *_name; | char *_name; | ||||
| void del_signal ( Signal *signal ); | |||||
| void send_signal_rename_notifications( Signal *s ); | |||||
| public: | public: | ||||
| void list_peers ( void (*callback) (const char *, const OSC::Signal *, void * ), void *v ); | void list_peers ( void (*callback) (const char *, const OSC::Signal *, void * ), void *v ); | ||||
| @@ -291,16 +288,20 @@ namespace OSC | |||||
| ~Endpoint ( ); | ~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 ); | 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 ); | 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 ( const char *path, const char *typespec ); | ||||
| void del_method ( Method* method ); | void del_method ( Method* method ); | ||||
| void del_signal ( Signal *signal ); | |||||
| void start ( void ); | void start ( void ); | ||||
| void stop ( void ); | void stop ( void ); | ||||
| int port ( void ) const; | 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, long v ); | ||||
| int send ( lo_address to, const char *path, int v1, int v2 ); | 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, 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 *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, float v2 ); | ||||
| int send ( lo_address to, const char *path, const char *v1, int v2, int v3 ); | 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, 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, 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, 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 ); | 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. | // can be used to point back to owning object. | ||||
| void *owner; | void *owner; | ||||
| sigc::signal <void> signal_peer_scan_complete; | |||||
| friend Signal::~Signal(); | |||||
| friend void Signal::rename ( const char *name ); | |||||
| }; | }; | ||||
| }; | }; | ||||
| @@ -32,6 +32,8 @@ using std::list; | |||||
| #include "Transport.H" | #include "Transport.H" | ||||
| #include "OSC/Endpoint.H" | |||||
| bool Control_Sequence::draw_with_gradient = true; | bool Control_Sequence::draw_with_gradient = true; | ||||
| @@ -44,28 +46,15 @@ Control_Sequence::Control_Sequence ( Track *track ) : Sequence( 0 ) | |||||
| { | { | ||||
| init(); | init(); | ||||
| _osc_connected_peer = _osc_connected_path = 0; | |||||
| _track = track; | _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; | _osc_output = 0; | ||||
| _output = 0; | |||||
| _mode = CV; | |||||
| mode( OSC ); | |||||
| if ( track ) | if ( track ) | ||||
| track->add( this ); | track->add( this ); | ||||
| @@ -90,25 +79,30 @@ Control_Sequence::~Control_Sequence ( ) | |||||
| engine->unlock(); | engine->unlock(); | ||||
| _output->shutdown(); | |||||
| delete _output; | |||||
| _output = NULL; | |||||
| delete _osc_output; | |||||
| _osc_output = NULL; | |||||
| if ( _output ) | |||||
| { | |||||
| _output->shutdown(); | |||||
| 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<char*>::iterator i = _persistent_osc_connections.begin(); | |||||
| i != _persistent_osc_connections.end(); | |||||
| ++i ) | |||||
| { | |||||
| free( *i ); | |||||
| } | |||||
| _persistent_osc_connections.clear(); | |||||
| Loggable::block_end(); | Loggable::block_end(); | ||||
| } | } | ||||
| @@ -123,7 +117,6 @@ Control_Sequence::init ( void ) | |||||
| color( fl_darker( FL_YELLOW ) ); | color( fl_darker( FL_YELLOW ) ); | ||||
| interpolation( Linear ); | interpolation( Linear ); | ||||
| frequency( 10 ); | |||||
| } | } | ||||
| @@ -139,21 +132,24 @@ void | |||||
| Control_Sequence::get_unjournaled ( Log_Entry &e ) const | Control_Sequence::get_unjournaled ( Log_Entry &e ) const | ||||
| { | { | ||||
| e.add( ":interpolation", _interpolation ); | e.add( ":interpolation", _interpolation ); | ||||
| if ( _osc_output->connected() ) | |||||
| if ( _osc_output && _osc_output->connected() ) | |||||
| { | { | ||||
| char *path; | |||||
| char *peer; | |||||
| _osc_output->get_connected_peer_name_and_path( &peer, &path ); | |||||
| e.add( ":osc-peer", peer ); | |||||
| e.add( ":osc-path", path ); | |||||
| 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 ); | |||||
| free( path ); | |||||
| free( peer ); | |||||
| free( s ); | |||||
| } | |||||
| } | } | ||||
| /* e.add( ":frequency", frequency() ); */ | |||||
| e.add( ":mode", mode() ); | |||||
| } | } | ||||
| void | void | ||||
| @@ -188,19 +184,65 @@ Control_Sequence::set ( Log_Entry &e ) | |||||
| } | } | ||||
| else if ( ! strcmp( ":interpolation", s ) ) | else if ( ! strcmp( ":interpolation", s ) ) | ||||
| { | { | ||||
| interpolation( (curve_type_e)atoi( v ) ); | |||||
| interpolation( (Curve_Type)atoi( v ) ); | |||||
| } | |||||
| else if ( ! strcmp( ":mode", s ) ) | |||||
| mode( (Mode)atoi( v ) ); | |||||
| else if ( ! strcmp( ":osc-output", s ) ) | |||||
| { | |||||
| _persistent_osc_connections.push_back( strdup( v ) ); | |||||
| } | } | ||||
| /* else if ( ! strcmp( ":frequency", s ) ) */ | |||||
| /* frequency( atoi( v ) ); */ | |||||
| else if ( ! strcmp( ":osc-peer", s ) ) | |||||
| } | |||||
| } | |||||
| void | |||||
| Control_Sequence::mode ( Mode m ) | |||||
| { | |||||
| if ( CV != m && mode() == CV ) | |||||
| { | |||||
| if ( _output ) | |||||
| { | { | ||||
| _osc_connected_peer = strdup( v ); | |||||
| _output->shutdown(); | |||||
| delete _output; | |||||
| _output = NULL; | |||||
| } | } | ||||
| else if ( !strcmp( ":osc-path", s ) ) | |||||
| } | |||||
| 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() ) | |||||
| { | { | ||||
| _osc_connected_path = strdup( v ); | |||||
| 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 | void | ||||
| @@ -284,31 +326,31 @@ Control_Sequence::draw ( void ) | |||||
| const Fl_Color selection_color = active ? this->selection_color() : fl_inactive( this->selection_color() ); | 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 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( 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 ); | |||||
| } | |||||
| 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 ) | |||||
| { | |||||
| fl_color( fl_darker( color ) ); | |||||
| 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 ); | |||||
| 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 ) | if ( interpolation() != None ) | ||||
| { | { | ||||
| @@ -379,21 +421,34 @@ Control_Sequence::menu_cb ( const Fl_Menu_ *m ) | |||||
| *index( peer_name, '/' ) = 0; | *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()) ) ) | if ( ! _osc_output->is_connected_to( ((OSC::Signal*)m->mvalue()->user_data()) ) ) | ||||
| { | { | ||||
| _persistent_osc_connections.push_back( peer_and_path ); | |||||
| connect_osc(); | connect_osc(); | ||||
| } | } | ||||
| else | 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<char*>::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 ); | interpolation( Linear ); | ||||
| else if ( ! strcmp( picked, "Interpolation/None" ) ) | else if ( ! strcmp( picked, "Interpolation/None" ) ) | ||||
| 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" ) ) | else if ( ! strcmp( picked, "/Rename" ) ) | ||||
| { | { | ||||
| @@ -431,31 +478,23 @@ Control_Sequence::menu_cb ( const Fl_Menu_ *m ) | |||||
| void | void | ||||
| Control_Sequence::connect_osc ( 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 ) ) | |||||
| { | |||||
| // MESSAGE( "Failed to connect output %s to %s:%s", _osc_output->path(), _osc_connected_peer, _osc_connected_path ); | |||||
| } | |||||
| else | |||||
| for ( std::list<char*>::iterator i = _persistent_osc_connections.begin(); | |||||
| i != _persistent_osc_connections.end(); | |||||
| ++i ) | |||||
| { | { | ||||
| tooltip( _osc_connected_path ); | |||||
| // _osc_connected_peer = _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 ); | |||||
| 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; | 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() ); | asprintf( &s, "%s/%s%s", peer_prefix, name, sig->path() ); | ||||
| peer_menu->add( s, 0, NULL, (void*)( sig ), | peer_menu->add( s, 0, NULL, (void*)( sig ), | ||||
| FL_MENU_TOGGLE | | |||||
| FL_MENU_TOGGLE | | |||||
| ( _osc_output->is_connected_to( sig ) ? FL_MENU_VALUE : 0 ) ); | ( _osc_output->is_connected_to( sig ) ? FL_MENU_VALUE : 0 ) ); | ||||
| free( s ); | free( s ); | ||||
| @@ -506,10 +550,10 @@ Control_Sequence::peer_callback( const char *name, const OSC::Signal *sig ) | |||||
| void | void | ||||
| Control_Sequence::add_osc_peers_to_menu ( Fl_Menu_Button *m, const char *prefix ) | 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 | int | ||||
| @@ -549,37 +593,25 @@ Control_Sequence::handle ( int m ) | |||||
| } | } | ||||
| else if ( Fl::event_button3() && ! ( Fl::event_state() & ( FL_ALT | FL_SHIFT | FL_CTRL ) ) ) | 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 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(); | 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/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( "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( "Rename", 0, 0, 0 ); | ||||
| menu.add( "Remove", 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() ); | menu_popup( &menu, x(), y() ); | ||||
| @@ -36,7 +36,14 @@ class Control_Sequence : public Sequence | |||||
| public: | public: | ||||
| enum curve_type_e { None, Linear, Quadratic }; | |||||
| enum Curve_Type { None, Linear, Quadratic }; | |||||
| enum Mode { | |||||
| CV, | |||||
| OSC, | |||||
| MIDI | |||||
| }; | |||||
| private: | private: | ||||
| @@ -44,8 +51,7 @@ private: | |||||
| /* these are used to cache the saved osc connection until the | /* these are used to cache the saved osc connection until the | ||||
| * session is loaded, at which time we will reconnect */ | * session is loaded, at which time we will reconnect */ | ||||
| char *_osc_connected_peer; | |||||
| char *_osc_connected_path; | |||||
| std::list<char*> _persistent_osc_connections; | |||||
| /* osc output port */ | /* osc output port */ | ||||
| OSC::Signal *_osc_output; | OSC::Signal *_osc_output; | ||||
| @@ -55,9 +61,7 @@ private: | |||||
| bool _highlighted; | bool _highlighted; | ||||
| curve_type_e _interpolation; | |||||
| int _frequency; | |||||
| float _interval; | |||||
| Curve_Type _interpolation; | |||||
| void init ( void ); | void init ( void ); | ||||
| @@ -66,6 +70,7 @@ private: | |||||
| static void menu_cb ( Fl_Widget *w, void *v ); | static void menu_cb ( Fl_Widget *w, void *v ); | ||||
| void menu_cb ( const Fl_Menu_ *m ); | void menu_cb ( const Fl_Menu_ *m ); | ||||
| Mode _mode; | |||||
| float _rate; | float _rate; | ||||
| @@ -87,6 +92,7 @@ protected: | |||||
| public: | public: | ||||
| static void process_osc ( void *v ); | static void process_osc ( void *v ); | ||||
| void process_osc ( void ); | void process_osc ( void ); | ||||
| @@ -103,10 +109,11 @@ public: | |||||
| Fl_Cursor cursor ( void ) const { return FL_CURSOR_CROSS; } | 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 */ | /* Engine */ | ||||
| void output ( JACK::Port *p ) { _output = p; } | void output ( JACK::Port *p ) { _output = p; } | ||||
| @@ -97,7 +97,10 @@ nframes_t | |||||
| Control_Sequence::process ( nframes_t nframes ) | Control_Sequence::process ( nframes_t nframes ) | ||||
| { | { | ||||
| THREAD_ASSERT( RT ); | THREAD_ASSERT( RT ); | ||||
| if ( ! _output ) | |||||
| return nframes; | |||||
| if ( _output->connected() ) /* don't waste CPU on disconnected ports */ | if ( _output->connected() ) /* don't waste CPU on disconnected ports */ | ||||
| { | { | ||||
| void *buf = _output->buffer( nframes ); | void *buf = _output->buffer( nframes ); | ||||
| @@ -23,6 +23,7 @@ | |||||
| #include "TLE.H" | #include "TLE.H" | ||||
| #include "NSM.H" | #include "NSM.H" | ||||
| #include "Project.H" | #include "Project.H" | ||||
| #include "OSC/Endpoint.H" | |||||
| #define OSC_INTERVAL 0.2f | #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 ); | timeline->osc->name( client_id ); | ||||
| int r = 0; | |||||
| if ( Project::validate( name ) ) | if ( Project::validate( name ) ) | ||||
| { | { | ||||
| if ( timeline->command_load( name, display_name ) ) | if ( timeline->command_load( name, display_name ) ) | ||||
| return ERR_OK; | |||||
| r = ERR_OK; | |||||
| else | else | ||||
| { | { | ||||
| *out_msg = strdup( "Failed to load for unknown reason" ); | *out_msg = strdup( "Failed to load for unknown reason" ); | ||||
| return ERR_GENERAL; | |||||
| r = ERR_GENERAL; | |||||
| } | } | ||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| if ( timeline->command_new( name, display_name ) ) | if ( timeline->command_new( name, display_name ) ) | ||||
| return ERR_OK; | |||||
| r =ERR_OK; | |||||
| else | else | ||||
| { | { | ||||
| *out_msg = strdup( "Failed to load for unknown reason" ); | *out_msg = strdup( "Failed to load for unknown reason" ); | ||||
| return ERR_GENERAL; | |||||
| r = ERR_GENERAL; | |||||
| } | } | ||||
| } | } | ||||
| return 0; | |||||
| timeline->discover_peers(); | |||||
| return r; | |||||
| } | } | ||||
| void | void | ||||
| @@ -52,6 +52,7 @@ | |||||
| /* */ | /* */ | ||||
| #include "OSC_Thread.H" | #include "OSC_Thread.H" | ||||
| #include "OSC/Endpoint.H" | |||||
| #include "NSM.H" | #include "NSM.H" | ||||
| extern NSM_Client *nsm; | 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 ); | Project::set_name ( display_name ? display_name : name ); | ||||
| // discover_peers(); | |||||
| return true; | |||||
| return true; | |||||
| } | } | ||||
| bool | bool | ||||
| @@ -1553,9 +1552,7 @@ Timeline::command_new ( const char *name, const char *display_name ) | |||||
| /* tle->main_window->redraw(); */ | /* tle->main_window->redraw(); */ | ||||
| // discover_peers(); | |||||
| return b; | |||||
| return b; | |||||
| } | } | ||||
| const char * | 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 */ | /* 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 ); | 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 ) | if ( ! osc_thread ) | ||||
| { | { | ||||
| osc_thread = new 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 *version = &argv[2]->s; | ||||
| const char *id = &argv[3]->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 ); | timeline->osc->hello( url ); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -1673,24 +1669,17 @@ Timeline::connect_osc ( void ) | |||||
| void | void | ||||
| Timeline::discover_peers ( void ) | Timeline::discover_peers ( void ) | ||||
| { | { | ||||
| lo_message m = lo_message_new(); | |||||
| 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." ); | |||||
| if ( nsm->is_active() ) | |||||
| { | |||||
| lo_message m = lo_message_new(); | |||||
| lo_message_add_string( m, "/non/finger" ); | |||||
| lo_message_add_string( m, osc->url() ); | |||||
| connect_osc(); | |||||
| nsm->broadcast( m ); | |||||
| lo_message_free( m ); | |||||
| } | |||||
| } | } | ||||
| @@ -31,7 +31,6 @@ | |||||
| #include <assert.h> | #include <assert.h> | ||||
| #include <list> | #include <list> | ||||
| #include "OSC/Endpoint.H" | |||||
| #include "OSC_Thread.H" | #include "OSC_Thread.H" | ||||
| class Fl_Scroll; | class Fl_Scroll; | ||||
| @@ -54,6 +53,10 @@ class Scalebar; | |||||
| class Sequence; | class Sequence; | ||||
| class Sequence_Widget; | class Sequence_Widget; | ||||
| namespace OSC { class Endpoint; } | |||||
| #include <lo/lo.h> | |||||
| #ifndef USE_SINGLEBUFFERED_TIMELINE | #ifndef USE_SINGLEBUFFERED_TIMELINE | ||||
| #include <FL/Fl_Overlay_Window.H> | #include <FL/Fl_Overlay_Window.H> | ||||
| #else | #else | ||||
| @@ -236,8 +239,6 @@ public: | |||||
| /* OSC */ | /* OSC */ | ||||
| void connect_osc ( void ); | void connect_osc ( void ); | ||||
| void discover_peers ( void ); | void discover_peers ( void ); | ||||