Browse Source

Implement storage and loading of unjournaled state for Loggable objects.

tags/non-daw-v1.1.0
Jonathan Moore Liles 16 years ago
parent
commit
15a579774c
7 changed files with 179 additions and 40 deletions
  1. +29
    -0
      Timeline/Log_Entry.C
  2. +2
    -0
      Timeline/Log_Entry.H
  3. +105
    -24
      Timeline/Loggable.C
  4. +12
    -8
      Timeline/Loggable.H
  5. +0
    -1
      Timeline/Project.C
  6. +25
    -6
      Timeline/Track.C
  7. +6
    -1
      Timeline/Track.H

+ 29
- 0
Timeline/Log_Entry.C View File

@@ -90,6 +90,35 @@ unescape ( char *s )
*r = '\0'; *r = '\0';
} }


/** return a dynamically allocated string representing this log entry */
char *
Log_Entry::print ( void ) const
{
/* FIXME: gross over-allocation */
char *r = (char*)malloc( 1024 );

r[0] = 0;

for ( int i = 0; i < size(); ++i )
{
const char *s, *v;

get( i, &s, &v );

/* FIXME: arbitrary limit */
char t[1024];
snprintf( t, sizeof( t ), "%s %s%s", s, v, size() == i + 1 ? "" : " " );

strcat( r, t );
}

char *r2 = (char*)malloc( strlen( r ) + 1 );

strcpy( r2, r );

return r2;
}

/** sigh. parse a string of ":name value :name value" pairs into an /** sigh. parse a string of ":name value :name value" pairs into an
* array of strings, one per pair */ * array of strings, one per pair */
// FIXME: doesn't handle the case of :name ":foo bar", nested quotes // FIXME: doesn't handle the case of :name ":foo bar", nested quotes


+ 2
- 0
Timeline/Log_Entry.H View File

@@ -67,6 +67,8 @@ public:
void get ( int n, const char **name, const char **value ) const; void get ( int n, const char **name, const char **value ) const;
char **sa ( void ); char **sa ( void );


char *print ( void ) const;

/* #define ADD ( type, format, exp ) \ */ /* #define ADD ( type, format, exp ) \ */
/* void add ( const char *name, type v ) \ */ /* void add ( const char *name, type v ) \ */
/* { \ */ /* { \ */


+ 105
- 24
Timeline/Loggable.C View File

@@ -50,6 +50,8 @@ off_t Loggable::_undo_offset = 0;


size_t Loggable::_loggables_size = 0; size_t Loggable::_loggables_size = 0;
Loggable ** Loggable::_loggables; Loggable ** Loggable::_loggables;
std::map <unsigned int, Log_Entry *> Loggable::_loggables_unjournaled;

std::map <std::string, create_func*> Loggable::_class_map; std::map <std::string, create_func*> Loggable::_class_map;
std::queue <char *> Loggable::_transaction; std::queue <char *> Loggable::_transaction;


@@ -61,6 +63,14 @@ void *Loggable::_snapshot_callback_arg = NULL;




Loggable::~Loggable ( )
{
_loggables[ _id - 1 ] = NULL;
}



/** ensure that _loggables array is big enough for /n/ elements */ /** ensure that _loggables array is big enough for /n/ elements */
void void
Loggable::ensure_size ( size_t n ) Loggable::ensure_size ( size_t n )
@@ -121,6 +131,8 @@ Loggable::open ( const char *filename )
return false; return false;
} }


load_unjournaled_state();

if ( newer( "snapshot", filename ) ) if ( newer( "snapshot", filename ) )
{ {
MESSAGE( "Loading snapshot" ); MESSAGE( "Loading snapshot" );
@@ -146,6 +158,33 @@ Loggable::open ( const char *filename )
return true; return true;
} }


bool
Loggable::load_unjournaled_state ( void )
{
FILE *fp;

fp = fopen( "unjournaled", "r" );

if ( ! fp )
return false;

unsigned int id;
char buf[BUFSIZ];

while ( fscanf( fp, "%X set %[^\n]\n", &id, buf ) == 2 )
{
Log_Entry *e = new Log_Entry( buf );

_loggables_unjournaled[ id - 1 ] = e;

Loggable *l = Loggable::find( id );
}

fclose( fp );

return true;
}

#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>


@@ -214,11 +253,45 @@ Loggable::close ( void )
} }
} }


save_unjournaled_state();

_log_id = 0; _log_id = 0;


return true; return true;
} }



/** save out unjournaled state for all loggables */
bool
Loggable::save_unjournaled_state ( void )
{

/* FIXME: check for errors */
FILE *fp = fopen( "unjournaled", "w" );

/* write out the unjournaled state of all currently active
* loggables */
for ( int i = 0; i < _log_id - 1; ++i )
{
Log_Entry *e = _loggables_unjournaled[ i ];

if ( e )
{
char *s = e->print();

fprintf( fp, "0x%X set %s\n", i + 1, s );

free( s );
}
}

/* write out the remembered state of inactive loggables. */

fclose( fp );

return true;
}

