Mixer: Changes to support project saving/loading.

This commit is contained in:
Jonathan Moore Liles 2009-12-27 23:25:28 -06:00
parent b7079c6147
commit d7f74e8e15
28 changed files with 1176 additions and 299 deletions

View File

@ -64,6 +64,9 @@ Fl_Scalepack::draw ( void )
if ( child( i )->visible() )
++v;
if ( 0 == v )
return;
int sz, pos;
if ( type() == HORIZONTAL )

View File

@ -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
{
_outs = 1;
_ins = 1;
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, "")
{
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 );
jm->initialize();
jm->color( FL_BLACK );
insert( NULL, jm );
{ JACK_Module *m = new JACK_Module();
m->is_default( true );
m->chain( this );
m->configure_outputs( 1 );
m->initialize();
add( m );
}
{
JACK_Module *m = new JACK_Module( 50, 50, "JACK" );
{ Module *m = new Gain_Module();
m->is_default( true );
m->initialize();
add( m );
}
{ Module *m = new Meter_Module();
m->is_default( true );
add( m );
}
{ 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,7 +272,7 @@ Chain::remove ( Module *m )
void
Chain::configure_ports ( void )
{
int old_outs = outs();
/* 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 )

View File

@ -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 );
};

View File

@ -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();
}

View File

@ -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 );

View File

@ -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();
}

View File

@ -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 );

View File

@ -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() );
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() );
}
}

View File

@ -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 );

View File

@ -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();
}

View File

@ -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 );

View File

@ -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;
}

View File

@ -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 );

View File

@ -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

View File

@ -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();
};

View File

@ -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();
}
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();
}

View File

@ -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

View File

@ -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 )
@ -45,14 +69,97 @@ Module::~Module ( )
control_output.clear();
}
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;
@ -69,6 +176,44 @@ Module::describe_inputs ( void ) const
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() )

View File

@ -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 );
};

View File

@ -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 );

View File

@ -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 );
Plugin_Module *m = new Plugin_Module();
m->load( pi );
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

View File

@ -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 );
};

324
Mixer/Project.C Normal file
View File

@ -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();
}

62
Mixer/Project.H Normal file
View File

@ -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; }
};

22
Mixer/const.h Normal file
View File

@ -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"

View File

@ -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
{

View File

@ -163,11 +163,16 @@ Loggable::load_unjournaled_state ( void )
bool
Loggable::replay ( const char *file )
{
FILE *fp = fopen( file, "r" );
replay( fp );
if ( FILE *fp = fopen( file, "r" ) )
{
bool r = replay( 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;

View File

@ -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 );