Mixer: Implement Spatialization Console.

This commit is contained in:
Jonathan Moore Liles 2013-06-25 22:28:51 -07:00
parent aedbca82be
commit 6d2aeaf405
12 changed files with 346 additions and 58 deletions

View File

@ -44,7 +44,7 @@
// needed for mixer->endpoint // needed for mixer->endpoint
#include "Mixer.H" #include "Mixer.H"
#include "Spatialization_Console.H"
#include "string_util.h" #include "string_util.h"
@ -81,23 +81,37 @@ Controller_Module::~Controller_Module ( )
/* shutdown JACK port, if we have one */ /* shutdown JACK port, if we have one */
mode( GUI ); mode( GUI );
// disconnect();
} }
void void
Controller_Module::handle_chain_name_changed() Controller_Module::handle_chain_name_changed()
{ {
if ( type() == SPATIALIZATION )
{
if ( Mixer::spatialization_console )
Mixer::spatialization_console->update();
}
// change_osc_path( generate_osc_path() ); // 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 void
Controller_Module::disconnect ( void ) Controller_Module::disconnect ( void )
{ {
for ( std::vector<Module::Port>::iterator i = control_output.begin(); for ( unsigned int i = 0; i < control_output.size(); ++i )
i != control_output.end(); control_output[i].disconnect();
++i )
{
(*i).disconnect();
}
} }
@ -266,7 +280,6 @@ Controller_Module::connect_spatializer_to ( Module *m )
control_output[0].connect_to( azimuth_port ); control_output[0].connect_to( azimuth_port );
control_output[1].connect_to( elevation_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 );
@ -309,8 +322,11 @@ Controller_Module::connect_spatializer_to ( Module *m )
} }
_type = SPATIALIZATION; _type = SPATIALIZATION;
if ( Mixer::spatialization_console )
Mixer::spatialization_console->update();
return true; return true;
}
} }
void void
@ -762,6 +778,13 @@ void
Controller_Module::handle_control_changed ( Port *p ) Controller_Module::handle_control_changed ( Port *p )
{ {
/* ignore changes initiated while mouse is over widget */ /* 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() ) ) if ( contains( Fl::pushed() ) )
return; return;

View File

@ -88,6 +88,7 @@ public:
void handle_control_changed ( Port *p ); void handle_control_changed ( Port *p );
void handle_chain_name_changed ( void ); void handle_chain_name_changed ( void );
void handle_control_disconnect ( Port *p );
virtual void command_remove ( void ); virtual void command_remove ( void );

View File

@ -37,6 +37,7 @@
#include <FL/Fl_File_Chooser.H> #include <FL/Fl_File_Chooser.H>
#include <FL/Fl_Theme_Chooser.H> #include <FL/Fl_Theme_Chooser.H>
#include <FL/Fl_Value_SliderX.H> #include <FL/Fl_Value_SliderX.H>
#include <Spatialization_Console.H>
#include "file.h" #include "file.h"
#include <string.h> #include <string.h>
@ -62,6 +63,8 @@ extern char *instance_name;
extern NSM_Client *nsm; extern NSM_Client *nsm;
Spatialization_Console *Mixer::spatialization_console = 0;
void void
@ -315,6 +318,19 @@ void Mixer::cb_menu(Fl_Widget* o) {
{ {
Fl::paste(*this); 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") ) else if (! strcmp( picked, "&Project/Se&ttings/&Rows/One") )
{ {
rows( 1 ); 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/Add &N Strips" );
o->add( "&Mixer/&Import Strip" ); o->add( "&Mixer/&Import Strip" );
o->add( "&Mixer/Paste", FL_CTRL + 'v', 0, 0 ); 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/Start Learning", FL_F + 9, 0, 0 );
o->add( "&Remote Control/Stop Learning", FL_F + 10, 0, 0 ); o->add( "&Remote Control/Stop Learning", FL_F + 10, 0, 0 );
o->add( "&Remote Control/Send State" ); 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/ */ /** retrun a pointer to the track named /name/, or NULL if no track is named /name/ */
Mixer_Strip * Mixer_Strip *
Mixer::track_by_name ( const char *name ) Mixer::track_by_name ( const char *name )

View File

@ -31,6 +31,7 @@
class Fl_Blink_Button; class Fl_Blink_Button;
class Fl_Flowpack; class Fl_Flowpack;
class Fl_Menu_Bar; class Fl_Menu_Bar;
class Spatialization_Console;
namespace OSC { class Endpoint; } namespace OSC { class Endpoint; }
#include <lo/lo.h> #include <lo/lo.h>
@ -55,7 +56,6 @@ private:
Fl_Color system_colors[3]; Fl_Color system_colors[3];
Mixer_Strip* track_by_name ( const char *name ); Mixer_Strip* track_by_name ( const char *name );
Mixer_Strip* track_by_number ( int n );
void snapshot ( void ); void snapshot ( void );
static void snapshot ( void *v ) { ((Mixer*)v)->snapshot(); } static void snapshot ( void *v ) { ((Mixer*)v)->snapshot(); }
@ -91,6 +91,11 @@ private:
public: public:
static Spatialization_Console *spatialization_console;
int nstrips ( void ) const;
Mixer_Strip* track_by_number ( int n );
void update_frequency ( float f ); void update_frequency ( float f );
void status ( const char *s ) { void status ( const char *s ) {

View File

@ -688,6 +688,12 @@ Mixer_Strip::menu ( void ) const
return m; return m;
} }
Controller_Module *
Mixer_Strip::spatializer ( void )
{
return spatialization_controller;
}
int int
Mixer_Strip::handle ( int m ) Mixer_Strip::handle ( int m )
{ {

View File

@ -141,6 +141,8 @@ protected:
public: public:
Controller_Module *spatializer ( void );
void send_feedback ( void ); void send_feedback ( void );
int number ( void ) const; int number ( void ) const;
static bool import_strip ( const char *filename ); static bool import_strip ( const char *filename );

View File

@ -248,7 +248,7 @@ public:
connected_port()->_module->handle_control_changed( connected_port() ); connected_port()->_module->handle_control_changed( connected_port() );
} }
float control_value ( ) const float control_value ( void ) const
{ {
if ( buffer() ) if ( buffer() )
return *((float*)buffer()); return *((float*)buffer());
@ -284,6 +284,10 @@ public:
if ( _connected && _connected != (void*)0x01 ) if ( _connected && _connected != (void*)0x01 )
{ {
_connected->_connected = NULL; _connected->_connected = NULL;
if ( _connected->_module )
_connected->_module->handle_control_disconnect( this );
_connected = NULL; _connected = NULL;
} }
else else
@ -464,7 +468,7 @@ public:
/* called whenever the value of a control port is changed. /* called whenever the value of a control port is changed.
This can be used to take appropriate action from the GUI thread */ This can be used to take appropriate action from the GUI thread */
virtual void handle_control_changed ( Port * ); virtual void handle_control_changed ( Port * );
virtual void handle_control_disconnect ( Port * ) {}
/* called whenever the name of the chain changes (usually because /* called whenever the name of the chain changes (usually because
* the name of the mixer strip changed). */ * the name of the mixer strip changed). */
virtual void handle_chain_name_changed (); virtual void handle_chain_name_changed ();

View File

@ -58,12 +58,16 @@ Panner::point_bbox ( const Point *p, int *X, int *Y, int *W, int *H ) const
Panner::Point * Panner::Point *
Panner::event_point ( void ) Panner::event_point ( void )
{ {
for ( int i = _ins; i--; ) for ( int i = _points.size(); i--; )
{ {
int px, py, pw, ph; int px, py, pw, ph;
Point *p = &_points[ i ]; Point *p = &_points[ i ];
if ( ! p->visible )
continue;
point_bbox( p, &px, &py, &pw, &ph ); 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 ); // 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; goto done;
} }
/* tx += b; */ /* tx += b; */
/* ty += b; */ /* ty += b; */
/* tw -= b * 2; */ /* tw -= b * 2; */
@ -131,12 +134,14 @@ Panner::draw ( void )
fl_color( FL_WHITE ); 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; int px, py, pw, ph;
point_bbox( p, &px, &py, &pw, &ph ); point_bbox( p, &px, &py, &pw, &ph );
@ -151,7 +156,7 @@ Panner::draw ( void )
py - ( po * 12 ), py - ( po * 12 ),
pw + ( po * 24 ), ph + (po * 24 )); 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 ); fl_pie( px + 5, py + 5, pw - 10, ph - 10, 0, 360 );
@ -176,8 +181,8 @@ Panner::draw ( void )
const char *s = p->label; const char *s = p->label;
fl_color( fl_rgb_color( 125,125,130 ) ); fl_color( fl_color_add_alpha( fl_rgb_color( 220,255,255 ), 127 ) );
fl_font( FL_HELVETICA, ph + 2 ); fl_font( FL_HELVETICA_BOLD_ITALIC, 12 );
fl_draw( s, px + 20, py + 1, 50, ph - 1, FL_ALIGN_LEFT ); fl_draw( s, px + 20, py + 1, 50, ph - 1, FL_ALIGN_LEFT );
} }
@ -221,10 +226,10 @@ Panner::handle ( int m )
return 1; return 1;
} }
case FL_RELEASE: case FL_RELEASE:
if ( Fl::event_button1() && drag ) if ( drag )
{ {
drag = NULL;
do_callback(); do_callback();
drag = NULL;
redraw(); redraw();
return 1; return 1;
} }
@ -233,6 +238,7 @@ Panner::handle ( int m )
case FL_MOUSEWHEEL: case FL_MOUSEWHEEL:
{ {
/* TODO: place point on opposite face of sphere */ /* TODO: place point on opposite face of sphere */
return 0;
} }
case FL_DRAG: case FL_DRAG:
{ {

View File

@ -33,6 +33,7 @@ class Panner : public Fl_Widget
void draw_the_box( int, int, int, int ); void draw_the_box( int, int, int, int );
public:
struct Point struct Point
{ {
/* axes */ /* axes */
@ -43,9 +44,13 @@ class Panner : public Fl_Widget
float a; float a;
const char *label; const char *label;
void *userdata;
Fl_Color color;
Point ( ) : d( 0.0f ), a( 0.0f ), label(0) { } bool visible;
Point ( float D, float A ) : d( D ), a( A ), label(0) { }
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/ */ /** translate angle /a/ into x/y coords and place the result in /X/ and /Y/ */
void void
@ -125,6 +130,7 @@ class Panner : public Fl_Widget
}; };
private:
/* channel configuration */ /* channel configuration */
int _ins, int _ins,
@ -183,8 +189,19 @@ public:
_points.push_back( Point( 1, 0 ) ); _points.push_back( Point( 1, 0 ) );
} }
void clear_points ( void ) { _points.clear(); }
void add_point( Panner::Point &p )
{
_points.push_back( p );
}
virtual ~Panner ( ) { } virtual ~Panner ( ) { }
Panner::Point *point ( int i ); Panner::Point *point ( int i );
int points ( void ) const { return _points.size(); }
Panner::Point *pushed ( void ) { return drag; }
}; };

View File

@ -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 <FL/Fl.H>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <FL/fl_draw.H>
#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();
}

View File

@ -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 <FL/Fl_Double_Window.H>
#include <Module.H>
class Fl_Pack;
class Fl_Flowpack;
class Module;
class Fl_Menu_Button;
class Panner;
class Controller_Module;
#include <vector>
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<Fl_Widget*> controls_by_port;
public:
void handle_control_changed ( Controller_Module *m );
void update ( void );
Spatialization_Console ( );
virtual ~Spatialization_Console ( );
};

View File

@ -65,6 +65,7 @@ src/Panner.C
src/Plugin_Module.C src/Plugin_Module.C
src/Project.C src/Project.C
src/main.C src/main.C
src/Spatialization_Console.C
''', ''',
target = 'non-mixer', target = 'non-mixer',
includes = ['.', 'src', '..', '../nonlib'], includes = ['.', 'src', '..', '../nonlib'],