diff --git a/Mixer/Chain.C b/Mixer/Chain.C index e246cf7..e8d8986 100644 --- a/Mixer/Chain.C +++ b/Mixer/Chain.C @@ -447,7 +447,19 @@ Chain::name ( const char *name ) bool Chain::add ( Module *m ) { - return insert( NULL, m ); + /* FIXME: hacky */ + if ( !strcmp( m->name(), "Controller" ) ) + return false; + else + return insert( NULL, m ); +} + +bool +Chain::add ( Controller_Module *m ) +{ + DMESSAGE( "Adding control" ); + add_control(m); + return true; } bool @@ -534,7 +546,7 @@ err: /* add a control to the control strip. Assumed to already be connected! */ void -Chain::add_control ( Module *m ) +Chain::add_control ( Controller_Module *m ) { engine()->lock(); diff --git a/Mixer/Chain.H b/Mixer/Chain.H index cc216d6..c93dfbf 100644 --- a/Mixer/Chain.H +++ b/Mixer/Chain.H @@ -33,6 +33,7 @@ class Mixer_Strip; class Fl_Flowpack; class Fl_Flip_Button; class Engine; +class Controller_Module; class Chain : public Fl_Group, public Loggable { @@ -109,8 +110,9 @@ public: Module *module ( int n ) const { return (Module*)modules_pack->child( n ); } void remove ( Module *m ); bool add ( Module *m ); + bool add ( Controller_Module *m ); bool insert ( Module *m, Module *n ); - void add_control ( Module *m ); + void add_control ( Controller_Module *m ); void initialize_with_default ( void ); diff --git a/Mixer/Controller_Module.C b/Mixer/Controller_Module.C index 1b9ef64..9b74f53 100644 --- a/Mixer/Controller_Module.C +++ b/Mixer/Controller_Module.C @@ -24,6 +24,9 @@ #include #include #include "FL/Fl_Arc_Dial.H" +#include +#include +#include #include "FL/Fl_Light_Button.H" #include "FL/Boxtypes.H" #include @@ -41,14 +44,14 @@ const float CONTROL_UPDATE_FREQ = 0.1f; void Controller_Module::get ( Log_Entry &e ) const { + Module::get( e ); Port *p = control_output[0].connected_port(); Module *m = p->module(); e.add( ":module", m ); e.add( ":port", m->control_input_port_index( p ) ); - - Module::get( e ); + e.add( ":mode", mode() ); } void @@ -83,10 +86,23 @@ Controller_Module::set ( Log_Entry &e ) if ( port >= 0 && module ) { - control_output[0].connect_to( &module->control_input[port] ); + connect_to( &module->control_input[port] ); module->chain()->add_control( this ); label( module->control_input[port].name() ); } + + for ( int i = 0; i < e.size(); ++i ) + { + const char *s, *v; + + e.get( i, &s, &v ); + + if ( ! strcmp( s, ":mode" ) ) + { + mode( (Mode)atoi( v ) ); + } + } + } @@ -162,23 +178,6 @@ Controller_Module::connect_to ( Port *p ) { control_output[0].connect_to( p ); - if( mode() == CV ) - { - chain()->engine()->lock(); - -// char name[256]; -// snprintf( name, sizeof( name ), "%s-CV", p->name() ); - - JACK::Port po( chain()->engine(), JACK::Port::Input, p->name(), 0, "CV" ); - - if ( po.valid() ) - { - jack_input.push_back( po ); - } - - chain()->engine()->unlock(); - } - Fl_Widget *w; if ( p->hints.type == Module::Port::Hints::BOOLEAN ) @@ -283,14 +282,117 @@ Controller_Module::resize ( int X, int Y, int W, int H ) } } + +void +Controller_Module::menu_cb ( Fl_Widget *w, void *v ) +{ + ((Controller_Module*)v)->menu_cb( (Fl_Menu_*) w ); +} + +void +Controller_Module::menu_cb ( const Fl_Menu_ *m ) +{ + char picked[256]; + + m->item_pathname( picked, sizeof( picked ) ); + + Logger log( this ); + + if ( ! strcmp( picked, "Mode/Manual" ) ) + mode( GUI ); + else if ( ! strcmp( picked, "Mode/Control Voltage" ) ) + mode( CV ); +} + +#include "FL/test_press.H" +#include "FL/menu_popup.H" + +/** build the context menu for this control */ +Fl_Menu_Button & +Controller_Module::menu ( void ) +{ + static Fl_Menu_Button m( 0, 0, 0, 0, "Controller" ); + + Fl_Menu_Item items[] = + { + { "Mode", 0, 0, 0, FL_SUBMENU }, + { "Manual", 0, 0, 0, FL_MENU_RADIO | ( mode() == GUI ? FL_MENU_VALUE : 0 ) }, + { "Control Voltage", 0, 0, 0, FL_MENU_RADIO | ( mode() == CV ? FL_MENU_VALUE : 0 ) }, +// { "Open Sound Control (OSC)", 0, 0, 0, FL_MENU_RADIO | ( mode() == OSC ? FL_MENU_VALUE : 0 ) }, + { 0 }, + { 0 }, + }; + + menu_set_callback( items, &Controller_Module::menu_cb, (void*)this ); + + m.copy( items, (void*)this ); + + return m; +} + int Controller_Module::handle ( int m ) { + + switch ( m ) + { + case FL_PUSH: + { + if ( test_press( FL_BUTTON3 ) ) + { + /* context menu */ + menu_popup( &menu() ); + + return 1; + } + else + return Fl_Group::handle( m ); + } + } + return Fl_Group::handle( m ); } +void +Controller_Module::mode ( Mode m ) +{ + + if( mode() != CV && m == CV ) + { + if ( control_output[0].connected() ) + { + chain()->engine()->lock(); + +// char name[256]; +// snprintf( name, sizeof( name ), "%s-CV", p->name() ); + + Port *p = control_output[0].connected_port(); + + JACK::Port po( chain()->engine(), JACK::Port::Input, p->name(), 0, "CV" ); + + if ( po.valid() ) + { + jack_input.push_back( po ); + } + + chain()->engine()->unlock(); + } + } + else if ( mode() == CV && m == GUI ) + { + chain()->engine()->lock(); + + jack_input.back().shutdown(); + jack_input.pop_back(); + + chain()->engine()->unlock(); + } + + _mode = m ; +} + void Controller_Module::process ( void ) { diff --git a/Mixer/Controller_Module.H b/Mixer/Controller_Module.H index 54700a8..3a4d59a 100644 --- a/Mixer/Controller_Module.H +++ b/Mixer/Controller_Module.H @@ -23,6 +23,9 @@ #include #include "JACK/Port.H" +class Fl_Menu_Button; +class Fl_Menu_; + class Fl_Valuator; class Controller_Module : public Module @@ -35,12 +38,16 @@ class Controller_Module : public Module volatile float control_value; + Fl_Menu_Button & menu ( void ); + static void menu_cb ( Fl_Widget *w, void *v ); + void menu_cb ( const Fl_Menu_ *m ); + public: enum Mode { GUI, CV, OSC, MIDI }; Mode mode ( void ) const { return _mode; } - void mode ( Mode v ) { _mode = v; } + void mode ( Mode v ); Controller_Module ( bool is_default = false ); // Controller_Module ( int W, int H, const char *L=0 );