diff --git a/mixer/src/Controller_Module.C b/mixer/src/Controller_Module.C index 25dc535..76a0489 100644 --- a/mixer/src/Controller_Module.C +++ b/mixer/src/Controller_Module.C @@ -44,7 +44,7 @@ // needed for mixer->endpoint #include "Mixer.H" - +#include "Spatialization_Console.H" #include "string_util.h" @@ -81,23 +81,37 @@ Controller_Module::~Controller_Module ( ) /* shutdown JACK port, if we have one */ mode( GUI ); + +// disconnect(); } void Controller_Module::handle_chain_name_changed() { + if ( type() == SPATIALIZATION ) + { + if ( Mixer::spatialization_console ) + Mixer::spatialization_console->update(); + } + // change_osc_path( generate_osc_path() ); } +void +Controller_Module::handle_control_disconnect ( Module::Port *p ) +{ + if ( type() == SPATIALIZATION ) + { + if ( Mixer::spatialization_console ) + Mixer::spatialization_console->update(); + } +} + void Controller_Module::disconnect ( void ) { - for ( std::vector::iterator i = control_output.begin(); - i != control_output.end(); - ++i ) - { - (*i).disconnect(); - } + for ( unsigned int i = 0; i < control_output.size(); ++i ) + control_output[i].disconnect(); } @@ -266,51 +280,53 @@ Controller_Module::connect_spatializer_to ( Module *m ) control_output[0].connect_to( azimuth_port ); control_output[1].connect_to( elevation_port ); - { - clear(); + clear(); - Panner *o = new Panner( 0,0, 92,92 ); + Panner *o = new Panner( 0,0, 92,92 ); - o->box(FL_FLAT_BOX); - o->color(FL_GRAY0); - o->selection_color(FL_BACKGROUND_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelcolor(FL_FOREGROUND_COLOR); - o->align(FL_ALIGN_TOP); - o->when(FL_WHEN_CHANGED); - label( "Spatialization" ); + o->box(FL_FLAT_BOX); + o->color(FL_GRAY0); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelcolor(FL_FOREGROUND_COLOR); + o->align(FL_ALIGN_TOP); + o->when(FL_WHEN_CHANGED); + label( "Spatialization" ); - o->align(FL_ALIGN_TOP); - o->labelsize( 10 ); + o->align(FL_ALIGN_TOP); + o->labelsize( 10 ); // o->callback( cb_panner_value_handle, new callback_data( this, azimuth_port_number, elevation_port_number ) ); - o->point( 0 )->azimuth( azimuth_value ); - o->point( 0 )->elevation( elevation_value ); + o->point( 0 )->azimuth( azimuth_value ); + o->point( 0 )->elevation( elevation_value ); - o->callback( cb_spatializer_handle, this ); + o->callback( cb_spatializer_handle, this ); - control = (Fl_Valuator*)o; + control = (Fl_Valuator*)o; - if ( _pad ) - { - Fl_Labelpad_Group *flg = new Fl_Labelpad_Group( o ); - flg->position( x(), y() ); - flg->set_visible_focus(); - size( flg->w(), flg->h() ); - add( flg ); - } - else - { - o->resize( x(), y(), w(), h() ); - add( o ); - resizable( o ); - init_sizes(); - } - - _type = SPATIALIZATION; - return true; + if ( _pad ) + { + Fl_Labelpad_Group *flg = new Fl_Labelpad_Group( o ); + flg->position( x(), y() ); + flg->set_visible_focus(); + size( flg->w(), flg->h() ); + add( flg ); } + else + { + o->resize( x(), y(), w(), h() ); + add( o ); + resizable( o ); + init_sizes(); + } + + _type = SPATIALIZATION; + + if ( Mixer::spatialization_console ) + Mixer::spatialization_console->update(); + + return true; } void @@ -762,6 +778,13 @@ void Controller_Module::handle_control_changed ( Port *p ) { /* ignore changes initiated while mouse is over widget */ + + if ( type() == SPATIALIZATION ) + { + if ( Mixer::spatialization_console ) + Mixer::spatialization_console->handle_control_changed( this ); + } + if ( contains( Fl::pushed() ) ) return; diff --git a/mixer/src/Controller_Module.H b/mixer/src/Controller_Module.H index 1edbe27..ee89913 100644 --- a/mixer/src/Controller_Module.H +++ b/mixer/src/Controller_Module.H @@ -88,6 +88,7 @@ public: void handle_control_changed ( Port *p ); void handle_chain_name_changed ( void ); + void handle_control_disconnect ( Port *p ); virtual void command_remove ( void ); diff --git a/mixer/src/Mixer.C b/mixer/src/Mixer.C index 456d2bc..de9806b 100644 --- a/mixer/src/Mixer.C +++ b/mixer/src/Mixer.C @@ -37,6 +37,7 @@ #include #include #include +#include #include "file.h" #include @@ -62,6 +63,8 @@ extern char *instance_name; extern NSM_Client *nsm; +Spatialization_Console *Mixer::spatialization_console = 0; + void @@ -315,6 +318,19 @@ void Mixer::cb_menu(Fl_Widget* o) { { Fl::paste(*this); } + else if ( !strcmp( picked, "&Mixer/Spatialization Console" ) ) + { + if ( ! spatialization_console ) + { + Spatialization_Console *o = new Spatialization_Console(); + spatialization_console = o; + } + + if ( spatialization_console->shown() ) + spatialization_console->hide(); + else + spatialization_console->show(); + } else if (! strcmp( picked, "&Project/Se&ttings/&Rows/One") ) { rows( 1 ); @@ -501,6 +517,7 @@ Mixer::Mixer ( int X, int Y, int W, int H, const char *L ) : o->add( "&Mixer/Add &N Strips" ); o->add( "&Mixer/&Import Strip" ); o->add( "&Mixer/Paste", FL_CTRL + 'v', 0, 0 ); + o->add( "&Mixer/Spatialization Console", FL_F + 8, 0, 0 ); o->add( "&Remote Control/Start Learning", FL_F + 9, 0, 0 ); o->add( "&Remote Control/Stop Learning", FL_F + 10, 0, 0 ); o->add( "&Remote Control/Send State" ); @@ -853,6 +870,12 @@ Mixer::rows ( int ideal_rows ) } } +int +Mixer::nstrips ( void ) const +{ + return mixer_strips->children(); +} + /** retrun a pointer to the track named /name/, or NULL if no track is named /name/ */ Mixer_Strip * Mixer::track_by_name ( const char *name ) diff --git a/mixer/src/Mixer.H b/mixer/src/Mixer.H index aaff477..ef7bcb2 100644 --- a/mixer/src/Mixer.H +++ b/mixer/src/Mixer.H @@ -31,6 +31,7 @@ class Fl_Blink_Button; class Fl_Flowpack; class Fl_Menu_Bar; +class Spatialization_Console; namespace OSC { class Endpoint; } #include @@ -55,7 +56,6 @@ private: Fl_Color system_colors[3]; Mixer_Strip* track_by_name ( const char *name ); - Mixer_Strip* track_by_number ( int n ); void snapshot ( void ); static void snapshot ( void *v ) { ((Mixer*)v)->snapshot(); } @@ -91,6 +91,11 @@ private: public: + static Spatialization_Console *spatialization_console; + + int nstrips ( void ) const; + Mixer_Strip* track_by_number ( int n ); + void update_frequency ( float f ); void status ( const char *s ) { diff --git a/mixer/src/Mixer_Strip.C b/mixer/src/Mixer_Strip.C index 7a78f95..b53f061 100644 --- a/mixer/src/Mixer_Strip.C +++ b/mixer/src/Mixer_Strip.C @@ -688,6 +688,12 @@ Mixer_Strip::menu ( void ) const return m; } +Controller_Module * +Mixer_Strip::spatializer ( void ) +{ + return spatialization_controller; +} + int Mixer_Strip::handle ( int m ) { diff --git a/mixer/src/Mixer_Strip.H b/mixer/src/Mixer_Strip.H index 3b6ec2a..2395a14 100644 --- a/mixer/src/Mixer_Strip.H +++ b/mixer/src/Mixer_Strip.H @@ -141,6 +141,8 @@ protected: public: + Controller_Module *spatializer ( void ); + void send_feedback ( void ); int number ( void ) const; static bool import_strip ( const char *filename ); diff --git a/mixer/src/Module.H b/mixer/src/Module.H index 0d95081..167cd17 100644 --- a/mixer/src/Module.H +++ b/mixer/src/Module.H @@ -248,7 +248,7 @@ public: connected_port()->_module->handle_control_changed( connected_port() ); } - float control_value ( ) const + float control_value ( void ) const { if ( buffer() ) return *((float*)buffer()); @@ -284,6 +284,10 @@ public: if ( _connected && _connected != (void*)0x01 ) { _connected->_connected = NULL; + + if ( _connected->_module ) + _connected->_module->handle_control_disconnect( this ); + _connected = NULL; } else @@ -464,7 +468,7 @@ public: /* called whenever the value of a control port is changed. This can be used to take appropriate action from the GUI thread */ virtual void handle_control_changed ( Port * ); - + virtual void handle_control_disconnect ( Port * ) {} /* called whenever the name of the chain changes (usually because * the name of the mixer strip changed). */ virtual void handle_chain_name_changed (); diff --git a/mixer/src/Panner.C b/mixer/src/Panner.C index 197acf6..45a1970 100644 --- a/mixer/src/Panner.C +++ b/mixer/src/Panner.C @@ -58,12 +58,16 @@ Panner::point_bbox ( const Point *p, int *X, int *Y, int *W, int *H ) const Panner::Point * Panner::event_point ( void ) { - for ( int i = _ins; i--; ) + for ( int i = _points.size(); i--; ) { + int px, py, pw, ph; Point *p = &_points[ i ]; + if ( ! p->visible ) + continue; + point_bbox( p, &px, &py, &pw, &ph ); // printf( "%d, %d -- %d %d %d %d\n", Fl::event_x(), Fl::event_y(), px, py, pw, ph ); @@ -120,7 +124,6 @@ Panner::draw ( void ) goto done; } - /* tx += b; */ /* ty += b; */ /* tw -= b * 2; */ @@ -131,12 +134,14 @@ Panner::draw ( void ) fl_color( FL_WHITE ); + for ( unsigned int i = 0; i < _points.size(); i++ ) { - Point *p = &_points[0]; + Point *p = &_points[i]; -// Fl_Color c = (Fl_Color)(10 + i); + if ( ! p->visible ) + continue; - Fl_Color c = fl_color_add_alpha( fl_rgb_color( 192, 192, 206 ), 127 ); + Fl_Color c = fl_color_add_alpha( p->color, 127 ); int px, py, pw, ph; point_bbox( p, &px, &py, &pw, &ph ); @@ -151,7 +156,7 @@ Panner::draw ( void ) py - ( po * 12 ), pw + ( po * 24 ), ph + (po * 24 )); - fl_color( fl_color_add_alpha( fl_rgb_color( 254,254,254 ), 254 ) ); +// fl_color( fl_color_add_alpha( fl_rgb_color( 254,254,254 ), 254 ) ); fl_pie( px + 5, py + 5, pw - 10, ph - 10, 0, 360 ); @@ -176,8 +181,8 @@ Panner::draw ( void ) const char *s = p->label; - fl_color( fl_rgb_color( 125,125,130 ) ); - fl_font( FL_HELVETICA, ph + 2 ); + fl_color( fl_color_add_alpha( fl_rgb_color( 220,255,255 ), 127 ) ); + fl_font( FL_HELVETICA_BOLD_ITALIC, 12 ); fl_draw( s, px + 20, py + 1, 50, ph - 1, FL_ALIGN_LEFT ); } @@ -221,10 +226,10 @@ Panner::handle ( int m ) return 1; } case FL_RELEASE: - if ( Fl::event_button1() && drag ) + if ( drag ) { - drag = NULL; do_callback(); + drag = NULL; redraw(); return 1; } @@ -233,6 +238,7 @@ Panner::handle ( int m ) case FL_MOUSEWHEEL: { /* TODO: place point on opposite face of sphere */ + return 0; } case FL_DRAG: { diff --git a/mixer/src/Panner.H b/mixer/src/Panner.H index 7fb2bfd..f15c17c 100644 --- a/mixer/src/Panner.H +++ b/mixer/src/Panner.H @@ -33,6 +33,7 @@ class Panner : public Fl_Widget void draw_the_box( int, int, int, int ); +public: struct Point { /* axes */ @@ -43,9 +44,13 @@ class Panner : public Fl_Widget float a; const char *label; + void *userdata; + Fl_Color color; - Point ( ) : d( 0.0f ), a( 0.0f ), label(0) { } - Point ( float D, float A ) : d( D ), a( A ), label(0) { } + bool visible; + + Point ( ) : d( 0.0f ), a( 0.0f ), label(0), visible(1){ } + Point ( float D, float A ) : d( D ), a( A ), label(0), visible(1) { } /** translate angle /a/ into x/y coords and place the result in /X/ and /Y/ */ void @@ -125,6 +130,7 @@ class Panner : public Fl_Widget }; +private: /* channel configuration */ int _ins, @@ -183,8 +189,19 @@ public: _points.push_back( Point( 1, 0 ) ); } + void clear_points ( void ) { _points.clear(); } + + void add_point( Panner::Point &p ) + { + _points.push_back( p ); + } + virtual ~Panner ( ) { } Panner::Point *point ( int i ); + int points ( void ) const { return _points.size(); } + + Panner::Point *pushed ( void ) { return drag; } + }; diff --git a/mixer/src/Spatialization_Console.C b/mixer/src/Spatialization_Console.C new file mode 100644 index 0000000..42876cf --- /dev/null +++ b/mixer/src/Spatialization_Console.C @@ -0,0 +1,144 @@ + +/*******************************************************************************/ +/* Copyright (C) 2009 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "Module.H" +#include "Spatialization_Console.H" +#include "Controller_Module.H" +#include "Chain.H" +#include "Panner.H" +#include "Mixer_Strip.H" +#include "Mixer.H" + +#include "debug.h" + + + +Spatialization_Console::Spatialization_Console ( void ) : Fl_Double_Window( 565, 565 ) +{ + _resized = false; + _min_width = 100; + + label( "Spatialization Console" ); + + fl_font( FL_HELVETICA, 14 ); + + panner = new Panner( 25,25, 512, 512 ); + + panner->callback( cb_panner_value_handle, this ); + panner->when( FL_WHEN_CHANGED ); + + end(); + + make_controls(); +} + +Spatialization_Console::~Spatialization_Console ( ) +{ +// controls_by_port.clear(); +} + + + +void +Spatialization_Console::make_controls ( void ) +{ + panner->clear_points(); + + for ( int i = 0; i < mixer->nstrips(); i++ ) + { + Mixer_Strip *o = mixer->track_by_number( i ); + + if ( o->spatializer() ) + { + Panner::Point p; + + p.color = o->color(); + p.userdata = o->spatializer(); + p.label = o->name(); + + if ( o->spatializer()->is_controlling() ) + { + p.visible = true; + + p.azimuth( o->spatializer()->control_output[0].control_value() ); + p.elevation( o->spatializer()->control_output[1].control_value() ); + } + else + p.visible = false; + + panner->add_point(p); + } + } + + panner->redraw(); +} + +void +Spatialization_Console::cb_panner_value_handle ( Fl_Widget *w, void *v ) +{ +// callback_data *cd = (callback_data*)v; + + Spatialization_Console *sc = (Spatialization_Console*)v; + + Panner::Point *p = sc->panner->pushed(); + + Controller_Module *cm = (Controller_Module*)p->userdata; + + cm->control_output[0].control_value( p->azimuth() ); + cm->control_output[1].control_value( p->elevation() ); +} + +/* Display changes initiated via automation or from other parts of the GUI */ +void +Spatialization_Console::handle_control_changed ( Controller_Module *m ) +{ + if ( Fl::pushed() == panner ) + return; + + for ( int i = 0; i < panner->points(); i++ ) + { + Panner::Point *p = panner->point(i); + + if ( p->userdata == m ) + { + p->azimuth( m->control_output[0].control_value() ); + p->elevation( m->control_output[1].control_value() ); + + if ( panner->visible_r() ) + panner->redraw(); + + break; + } + } +} + +void +Spatialization_Console::update ( void ) +{ + make_controls(); +} diff --git a/mixer/src/Spatialization_Console.H b/mixer/src/Spatialization_Console.H new file mode 100644 index 0000000..b2c8b62 --- /dev/null +++ b/mixer/src/Spatialization_Console.H @@ -0,0 +1,56 @@ + +/*******************************************************************************/ +/* Copyright (C) 2009 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +#pragma once + +#include +#include + +class Fl_Pack; +class Fl_Flowpack; +class Module; +class Fl_Menu_Button; +class Panner; +class Controller_Module; +#include + +class Spatialization_Console : public Fl_Double_Window +{ + Panner *panner; + + static void cb_panner_value_handle ( Fl_Widget *w, void *v ); + void make_controls ( void ); + + bool _resized; + int _min_width; + + int azimuth_port_number; + int elevation_port_number; + + std::vector controls_by_port; + +public: + + void handle_control_changed ( Controller_Module *m ); + + void update ( void ); + + Spatialization_Console ( ); + virtual ~Spatialization_Console ( ); +}; diff --git a/mixer/wscript b/mixer/wscript index 63d4bbf..e969762 100644 --- a/mixer/wscript +++ b/mixer/wscript @@ -65,6 +65,7 @@ src/Panner.C src/Plugin_Module.C src/Project.C src/main.C +src/Spatialization_Console.C ''', target = 'non-mixer', includes = ['.', 'src', '..', '../nonlib'],