@@ -64,6 +64,9 @@ Fl_Scalepack::draw ( void ) | |||
if ( child( i )->visible() ) | |||
++v; | |||
if ( 0 == v ) | |||
return; | |||
int sz, pos; | |||
if ( type() == HORIZONTAL ) | |||
@@ -71,6 +71,7 @@ | |||
#include "FL/Fl_Scroll.H" | |||
#include <string.h> | |||
#include "Mixer_Strip.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; | |||
_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<Module*>::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 ) | |||
@@ -17,6 +17,8 @@ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
#pragma once | |||
#include <FL/Fl.H> | |||
#include <FL/Fl_Pack.H> | |||
#include <FL/Fl_Button.H> | |||
@@ -25,11 +27,13 @@ | |||
#include "JACK/Port.H" | |||
#include <vector> | |||
#include <list> | |||
#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 <Module::Port> port; | |||
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: | |||
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 ); | |||
}; |
@@ -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(); | |||
} | |||
@@ -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 ); | |||
@@ -22,8 +22,8 @@ | |||
#include <math.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::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(); | |||
} | |||
@@ -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 ); | |||
@@ -25,8 +25,10 @@ | |||
#include <string.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? */ | |||
{ | |||
@@ -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() ); | |||
} | |||
} | |||
@@ -26,20 +26,16 @@ | |||
class JACK_Module : public Module | |||
{ | |||
const char *_strip_name; | |||
std::vector<JACK::Port> jack_input; | |||
std::vector<JACK::Port> 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 ); | |||
@@ -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(); | |||
} | |||
@@ -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 ); | |||
@@ -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; | |||
} | |||
@@ -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 ); | |||
@@ -24,9 +24,12 @@ | |||
#include <FL/Fl_Pack.H> | |||
#include <FL/Fl_Scroll.H> | |||
#include <FL/Fl_Menu_Bar.H> | |||
#include "Engine/Engine.H" | |||
#include "Project.H" | |||
#include <string.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 ); | |||
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 | |||
@@ -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(); | |||
}; | |||
@@ -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(); | |||
} | |||
@@ -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 "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 |
@@ -25,9 +25,33 @@ | |||
#include <stdio.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 ( ) | |||
{ | |||
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() ) | |||
@@ -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 ); | |||
}; |
@@ -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 ); | |||
@@ -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 <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 *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 | |||
@@ -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 ); | |||
}; |
@@ -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 "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 <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 | |||
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 | |||
{ | |||
@@ -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; | |||
@@ -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 ); | |||