/** must be called after construction in create() methods */ /** must be called after construction in create() methods */
void void
Loggable::update_id ( unsigned int id ) Loggable::update_id ( unsigned int id )
@@ -338,6 +411,12 @@ Loggable::do_this ( const char *s, bool reverse )
/* create */ /* create */
Loggable *l = _class_map[ std::string( classname ) ]( e, id ); Loggable *l = _class_map[ std::string( classname ) ]( e, id );
l->log_create(); l->log_create();

/* we're now creating a loggable. Apply any unjournaled
* state it may have had in the past under this log ID */

if ( _loggables_unjournaled[ id - 1 ] )
l->set( *_loggables_unjournaled[ id - 1 ] );
} }


} }
@@ -391,29 +470,6 @@ Loggable::undo ( void )
_undo_offset = uo; _undo_offset = uo;
} }


/** Make all loggable ids consecutive. This invalidates any existing
* journal or snapshot, so you *must* write out a new one after
* performing this operation*/
void
Loggable::compact_ids ( void )
{
unsigned int id = 0;
for ( unsigned int i = 0; i < _log_id; ++i )
if ( _loggables[ i ] )
{
++id;

if ( _loggables[ id - 1 ] )
continue;

_loggables[ id - 1 ] = _loggables[ i ];
_loggables[ i ] = NULL;
_loggables[ id - 1 ]->_id = id;
}

_log_id = id;
}

/** write a snapshot of the current state of all loggable objects to /** write a snapshot of the current state of all loggable objects to
* file handle /fp/ */ * file handle /fp/ */
bool bool
@@ -468,7 +524,6 @@ Loggable::compact ( void )
fseek( _fp, 0, SEEK_SET ); fseek( _fp, 0, SEEK_SET );
ftruncate( fileno( _fp ), 0 ); ftruncate( fileno( _fp ), 0 );


compact_ids();
if ( ! snapshot( _fp ) ) if ( ! snapshot( _fp ) )
FATAL( "Could not write snapshot!" ); FATAL( "Could not write snapshot!" );


@@ -654,11 +709,37 @@ Loggable::log_create ( void ) const
Loggable::flush(); Loggable::flush();
} }


/** record this loggable's unjournaled state in memory */
void
Loggable::record_unjournaled ( void ) const
{
Log_Entry *e = new Log_Entry();

get_unjournaled( *e );

Log_Entry **le = &_loggables_unjournaled[ _id - 1 ];

if ( *le )
delete *le;

if ( e->size() )
{
*le = e;
DMESSAGE( "logging %s", (*le)->print() );
}
else
/* don't waste space on loggables with no unjournaled properties */
*le = NULL;
}

/** Log object destruction. *Must* be called at the beginning of the /** Log object destruction. *Must* be called at the beginning of the
* destructors of leaf classes */ * destructors of leaf classes */
void void
Loggable::log_destroy ( void ) const Loggable::log_destroy ( void ) const
{ {
/* the unjournaled state may have changed: make a note of it. */
record_unjournaled();

if ( ! _fp ) if ( ! _fp )
/* tearing down... don't bother */ /* tearing down... don't bother */
return; return;


+ 12
- 8
Timeline/Loggable.H View File

@@ -73,6 +73,7 @@ class Loggable


static size_t _loggables_size; static size_t _loggables_size;
static Loggable ** _loggables; static Loggable ** _loggables;
static std::map <unsigned int, Log_Entry *> _loggables_unjournaled;


static std::map <std::string, create_func*> _class_map; static std::map <std::string, create_func*> _class_map;


@@ -94,13 +95,14 @@ private:


static void ensure_size ( size_t n ); static void ensure_size ( size_t n );


void log_print( const Log_Entry *o, const Log_Entry *n ) const;
void log_print ( const Log_Entry *o, const Log_Entry *n ) const;
static void log ( const char *fmt, ... ); static void log ( const char *fmt, ... );


static void flush ( void ); static void flush ( void );


static bool snapshot( FILE * fp );
static bool snapshot( const char *name );
static bool snapshot ( FILE * fp );
static bool snapshot ( const char *name );
static bool save_unjournaled_state ( void );
static bool replay ( FILE *fp ); static bool replay ( FILE *fp );


void init ( bool loggable=true ) void init ( bool loggable=true )
@@ -125,7 +127,8 @@ private:
/* not implemented */ /* not implemented */
const Loggable & operator= ( const Loggable &rhs ); const Loggable & operator= ( const Loggable &rhs );


static void compact_ids ( void );
void record_unjournaled ( void ) const;
static bool load_unjournaled_state ( void );


public: public:


@@ -153,10 +156,7 @@ public:


void update_id ( unsigned int id ); void update_id ( unsigned int id );


virtual ~Loggable ( )
{
_loggables[ _id - 1 ] = NULL;
}
virtual ~Loggable ( );


static static
void void
@@ -167,6 +167,10 @@ public:


/* log messages for journal */ /* log messages for journal */
virtual void get ( Log_Entry &e ) const = 0; virtual void get ( Log_Entry &e ) const = 0;
virtual void get_unjournaled ( Log_Entry & ) const
{
/* implementation optional */
}
virtual void set ( Log_Entry &e ) = 0; virtual void set ( Log_Entry &e ) = 0;


virtual const char *class_name ( void ) const = 0; virtual const char *class_name ( void ) const = 0;


+ 0
- 1
Timeline/Project.C View File

@@ -176,7 +176,6 @@ Project::close ( void )
tle->save_timeline_settings(); tle->save_timeline_settings();


Loggable::close(); Loggable::close();

// write_info(); // write_info();


_is_open = false; _is_open = false;


+ 25
- 6
Timeline/Track.C View File

@@ -73,21 +73,25 @@ Track::Track ( ) : Fl_Group( 0, 0, 1, 1 )
timeline->add_track( this ); timeline->add_track( this );
} }



