@@ -64,6 +64,9 @@ Fl_Scalepack::draw ( void ) | |||||
if ( child( i )->visible() ) | if ( child( i )->visible() ) | ||||
++v; | ++v; | ||||
if ( 0 == v ) | |||||
return; | |||||
int sz, pos; | int sz, pos; | ||||
if ( type() == HORIZONTAL ) | if ( type() == HORIZONTAL ) | ||||
@@ -71,6 +71,7 @@ | |||||
#include "FL/Fl_Scroll.H" | #include "FL/Fl_Scroll.H" | ||||
#include <string.h> | #include <string.h> | ||||
#include "Mixer_Strip.H" | |||||
#include <dsp.h> | #include <dsp.h> | ||||
@@ -80,16 +81,59 @@ std::list <Chain*> 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; | _configure_outputs_callback = NULL; | ||||
_strip = NULL; | |||||
_name = NULL; | _name = NULL; | ||||
labelsize( 10 ); | |||||
align( FL_ALIGN_TOP ); | |||||
{ Fl_Tabs *o = tabs = new Fl_Tabs( X, Y, W, H ); | { Fl_Tabs *o = tabs = new Fl_Tabs( X, Y, W, H ); | ||||
{ Fl_Group *o = new Fl_Group( X, Y + 24, W, H - 24, "Chain" ); | { Fl_Group *o = new Fl_Group( X, Y + 24, W, H - 24, "Chain" ); | ||||
o->box( FL_FLAT_BOX ); | o->box( FL_FLAT_BOX ); | ||||
@@ -127,11 +171,27 @@ Chain::Chain ( int X, int Y, int W, int H, const char *L ) : | |||||
end(); | end(); | ||||
chain.push_back( this ); | chain.push_back( this ); | ||||
log_create(); | |||||
} | } | ||||
Chain::~Chain ( ) | Chain::~Chain ( ) | ||||
{ | { | ||||
chain.remove( this ); | 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. */ | /* Fill this chain with JACK I/O, Gain, and Meter modules. */ | ||||
@@ -139,22 +199,30 @@ void | |||||
Chain::initialize_with_default ( 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->chain( this ); | ||||
m->initialize(); | m->initialize(); | ||||
m->color( FL_BLACK ); | |||||
insert( NULL, m ); | |||||
add( m ); | |||||
} | } | ||||
} | } | ||||
@@ -204,8 +272,8 @@ Chain::remove ( Module *m ) | |||||
void | void | ||||
Chain::configure_ports ( void ) | Chain::configure_ports ( void ) | ||||
{ | { | ||||
int old_outs = outs(); | |||||
int nouts = 0; | |||||
/* int old_outs = outs(); */ | |||||
int nouts = 0; | |||||
engine->lock(); | engine->lock(); | ||||
@@ -215,15 +283,15 @@ Chain::configure_ports ( void ) | |||||
nouts = module( i )->noutputs(); | nouts = module( i )->noutputs(); | ||||
} | } | ||||
outs( nouts ); | |||||
/* outs( nouts ); */ | |||||
int req_buffers = required_buffers(); | 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 ); | DMESSAGE( "required_buffers = %i", req_buffers ); | ||||
@@ -329,6 +397,12 @@ Chain::name ( const char *name ) | |||||
#include "FL/menu_popup.H" | #include "FL/menu_popup.H" | ||||
bool | |||||
Chain::add ( Module *m ) | |||||
{ | |||||
return insert( NULL, m ); | |||||
} | |||||
bool | bool | ||||
Chain::insert ( Module *m, Module *n ) | Chain::insert ( Module *m, Module *n ) | ||||
{ | { | ||||
@@ -389,6 +463,8 @@ Chain::insert ( Module *m, Module *n ) | |||||
n->ncontrol_inputs(), | n->ncontrol_inputs(), | ||||
n->ncontrol_outputs() ); | n->ncontrol_outputs() ); | ||||
strip()->handle_module_added( n ); | |||||
configure_ports(); | configure_ports(); | ||||
engine->unlock(); | engine->unlock(); | ||||
@@ -498,23 +574,23 @@ Chain::build_process_queue ( void ) | |||||
m->handle_port_connection_change(); | m->handle_port_connection_change(); | ||||
} | } | ||||
DMESSAGE( "Process queue looks like:" ); | |||||
/* DMESSAGE( "Process queue looks like:" ); */ | |||||
for ( std::list<Module*>::const_iterator i = process_queue.begin(); i != process_queue.end(); ++i ) | for ( std::list<Module*>::const_iterator i = process_queue.begin(); i != process_queue.end(); ++i ) | ||||
{ | { | ||||
const Module* m = *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; | delete[] s; | ||||
} | } | ||||
@@ -564,10 +640,9 @@ Chain::handle ( int m ) | |||||
{ | { | ||||
if ( test_press( FL_BUTTON3 | FL_CTRL ) ) | 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 | else | ||||
{ | { | ||||
@@ -604,6 +679,11 @@ Chain::handle ( int m ) | |||||
return Fl_Group::handle( m ); | return Fl_Group::handle( m ); | ||||
} | } | ||||
void | |||||
Chain::strip ( Mixer_Strip * ms ) | |||||
{ | |||||
_strip = ms; | |||||
} | |||||
void | void | ||||
Chain::process ( nframes_t nframes ) | Chain::process ( nframes_t nframes ) | ||||
@@ -17,6 +17,8 @@ | |||||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||||
/*******************************************************************************/ | /*******************************************************************************/ | ||||
#pragma once | |||||
#include <FL/Fl.H> | #include <FL/Fl.H> | ||||
#include <FL/Fl_Pack.H> | #include <FL/Fl_Pack.H> | ||||
#include <FL/Fl_Button.H> | #include <FL/Fl_Button.H> | ||||
@@ -25,11 +27,13 @@ | |||||
#include "JACK/Port.H" | #include "JACK/Port.H" | ||||
#include <vector> | #include <vector> | ||||
#include <list> | #include <list> | ||||
#include "Loggable.H" | |||||
class Mixer_Strip; | |||||
class Fl_Flowpack; | class Fl_Flowpack; | ||||
class Fl_Tabs; | class Fl_Tabs; | ||||
class Chain : public Fl_Group { | |||||
class Chain : public Fl_Group, public Loggable { | |||||
Fl_Pack *modules_pack; | Fl_Pack *modules_pack; | ||||
Fl_Flowpack *controls_pack; | Fl_Flowpack *controls_pack; | ||||
@@ -38,8 +42,10 @@ class Chain : public Fl_Group { | |||||
void cb_handle(Fl_Widget*); | void cb_handle(Fl_Widget*); | ||||
static void cb_handle(Fl_Widget*, void*); | static void cb_handle(Fl_Widget*, void*); | ||||
int _ins; | |||||
int _outs; | |||||
/* int _ins; */ | |||||
/* int _outs; */ | |||||
Mixer_Strip *_strip; | |||||
// sample_t **_buffer; | // sample_t **_buffer; | ||||
// int _nbuffers; | // int _nbuffers; | ||||
@@ -59,9 +65,20 @@ class Chain : public Fl_Group { | |||||
static std::vector <Module::Port> port; | static std::vector <Module::Port> port; | ||||
static std::list <Chain*> chain; | static std::list <Chain*> chain; | ||||
protected: | |||||
void get ( Log_Entry &e ) const; | |||||
void set ( Log_Entry &e ); | |||||
int handle ( int m ); | |||||
void draw ( void ); | |||||
public: | 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; } | const char *name ( void ) const { return _name; } | ||||
void name ( const char *name ); | void name ( const char *name ); | ||||
@@ -69,18 +86,20 @@ public: | |||||
int required_buffers ( void ); | int required_buffers ( void ); | ||||
Chain ( int X, int Y, int W, int H, const char *L = 0 ); | Chain ( int X, int Y, int W, int H, const char *L = 0 ); | ||||
Chain ( ); | |||||
virtual ~Chain ( ); | virtual ~Chain ( ); | ||||
bool can_support_input_channels ( int n ); | 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(); } | int modules ( void ) const { return modules_pack->children(); } | ||||
Module *module ( int n ) const { return (Module*)modules_pack->child( n ); } | Module *module ( int n ) const { return (Module*)modules_pack->child( n ); } | ||||
void remove ( Module *m ); | void remove ( Module *m ); | ||||
bool add ( Module *m ); | |||||
bool insert ( Module *m, Module *n ); | bool insert ( Module *m, Module *n ); | ||||
void add_control ( Module *m ); | void add_control ( Module *m ); | ||||
@@ -98,10 +117,7 @@ public: | |||||
void process ( nframes_t ); | 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 ); | |||||
}; | }; |
@@ -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( "" ); | // label( "" ); | ||||
box( FL_NO_BOX ); | box( FL_NO_BOX ); | ||||
@@ -47,6 +95,7 @@ Controller_Module::Controller_Module ( int W, int H, const char *L ) | |||||
_pad = true; | _pad = true; | ||||
control = 0; | control = 0; | ||||
control_value =0.0f; | control_value =0.0f; | ||||
add_port( Port( this, Port::OUTPUT, Port::CONTROL ) ); | add_port( Port( this, Port::OUTPUT, Port::CONTROL ) ); | ||||
mode( GUI ); | mode( GUI ); | ||||
@@ -56,11 +105,15 @@ Controller_Module::Controller_Module ( int W, int H, const char *L ) | |||||
end(); | end(); | ||||
Fl::add_timeout( CONTROL_UPDATE_FREQ, update_cb, this ); | Fl::add_timeout( CONTROL_UPDATE_FREQ, update_cb, this ); | ||||
log_create(); | |||||
} | } | ||||
Controller_Module::~Controller_Module ( ) | Controller_Module::~Controller_Module ( ) | ||||
{ | { | ||||
Fl::remove_timeout( update_cb, this ); | Fl::remove_timeout( update_cb, this ); | ||||
log_destroy(); | |||||
} | } | ||||
@@ -42,7 +42,8 @@ public: | |||||
Mode mode ( void ) const { return _mode; } | Mode mode ( void ) const { return _mode; } | ||||
void mode ( Mode v ) { _mode = v; } | 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 ( ); | virtual ~Controller_Module ( ); | ||||
const char *name ( void ) const { return "Controller"; } | const char *name ( void ) const { return "Controller"; } | ||||
@@ -57,8 +58,13 @@ public: | |||||
void connect_to ( Port *p ); | void connect_to ( Port *p ); | ||||
LOG_CREATE_FUNC( Controller_Module ); | |||||
protected: | protected: | ||||
void get ( Log_Entry &e ) const; | |||||
void set ( Log_Entry &e ); | |||||
// virtual void draw ( void ); | // virtual void draw ( void ); | ||||
virtual void process ( void ); | virtual void process ( void ); | ||||
@@ -22,8 +22,8 @@ | |||||
#include <math.h> | #include <math.h> | ||||
#include <dsp.h> | #include <dsp.h> | ||||
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::INPUT, Port::AUDIO ) ); | ||||
add_port( Port( this, Port::OUTPUT, 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 ); | add_port( p ); | ||||
color( FL_BLACK ); | |||||
// color( FL_BLACK ); | |||||
end(); | end(); | ||||
log_create(); | |||||
} | } | ||||
Gain_Module::~Gain_Module ( ) | Gain_Module::~Gain_Module ( ) | ||||
{ | { | ||||
log_destroy(); | |||||
} | } | ||||
@@ -25,6 +25,7 @@ class Gain_Module : public Module | |||||
{ | { | ||||
public: | public: | ||||
Gain_Module ( ); | |||||
Gain_Module ( int W, int H, const char *L=0 ); | Gain_Module ( int W, int H, const char *L=0 ); | ||||
virtual ~Gain_Module ( ); | virtual ~Gain_Module ( ); | ||||
@@ -33,6 +34,8 @@ public: | |||||
int can_support_inputs ( int n ) { return n; } | int can_support_inputs ( int n ) { return n; } | ||||
bool configure_inputs ( int n ); | bool configure_inputs ( int n ); | ||||
LOG_CREATE_FUNC( Gain_Module ); | |||||
protected: | protected: | ||||
virtual void process ( void ); | virtual void process ( void ); | ||||
@@ -25,8 +25,10 @@ | |||||
#include <string.h> | #include <string.h> | ||||
#include "Chain.H" | #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? */ | /* 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(); | end(); | ||||
log_create(); | |||||
} | } | ||||
JACK_Module::~JACK_Module ( ) | |||||
{ | |||||
log_destroy(); | |||||
configure_inputs( 0 ); | |||||
} | |||||
int | int | ||||
JACK_Module::can_support_inputs ( int n ) | JACK_Module::can_support_inputs ( int n ) | ||||
{ | { | ||||
@@ -137,11 +149,6 @@ JACK_Module::initialize ( void ) | |||||
return true; | return true; | ||||
} | } | ||||
JACK_Module::~JACK_Module ( ) | |||||
{ | |||||
configure_inputs( 0 ); | |||||
} | |||||
void | void | ||||
JACK_Module::handle_control_changed ( Port *p ) | 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)" ); | DMESSAGE( "Adjusting number of inputs (JACK outputs)" ); | ||||
configure_inputs( p->control_value() ); | configure_inputs( p->control_value() ); | ||||
chain()->configure_ports(); | |||||
if ( chain() ) | |||||
chain()->configure_ports(); | |||||
} | } | ||||
else if ( 0 == strcmp( p->name(), "Outputs" ) ) | else if ( 0 == strcmp( p->name(), "Outputs" ) ) | ||||
{ | { | ||||
DMESSAGE( "Adjusting number of outputs (JACK inputs)" ); | 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() ); | configure_outputs( p->control_value() ); | ||||
chain()->configure_ports(); | chain()->configure_ports(); | ||||
} | } | ||||
else | |||||
configure_outputs( p->control_value() ); | |||||
} | } | ||||
} | } | ||||
@@ -26,20 +26,16 @@ | |||||
class JACK_Module : public Module | class JACK_Module : public Module | ||||
{ | { | ||||
const char *_strip_name; | |||||
std::vector<JACK::Port> jack_input; | std::vector<JACK::Port> jack_input; | ||||
std::vector<JACK::Port> jack_output; | std::vector<JACK::Port> jack_output; | ||||
public: | public: | ||||
JACK_Module ( int W, int H, const char *L=0 ); | |||||
JACK_Module ( ); | |||||
virtual ~JACK_Module ( ); | virtual ~JACK_Module ( ); | ||||
const char *name ( void ) const { return "JACK"; } | const char *name ( void ) const { return "JACK"; } | ||||
void strip_name ( const char *name ) { _strip_name = name; } | |||||
bool initialize ( void ); | bool initialize ( void ); | ||||
int can_support_inputs ( int ); | int can_support_inputs ( int ); | ||||
@@ -51,6 +47,8 @@ public: | |||||
void handle_control_changed ( Port *p ); | void handle_control_changed ( Port *p ); | ||||
void handle_chain_name_changed (); | void handle_chain_name_changed (); | ||||
LOG_CREATE_FUNC( JACK_Module ); | |||||
protected: | protected: | ||||
virtual void process ( void ); | virtual void process ( void ); | ||||
@@ -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 ); | 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 ); | dpm_pack->type( FL_HORIZONTAL ); | ||||
control_value = new float[1]; | control_value = new float[1]; | ||||
*control_value = -70.0f; | |||||
end(); | end(); | ||||
@@ -64,9 +115,14 @@ Meter_Indicator_Module::Meter_Indicator_Module ( int W, int H, const char *L ) | |||||
Meter_Indicator_Module::~Meter_Indicator_Module ( ) | Meter_Indicator_Module::~Meter_Indicator_Module ( ) | ||||
{ | { | ||||
if ( control_value ) | if ( control_value ) | ||||
{ | |||||
delete[] control_value; | delete[] control_value; | ||||
control_value = NULL; | |||||
} | |||||
Fl::remove_timeout( update_cb, this ); | Fl::remove_timeout( update_cb, this ); | ||||
log_destroy(); | |||||
} | } | ||||
@@ -39,7 +39,7 @@ class Meter_Indicator_Module : public Module | |||||
public: | public: | ||||
Meter_Indicator_Module ( int W, int H, const char *L=0 ); | |||||
Meter_Indicator_Module ( bool is_default = false ); | |||||
virtual ~Meter_Indicator_Module ( ); | virtual ~Meter_Indicator_Module ( ); | ||||
const char *name ( void ) const { return "Meter Indicator"; } | const char *name ( void ) const { return "Meter Indicator"; } | ||||
@@ -54,8 +54,12 @@ public: | |||||
void connect_to ( Port *p ); | void connect_to ( Port *p ); | ||||
LOG_CREATE_FUNC( Meter_Indicator_Module ); | |||||
protected: | protected: | ||||
void get ( Log_Entry &e ) const; | |||||
void set ( Log_Entry &e ); | |||||
// virtual void draw ( void ); | // virtual void draw ( void ); | ||||
virtual void process ( void ); | virtual void process ( void ); | ||||
@@ -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 ); | box( FL_THIN_UP_FRAME ); | ||||
dpm_pack = new Fl_Scalepack( x(), y(), w(), h() ); | 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 ); | Fl::add_timeout( METER_UPDATE_FREQ, update_cb, this ); | ||||
log_create(); | |||||
} | } | ||||
Meter_Module::~Meter_Module ( ) | Meter_Module::~Meter_Module ( ) | ||||
@@ -65,6 +66,8 @@ Meter_Module::~Meter_Module ( ) | |||||
delete[] control_value; | delete[] control_value; | ||||
Fl::remove_timeout( update_cb, this ); | Fl::remove_timeout( update_cb, this ); | ||||
log_destroy(); | |||||
} | } | ||||
void | void | ||||
@@ -117,8 +120,6 @@ Meter_Module::configure_inputs ( int n ) | |||||
audio_input.pop_back(); | audio_input.pop_back(); | ||||
audio_output.back().disconnect(); | audio_output.back().disconnect(); | ||||
audio_output.pop_back(); | 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--; ) | for ( int i = n; i--; ) | ||||
f[i] = -70.0f; | f[i] = -70.0f; | ||||
control_output[0].connect_to( f); | |||||
control_output[0].connect_to( f ); | |||||
} | } | ||||
if ( control_value ) | if ( control_value ) | ||||
delete [] control_value; | delete [] control_value; | ||||
control_value = new float[n]; | control_value = new float[n]; | ||||
for ( int i = n; i--; ) | |||||
control_value[i] = -70.0f; | |||||
return true; | return true; | ||||
} | } | ||||
@@ -34,7 +34,7 @@ class Meter_Module : public Module | |||||
public: | public: | ||||
Meter_Module ( int W, int H, const char *L=0 ); | |||||
Meter_Module ( ); | |||||
virtual ~Meter_Module ( ); | virtual ~Meter_Module ( ); | ||||
const char *name ( void ) const { return "Meter"; } | const char *name ( void ) const { return "Meter"; } | ||||
@@ -42,6 +42,8 @@ public: | |||||
int can_support_inputs ( int n ) { return n > 0 ? n : -1; } | int can_support_inputs ( int n ) { return n > 0 ? n : -1; } | ||||
bool configure_inputs ( int n ); | bool configure_inputs ( int n ); | ||||
LOG_CREATE_FUNC( Meter_Module ); | |||||
protected: | protected: | ||||
virtual int handle ( int m ); | virtual int handle ( int m ); | ||||
@@ -24,9 +24,12 @@ | |||||
#include <FL/Fl_Pack.H> | #include <FL/Fl_Pack.H> | ||||
#include <FL/Fl_Scroll.H> | #include <FL/Fl_Scroll.H> | ||||
#include <FL/Fl_Menu_Bar.H> | |||||
#include "Engine/Engine.H" | #include "Engine/Engine.H" | ||||
#include "Project.H" | |||||
#include <string.h> | #include <string.h> | ||||
#include "debug.h" | #include "debug.h" | ||||
@@ -48,12 +51,18 @@ Mixer::Mixer ( int X, int Y, int W, int H, const char *L ) : | |||||
{ | { | ||||
box( FL_NO_BOX ); | box( FL_NO_BOX ); | ||||
labelsize( 96 ); | 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->box( FL_NO_BOX ); | ||||
o->type( Fl_Scroll::HORIZONTAL_ALWAYS ); | 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" ); | label( "Non-Mixer" ); | ||||
align( (Fl_Align)(FL_ALIGN_CENTER | FL_ALIGN_INSIDE) ); | align( (Fl_Align)(FL_ALIGN_CENTER | FL_ALIGN_INSIDE) ); | ||||
o->box( FL_NO_BOX ); | 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 ); | 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 ) | void Mixer::add ( Mixer_Strip *ms ) | ||||
@@ -181,7 +190,7 @@ void | |||||
Mixer::snapshot ( void ) | Mixer::snapshot ( void ) | ||||
{ | { | ||||
for ( int i = 0; i < mixer_strips->children(); ++i ) | 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() ); | // 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 | int | ||||
Mixer::handle ( int m ) | Mixer::handle ( int m ) | ||||
{ | { | ||||
@@ -216,9 +235,8 @@ Mixer::handle ( int m ) | |||||
} | } | ||||
else if ( Fl::event_ctrl() && Fl::event_key() == 's' ) | 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; | return 1; | ||||
} | } | ||||
else | else | ||||
@@ -56,6 +56,8 @@ public: | |||||
void remove ( Mixer_Strip *ms ); | void remove ( Mixer_Strip *ms ); | ||||
bool contains ( Mixer_Strip *ms ); | bool contains ( Mixer_Strip *ms ); | ||||
bool save ( void ); | |||||
Mixer ( int X, int Y, int W, int H, const char *L ); | Mixer ( int X, int Y, int W, int H, const char *L ); | ||||
virtual ~Mixer(); | virtual ~Mixer(); | ||||
}; | }; | ||||
@@ -58,12 +58,8 @@ void | |||||
Mixer_Strip::get ( Log_Entry &e ) const | Mixer_Strip::get ( Log_Entry &e ) const | ||||
{ | { | ||||
e.add( ":name", name() ); | 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()); | e.add( ":color", (unsigned long)color()); | ||||
} | } | ||||
void | void | ||||
@@ -77,13 +73,7 @@ Mixer_Strip::set ( Log_Entry &e ) | |||||
if ( ! strcmp( s, ":name" ) ) | if ( ! strcmp( s, ":name" ) ) | ||||
name( v ); | 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 ); | prepost_button->value( strcmp( v, "pre" ) == 0 ); | ||||
else if ( ! strcmp( s, ":color" ) ) | else if ( ! strcmp( s, ":color" ) ) | ||||
{ | { | ||||
@@ -96,23 +86,62 @@ Mixer_Strip::set ( Log_Entry &e ) | |||||
mixer->add( this ); | 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 ) ); | label( strdup( strip_name ) ); | ||||
init(); | init(); | ||||
chain( new Chain() ); | |||||
_chain->initialize_with_default(); | |||||
_chain->configure_ports(); | |||||
color( (Fl_Color)rand() ); | color( (Fl_Color)rand() ); | ||||
// name( strdup( strip_name ) ); | // name( strdup( strip_name ) ); | ||||
configure_ports( channels ); | |||||
log_create(); | log_create(); | ||||
} | } | ||||
/* virgin strip created from journal */ | |||||
Mixer_Strip::Mixer_Strip() : Fl_Group( 0, 0, 120, 600 ) | Mixer_Strip::Mixer_Strip() : Fl_Group( 0, 0, 120, 600 ) | ||||
{ | { | ||||
init(); | init(); | ||||
@@ -122,7 +151,7 @@ Mixer_Strip::Mixer_Strip() : Fl_Group( 0, 0, 120, 600 ) | |||||
Mixer_Strip::~Mixer_Strip ( ) | Mixer_Strip::~Mixer_Strip ( ) | ||||
{ | { | ||||
configure_ports( 0 ); | |||||
log_destroy(); | |||||
} | } | ||||
@@ -154,7 +183,8 @@ Mixer_Strip::name ( const char *name ) { | |||||
char *s = strdup( name ); | char *s = strdup( name ); | ||||
name_field->value( s ); | name_field->value( s ); | ||||
label( s ); | label( s ); | ||||
chain->name( s ); | |||||
if ( _chain ) | |||||
_chain->name( s ); | |||||
} | } | ||||
void | void | ||||
@@ -169,90 +199,38 @@ Mixer_Strip::configure_outputs ( void ) | |||||
DMESSAGE( "Got signal to configure outputs" ); | 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 | void | ||||
Mixer_Strip::process ( nframes_t nframes ) | Mixer_Strip::process ( nframes_t nframes ) | ||||
{ | { | ||||
THREAD_ASSERT( RT ); | 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 */ | /* update GUI with values from RT thread */ | ||||
@@ -265,6 +243,8 @@ Mixer_Strip::update ( void ) | |||||
void | void | ||||
Mixer_Strip::init ( ) | Mixer_Strip::init ( ) | ||||
{ | { | ||||
_chain = 0; | |||||
chain_buffers = 0; | chain_buffers = 0; | ||||
chain_buffer = NULL; | chain_buffer = NULL; | ||||
@@ -332,24 +312,31 @@ Mixer_Strip::init ( ) | |||||
{ Fl_Pack* o = fader_pack = new Fl_Pack(4, 116, 103, 330 ); | { Fl_Pack* o = fader_pack = new Fl_Pack(4, 116, 103, 330 ); | ||||
o->spacing( 20 ); | o->spacing( 20 ); | ||||
o->type( Fl_Pack::HORIZONTAL ); | 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(); | o->end(); | ||||
Fl_Group::current()->resizable(o); | Fl_Group::current()->resizable(o); | ||||
} // Fl_Group* o | } // Fl_Group* o | ||||
o->end(); | o->end(); | ||||
Fl_Group::current()->resizable(o); | 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->labelsize( 9 ); | ||||
o->hide(); | 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(); | o->end(); | ||||
} | } | ||||
@@ -357,7 +344,9 @@ Mixer_Strip::init ( ) | |||||
Fl_Group::current()->resizable(o); | 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->spacing( 2 ); | ||||
o->type( Fl_Pack::VERTICAL ); | o->type( Fl_Pack::VERTICAL ); | ||||
@@ -380,10 +369,11 @@ Mixer_Strip::init ( ) | |||||
} // Panner* o | } // Panner* o | ||||
#endif | #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->pad( false ); | ||||
m->connect_to( &chain->module( 0 )->control_input[1] ); | |||||
// m->connect_to( &_chain->module( 0 )->control_input[1] ); | |||||
m->size( 33, 24 ); | m->size( 33, 24 ); | ||||
} | } | ||||
o->end(); | o->end(); | ||||
@@ -392,49 +382,8 @@ Mixer_Strip::init ( ) | |||||
end(); | end(); | ||||
color( FL_BLACK ); | 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(); | |||||
} | } | ||||
@@ -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 <FL/Fl.H> | #include <FL/Fl.H> | ||||
#include "DPM.H" | #include "DPM.H" | ||||
#include "Panner.H" | #include "Panner.H" | ||||
@@ -26,6 +43,9 @@ | |||||
#include "Loggable.H" | #include "Loggable.H" | ||||
class Chain; | class Chain; | ||||
class Fl_Flowpack; | class Fl_Flowpack; | ||||
class Controller_Module; | |||||
class Meter_Indicator_Module; | |||||
class Module; | |||||
class Mixer_Strip : public Fl_Group, public Loggable { | class Mixer_Strip : public Fl_Group, public Loggable { | ||||
@@ -42,8 +62,14 @@ public: | |||||
Fl_Input *name_field; | Fl_Input *name_field; | ||||
Fl_Flowpack *controls_pack; | 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; | sample_t **chain_buffer; | ||||
int chain_buffers; | int chain_buffers; | ||||
@@ -69,6 +95,10 @@ protected: | |||||
public: | public: | ||||
void chain ( Chain *c ); | |||||
void log_children ( void ); | |||||
void color ( Fl_Color c ) | void color ( Fl_Color c ) | ||||
{ | { | ||||
_color = c; | _color = c; | ||||
@@ -90,10 +120,11 @@ public: | |||||
bool configure_ports ( int n ); | bool configure_ports ( int n ); | ||||
void handle_module_added ( Module *m ); | |||||
void update ( void ); | void update ( void ); | ||||
// int channels ( void ) const { return _in.size(); } | // int channels ( void ) const { return _in.size(); } | ||||
void name ( const char *name ); | void name ( const char *name ); | ||||
const char *name ( void ) const { return label(); } | const char *name ( void ) const { return label(); } | ||||
}; | }; | ||||
#endif |
@@ -25,9 +25,33 @@ | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include "Module_Parameter_Editor.H" | #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 ( ) | Module::~Module ( ) | ||||
{ | { | ||||
for ( unsigned int i = 0; i < audio_input.size(); ++i ) | 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 | /* 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 | 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. | input, 2.0 is the value of the second control input etc. | ||||
*/ | |||||
*/ | |||||
char * | char * | ||||
Module::describe_inputs ( void ) const | |||||
Module::get_parameters ( void ) const | |||||
{ | { | ||||
char *s = new char[1024]; | char *s = new char[1024]; | ||||
s[0] = 0; | s[0] = 0; | ||||
@@ -60,15 +167,53 @@ Module::describe_inputs ( void ) const | |||||
if ( control_input.size() ) | 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; | 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 | void | ||||
@@ -87,10 +232,14 @@ Module::draw_box ( void ) | |||||
fl_push_clip( tx, ty, tw, th ); | fl_push_clip( tx, ty, tw, th ); | ||||
Fl_Color c = is_default() ? FL_BLACK : color(); | |||||
int spacing = w() / instances(); | int spacing = w() / instances(); | ||||
for ( int i = instances(); i--; ) | 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() ) | if ( audio_input.size() && audio_output.size() ) | ||||
@@ -30,41 +30,43 @@ | |||||
#include "util/Thread.H" | #include "util/Thread.H" | ||||
#include "Loggable.H" | |||||
class Chain; | class Chain; | ||||
class Module_Parameter_Editor; | 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 _ins; | ||||
int _outs; | int _outs; | ||||
int _instances; | int _instances; | ||||
unsigned long _nframes; | unsigned long _nframes; | ||||
Chain *_chain; | Chain *_chain; | ||||
bool _is_default; | |||||
Module_Parameter_Editor *_editor; | Module_Parameter_Editor *_editor; | ||||
void cb_handle(Fl_Widget*); | void cb_handle(Fl_Widget*); | ||||
static void cb_handle(Fl_Widget*, void*); | static void cb_handle(Fl_Widget*, void*); | ||||
void init ( void ); | |||||
public: | 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 | class Port | ||||
{ | { | ||||
/* char *type_names[] = { "Audio", "Control" }; */ | /* char *type_names[] = { "Audio", "Control" }; */ | ||||
/* char *direction_names[] = { "Input", "Output" }; */ | /* char *direction_names[] = { "Input", "Output" }; */ | ||||
void update_connected_port_buffer ( void ) | |||||
{ | |||||
if ( connected() ) | |||||
connected_port()->_buf = _buf; | |||||
} | |||||
public: | public: | ||||
@@ -175,7 +177,7 @@ public: | |||||
void connect_to ( void *buf ) | void connect_to ( void *buf ) | ||||
{ | { | ||||
_buf = buf; | _buf = buf; | ||||
// _connected = (Port*)0x01; | |||||
update_connected_port_buffer(); | |||||
} | } | ||||
void disconnect ( void ) | void disconnect ( void ) | ||||
@@ -210,16 +212,14 @@ public: | |||||
H = h() - 10; | 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 ( ); | virtual ~Module ( ); | ||||
LOG_NAME_FUNC( Module ); | |||||
// static Module * pick_plugin ( void ); | // 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; } | Chain *chain ( void ) const { return _chain; } | ||||
void chain ( Chain * v ) { _chain = v; } | 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; } | virtual bool initialize ( void ) { return true; } | ||||
@@ -314,8 +333,6 @@ public: | |||||
virtual void handle_port_connection_change () {} | virtual void handle_port_connection_change () {} | ||||
protected: | protected: | ||||
void draw_connections ( void ); | void draw_connections ( void ); | ||||
@@ -325,4 +342,7 @@ protected: | |||||
virtual void draw ( void ) { Module::draw_box(); Module::draw_label(); } | virtual void draw ( void ) { Module::draw_box(); Module::draw_label(); } | ||||
virtual int handle ( int m ); | virtual int handle ( int m ); | ||||
virtual void get ( Log_Entry &e ) const; | |||||
virtual void set ( Log_Entry &e ); | |||||
}; | }; |
@@ -281,7 +281,8 @@ Module_Parameter_Editor::bind_control ( int i ) | |||||
/* can only bind once */ | /* can only bind once */ | ||||
return; | 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->chain( _module->chain() ); | ||||
o->connect_to( p ); | o->connect_to( p ); | ||||
@@ -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(); | init(); | ||||
end(); | end(); | ||||
log_create(); | |||||
} | } | ||||
Plugin_Module::~Plugin_Module ( ) | Plugin_Module::~Plugin_Module ( ) | ||||
{ | { | ||||
log_destroy(); | |||||
plugin_instances( 0 ); | 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 <FL/Fl_Menu_Button.H> | #include <FL/Fl_Menu_Button.H> | ||||
@@ -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::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; | delete[] pia; | ||||
@@ -342,9 +364,14 @@ Plugin_Module::plugin_instances ( unsigned int n ) | |||||
} | } | ||||
bool | 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; | _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; | bool neg_max = max < 0.0f ? true : false; | ||||
if (!neg_min && !neg_max) { | 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) { | } else if (neg_min && neg_max) { | ||||
Default = -exp(log(-min) * lp + log(-max) * up); | |||||
Default = -exp(::log(-min) * lp + ::log(-max) * up); | |||||
} else { | } else { | ||||
// Logarithmic range has asymptote | // Logarithmic range has asymptote | ||||
// so just use linear scale | // so just use linear scale | ||||
@@ -20,6 +20,7 @@ | |||||
#pragma once | #pragma once | ||||
#include "Module.H" | #include "Module.H" | ||||
#include "Loggable.H" | |||||
class Plugin_Module : Module { | class Plugin_Module : Module { | ||||
@@ -61,7 +62,7 @@ class Plugin_Module : Module { | |||||
static Plugin_Info* discover ( void ); | static Plugin_Info* discover ( void ); | ||||
bool load ( Plugin_Info * ); | |||||
bool load ( unsigned long id ); | |||||
void set_input_buffer ( int n, void *buf ); | void set_input_buffer ( int n, void *buf ); | ||||
void set_output_buffer ( int n, void *buf ); | void set_output_buffer ( int n, void *buf ); | ||||
@@ -77,7 +78,6 @@ class Plugin_Module : Module { | |||||
public: | public: | ||||
Plugin_Module( int W, int H, const char *L = 0 ); | |||||
Plugin_Module ( ); | Plugin_Module ( ); | ||||
virtual ~Plugin_Module(); | virtual ~Plugin_Module(); | ||||
@@ -97,8 +97,12 @@ public: | |||||
void handle_port_connection_change ( void ); | void handle_port_connection_change ( void ); | ||||
LOG_CREATE_FUNC( Plugin_Module ); | |||||
protected: | protected: | ||||
virtual int handle ( int ); | virtual int handle ( int ); | ||||
void get ( Log_Entry &e ) const; | |||||
void set ( Log_Entry &e ); | |||||
}; | }; |
@@ -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 <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <sys/types.h> | |||||
#include <sys/stat.h> | |||||
#include <sys/fcntl.h> | |||||
#include <errno.h> | |||||
#include "Loggable.H" | |||||
#include "Project.H" | |||||
#include <FL/filename.H> | |||||
#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(); | |||||
} |
@@ -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; } | |||||
}; |
@@ -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" |
@@ -34,6 +34,7 @@ | |||||
#include "Engine/Engine.H" | #include "Engine/Engine.H" | ||||
#include "util/Thread.H" | #include "util/Thread.H" | ||||
#include "util/debug.h" | #include "util/debug.h" | ||||
#include "Project.H" | |||||
Engine *engine; | Engine *engine; | ||||
Mixer *mixer; | Mixer *mixer; | ||||
@@ -44,6 +45,20 @@ Fl_Single_Window *main_window; | |||||
#include "Loggable.H" | #include "Loggable.H" | ||||
#include <FL/Fl_Tooltip.H> | #include <FL/Fl_Tooltip.H> | ||||
/* 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 <signal.h> | |||||
int | int | ||||
main ( int argc, char **argv ) | main ( int argc, char **argv ) | ||||
{ | { | ||||
@@ -57,12 +72,21 @@ main ( int argc, char **argv ) | |||||
Fl_Tooltip::size( 14 ); | Fl_Tooltip::size( 14 ); | ||||
Fl_Tooltip::hoverdelay( 0.1f ); | Fl_Tooltip::hoverdelay( 0.1f ); | ||||
Fl::visible_focus( 0 ); | |||||
// Fl::visible_focus( 0 ); | |||||
LOG_REGISTER_CREATE( Mixer_Strip ); | 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(); | init_boxtypes(); | ||||
signal( SIGPIPE, SIG_IGN ); | |||||
Fl::get_system_colors(); | Fl::get_system_colors(); | ||||
Fl::scheme( "plastic" ); | Fl::scheme( "plastic" ); | ||||
// Fl::scheme( "gtk+" ); | // Fl::scheme( "gtk+" ); | ||||
@@ -91,11 +115,13 @@ main ( int argc, char **argv ) | |||||
if ( argc > 1 ) | 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 | else | ||||
{ | { | ||||
@@ -163,11 +163,16 @@ Loggable::load_unjournaled_state ( void ) | |||||
bool | bool | ||||
Loggable::replay ( const char *file ) | 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 */ | /** replay journal or snapshot */ | ||||
@@ -279,7 +284,7 @@ void | |||||
Loggable::update_id ( unsigned int id ) | Loggable::update_id ( unsigned int id ) | ||||
{ | { | ||||
/* make sure we're the last one */ | /* 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 ); | assert( _loggables[ _id ].loggable == this ); | ||||
_loggables[ _id ].loggable = NULL; | _loggables[ _id ].loggable = NULL; | ||||
@@ -127,10 +127,10 @@ private: | |||||
static bool load_unjournaled_state ( void ); | static bool load_unjournaled_state ( void ); | ||||
static bool replay ( FILE *fp ); | static bool replay ( FILE *fp ); | ||||
static bool replay ( const char *name ); | |||||
public: | public: | ||||
static bool replay ( const char *name ); | |||||
static bool snapshot( FILE * fp ); | static bool snapshot( FILE * fp ); | ||||
static bool snapshot( const char *name ); | static bool snapshot( const char *name ); | ||||