| @@ -41,7 +41,6 @@ | |||
| #include "Engine/Engine.H" | |||
| #include "Chain.H" | |||
| #include "OSC/Endpoint.H" | |||
| // needed for mixer->endpoint | |||
| @@ -65,7 +64,6 @@ Controller_Module::Controller_Module ( bool is_default ) : Module( is_default, 5 | |||
| add_port( Port( this, Port::OUTPUT, Port::CONTROL ) ); | |||
| _mode = GUI; | |||
| _osc_path = NULL; | |||
| // mode( GUI ); | |||
| // mode( CV ); | |||
| @@ -86,69 +84,12 @@ Controller_Module::~Controller_Module ( ) | |||
| /* shutdown JACK port, if we have one */ | |||
| mode( GUI ); | |||
| change_osc_path( NULL ); | |||
| } | |||
| void | |||
| Controller_Module::handle_chain_name_changed() | |||
| { | |||
| change_osc_path( generate_osc_path() ); | |||
| } | |||
| char * | |||
| Controller_Module::generate_osc_path () | |||
| { | |||
| const Port *p = control_output[0].connected_port(); | |||
| if ( !p ) | |||
| return NULL; | |||
| char *path; | |||
| // /mixer/strip/STRIPNAME/control/MODULENAME/CONTROLNAME | |||
| asprintf( &path, "/mixer/strip/%s/control/%s/%s", 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--; ) | |||
| { | |||
| if ( path[i] == ' ' ) | |||
| path[i] = '_'; | |||
| } | |||
| return path; | |||
| } | |||
| void | |||
| Controller_Module::change_osc_path ( char *path ) | |||
| { | |||
| if ( _osc_path ) | |||
| { | |||
| mixer->osc_endpoint->del_method( _osc_path, "f" ); | |||
| free( _osc_path ); | |||
| free( _osc_path_cv ); | |||
| _osc_path = NULL; | |||
| _osc_path_cv = NULL; | |||
| } | |||
| if ( path ) | |||
| { | |||
| _osc_path_cv = (char*)malloc( strlen( path ) + 4 ); | |||
| _osc_path_cv[0] = 0; | |||
| strcpy( _osc_path_cv, path ); | |||
| strcat( _osc_path_cv, "/cv" ); | |||
| mixer->osc_endpoint->add_method( path, "f", &Controller_Module::osc_control_change_exact, this, "value" ); | |||
| mixer->osc_endpoint->add_method( _osc_path_cv, "f", &Controller_Module::osc_control_change_cv, this, "value" ); | |||
| _osc_path = path; | |||
| tooltip( _osc_path ); | |||
| } | |||
| // change_osc_path( generate_osc_path() ); | |||
| } | |||
| @@ -463,8 +404,6 @@ Controller_Module::connect_to ( Port *p ) | |||
| } | |||
| // create OSC port | |||
| change_osc_path( generate_osc_path() ); | |||
| } | |||
| void | |||
| @@ -550,7 +489,7 @@ Controller_Module::menu ( void ) | |||
| { "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 ) }, | |||
| // { "Open Sound Control (OSC)", 0, 0, 0, FL_MENU_RADIO | ( mode() == OSC ? FL_MENU_VALUE : 0 ) }, | |||
| { 0 }, | |||
| { 0 }, | |||
| }; | |||
| @@ -587,14 +526,20 @@ Controller_Module::handle ( int m ) | |||
| } | |||
| void | |||
| Controller_Module::handle_control_changed ( Port * ) | |||
| Controller_Module::handle_control_changed ( Port *p ) | |||
| { | |||
| /* ignore changes initiated while mouse is over widget */ | |||
| if ( contains( Fl::pushed() ) ) | |||
| return; | |||
| if ( p ) | |||
| control_value = p->control_value(); | |||
| if ( control->value() != control_value ) | |||
| { | |||
| redraw(); | |||
| DMESSAGE( "handle_control_changed" ); | |||
| } | |||
| if ( type() == SPATIALIZATION ) | |||
| { | |||
| @@ -652,64 +597,3 @@ Controller_Module::process ( nframes_t nframes ) | |||
| control_value = f; | |||
| } | |||
| } | |||
| int | |||
| Controller_Module::osc_control_change_exact ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) | |||
| { | |||
| Controller_Module *c = (Controller_Module*)user_data; | |||
| if ( c->mode() != OSC ) | |||
| return 0; | |||
| OSC_DMSG(); | |||
| const Port *p = c->control_output[0].connected_port(); | |||
| float f = argv[0]->f; | |||
| if ( p->hints.ranged ) | |||
| { | |||
| if ( f > p->hints.maximum ) | |||
| f = p->hints.maximum; | |||
| else if ( f < p->hints.minimum ) | |||
| f = p->hints.minimum; | |||
| } | |||
| c->control_value = f; | |||
| mixer->osc_endpoint->send( lo_message_get_source( msg ), "/reply", path, "ok" ); | |||
| return 0; | |||
| } | |||
| int | |||
| Controller_Module::osc_control_change_cv ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) | |||
| { | |||
| Controller_Module *c = (Controller_Module*)user_data; | |||
| if ( c->mode() != OSC ) | |||
| return 0; | |||
| OSC_DMSG(); | |||
| const Port *p = c->control_output[0].connected_port(); | |||
| float f = argv[0]->f; | |||
| if (p->hints.ranged ) | |||
| { | |||
| // scale value to range. | |||
| // we assume that CV values are between 0 and 1 | |||
| float scale = p->hints.maximum - p->hints.minimum; | |||
| float offset = p->hints.minimum; | |||
| f = ( f * scale ) + offset; | |||
| } | |||
| c->control_value = f; | |||
| mixer->osc_endpoint->send( lo_message_get_source( msg ), "/reply", path, "ok" ); | |||
| return 0; | |||
| } | |||
| @@ -106,9 +106,6 @@ private: | |||
| char *generate_osc_path ( void ); | |||
| void change_osc_path ( char *path ); | |||
| static int osc_control_change_exact ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); | |||
| static int osc_control_change_cv ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); | |||
| std::vector<JACK::Port> jack_input; | |||
| Mode _mode; | |||
| Type _type; | |||
| @@ -37,6 +37,7 @@ | |||
| #include <FL/Fl_Menu_Button.H> | |||
| #include "FL/test_press.H" | |||
| #include "FL/menu_popup.H" | |||
| #include "Mixer.H" | |||
| @@ -65,7 +66,6 @@ Module::Module ( ) : Fl_Group( 0, 0, 50, 50, "Unnamed" ) | |||
| { | |||
| init(); | |||
| log_create(); | |||
| } | |||
| @@ -83,12 +83,16 @@ Module::~Module ( ) | |||
| for ( unsigned int i = 0; i < audio_output.size(); ++i ) | |||
| audio_output[i].disconnect(); | |||
| for ( unsigned int i = 0; i < control_input.size(); ++i ) | |||
| { | |||
| control_input[i].disconnect(); | |||
| control_input[i].destroy_osc_port(); | |||
| } | |||
| for ( unsigned int i = 0; i < control_output.size(); ++i ) | |||
| control_output[i].disconnect(); | |||
| audio_input.clear(); | |||
| audio_output.clear(); | |||
| control_input.clear(); | |||
| control_output.clear(); | |||
| } | |||
| @@ -187,6 +191,118 @@ Module::paste_before ( void ) | |||
| m->copy(); | |||
| } | |||
| char * | |||
| Module::Port::generate_osc_path () | |||
| { | |||
| const Port *p = this; | |||
| char *path; | |||
| // /mixer/strip/STRIPNAME/control/MODULENAME/CONTROLNAME | |||
| asprintf( &path, "/mixer/strip/%s/control/%s/%s", module()->chain()->name(), p->module()->label(), p->name() ); | |||
| // asprintf( &path, "/mixer/strip/control/%s/%s", 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--; ) | |||
| { | |||
| if ( path[i] == ' ' ) | |||
| path[i] = '_'; | |||
| } | |||
| return path; | |||
| } | |||
| void | |||
| Module::Port::change_osc_path ( char *path ) | |||
| { | |||
| if ( _osc_path ) | |||
| { | |||
| mixer->osc_endpoint->del_method( _osc_path, "f" ); | |||
| free( _osc_path ); | |||
| free( _osc_path_cv ); | |||
| _osc_path = NULL; | |||
| _osc_path_cv = NULL; | |||
| } | |||
| if ( path ) | |||
| { | |||
| _osc_path_cv = (char*)malloc( strlen( path ) + 4 ); | |||
| _osc_path_cv[0] = 0; | |||
| strcpy( _osc_path_cv, path ); | |||
| strcat( _osc_path_cv, "/cv" ); | |||
| mixer->osc_endpoint->add_method( path, "f", &Module::Port::osc_control_change_exact, this, "value" ); | |||
| mixer->osc_endpoint->add_method( _osc_path_cv, "f", &Module::Port::osc_control_change_cv, this, "value" ); | |||
| _osc_path = path; | |||
| // tooltip( _osc_path ); | |||
| } | |||
| } | |||
| int | |||
| Module::Port::osc_control_change_exact ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) | |||
| { | |||
| Module::Port *p = (Module::Port*)user_data; | |||
| OSC_DMSG(); | |||
| // const Port *p = c->control_output[0].connected_port(); | |||
| float f = argv[0]->f; | |||
| if ( p->hints.ranged ) | |||
| { | |||
| if ( f > p->hints.maximum ) | |||
| f = p->hints.maximum; | |||
| else if ( f < p->hints.minimum ) | |||
| f = p->hints.minimum; | |||
| } | |||
| p->control_value( f ); | |||
| mixer->osc_endpoint->send( lo_message_get_source( msg ), "/reply", path, "ok" ); | |||
| return 0; | |||
| } | |||
| int | |||
| Module::Port::osc_control_change_cv ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) | |||
| { | |||
| Module::Port *p = (Module::Port*)user_data; | |||
| // const Port *p = c->control_output[0].connected_port(); | |||
| float f = argv[0]->f; | |||
| if (p->hints.ranged ) | |||
| { | |||
| // scale value to range. | |||
| // we assume that CV values are between 0 and 1 | |||
| float scale = p->hints.maximum - p->hints.minimum; | |||
| float offset = p->hints.minimum; | |||
| f = ( f * scale ) + offset; | |||
| } | |||
| p->control_value( f ); | |||
| // c->control_value = f; | |||
| mixer->osc_endpoint->send( lo_message_get_source( msg ), "/reply", path, "ok" ); | |||
| return 0; | |||
| } | |||
| void | |||
| Module::set ( Log_Entry &e ) | |||
| { | |||
| @@ -30,6 +30,7 @@ | |||
| #include "Loggable.H" | |||
| #include "JACK/Port.H" | |||
| #include "OSC/Endpoint.H" | |||
| class Chain; | |||
| class Module_Parameter_Editor; | |||
| @@ -97,7 +98,7 @@ public: | |||
| float maximum; | |||
| float default_value; | |||
| int dimensions; | |||
| Hints ( ) | |||
| { | |||
| type = LINEAR; | |||
| @@ -109,6 +110,9 @@ public: | |||
| } | |||
| }; | |||
| static int osc_control_change_exact ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); | |||
| static int osc_control_change_cv ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); | |||
| Hints hints; | |||
| Port ( Module *module, Direction direction, Type type, const char *name = 0 ) | |||
| @@ -120,6 +124,8 @@ public: | |||
| _nframes = 0; | |||
| _connected = 0; | |||
| _module = module; | |||
| _osc_path = 0; | |||
| _osc_path_cv = 0; | |||
| } | |||
| Port ( const Port& p ) | |||
| @@ -132,10 +138,13 @@ public: | |||
| _connected = p._connected; | |||
| _module = p._module; | |||
| hints = p.hints; | |||
| _osc_path = p._osc_path; | |||
| _osc_path_cv = p._osc_path; | |||
| } | |||
| virtual ~Port ( ) | |||
| { | |||
| // change_osc_path( NULL ); | |||
| // disconnect(); | |||
| } | |||
| @@ -149,6 +158,17 @@ public: | |||
| void buffer ( void *buf, nframes_t nframes ) { _buf = buf; _nframes = nframes; }; | |||
| void *buffer ( void ) const { return _buf; } | |||
| void update_osc_port ( ) | |||
| { | |||
| if ( INPUT == _direction ) | |||
| change_osc_path( generate_osc_path() ); | |||
| } | |||
| void destroy_osc_port ( ) | |||
| { | |||
| change_osc_path( NULL ); | |||
| } | |||
| void control_value_no_callback ( float f ) | |||
| { | |||
| THREAD_ASSERT( UI ); | |||
| @@ -163,6 +183,8 @@ public: | |||
| { | |||
| control_value_no_callback( f ); | |||
| _module->handle_control_changed( this ); | |||
| if ( connected() ) | |||
| connected_port()->_module->handle_control_changed( connected_port() ); | |||
| } | |||
| float control_value ( ) const | |||
| @@ -208,6 +230,9 @@ public: | |||
| private: | |||
| char *generate_osc_path ( void ); | |||
| void change_osc_path ( char *path ); | |||
| Port *_connected; | |||
| Type _type; | |||
| Direction _direction; | |||
| @@ -215,6 +240,9 @@ public: | |||
| void *_buf; | |||
| nframes_t _nframes; | |||
| Module *_module; | |||
| char *_osc_path; | |||
| char *_osc_path_cv; | |||
| }; | |||
| void bbox ( int &X, int &Y, int &W, int &H ) | |||
| @@ -317,7 +345,15 @@ public: | |||
| } | |||
| Chain *chain ( void ) const { return _chain; } | |||
| void chain ( Chain * v ) { _chain = v; } | |||
| void chain ( Chain * v ) | |||
| { | |||
| _chain = v; | |||
| for ( int i = 0; i < ncontrol_inputs(); ++i ) | |||
| { | |||
| control_input[i].update_osc_port(); | |||
| } | |||
| } | |||
| char *get_parameters ( void ) const; | |||
| void set_parameters ( const char * ); | |||