From d7f74e8e1555fe3cf5edcfe18de34776ba487cfa Mon Sep 17 00:00:00 2001 From: Jonathan Moore Liles Date: Sun, 27 Dec 2009 23:25:28 -0600 Subject: [PATCH] Mixer: Changes to support project saving/loading. --- FL/Fl_Scalepack.C | 3 + Mixer/Chain.C | 150 +++++++++++---- Mixer/Chain.H | 40 ++-- Mixer/Controller_Module.C | 57 +++++- Mixer/Controller_Module.H | 8 +- Mixer/Gain_Module.C | 9 +- Mixer/Gain_Module.H | 3 + Mixer/JACK_Module.C | 29 ++- Mixer/JACK_Module.H | 8 +- Mixer/Meter_Indicator_Module.C | 60 +++++- Mixer/Meter_Indicator_Module.H | 6 +- Mixer/Meter_Module.C | 14 +- Mixer/Meter_Module.H | 4 +- Mixer/Mixer.C | 36 +++- Mixer/Mixer.H | 2 + Mixer/Mixer_Strip.C | 243 ++++++++++-------------- Mixer/Mixer_Strip.H | 41 +++- Mixer/Module.C | 161 +++++++++++++++- Mixer/Module.H | 68 ++++--- Mixer/Module_Parameter_Editor.C | 3 +- Mixer/Plugin_Module.C | 63 +++++-- Mixer/Plugin_Module.H | 8 +- Mixer/Project.C | 324 ++++++++++++++++++++++++++++++++ Mixer/Project.H | 62 ++++++ Mixer/const.h | 22 +++ Mixer/main.C | 34 +++- nonlib/Loggable.C | 13 +- nonlib/Loggable.H | 2 +- 28 files changed, 1175 insertions(+), 298 deletions(-) create mode 100644 Mixer/Project.C create mode 100644 Mixer/Project.H create mode 100644 Mixer/const.h diff --git a/FL/Fl_Scalepack.C b/FL/Fl_Scalepack.C index e8564cd..a86b985 100644 --- a/FL/Fl_Scalepack.C +++ b/FL/Fl_Scalepack.C @@ -64,6 +64,9 @@ Fl_Scalepack::draw ( void ) if ( child( i )->visible() ) ++v; + if ( 0 == v ) + return; + int sz, pos; if ( type() == HORIZONTAL ) diff --git a/Mixer/Chain.C b/Mixer/Chain.C index d93def3..99c7bdb 100644 --- a/Mixer/Chain.C +++ b/Mixer/Chain.C @@ -71,6 +71,7 @@ #include "FL/Fl_Scroll.H" #include +#include "Mixer_Strip.H" #include @@ -80,16 +81,59 @@ std::list Chain::chain; -Chain::Chain ( int X, int Y, int W, int H, const char *L ) : - Fl_Group( X, Y, W, H, L) +void +Chain::get ( Log_Entry &e ) const +{ + e.add( ":strip", strip() ); +} + +void +Chain::set ( Log_Entry &e ) +{ + for ( int i = 0; i < e.size(); ++i ) + { + const char *s, *v; + + e.get( i, &s, &v ); + + if ( ! strcmp( s, ":strip" ) ) + { + int i; + sscanf( v, "%X", &i ); + Mixer_Strip *t = (Mixer_Strip*)Loggable::find( i ); + + assert( t ); + + t->chain( this ); + } + } +} + + + + +/* Chain::Chain ( int X, int Y, int W, int H, const char *L ) : */ +/* Fl_Group( X, Y, W, H, L) */ +Chain::Chain ( ) : Fl_Group( 0, 0, 100, 100, "") + { - _outs = 1; - _ins = 1; + int X = 0; + int Y = 0; + int W = 100; + int H = 100; + +/* _outs = 1; */ +/* _ins = 1; */ _configure_outputs_callback = NULL; + _strip = NULL; + _name = NULL; + labelsize( 10 ); + align( FL_ALIGN_TOP ); + { Fl_Tabs *o = tabs = new Fl_Tabs( X, Y, W, H ); { Fl_Group *o = new Fl_Group( X, Y + 24, W, H - 24, "Chain" ); o->box( FL_FLAT_BOX ); @@ -127,11 +171,27 @@ Chain::Chain ( int X, int Y, int W, int H, const char *L ) : end(); chain.push_back( this ); + + log_create(); } Chain::~Chain ( ) { chain.remove( this ); + log_destroy(); +} + + + +void +Chain::log_children ( void ) +{ + log_create(); + + for ( int i = 0; i < modules(); ++i ) + { + module(i)->log_create(); + } } /* Fill this chain with JACK I/O, Gain, and Meter modules. */ @@ -139,22 +199,30 @@ void Chain::initialize_with_default ( void ) { - { - JACK_Module *jm = new JACK_Module( 50, 50, "JACK" ); - jm->chain( this ); - jm->configure_outputs( 1 ); + { JACK_Module *m = new JACK_Module(); + m->is_default( true ); + m->chain( this ); + m->configure_outputs( 1 ); + m->initialize(); + add( m ); + } + + { Module *m = new Gain_Module(); + m->is_default( true ); + m->initialize(); + add( m ); + } - jm->initialize(); - jm->color( FL_BLACK ); - insert( NULL, jm ); + { Module *m = new Meter_Module(); + m->is_default( true ); + add( m ); } - { - JACK_Module *m = new JACK_Module( 50, 50, "JACK" ); + { JACK_Module *m = new JACK_Module(); + m->is_default( true ); m->chain( this ); m->initialize(); - m->color( FL_BLACK ); - insert( NULL, m ); + add( m ); } } @@ -204,8 +272,8 @@ Chain::remove ( Module *m ) void Chain::configure_ports ( void ) { - int old_outs = outs(); - int nouts = 0; +/* int old_outs = outs(); */ + int nouts = 0; engine->lock(); @@ -215,15 +283,15 @@ Chain::configure_ports ( void ) nouts = module( i )->noutputs(); } - outs( nouts ); +/* outs( nouts ); */ int req_buffers = required_buffers(); - if ( outs() != old_outs ) - { - if ( configure_outputs_callback() ) - configure_outputs_callback()( this, _configure_outputs_userdata ); - } +/* if ( outs() != old_outs ) */ +/* { */ +/* if ( configure_outputs_callback() ) */ +/* configure_outputs_callback()( this, _configure_outputs_userdata ); */ +/* } */ DMESSAGE( "required_buffers = %i", req_buffers ); @@ -329,6 +397,12 @@ Chain::name ( const char *name ) #include "FL/menu_popup.H" +bool +Chain::add ( Module *m ) +{ + return insert( NULL, m ); +} + bool Chain::insert ( Module *m, Module *n ) { @@ -389,6 +463,8 @@ Chain::insert ( Module *m, Module *n ) n->ncontrol_inputs(), n->ncontrol_outputs() ); + strip()->handle_module_added( n ); + configure_ports(); engine->unlock(); @@ -498,23 +574,23 @@ Chain::build_process_queue ( void ) m->handle_port_connection_change(); } - DMESSAGE( "Process queue looks like:" ); +/* DMESSAGE( "Process queue looks like:" ); */ for ( std::list::const_iterator i = process_queue.begin(); i != process_queue.end(); ++i ) { const Module* m = *i; - if ( m->audio_input.size() || m->audio_output.size() ) - DMESSAGE( "\t%s", (*i)->name() ); - else if ( m->control_output.size() ) - DMESSAGE( "\t%s -->", (*i)->name() ); - else if ( m->control_input.size() ) - DMESSAGE( "\t%s <--", (*i)->name() ); +/* if ( m->audio_input.size() || m->audio_output.size() ) */ +/* DMESSAGE( "\t%s", (*i)->name() ); */ +/* else if ( m->control_output.size() ) */ +/* DMESSAGE( "\t%s -->", (*i)->name() ); */ +/* else if ( m->control_input.size() ) */ +/* DMESSAGE( "\t%s <--", (*i)->name() ); */ { - char *s = m->describe_inputs(); + char *s = m->get_parameters(); - DMESSAGE( "(%s)", s ); +/* DMESSAGE( "(%s)", s ); */ delete[] s; } @@ -564,10 +640,9 @@ Chain::handle ( int m ) { if ( test_press( FL_BUTTON3 | FL_CTRL ) ) { - if ( FL_BLACK == m->color() ) + if ( m->is_default() ) { - /* FIXME: hack */ - fl_alert( "Cannot delete this module." ); + fl_alert( "Default modules may not be deleted." ); } else { @@ -604,6 +679,11 @@ Chain::handle ( int m ) return Fl_Group::handle( m ); } +void +Chain::strip ( Mixer_Strip * ms ) +{ + _strip = ms; +} void Chain::process ( nframes_t nframes ) diff --git a/Mixer/Chain.H b/Mixer/Chain.H index 61cac36..0b461e5 100644 --- a/Mixer/Chain.H +++ b/Mixer/Chain.H @@ -17,6 +17,8 @@ /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*******************************************************************************/ +#pragma once + #include #include #include @@ -25,11 +27,13 @@ #include "JACK/Port.H" #include #include +#include "Loggable.H" +class Mixer_Strip; class Fl_Flowpack; class Fl_Tabs; -class Chain : public Fl_Group { +class Chain : public Fl_Group, public Loggable { Fl_Pack *modules_pack; Fl_Flowpack *controls_pack; @@ -38,8 +42,10 @@ class Chain : public Fl_Group { void cb_handle(Fl_Widget*); static void cb_handle(Fl_Widget*, void*); - int _ins; - int _outs; +/* int _ins; */ +/* int _outs; */ + + Mixer_Strip *_strip; // sample_t **_buffer; // int _nbuffers; @@ -59,9 +65,20 @@ class Chain : public Fl_Group { static std::vector port; static std::list chain; +protected: + + void get ( Log_Entry &e ) const; + void set ( Log_Entry &e ); + + int handle ( int m ); + void draw ( void ); + public: + void resize ( int X, int Y, int W, int H ); + Mixer_Strip *strip ( void ) const { return _strip; } + void strip ( Mixer_Strip *v ); const char *name ( void ) const { return _name; } void name ( const char *name ); @@ -69,18 +86,20 @@ public: int required_buffers ( void ); Chain ( int X, int Y, int W, int H, const char *L = 0 ); + Chain ( ); virtual ~Chain ( ); bool can_support_input_channels ( int n ); - void ins ( int i ) { _ins = i; } - void outs ( int i ) { _outs = i; } - int ins ( void ) const { return _ins; } - int outs ( void ) const { return _outs; } +/* void ins ( int i ) { _ins = i; } */ +/* void outs ( int i ) { _outs = i; } */ +/* int ins ( void ) const { return _ins; } */ +/* int outs ( void ) const { return _outs; } */ int modules ( void ) const { return modules_pack->children(); } Module *module ( int n ) const { return (Module*)modules_pack->child( n ); } void remove ( Module *m ); + bool add ( Module *m ); bool insert ( Module *m, Module *n ); void add_control ( Module *m ); @@ -98,10 +117,7 @@ public: void process ( nframes_t ); -protected: - - int handle ( int m ); - void draw ( void ); - void resize ( int X, int Y, int W, int H ); + void log_children ( void ); + LOG_CREATE_FUNC( Chain ); }; diff --git a/Mixer/Controller_Module.C b/Mixer/Controller_Module.C index 155c48c..990327d 100644 --- a/Mixer/Controller_Module.C +++ b/Mixer/Controller_Module.C @@ -38,8 +38,56 @@ const float CONTROL_UPDATE_FREQ = 0.1f; -Controller_Module::Controller_Module ( int W, int H, const char *L ) - : Module ( W, 100, L ) +void +Controller_Module::get ( Log_Entry &e ) const +{ + + 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 ); +} + +void +Controller_Module::set ( Log_Entry &e ) +{ + Module::set( e ); + + int port = -1; + Module *module = NULL; + + for ( int i = 0; i < e.size(); ++i ) + { + const char *s, *v; + + e.get( i, &s, &v ); + + if ( ! strcmp( s, ":port" ) ) + { + port = atoi( v ); + } + else if ( ! strcmp( s, ":module" ) ) + { + int i; + sscanf( v, "%X", &i ); + Module *t = (Module*)Loggable::find( i ); + + assert( t ); + + module = t; + } + } + + if ( port >= 0 && module ) + control_output[0].connect_to( &module->control_input[port] ); +} + + + +Controller_Module::Controller_Module ( bool is_default ) : Module( is_default, 50, 100, name() ) { // label( "" ); box( FL_NO_BOX ); @@ -47,6 +95,7 @@ Controller_Module::Controller_Module ( int W, int H, const char *L ) _pad = true; control = 0; control_value =0.0f; + add_port( Port( this, Port::OUTPUT, Port::CONTROL ) ); mode( GUI ); @@ -56,11 +105,15 @@ Controller_Module::Controller_Module ( int W, int H, const char *L ) end(); Fl::add_timeout( CONTROL_UPDATE_FREQ, update_cb, this ); + + log_create(); + } Controller_Module::~Controller_Module ( ) { Fl::remove_timeout( update_cb, this ); + log_destroy(); } diff --git a/Mixer/Controller_Module.H b/Mixer/Controller_Module.H index 7ca2a97..ac7c28e 100644 --- a/Mixer/Controller_Module.H +++ b/Mixer/Controller_Module.H @@ -42,7 +42,8 @@ public: Mode mode ( void ) const { return _mode; } void mode ( Mode v ) { _mode = v; } - Controller_Module ( int W, int H, const char *L=0 ); + Controller_Module ( bool is_default = false ); +// Controller_Module ( int W, int H, const char *L=0 ); virtual ~Controller_Module ( ); const char *name ( void ) const { return "Controller"; } @@ -57,8 +58,13 @@ public: void connect_to ( Port *p ); + LOG_CREATE_FUNC( Controller_Module ); + + protected: + void get ( Log_Entry &e ) const; + void set ( Log_Entry &e ); // virtual void draw ( void ); virtual void process ( void ); diff --git a/Mixer/Gain_Module.C b/Mixer/Gain_Module.C index 2d148fd..544f3d3 100644 --- a/Mixer/Gain_Module.C +++ b/Mixer/Gain_Module.C @@ -22,8 +22,8 @@ #include #include -Gain_Module::Gain_Module ( int W, int H, const char *L ) - : Module ( W, 24, L ) +Gain_Module::Gain_Module ( ) + : Module ( 50, 24, name() ) { add_port( Port( this, Port::INPUT, Port::AUDIO ) ); add_port( Port( this, Port::OUTPUT, Port::AUDIO ) ); @@ -41,13 +41,16 @@ Gain_Module::Gain_Module ( int W, int H, const char *L ) add_port( p ); - color( FL_BLACK ); +// color( FL_BLACK ); end(); + + log_create(); } Gain_Module::~Gain_Module ( ) { + log_destroy(); } diff --git a/Mixer/Gain_Module.H b/Mixer/Gain_Module.H index 0baa02a..aa3b46a 100644 --- a/Mixer/Gain_Module.H +++ b/Mixer/Gain_Module.H @@ -25,6 +25,7 @@ class Gain_Module : public Module { public: + Gain_Module ( ); Gain_Module ( int W, int H, const char *L=0 ); virtual ~Gain_Module ( ); @@ -33,6 +34,8 @@ public: int can_support_inputs ( int n ) { return n; } bool configure_inputs ( int n ); + LOG_CREATE_FUNC( Gain_Module ); + protected: virtual void process ( void ); diff --git a/Mixer/JACK_Module.C b/Mixer/JACK_Module.C index 2c8b640..b2502f1 100644 --- a/Mixer/JACK_Module.C +++ b/Mixer/JACK_Module.C @@ -25,8 +25,10 @@ #include #include "Chain.H" -JACK_Module::JACK_Module ( int W, int H, const char *L ) - : Module ( W, 24, L ) + + +JACK_Module::JACK_Module ( ) + : Module ( 50, 24, name() ) { /* FIXME: how do Controls find out that a connected value has changed? How does this work in ladspa? */ { @@ -54,8 +56,18 @@ JACK_Module::JACK_Module ( int W, int H, const char *L ) } end(); + + log_create(); } +JACK_Module::~JACK_Module ( ) +{ + log_destroy(); + configure_inputs( 0 ); +} + + + int JACK_Module::can_support_inputs ( int n ) { @@ -137,11 +149,6 @@ JACK_Module::initialize ( void ) return true; } -JACK_Module::~JACK_Module ( ) -{ - configure_inputs( 0 ); -} - void JACK_Module::handle_control_changed ( Port *p ) { @@ -149,16 +156,20 @@ JACK_Module::handle_control_changed ( Port *p ) { DMESSAGE( "Adjusting number of inputs (JACK outputs)" ); configure_inputs( p->control_value() ); - chain()->configure_ports(); + if ( chain() ) + chain()->configure_ports(); } else if ( 0 == strcmp( p->name(), "Outputs" ) ) { DMESSAGE( "Adjusting number of outputs (JACK inputs)" ); - if ( chain()->can_configure_outputs( this, p->control_value() ) ) + if ( chain() && chain()->can_configure_outputs( this, p->control_value() ) ) { configure_outputs( p->control_value() ); chain()->configure_ports(); } + else + configure_outputs( p->control_value() ); + } } diff --git a/Mixer/JACK_Module.H b/Mixer/JACK_Module.H index c3a16a9..3dcc83f 100644 --- a/Mixer/JACK_Module.H +++ b/Mixer/JACK_Module.H @@ -26,20 +26,16 @@ class JACK_Module : public Module { - const char *_strip_name; - std::vector jack_input; std::vector jack_output; public: - JACK_Module ( int W, int H, const char *L=0 ); + JACK_Module ( ); virtual ~JACK_Module ( ); const char *name ( void ) const { return "JACK"; } - void strip_name ( const char *name ) { _strip_name = name; } - bool initialize ( void ); int can_support_inputs ( int ); @@ -51,6 +47,8 @@ public: void handle_control_changed ( Port *p ); void handle_chain_name_changed (); + LOG_CREATE_FUNC( JACK_Module ); + protected: virtual void process ( void ); diff --git a/Mixer/Meter_Indicator_Module.C b/Mixer/Meter_Indicator_Module.C index 1555af3..682a5f1 100644 --- a/Mixer/Meter_Indicator_Module.C +++ b/Mixer/Meter_Indicator_Module.C @@ -40,8 +40,58 @@ const float CONTROL_UPDATE_FREQ = 0.1f; -Meter_Indicator_Module::Meter_Indicator_Module ( int W, int H, const char *L ) - : Module ( W, 100, L ) + +void +Meter_Indicator_Module::get ( Log_Entry &e ) const +{ + + Port *p = control_input[0].connected_port(); + Module *m = p->module(); + + e.add( ":module", m ); + e.add( ":port", m->control_output_port_index( p ) ); + + Module::get( e ); +} + +void +Meter_Indicator_Module::set ( Log_Entry &e ) +{ + Module::set( e ); + + int port; + Module *module = NULL; + + for ( int i = 0; i < e.size(); ++i ) + { + const char *s, *v; + + e.get( i, &s, &v ); + + if ( ! strcmp( s, ":port" ) ) + { + port = atoi( v ); + } + else if ( ! strcmp( s, ":module" ) ) + { + int i; + sscanf( v, "%X", &i ); + Module *t = (Module*)Loggable::find( i ); + + assert( t ); + + module = t; + } + } + + if ( port >= 0 && module ) + control_input[0].connect_to( &module->control_output[port] ); +} + + + +Meter_Indicator_Module::Meter_Indicator_Module ( bool is_default ) + : Module ( is_default, 50, 100, name() ) { box( FL_NO_BOX ); @@ -55,6 +105,7 @@ Meter_Indicator_Module::Meter_Indicator_Module ( int W, int H, const char *L ) dpm_pack->type( FL_HORIZONTAL ); control_value = new float[1]; + *control_value = -70.0f; end(); @@ -64,9 +115,14 @@ Meter_Indicator_Module::Meter_Indicator_Module ( int W, int H, const char *L ) Meter_Indicator_Module::~Meter_Indicator_Module ( ) { if ( control_value ) + { delete[] control_value; + control_value = NULL; + } Fl::remove_timeout( update_cb, this ); + + log_destroy(); } diff --git a/Mixer/Meter_Indicator_Module.H b/Mixer/Meter_Indicator_Module.H index 717ab63..67f436e 100644 --- a/Mixer/Meter_Indicator_Module.H +++ b/Mixer/Meter_Indicator_Module.H @@ -39,7 +39,7 @@ class Meter_Indicator_Module : public Module public: - Meter_Indicator_Module ( int W, int H, const char *L=0 ); + Meter_Indicator_Module ( bool is_default = false ); virtual ~Meter_Indicator_Module ( ); const char *name ( void ) const { return "Meter Indicator"; } @@ -54,8 +54,12 @@ public: void connect_to ( Port *p ); + LOG_CREATE_FUNC( Meter_Indicator_Module ); + protected: + void get ( Log_Entry &e ) const; + void set ( Log_Entry &e ); // virtual void draw ( void ); virtual void process ( void ); diff --git a/Mixer/Meter_Module.C b/Mixer/Meter_Module.C index f816b3a..5cd3f83 100644 --- a/Mixer/Meter_Module.C +++ b/Mixer/Meter_Module.C @@ -31,8 +31,8 @@ const float METER_UPDATE_FREQ = 0.1f; -Meter_Module::Meter_Module ( int W, int, const char *L ) - : Module ( W, 100, L ) +Meter_Module::Meter_Module ( ) + : Module ( 50, 100, name() ) { box( FL_THIN_UP_FRAME ); dpm_pack = new Fl_Scalepack( x(), y(), w(), h() ); @@ -57,6 +57,7 @@ Meter_Module::Meter_Module ( int W, int, const char *L ) Fl::add_timeout( METER_UPDATE_FREQ, update_cb, this ); + log_create(); } Meter_Module::~Meter_Module ( ) @@ -65,6 +66,8 @@ Meter_Module::~Meter_Module ( ) delete[] control_value; Fl::remove_timeout( update_cb, this ); + + log_destroy(); } void @@ -117,8 +120,6 @@ Meter_Module::configure_inputs ( int n ) audio_input.pop_back(); audio_output.back().disconnect(); audio_output.pop_back(); - control_output.back().disconnect(); - control_output.pop_back(); } } @@ -130,14 +131,15 @@ Meter_Module::configure_inputs ( int n ) for ( int i = n; i--; ) f[i] = -70.0f; - control_output[0].connect_to( f); + control_output[0].connect_to( f ); } if ( control_value ) delete [] control_value; control_value = new float[n]; - + for ( int i = n; i--; ) + control_value[i] = -70.0f; return true; } diff --git a/Mixer/Meter_Module.H b/Mixer/Meter_Module.H index 7ea34d3..af07fe8 100644 --- a/Mixer/Meter_Module.H +++ b/Mixer/Meter_Module.H @@ -34,7 +34,7 @@ class Meter_Module : public Module public: - Meter_Module ( int W, int H, const char *L=0 ); + Meter_Module ( ); virtual ~Meter_Module ( ); const char *name ( void ) const { return "Meter"; } @@ -42,6 +42,8 @@ public: int can_support_inputs ( int n ) { return n > 0 ? n : -1; } bool configure_inputs ( int n ); + LOG_CREATE_FUNC( Meter_Module ); + protected: virtual int handle ( int m ); diff --git a/Mixer/Mixer.C b/Mixer/Mixer.C index 7e3dc10..f0cf01e 100644 --- a/Mixer/Mixer.C +++ b/Mixer/Mixer.C @@ -24,9 +24,12 @@ #include #include +#include #include "Engine/Engine.H" +#include "Project.H" + #include #include "debug.h" @@ -48,12 +51,18 @@ Mixer::Mixer ( int X, int Y, int W, int H, const char *L ) : { box( FL_NO_BOX ); labelsize( 96 ); - { - Fl_Scroll *o = scroll = new Fl_Scroll( X, Y, W, H ); + { Fl_Menu_Bar *o = new Fl_Menu_Bar( X, Y, W, 24 ); + o->add( "&Project/&New" ); + o->add( "&Project/&Open" ); + o->add( "&Project/&Quit" ); + o->add( "&Mixer/&Add Strip" ); + o->add( "&Options" ); + } + { Fl_Scroll *o = scroll = new Fl_Scroll( X, Y + 24, W, H - 24 ); o->box( FL_NO_BOX ); o->type( Fl_Scroll::HORIZONTAL_ALWAYS ); { - Fl_Pack *o = mixer_strips = new Fl_Pack( X, Y, W, H - 18 ); + Fl_Pack *o = mixer_strips = new Fl_Pack( X, Y + 24, W, H - 18 - 24 ); label( "Non-Mixer" ); align( (Fl_Align)(FL_ALIGN_CENTER | FL_ALIGN_INSIDE) ); o->box( FL_NO_BOX ); @@ -84,9 +93,9 @@ void Mixer::resize ( int X, int Y, int W, int H ) { Fl_Group::resize( X, Y, W, H ); - mixer_strips->resize( X, Y, W, H - 18 ); + mixer_strips->resize( X, Y + 24, W, H - 18 - 24 ); - scroll->resize( X, Y, W, H ); + scroll->resize( X, Y + 24, W, H - 24 ); } void Mixer::add ( Mixer_Strip *ms ) @@ -181,7 +190,7 @@ void Mixer::snapshot ( void ) { for ( int i = 0; i < mixer_strips->children(); ++i ) - ((Mixer_Strip*)mixer_strips->child( i ))->log_create(); + ((Mixer_Strip*)mixer_strips->child( i ))->log_children(); } @@ -197,6 +206,16 @@ Mixer::new_strip ( void ) // scroll->size( mixer_strips->w(), scroll->h() ); } +bool +Mixer::save ( void ) +{ + MESSAGE( "Saving state" ); + Loggable::snapshot_callback( &Mixer::snapshot, this ); + Loggable::snapshot( "save.mix" ); + return true; +} + + int Mixer::handle ( int m ) { @@ -216,9 +235,8 @@ Mixer::handle ( int m ) } else if ( Fl::event_ctrl() && Fl::event_key() == 's' ) { - MESSAGE( "Saving state" ); - Loggable::snapshot_callback( &Mixer::snapshot, this ); - Loggable::snapshot( "save.mix" ); +// save(); + Project::save(); return 1; } else diff --git a/Mixer/Mixer.H b/Mixer/Mixer.H index 662b042..aa31482 100644 --- a/Mixer/Mixer.H +++ b/Mixer/Mixer.H @@ -56,6 +56,8 @@ public: void remove ( Mixer_Strip *ms ); bool contains ( Mixer_Strip *ms ); + bool save ( void ); + Mixer ( int X, int Y, int W, int H, const char *L ); virtual ~Mixer(); }; diff --git a/Mixer/Mixer_Strip.C b/Mixer/Mixer_Strip.C index 3011e78..a00531d 100644 --- a/Mixer/Mixer_Strip.C +++ b/Mixer/Mixer_Strip.C @@ -58,12 +58,8 @@ void Mixer_Strip::get ( Log_Entry &e ) const { e.add( ":name", name() ); -// e.add( ":controllable", controllable() ); -// e.add( ":inputs", _in.size() ); -/* e.add( ":gain", gain_slider->value() ); */ - e.add( ":meter_point", prepost_button->value() ? "pre" : "post" ); + e.add( ":width", prepost_button->value() ? "wide" : "narrow" ); e.add( ":color", (unsigned long)color()); - } void @@ -77,13 +73,7 @@ Mixer_Strip::set ( Log_Entry &e ) if ( ! strcmp( s, ":name" ) ) name( v ); -// else if ( ! strcmp( s, ":controllable" ) ) -// controllable( atoi( v ) ); - else if ( ! strcmp( s, ":inputs" ) ) - configure_ports( atoi( v ) ); -/* else if ( ! strcmp( s, ":gain" ) ) */ -/* gain_slider->value( atof( v ) ); */ - else if ( ! strcmp( s, ":meter_point" ) ) + else if ( ! strcmp( s, ":width" ) ) prepost_button->value( strcmp( v, "pre" ) == 0 ); else if ( ! strcmp( s, ":color" ) ) { @@ -96,23 +86,62 @@ Mixer_Strip::set ( Log_Entry &e ) mixer->add( this ); } +void +Mixer_Strip::log_children ( void ) +{ + log_create(); + + _chain->log_children(); +} -Mixer_Strip::Mixer_Strip( const char *strip_name, int channels ) : Fl_Group( 0, 0, 120, 600 ) +void +Mixer_Strip::chain ( Chain *c ) { + if ( _chain ) + delete _chain; + _chain = c; + + c->strip( this ); + + Fl_Group *g = signal_group; + + c->resize( g->x(), g->y(), g->w(), g->h() ); + g->add( c ); + g->resizable( c ); + + c->labelsize( 10 ); + c->align( FL_ALIGN_TOP ); + c->color( FL_RED ); + c->configure_outputs_callback( configure_outputs, this ); + c->name( name() ); + + gain_controller->chain( c ); + jack_input_controller->chain( c ); + meter_indicator->chain( c ); +} + +/* add a new mixer strip (with default configuration) */ +Mixer_Strip::Mixer_Strip( const char *strip_name, int channels ) : Fl_Group( 0, 0, 120, 600 ) +{ label( strdup( strip_name ) ); init(); + chain( new Chain() ); + + _chain->initialize_with_default(); + + _chain->configure_ports(); + color( (Fl_Color)rand() ); // name( strdup( strip_name ) ); - configure_ports( channels ); - log_create(); } +/* virgin strip created from journal */ Mixer_Strip::Mixer_Strip() : Fl_Group( 0, 0, 120, 600 ) { init(); @@ -122,7 +151,7 @@ Mixer_Strip::Mixer_Strip() : Fl_Group( 0, 0, 120, 600 ) Mixer_Strip::~Mixer_Strip ( ) { - configure_ports( 0 ); + log_destroy(); } @@ -154,7 +183,8 @@ Mixer_Strip::name ( const char *name ) { char *s = strdup( name ); name_field->value( s ); label( s ); - chain->name( s ); + if ( _chain ) + _chain->name( s ); } void @@ -169,90 +199,38 @@ Mixer_Strip::configure_outputs ( void ) DMESSAGE( "Got signal to configure outputs" ); } -bool -Mixer_Strip::configure_ports ( int n ) +/* called by the chain to let us know that a module has been added */ +void +Mixer_Strip::handle_module_added ( Module *m ) { -/* /\* figure out how many buffers we have to create *\/ */ -/* int required_buffers = chain->required_buffers(); */ - -/* engine->lock(); */ - -/* if ( chain_buffers > 0 ) */ -/* { */ -/* for ( int i = chain_buffers; --i; ) */ -/* { */ -/* delete chain_buffer[i]; */ -/* chain_buffer[i] = NULL; */ -/* } */ -/* delete chain_buffer; */ -/* chain_buffer = NULL; */ -/* chain_buffers = 0; */ -/* } */ - -/* sample_t **buf = new sample_t*[required_buffers]; */ -/* for ( int i = 0; i < required_buffers; ++i ) */ -/* buf[i] = new sample_t[nframes]; */ - -/* chain_buffers = required_buffers; */ -/* chain_buffer = buf; */ - -/* engine->unlock(); */ - -/* /\* FIXME: bogus *\/ */ -/* return true; */ + if ( m->is_default() ) + { + DMESSAGE( "Connecting controls to default module \"%s\"", m->name() ); + /* connect default modules to their default controllers/indicators */ + if ( ! strcmp( m->name(), "JACK" ) && m->ninputs() == 0 ) + { + if ( !jack_input_controller->control_output[0].connected() ) + jack_input_controller->connect_to( &m->control_input[1] ); + } + else if ( ! strcmp( m->name(), "Gain" ) ) + { + gain_controller->connect_to( &m->control_input[0] ); + } + else if ( ! strcmp( m->name(), "Meter" ) ) + { + meter_indicator->connect_to( &m->control_output[0] ); + } + } } - void Mixer_Strip::process ( nframes_t nframes ) { THREAD_ASSERT( RT ); -/* sample_t *gain_buf = NULL; */ -/* float g = gain_slider->value(); */ - -/* if ( _control && _control->connected() ) */ -/* { */ -/* gain_buf = (sample_t*)_control->buffer( nframes ); */ - -/* /\* // bring it up to 0.0-2.0f *\/ */ -/* /\* for ( int i = nframes; i--; ) *\/ */ -/* /\* gain_buf[i] += 1.0f; *\/ */ - -/* // apply gain from slider */ -/* buffer_apply_gain( gain_buf, nframes, g ); */ - -/* /\* FIXME: bullshit! *\/ */ -/* _control_peak = gain_buf[0]; */ -/* } */ -/* else */ -/* { */ -/* _control_peak = 0; */ -/* } */ - -/* for ( int i = channels(); i--; ) */ -/* { */ -/* if ( _in[i].connected()) */ -/* { */ -/* if ( gain_buf ) */ -/* buffer_copy_and_apply_gain_buffer( (sample_t*)_out[i].buffer( nframes ), (sample_t*)_in[i].buffer( nframes ), gain_buf, nframes ); */ -/* else */ -/* buffer_copy_and_apply_gain( (sample_t*)_out[i].buffer( nframes ), (sample_t*)_in[i].buffer( nframes ), nframes, g ); */ - -/* sample_t *meter_buffer = prepost_button->value() == 1 ? (sample_t*)_in[i].buffer( nframes ) : (sample_t*)_out[i].buffer( nframes ); */ - -/* /\* set peak value (in dB) *\/ */ -/* _peak[i] = 20 * log10( get_peak_sample( meter_buffer, nframes ) / 2.0f ); */ -/* } */ -/* else */ -/* { */ -/* buffer_fill_with_silence( (sample_t*)_out[i].buffer( nframes ), nframes ); */ -/* } */ -/* } */ - - chain->process( nframes ); + _chain->process( nframes ); } /* update GUI with values from RT thread */ @@ -265,6 +243,8 @@ Mixer_Strip::update ( void ) void Mixer_Strip::init ( ) { + _chain = 0; + chain_buffers = 0; chain_buffer = NULL; @@ -332,24 +312,31 @@ Mixer_Strip::init ( ) { Fl_Pack* o = fader_pack = new Fl_Pack(4, 116, 103, 330 ); o->spacing( 20 ); o->type( Fl_Pack::HORIZONTAL ); + { Controller_Module *o = gain_controller = new Controller_Module( true ); +// o->chain( _chain ); + o->pad( false ); +// o->connect_to( &gain_module->control_input[0] ); + o->size( 33, 0 ); + } + { Meter_Indicator_Module *o = meter_indicator = new Meter_Indicator_Module( true ); +// o->chain( _chain ); + o->pad( false ); +// o->connect_to( &meter_module->control_output[0] ); + o->size( 58, 0 ); + o->clip_children( 0 ); + Fl_Group::current()->resizable(o); + + } + o->end(); Fl_Group::current()->resizable(o); } // Fl_Group* o o->end(); Fl_Group::current()->resizable(o); } - { Fl_Group *o = new Fl_Group( 4, 114, 110, 330, "Signal" ); + { Fl_Group *o = signal_group = new Fl_Group( 4, 114, 110, 330, "Signal" ); o->labelsize( 9 ); o->hide(); - { Chain *o = chain = new Chain( 4, 116, 110, 330 ); - o->labelsize( 10 ); - o->align( FL_ALIGN_TOP ); - o->color( FL_RED ); - o->configure_outputs_callback( configure_outputs, this ); - o->name( name() ); - o->initialize_with_default(); - Fl_Group::current()->resizable(o); - } o->end(); } @@ -357,7 +344,9 @@ Mixer_Strip::init ( ) Fl_Group::current()->resizable(o); } - { Fl_Pack *o = new Fl_Pack( 2, 440, 114, 40 ); +// log_create(); + + { Fl_Pack *o = panner_pack = new Fl_Pack( 2, 440, 114, 40 ); o->spacing( 2 ); o->type( Fl_Pack::VERTICAL ); @@ -380,10 +369,11 @@ Mixer_Strip::init ( ) } // Panner* o #endif { - Controller_Module *m = new Controller_Module( 100, 24, "Inputs" ); - m->chain( chain ); + Controller_Module *m = jack_input_controller = new Controller_Module( true ); + m->label( "Inputs" ); + m->chain( _chain ); m->pad( false ); - m->connect_to( &chain->module( 0 )->control_input[1] ); +// m->connect_to( &_chain->module( 0 )->control_input[1] ); m->size( 33, 24 ); } o->end(); @@ -392,49 +382,8 @@ Mixer_Strip::init ( ) end(); color( FL_BLACK ); -// controllable( true ); - - { - Module *gain_module; - - { - Module *m = gain_module = new Gain_Module( 50, 50, "Gain" ); - m->initialize(); - chain->insert( chain->module( chain->modules() - 1 ), m ); - } - - { - Controller_Module *m = new Controller_Module( 100, 0, "Gain" ); - m->chain( chain ); - m->pad( false ); - m->connect_to( &gain_module->control_input[0] ); - m->size( 33, 0 ); - - fader_pack->add( m ); - } - - Module *meter_module; - - { - Module *m = meter_module = new Meter_Module( 50, 50, "Meter" ); - chain->insert( chain->module( chain->modules() - 1 ), m ); - } - { - Meter_Indicator_Module *m = new Meter_Indicator_Module( 100, 0, "" ); - m->chain( chain ); - m->pad( false ); - m->connect_to( &meter_module->control_output[0] ); - m->size( 58, 0 ); - m->clip_children( 0 ); - - fader_pack->add( m ); - - fader_pack->resizable( m ); - } - - chain->configure_ports(); - } + // _chain->configure_ports(); } diff --git a/Mixer/Mixer_Strip.H b/Mixer/Mixer_Strip.H index ac9c7f3..40e2329 100644 --- a/Mixer/Mixer_Strip.H +++ b/Mixer/Mixer_Strip.H @@ -1,7 +1,24 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0108 -#ifndef Mixer_Strip_H -#define Mixer_Strip_H +/*******************************************************************************/ +/* Copyright (C) 2010 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 "DPM.H" #include "Panner.H" @@ -26,6 +43,9 @@ #include "Loggable.H" class Chain; class Fl_Flowpack; +class Controller_Module; +class Meter_Indicator_Module; +class Module; class Mixer_Strip : public Fl_Group, public Loggable { @@ -42,8 +62,14 @@ public: Fl_Input *name_field; Fl_Flowpack *controls_pack; + Fl_Group *signal_group; + Fl_Pack *panner_pack; + + Chain *_chain; - Chain *chain; + Controller_Module *gain_controller; + Controller_Module *jack_input_controller; + Meter_Indicator_Module *meter_indicator; sample_t **chain_buffer; int chain_buffers; @@ -69,6 +95,10 @@ protected: public: + void chain ( Chain *c ); + + void log_children ( void ); + void color ( Fl_Color c ) { _color = c; @@ -90,10 +120,11 @@ public: bool configure_ports ( int n ); + void handle_module_added ( Module *m ); + void update ( void ); // int channels ( void ) const { return _in.size(); } void name ( const char *name ); const char *name ( void ) const { return label(); } }; -#endif diff --git a/Mixer/Module.C b/Mixer/Module.C index 022e29f..c79a67a 100644 --- a/Mixer/Module.C +++ b/Mixer/Module.C @@ -25,9 +25,33 @@ #include #include "Module_Parameter_Editor.H" +#include "Chain.H" +Module::Module ( int W, int H, const char *L ) : Fl_Group( 0, 0, W, H, L ) +{ + init(); + + log_create(); +} + +Module::Module ( bool is_default, int W, int H, const char *L ) : Fl_Group( 0, 0, W, H, L ), Loggable( !is_default ) +{ + this->is_default( is_default ); + + init(); + + log_create(); +} + +Module::Module ( ) : Fl_Group( 0, 0, 0, 50, "Unnamed" ) +{ + init(); + + log_create(); +} + Module::~Module ( ) { for ( unsigned int i = 0; i < audio_input.size(); ++i ) @@ -47,12 +71,95 @@ Module::~Module ( ) +void +Module::init ( void ) +{ + _is_default = false; + _editor = 0; + _chain = 0; + _instances = 1; + box( FL_UP_BOX ); + labeltype( FL_NO_LABEL ); + clip_children( 1 ); +} + + +void +Module::get ( Log_Entry &e ) const +{ +// e.add( ":name", label() ); +// e.add( ":color", (unsigned long)color()); + { + char *s = get_parameters(); + if ( strlen( s ) ) + e.add( ":parameter_values", s ); + delete[] s; + } + e.add( ":is_default", is_default() ); + e.add( ":chain", chain() ); +} + +void +Module::set ( Log_Entry &e ) +{ + for ( int i = 0; i < e.size(); ++i ) + { + const char *s, *v; + + e.get( i, &s, &v ); + + if ( ! strcmp( s, ":chain" ) ) + { + /* This trickiness is because we may need to know the name of + our chain before we actually get added to it. */ + int i; + sscanf( v, "%X", &i ); + Chain *t = (Chain*)Loggable::find( i ); + + assert( t ); + + chain( t ); + } + } + + for ( int i = 0; i < e.size(); ++i ) + { + const char *s, *v; + + e.get( i, &s, &v ); + +/* if ( ! strcmp( s, ":name" ) ) */ +/* label( v ); */ + if ( ! strcmp( s, ":parameter_values" ) ) + { + set_parameters( v ); + } + else if ( ! ( strcmp( s, ":is_default" ) ) ) + { + is_default( atoi( v ) ); + } + else if ( ! strcmp( s, ":chain" ) ) + { + int i; + sscanf( v, "%X", &i ); + Chain *t = (Chain*)Loggable::find( i ); + + assert( t ); + + t->add( this ); + } + } +} + + + + /* return a string serializing this module's parameter settings. The format is 1.0:2.0:... Where 1.0 is the value of the first control input, 2.0 is the value of the second control input etc. - */ +*/ char * -Module::describe_inputs ( void ) const +Module::get_parameters ( void ) const { char *s = new char[1024]; s[0] = 0; @@ -60,15 +167,53 @@ Module::describe_inputs ( void ) const if ( control_input.size() ) { - for ( unsigned int i = 0; i < control_input.size(); ++i ) - sp += snprintf( sp, 1024 - (sp - s),"%f:", control_input[i].control_value() ); + for ( unsigned int i = 0; i < control_input.size(); ++i ) + sp += snprintf( sp, 1024 - (sp - s),"%f:", control_input[i].control_value() ); - *(sp - 1) = '\0'; + *(sp - 1) = '\0'; } return s; } +void +Module::set_parameters ( const char *parameters ) +{ + char *s = strdup( parameters ); + char *sp = s; + + char *start = s; + int i = 0; + for ( char *sp = s; ; ++sp ) + { + if ( ':' == *sp || '\0' == *sp ) + { + char was = *sp; + + *sp = '\0'; + + DMESSAGE( start ); + + if ( i < control_input.size() ) + control_input[i].control_value( atof( start ) ); + else + { + WARNING( "Module has no parameter at index %i", i ); + break; + } + + i++; + + if ( '\0' == was ) + break; + + start = sp + 1; + } + } + + free( s ); +} + void @@ -87,10 +232,14 @@ Module::draw_box ( void ) fl_push_clip( tx, ty, tw, th ); + + Fl_Color c = is_default() ? FL_BLACK : color(); + + int spacing = w() / instances(); for ( int i = instances(); i--; ) { - fl_draw_box( box(), tx + (spacing * i), ty, tw / instances(), th, Fl::belowmouse() == this ? fl_lighter( color() ) : color() ); + fl_draw_box( box(), tx + (spacing * i), ty, tw / instances(), th, Fl::belowmouse() == this ? fl_lighter( c ) : c ); } if ( audio_input.size() && audio_output.size() ) diff --git a/Mixer/Module.H b/Mixer/Module.H index 0511694..4f6b37c 100644 --- a/Mixer/Module.H +++ b/Mixer/Module.H @@ -30,41 +30,43 @@ #include "util/Thread.H" +#include "Loggable.H" + class Chain; class Module_Parameter_Editor; -class Module : public Fl_Group { - - void init ( void ) - { - _editor = 0; - _chain = 0; - _instances = 1; - box( FL_UP_BOX ); - labeltype( FL_NO_LABEL ); - clip_children( 1 ); - } +class Module : public Fl_Group, public Loggable { int _ins; int _outs; int _instances; unsigned long _nframes; Chain *_chain; + bool _is_default; Module_Parameter_Editor *_editor; void cb_handle(Fl_Widget*); static void cb_handle(Fl_Widget*, void*); - + void init ( void ); public: + /* true if this module was added by default and not under normal user control */ + bool is_default ( void ) const { return _is_default; } + void is_default ( bool v ) { _is_default = v; } + class Port { /* char *type_names[] = { "Audio", "Control" }; */ /* char *direction_names[] = { "Input", "Output" }; */ + void update_connected_port_buffer ( void ) + { + if ( connected() ) + connected_port()->_buf = _buf; + } public: @@ -175,7 +177,7 @@ public: void connect_to ( void *buf ) { _buf = buf; -// _connected = (Port*)0x01; + update_connected_port_buffer(); } void disconnect ( void ) @@ -210,16 +212,14 @@ public: H = h() - 10; } - Module ( int W, int H, const char *L = 0 ) : Fl_Group( 0, 0, W, H, L ) - { - init(); - } - Module ( ) : Fl_Group( 0, 0, 0, 50, "Unnamed" ) - { - init(); - } + Module ( int W, int H, const char *L = 0 ); + Module ( ); + Module ( bool is_default, int W, int H, const char *L = 0 ); + virtual ~Module ( ); + LOG_NAME_FUNC( Module ); + // static Module * pick_plugin ( void ); @@ -286,10 +286,29 @@ public: } + int control_input_port_index ( Port *p ) + { + for ( unsigned int i = control_input.size(); i--; ) + if ( &control_input[i] == p ) + return i; + + return -1; + } + + int control_output_port_index ( Port *p ) + { + for ( unsigned int i = control_output.size(); i--; ) + if ( &control_output[i] == p ) + return i; + + return -1; + } + Chain *chain ( void ) const { return _chain; } void chain ( Chain * v ) { _chain = v; } - char *describe_inputs ( void ) const; + char *get_parameters ( void ) const; + void set_parameters ( const char * ); virtual bool initialize ( void ) { return true; } @@ -314,8 +333,6 @@ public: virtual void handle_port_connection_change () {} - - protected: void draw_connections ( void ); @@ -325,4 +342,7 @@ protected: virtual void draw ( void ) { Module::draw_box(); Module::draw_label(); } virtual int handle ( int m ); + virtual void get ( Log_Entry &e ) const; + virtual void set ( Log_Entry &e ); + }; diff --git a/Mixer/Module_Parameter_Editor.C b/Mixer/Module_Parameter_Editor.C index 22d270f..d36c9d5 100644 --- a/Mixer/Module_Parameter_Editor.C +++ b/Mixer/Module_Parameter_Editor.C @@ -281,7 +281,8 @@ Module_Parameter_Editor::bind_control ( int i ) /* can only bind once */ return; - Controller_Module *o = new Controller_Module( 50, 50, p->name() ); + Controller_Module *o = new Controller_Module(); + o->label( p->name() ); o->chain( _module->chain() ); o->connect_to( p ); diff --git a/Mixer/Plugin_Module.C b/Mixer/Plugin_Module.C index d9ae6f5..10c7e1c 100644 --- a/Mixer/Plugin_Module.C +++ b/Mixer/Plugin_Module.C @@ -54,26 +54,54 @@ struct Plugin_Module::ImplementationData -Plugin_Module::Plugin_Module ( int , int , const char *L ) : Module( 50, 50, L ) +Plugin_Module::Plugin_Module ( ) : Module( 50, 50, name() ) { init(); end(); + + log_create(); } Plugin_Module::~Plugin_Module ( ) { + log_destroy(); plugin_instances( 0 ); } -/* void */ -/* Plugin_Module::detect_plugins ( void ) */ -/* { */ -/* LADPSAInfo *li = new LADSPAInfo(); */ -/* } */ +void +Plugin_Module::get ( Log_Entry &e ) const +{ +// char s[512]; +// snprintf( s, sizeof( s ), "ladspa:%lu", _idata->descriptor->UniqueID ); + e.add( ":plugin_id", _idata->descriptor->UniqueID ); + + Module::get( e ); +} + +void +Plugin_Module::set ( Log_Entry &e ) +{ + for ( int i = 0; i < e.size(); ++i ) + { + const char *s, *v; + + e.get( i, &s, &v ); + + if ( ! strcmp( s, ":plugin_id" ) ) + { + load( (unsigned long) atoll ( v ) ); + } + } + + Module::set( e ); +} + + + #include @@ -106,15 +134,9 @@ Plugin_Module::pick_plugin ( void ) Plugin_Module::Plugin_Info *pi = (Plugin_Module::Plugin_Info*)menu->menu()[ menu->value() ].user_data(); - Plugin_Module *m = new Plugin_Module( 50, 50 ); - - m->load( pi ); + Plugin_Module *m = new Plugin_Module(); - const char *plugin_name = pi->path; - - char *label = strdup( rindex(plugin_name, '/') + 1 ); - - m->label( label ); + m->load( pi->id ); delete[] pia; @@ -342,9 +364,14 @@ Plugin_Module::plugin_instances ( unsigned int n ) } bool -Plugin_Module::load ( Plugin_Module::Plugin_Info *pi ) +Plugin_Module::load ( unsigned long id ) { - _idata->descriptor = ladspainfo->GetDescriptorByID( pi->id ); + if ( !ladspainfo ) + ladspainfo = new LADSPAInfo(); + + _idata->descriptor = ladspainfo->GetDescriptorByID( id ); + + label( _idata->descriptor->Name ); _plugin_ins = _plugin_outs = 0; @@ -488,9 +515,9 @@ Plugin_Module::load ( Plugin_Module::Plugin_Info *pi ) bool neg_max = max < 0.0f ? true : false; if (!neg_min && !neg_max) { - Default = exp(log(min) * lp + log(max) * up); + Default = exp(::log(min) * lp + ::log(max) * up); } else if (neg_min && neg_max) { - Default = -exp(log(-min) * lp + log(-max) * up); + Default = -exp(::log(-min) * lp + ::log(-max) * up); } else { // Logarithmic range has asymptote // so just use linear scale diff --git a/Mixer/Plugin_Module.H b/Mixer/Plugin_Module.H index 1e7f2b5..2d04040 100644 --- a/Mixer/Plugin_Module.H +++ b/Mixer/Plugin_Module.H @@ -20,6 +20,7 @@ #pragma once #include "Module.H" +#include "Loggable.H" class Plugin_Module : Module { @@ -61,7 +62,7 @@ class Plugin_Module : Module { static Plugin_Info* discover ( void ); - bool load ( Plugin_Info * ); + bool load ( unsigned long id ); void set_input_buffer ( int n, void *buf ); void set_output_buffer ( int n, void *buf ); @@ -77,7 +78,6 @@ class Plugin_Module : Module { public: - Plugin_Module( int W, int H, const char *L = 0 ); Plugin_Module ( ); virtual ~Plugin_Module(); @@ -97,8 +97,12 @@ public: void handle_port_connection_change ( void ); + LOG_CREATE_FUNC( Plugin_Module ); + protected: virtual int handle ( int ); + void get ( Log_Entry &e ) const; + void set ( Log_Entry &e ); }; diff --git a/Mixer/Project.C b/Mixer/Project.C new file mode 100644 index 0000000..43e716b --- /dev/null +++ b/Mixer/Project.C @@ -0,0 +1,324 @@ + +/*******************************************************************************/ +/* Copyright (C) 2008 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. */ +/*******************************************************************************/ + +/* Routings for opening/closing/creation of projects. All the actual + project state belongs to Timeline and other classes. */ + +/* Project management routines. */ + +#include +#include +#include +#include +#include +#include +#include + +#include "Loggable.H" +#include "Project.H" + +#include + +#include "const.h" +#include "util/debug.h" +#include "util/file.h" + +#include "Mixer.H" + +const int PROJECT_VERSION = 1; + + + +const char *Project::_errstr[] = +{ + "Not a Non-Mixer project", + "Locked by another process", + "Access denied", + "Incompatible project version" +}; + +char Project::_name[256]; +char Project::_created_on[40]; +char Project::_path[512]; +bool Project::_is_open = false; +int Project::_lockfd = 0; + + + +/***********/ +/* Private */ +/***********/ + +void +Project::set_name ( const char *name ) +{ + strcpy( Project::_name, name ); + + if ( Project::_name[ strlen( Project::_name ) - 1 ] == '/' ) + Project::_name[ strlen( Project::_name ) - 1 ] = '\0'; + + char *s = rindex( Project::_name, '/' ); + + s = s ? s + 1 : Project::_name; + + memmove( Project::_name, s, strlen( s ) + 1 ); + + for ( s = Project::_name; *s; ++s ) + if ( *s == '_' || *s == '-' ) + *s = ' '; +} + +bool +Project::write_info ( void ) +{ + FILE *fp; + + if ( ! ( fp = fopen( "info", "w" ) ) ) + { + WARNING( "could not open project info file for writing." ); + return false; + } + + char s[40]; + + if ( ! *_created_on ) + { + time_t t = time( NULL ); + ctime_r( &t, s ); + s[ strlen( s ) - 1 ] = '\0'; + } + else + strcpy( s, _created_on ); + + fprintf( fp, "created by\n\t%s\ncreated on\n\t%s\nversion\n\t%d\n", + APP_TITLE " " VERSION, + s, + PROJECT_VERSION ); + + fclose( fp ); + + return true; +} + +bool +Project::read_info ( int *version, char **creation_date ) +{ + FILE *fp; + + if ( ! ( fp = fopen( "info", "r" ) ) ) + { + WARNING( "could not open project info file for reading." ); + return false; + } + + *version = 0; + *creation_date = 0; + + char *name, *value; + + while ( fscanf( fp, "%a[^\n]\n\t%a[^\n]\n", &name, &value ) == 2 ) + { + MESSAGE( "Info: %s = %s", name, value ); + + if ( ! strcmp( name, "version" ) ) + *version = atoi( value ); + else if ( ! strcmp( name, "created on" ) ) + *creation_date = strdup( value ); + + free( name ); + free( value ); + } + + fclose( fp ); + + return true; +} + +/**********/ +/* Public */ +/**********/ + +/** Save out any settings and unjournaled state... */ +bool +Project::save ( void ) +{ + if ( ! open() ) + return true; + +// tle->save_timeline_settings(); + + return mixer->save(); + +// return Loggable::save_unjournaled_state(); +} + + +/** Close the project (reclaiming all memory) */ +bool +Project::close ( void ) +{ + if ( ! open() ) + return true; + + if ( ! save() ) + return false; + +/* Loggable::close(); */ +/* // write_info(); */ + + _is_open = false; + + *Project::_name = '\0'; + *Project::_created_on = '\0'; + + release_lock( &_lockfd, ".lock" ); + + return true; +} + +/** Ensure a project is valid before opening it... */ +bool +Project::validate ( const char *name ) +{ + bool r = true; + + char pwd[512]; + + fl_filename_absolute( pwd, sizeof( pwd ), "." ); + + if ( chdir( name ) ) + { + WARNING( "Cannot change to project dir \"%s\"", name ); + return false; + } + + if ( ! exists( "info" ) || + ! exists( "snapshot" )) + { + WARNING( "Not a Non-Mixer project: \"%s\"", name ); + r = false; + } + + chdir( pwd ); + + return r; +} + +/** Try to open project /name/. Returns 0 if sucsessful, an error code + * otherwise */ +int +Project::open ( const char *name ) +{ + if ( ! validate( name ) ) + return E_INVALID; + + close(); + + chdir( name ); + + if ( ! acquire_lock( &_lockfd, ".lock" ) ) + return E_LOCKED; + + int version; + char *creation_date; + + if ( ! read_info( &version, &creation_date ) ) + return E_INVALID; + + if ( version != PROJECT_VERSION ) + return E_VERSION; + + if ( ! Loggable::replay( "snapshot" ) ) + return E_INVALID; + + if ( creation_date ) + { + strcpy( _created_on, creation_date ); + free( creation_date ); + } + else + *_created_on = 0; + + set_name( name ); + + *_path = '\0'; + fl_filename_absolute( _path, sizeof( _path ), "." ); + + _is_open = true; + +// tle->load_timeline_settings(); + +// timeline->zoom_fit(); + + MESSAGE( "Loaded project \"%s\"", name ); + + return 0; +} + +/** Create a new project /name/ from existing template + * /template_name/ */ +bool +Project::create ( const char *name, const char *template_name ) +{ + if ( exists( name ) ) + { + WARNING( "Project already exists" ); + return false; + } + + close(); + + if ( mkdir( name, 0777 ) ) + { + WARNING( "Cannot create project directory" ); + return false; + } + + if ( chdir( name ) ) + FATAL( "WTF? Cannot change to new project directory" ); + + mkdir( "sources", 0777 ); + creat( "snapshot", 0666 ); + + /* TODO: copy template */ + + write_info(); + + if ( open( name ) == 0 ) + { +// /* add the bare essentials */ +// timeline->beats_per_minute( 0, 120 ); +// timeline->time( 0, 4, 4 ); + + MESSAGE( "Created project \"%s\" from template \"%s\"", name, template_name ); + return true; + } + else + { + WARNING( "Failed to open newly created project" ); + return false; + } +} + +/** Replace the journal with a snapshot of the current state */ +void +Project::compact ( void ) +{ + Loggable::compact(); +} diff --git a/Mixer/Project.H b/Mixer/Project.H new file mode 100644 index 0000000..2ea2b24 --- /dev/null +++ b/Mixer/Project.H @@ -0,0 +1,62 @@ + +/*******************************************************************************/ +/* Copyright (C) 2008, 2010 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. */ +/*******************************************************************************/ + +const char template_dir[] = "share/non-daw/templates"; +const char user_template_dir[] = "~/.non-daw/templates"; + +#include "types.h" + +class Project +{ + + static int _lockfd; + static bool _is_open; + static char _name[256]; + static char _path[512]; + static char _created_on[40]; + + static bool write_info ( void ); + static bool read_info ( int *version, char **creation_date ); + static void set_name ( const char *name ); + static const char *_errstr[]; + +public: + + enum + { + E_INVALID = -1, + E_LOCKED = -2, + E_PERM = -3, + E_SAMPLERATE = -4, + E_VERSION = -5 + }; + + static const char *errstr ( int n ) { return _errstr[ ( 0 - n ) - 1 ]; } + + static const char *name ( void ) { return Project::_name; } + static void compact ( void ); + static bool close ( void ); + static bool save ( void ); + static bool validate ( const char *name ); + static int open ( const char *name ); + static bool open ( void ) { return _is_open; } + static bool create ( const char *name, const char *template_name ); + + static const char *created_on ( void ) { return _created_on; } +}; diff --git a/Mixer/const.h b/Mixer/const.h new file mode 100644 index 0000000..10d1e48 --- /dev/null +++ b/Mixer/const.h @@ -0,0 +1,22 @@ + +/*******************************************************************************/ +/* Copyright (C) 2008 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. */ +/*******************************************************************************/ + +#define APP_NAME "Non-Mixer" +#define APP_TITLE "The Non-Mixer" +#define __MODULE__ "non-mixer" diff --git a/Mixer/main.C b/Mixer/main.C index 343920f..63bd3a7 100644 --- a/Mixer/main.C +++ b/Mixer/main.C @@ -34,6 +34,7 @@ #include "Engine/Engine.H" #include "util/Thread.H" #include "util/debug.h" +#include "Project.H" Engine *engine; Mixer *mixer; @@ -44,6 +45,20 @@ Fl_Single_Window *main_window; #include "Loggable.H" #include + +/* for registration */ +#include "Module.H" +#include "Gain_Module.H" +#include "Plugin_Module.H" +#include "JACK_Module.H" +#include "Meter_Module.H" +#include "Meter_Indicator_Module.H" +#include "Controller_Module.H" +#include "Chain.H" + + +#include + int main ( int argc, char **argv ) { @@ -57,12 +72,21 @@ main ( int argc, char **argv ) Fl_Tooltip::size( 14 ); Fl_Tooltip::hoverdelay( 0.1f ); - Fl::visible_focus( 0 ); +// Fl::visible_focus( 0 ); LOG_REGISTER_CREATE( Mixer_Strip ); + LOG_REGISTER_CREATE( Chain ); + LOG_REGISTER_CREATE( Plugin_Module ); + LOG_REGISTER_CREATE( Gain_Module ); + LOG_REGISTER_CREATE( Meter_Module ); + LOG_REGISTER_CREATE( JACK_Module ); + LOG_REGISTER_CREATE( Meter_Indicator_Module ); + LOG_REGISTER_CREATE( Controller_Module ); init_boxtypes(); + signal( SIGPIPE, SIG_IGN ); + Fl::get_system_colors(); Fl::scheme( "plastic" ); // Fl::scheme( "gtk+" ); @@ -91,11 +115,13 @@ main ( int argc, char **argv ) if ( argc > 1 ) { - char name[1024]; +/* char name[1024]; */ - snprintf( name, sizeof( name ), "%s/history", argv[1] ); +/* snprintf( name, sizeof( name ), "%s/history", argv[1] ); */ - Loggable::open( name ); +/* Loggable::open( name ); */ + MESSAGE( "Loading \"%s\"", argv[1] ); + Project::open( argv[1] ); } else { diff --git a/nonlib/Loggable.C b/nonlib/Loggable.C index bea654e..0fa91f4 100644 --- a/nonlib/Loggable.C +++ b/nonlib/Loggable.C @@ -163,11 +163,16 @@ Loggable::load_unjournaled_state ( void ) bool Loggable::replay ( const char *file ) { - FILE *fp = fopen( file, "r" ); + if ( FILE *fp = fopen( file, "r" ) ) + { + bool r = replay( fp ); - replay( fp ); + fclose( fp ); - fclose( fp ); + return r; + } + else + return false; } /** replay journal or snapshot */ @@ -279,7 +284,7 @@ void Loggable::update_id ( unsigned int id ) { /* make sure we're the last one */ - assert( _id == _log_id ); + ASSERT( _id == _log_id, "%u != %u", _id, _log_id ); assert( _loggables[ _id ].loggable == this ); _loggables[ _id ].loggable = NULL; diff --git a/nonlib/Loggable.H b/nonlib/Loggable.H index 0e43a7c..f423b82 100644 --- a/nonlib/Loggable.H +++ b/nonlib/Loggable.H @@ -127,10 +127,10 @@ private: static bool load_unjournaled_state ( void ); static bool replay ( FILE *fp ); - static bool replay ( const char *name ); public: + static bool replay ( const char *name ); static bool snapshot( FILE * fp ); static bool snapshot( const char *name );