Browse Source

Mixer: Changes to support project saving/loading.

tags/non-daw-v1.1.0
Jonathan Moore Liles 15 years ago
parent
commit
d7f74e8e15
28 changed files with 1175 additions and 298 deletions
  1. +3
    -0
      FL/Fl_Scalepack.C
  2. +115
    -35
      Mixer/Chain.C
  3. +28
    -12
      Mixer/Chain.H
  4. +55
    -2
      Mixer/Controller_Module.C
  5. +7
    -1
      Mixer/Controller_Module.H
  6. +6
    -3
      Mixer/Gain_Module.C
  7. +3
    -0
      Mixer/Gain_Module.H
  8. +20
    -9
      Mixer/JACK_Module.C
  9. +3
    -5
      Mixer/JACK_Module.H
  10. +58
    -2
      Mixer/Meter_Indicator_Module.C
  11. +5
    -1
      Mixer/Meter_Indicator_Module.H
  12. +8
    -6
      Mixer/Meter_Module.C
  13. +3
    -1
      Mixer/Meter_Module.H
  14. +27
    -9
      Mixer/Mixer.C
  15. +2
    -0
      Mixer/Mixer.H
  16. +96
    -147
      Mixer/Mixer_Strip.C
  17. +36
    -5
      Mixer/Mixer_Strip.H
  18. +155
    -6
      Mixer/Module.C
  19. +44
    -24
      Mixer/Module.H
  20. +2
    -1
      Mixer/Module_Parameter_Editor.C
  21. +45
    -18
      Mixer/Plugin_Module.C
  22. +6
    -2
      Mixer/Plugin_Module.H
  23. +324
    -0
      Mixer/Project.C
  24. +62
    -0
      Mixer/Project.H
  25. +22
    -0
      Mixer/const.h
  26. +30
    -4
      Mixer/main.C
  27. +9
    -4
      nonlib/Loggable.C
  28. +1
    -1
      nonlib/Loggable.H

+ 3
- 0
FL/Fl_Scalepack.C 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 )


+ 115
- 35
Mixer/Chain.C 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
{
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 )


+ 28
- 12
Mixer/Chain.H 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 );
};

+ 55
- 2
Mixer/Controller_Module.C 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();
}



+ 7
- 1
Mixer/Controller_Module.H 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 );


+ 6
- 3
Mixer/Gain_Module.C 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();
}



+ 3
- 0
Mixer/Gain_Module.H 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 );


+ 20
- 9
Mixer/JACK_Module.C 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() );
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() );

}
}



+ 3
- 5
Mixer/JACK_Module.H 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 );


+ 58
- 2
Mixer/Meter_Indicator_Module.C 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();
}



+ 5
- 1
Mixer/Meter_Indicator_Module.H 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 );


+ 8
- 6
Mixer/Meter_Module.C 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;
}


+ 3
- 1
Mixer/Meter_Module.H 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 );


+ 27
- 9
Mixer/Mixer.C 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


+ 2
- 0
Mixer/Mixer.H 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();
};


+ 96
- 147
Mixer/Mixer_Strip.C 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();
}

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




+ 36
- 5
Mixer/Mixer_Strip.H 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

+ 155
- 6
Mixer/Module.C 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 )
@@ -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() )


+ 44
- 24
Mixer/Module.H 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 );

};

+ 2
- 1
Mixer/Module_Parameter_Editor.C 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 );


+ 45
- 18
Mixer/Plugin_Module.C 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 );

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


+ 6
- 2
Mixer/Plugin_Module.H 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
- 0
Mixer/Project.C 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
- 0
Mixer/Project.H 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
- 0
Mixer/const.h 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"

+ 30
- 4
Mixer/main.C 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
{


+ 9
- 4
nonlib/Loggable.C View File

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


+ 1
- 1
nonlib/Loggable.H 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 );


Loading…
Cancel
Save