diff --git a/mixer/src/Controller_Module.C b/mixer/src/Controller_Module.C index 9b4b2e9..087a100 100644 --- a/mixer/src/Controller_Module.C +++ b/mixer/src/Controller_Module.C @@ -45,6 +45,8 @@ // needed for mixer->endpoint #include "Mixer.H" +#include "string_util.h" + bool Controller_Module::learn_by_number = false; @@ -358,7 +360,7 @@ Controller_Module::connect_to ( Port *p ) w = o; o->type(4); - o->color( FL_DARK1 ); + o->color( FL_BACKGROUND2_COLOR ); o->selection_color( fl_color_average( FL_GRAY, FL_CYAN, 0.5 ) ); o->minimum(1.5); o->maximum(0); @@ -496,6 +498,181 @@ Controller_Module::menu_cb ( const Fl_Menu_ *m ) mode( CV ); else if ( ! strcmp( picked, "/Remove" ) ) command_remove(); + else if ( ! strncmp( picked, "Connect To/", strlen( "Connect To/" ) ) ) + { + char *peer_name = index( picked, '/' ) + 1; + + *index( peer_name, '/' ) = 0; + +// OSC::Signal s = (OSC::Signal*)m->mvalue()->user_data(); + const char *path = ((OSC::Signal*)m->mvalue()->user_data())->path(); + + /* if ( ! _osc_output()->is_connected_to( ((OSC::Signal*)m->mvalue()->user_data()) ) ) */ + /* { */ + /* _persistent_osc_connections.push_back( strdup(path) ); */ + + Port *p = control_output[0].connected_port(); + + if ( learn_by_number ) + { + char *our_path = p->osc_number_path(); + + mixer->osc_endpoint->add_translation( path, our_path ); + + free(our_path); + } + else + mixer->osc_endpoint->add_translation( path, p->osc_path() ); + } + else if ( ! strncmp( picked, "Disconnect From/", strlen( "Disconnect From/" ) ) ) + { + /* char *peer_name = index( picked, '/' ) + 1; */ + + /* *index( peer_name, '/' ) = 0; */ + +// OSC::Signal s = (OSC::Signal*)m->mvalue()->user_data(); + const char *path = (const char*)m->mvalue()->user_data(); + + /* if ( ! _osc_output()->is_connected_to( ((OSC::Signal*)m->mvalue()->user_data()) ) ) */ + /* { */ + /* _persistent_osc_connections.push_back( strdup(path) ); */ + + // Port *p = control_output[0].connected_port(); + + mixer->osc_endpoint->del_translation( path ); + + /* if ( learn_by_number ) */ + /* { */ + /* char *our_path = p->osc_number_path(); */ + + /* mixer->osc_endpoint->add_translation( path, our_path ); */ + + /* free(our_path); */ + /* } */ + /* else */ + /* mixer->osc_endpoint->add_translation( path, p->osc_path() ); */ + } + + + + /* } */ + /* else */ + /* { */ + /* /\* timeline->osc->disconnect_signal( _osc_output(), path ); *\/ */ + + /* /\* for ( std::list::iterator i = _persistent_osc_connections.begin(); *\/ */ + /* /\* i != _persistent_osc_connections.end(); *\/ */ + /* /\* ++i ) *\/ */ + /* /\* { *\/ */ + /* /\* if ( !strcmp( *i, path ) ) *\/ */ + /* /\* { *\/ */ + /* /\* free( *i ); *\/ */ + /* /\* i = _persistent_osc_connections.erase( i ); *\/ */ + /* /\* break; *\/ */ + /* /\* } *\/ */ + /* /\* } *\/ */ + + /* //free( path ); */ + /* } */ + + + +} +static Fl_Menu_Button *peer_menu; +static const char *peer_prefix; + +void +Controller_Module::peer_callback( OSC::Signal *sig, OSC::Signal::State state, void *v ) +{ + char *s; + + DMESSAGE( "Paramter limits: %f %f", sig->parameter_limits().min, sig->parameter_limits().max ); + + /* only show outputs */ + if ( sig->direction() != OSC::Signal::Output ) + return; + + + /* only list CV signals for now */ + if ( ! ( sig->parameter_limits().min == 0.0 && + sig->parameter_limits().max == 1.0 ) ) + return; + + if ( ! v ) + { + /* if( state == OSC::Signal::Created ) */ + /* timeline->connect_osc(); */ + /* else */ + /* timeline->update_osc_connection_state(); */ + } + else + { + /* building menu */ + const char *name = sig->peer_name(); + + assert( sig->path() ); + + char *path = strdup( sig->path() ); + + unescape_url( path ); + + asprintf( &s, "%s/%s", peer_prefix, path ); + + peer_menu->add( s, 0, NULL, (void*)( sig ), 0 ); + + /* FL_MENU_TOGGLE | */ + /* ( ((Controller_Module*)v)->_osc_output()->is_connected_to( sig ) ? FL_MENU_VALUE : 0 ) ); */ + + free( path ); + + free( s ); + } +} + +void +Controller_Module::add_osc_peers_to_menu ( Fl_Menu_Button *m, const char *prefix ) +{ + mixer->osc_endpoint->peer_signal_notification_callback( &Controller_Module::peer_callback, NULL ); + + peer_menu = m; + peer_prefix = prefix; + + mixer->osc_endpoint->list_peer_signals( this ); +} + +void +Controller_Module::add_osc_connections_to_menu ( Fl_Menu_Button *m, const char *prefix ) +{ + /* peer_menu = m; */ + const char *peer_prefix = prefix; + +// mixer->osc_endpoint->list_peer_signals( this ); + + Port *p = control_output[0].connected_port(); + + const char ** conn = mixer->osc_endpoint->get_connections( p->osc_path() ); + + if ( conn ) + { + for ( const char **s = conn; *s; s++ ) + { + /* building menu */ + + char *path = strdup( *s ); + + unescape_url( path ); + + char *ns; + asprintf( &ns, "%s/%s", peer_prefix, path ); + + peer_menu->add( ns, 0, NULL, const_cast(*s), 0 ); + + free( path ); +// free(*s); + } + + free( conn ); + } } /** build the context menu for this control */ @@ -504,19 +681,21 @@ Controller_Module::menu ( void ) { static Fl_Menu_Button m( 0, 0, 0, 0, "Controller" ); - Fl_Menu_Item items[] = - { - { "Mode", 0, 0, 0, FL_SUBMENU }, - { "GUI + OSC", 0, 0, 0, FL_MENU_RADIO | ( mode() == GUI ? FL_MENU_VALUE : 0 ) }, - { "Control Voltage (JACK)", 0, 0, 0, FL_MENU_RADIO | ( mode() == CV ? FL_MENU_VALUE : 0 ) }, - { 0 }, - { "Remove", 0, 0, 0, 0 }, - { 0 }, - }; + m.clear(); - menu_set_callback( items, &Controller_Module::menu_cb, (void*)this ); + if ( mode() == GUI ) + { + add_osc_peers_to_menu( &m, "Connect To" ); + add_osc_connections_to_menu( &m, "Disconnect From" ); + } - m.copy( items, (void*)this ); + m.add( "Mode/GUI + OSC", 0, 0, 0, FL_MENU_RADIO | ( mode() == GUI ? FL_MENU_VALUE : 0 )); + m.add( "Mode/Control Voltage (JACK)", 0, 0, 0, FL_MENU_RADIO | ( mode() == CV ? FL_MENU_VALUE : 0 )); + m.add( "Remove", 0, 0, 0, is_default() ? FL_MENU_INACTIVE : 0 ); + +// menu_set_callback( m.items(), &Controller_Module::menu_cb, (void*)this ); + m.callback( &Controller_Module::menu_cb, (void*)this ); + // m.copy( items, (void*)this ); return m; } diff --git a/mixer/src/Controller_Module.H b/mixer/src/Controller_Module.H index f1a5477..1edbe27 100644 --- a/mixer/src/Controller_Module.H +++ b/mixer/src/Controller_Module.H @@ -40,6 +40,12 @@ class Controller_Module : public Module static void menu_cb ( Fl_Widget *w, void *v ); void menu_cb ( const Fl_Menu_ *m ); + + static void peer_callback( OSC::Signal *sig, OSC::Signal::State state, void *v ); + void peer_callback( OSC::Signal *sig, OSC::Signal::State state ); + void add_osc_peers_to_menu ( Fl_Menu_Button *m, const char *prefix ); + void add_osc_connections_to_menu ( Fl_Menu_Button *m, const char *prefix ); + public: static bool _learn_mode; diff --git a/mixer/src/Module.H b/mixer/src/Module.H index 2a089d7..682cda9 100644 --- a/mixer/src/Module.H +++ b/mixer/src/Module.H @@ -170,6 +170,8 @@ public: void buffer ( void *buf, nframes_t nframes ) { _buf = buf; _nframes = nframes; }; void *buffer ( void ) const { return _buf; } + OSC::Signal *scaled_signal ( void ) { return _scaled_signal; } + const char *osc_path ( ) { if ( _scaled_signal ) diff --git a/nonlib/OSC/Endpoint.C b/nonlib/OSC/Endpoint.C index 77d4791..64651d2 100644 --- a/nonlib/OSC/Endpoint.C +++ b/nonlib/OSC/Endpoint.C @@ -625,6 +625,29 @@ namespace OSC return 1; } + const char** + Endpoint::get_connections ( const char *path ) + { + const char ** conn = NULL; + + int j = 0; + for ( std::map::iterator i = _translations.begin(); + i != _translations.end(); + i++ ) + { + if ( !strcmp( i->second.path.c_str(), path ) ) + { + conn = (const char**)realloc( conn, sizeof( char * ) * (j+2)); + conn[j++] = i->first.c_str(); + } + } + + if ( conn ) + conn[j] = 0; + + return conn; + } + void Endpoint::clear_translations ( void ) { diff --git a/nonlib/OSC/Endpoint.H b/nonlib/OSC/Endpoint.H index 2bad507..58080fa 100644 --- a/nonlib/OSC/Endpoint.H +++ b/nonlib/OSC/Endpoint.H @@ -324,6 +324,7 @@ namespace OSC return _addr; } + const char * * get_connections ( const char *path ); void clear_translations ( void ); void del_translation ( const char *a ); void add_translation ( const char *a, const char *b );