Track::~Track ( ) Track::~Track ( )
{ {
Loggable::block_start(); Loggable::block_start();


/* must destroy sequences first to preserve proper log order */
takes->clear();
control->clear();
annotation->clear();
delete sequence();

takes = NULL; takes = NULL;
control = NULL; control = NULL;
annotation = NULL; annotation = NULL;


solo( false );

Fl_Group::clear();

log_destroy(); log_destroy();


/* ensure that soloing accounting is performed */
solo( false );

timeline->remove_track( this ); timeline->remove_track( this );


/* give up our ports */ /* give up our ports */
@@ -101,6 +105,7 @@ Track::~Track ( )


Loggable::block_end(); Loggable::block_end();
} }

#include "FL/Boxtypes.H" #include "FL/Boxtypes.H"


void void
@@ -258,6 +263,12 @@ Track::set ( Log_Entry &e )
} }
else if ( ! strcmp( s, ":show-all-takes" ) ) else if ( ! strcmp( s, ":show-all-takes" ) )
show_all_takes( atoi( v ) ); show_all_takes( atoi( v ) );
else if ( ! strcmp( s, ":solo" ) )
solo( atoi( v ) );
else if ( ! strcmp( s, ":mute" ) )
mute( atoi( v ) );
else if ( ! strcmp( s, ":arm" ) )
armed( atoi( v ) );
else if ( ! strcmp( s, ":sequence" ) ) else if ( ! strcmp( s, ":sequence" ) )
{ {
int i; int i;
@@ -290,11 +301,19 @@ Track::get ( Log_Entry &e ) const
e.add( ":name", _name ); e.add( ":name", _name );
e.add( ":sequence", sequence() ); e.add( ":sequence", sequence() );
e.add( ":selected", _selected ); e.add( ":selected", _selected );
e.add( ":color", (unsigned long)color());
}

void
Track::get_unjournaled ( Log_Entry &e ) const
{
e.add( ":height", size() ); e.add( ":height", size() );
e.add( ":inputs", input.size() ); e.add( ":inputs", input.size() );
e.add( ":outputs", output.size() ); e.add( ":outputs", output.size() );
e.add( ":color", (unsigned long)color());
e.add( ":show-all-takes", _show_all_takes ); e.add( ":show-all-takes", _show_all_takes );
e.add( ":armed", armed() );
e.add( ":mute", mute() );
e.add( ":solo", solo() );
} }


void void


+ 6
- 1
Timeline/Track.H View File

@@ -104,6 +104,7 @@ private:
protected: protected:


void get ( Log_Entry &e ) const; void get ( Log_Entry &e ) const;
void get_unjournaled ( Log_Entry &e ) const;
void set ( Log_Entry &e ); void set ( Log_Entry &e );


public: public:
@@ -177,11 +178,15 @@ public:


const char * name ( void ) const { return _name; } const char * name ( void ) const { return _name; }
bool mute ( void ) const { return mute_button->value(); } bool mute ( void ) const { return mute_button->value(); }
void mute ( bool b ) { mute_button->value( b ); }
bool solo ( void ) const { return solo_button->value(); } bool solo ( void ) const { return solo_button->value(); }
void solo ( bool b );

bool armed ( void ) const { return record_button->value(); } bool armed ( void ) const { return record_button->value(); }
void armed ( bool b ) { record_button->value( b ); }

bool selected ( void ) const { return _selected; } bool selected ( void ) const { return _selected; }


void solo ( bool b );


static void cb_input_field ( Fl_Widget *w, void *v ); static void cb_input_field ( Fl_Widget *w, void *v );
void cb_input_field ( void ); void cb_input_field ( void );


Loading…
Cancel
Save