diff --git a/Timeline/Audio_Sequence.H b/Timeline/Audio_Sequence.H index a667e6e..9566cf8 100644 --- a/Timeline/Audio_Sequence.H +++ b/Timeline/Audio_Sequence.H @@ -21,7 +21,7 @@ #include "Sequence.H" #include "Region.H" - +#include "Track.H" #include @@ -30,15 +30,49 @@ class Audio_Sequence : public Sequence protected: + void + get ( Log_Entry &e ) + { + Sequence::get( e ); + + e.add( ":t", _track ); + } + + void + set ( Log_Entry &e ) + { + Sequence::set( e ); + + for ( int i = 0; i < e.size(); ++i ) + { + const char *s, *v; + + e.get( i, &s, &v ); + + if ( ! strcmp( ":t", s ) ) + { + int i; + sscanf( v, "%X", &i ); + Track *t = (Track*)Loggable::find( i ); + + assert( t ); + + t->track( this ); + } + } + } + Audio_Sequence ( ) : Sequence( 0, 0, 0, 0 ) { } + + public: LOG_CREATE_FUNC( Audio_Sequence ); - Audio_Sequence ( int X, int Y, int W, int H ) : Sequence( X, Y, W, H ) + Audio_Sequence ( Track *track ) : Sequence( 0, 0, 0, 0, track ) { log_create(); } @@ -51,7 +85,7 @@ public: Sequence * clone_empty ( void ) { - Audio_Sequence *t = new Audio_Sequence( x(), y(), w(), h() ); + Audio_Sequence *t = new Audio_Sequence( track() ); return t; } diff --git a/Timeline/Control_Sequence.C b/Timeline/Control_Sequence.C new file mode 100644 index 0000000..9e72878 --- /dev/null +++ b/Timeline/Control_Sequence.C @@ -0,0 +1,135 @@ + +/*******************************************************************************/ +/* 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. */ +/*******************************************************************************/ + +#include "Control_Sequence.H" +#include "Track.H" + +void +Control_Sequence::get ( Log_Entry &e ) +{ + Sequence::get( e ); + + e.add( ":t", _track ); +} + +void +Control_Sequence::set ( Log_Entry &e ) +{ + Sequence::set( e ); + + for ( int i = 0; i < e.size(); ++i ) + { + const char *s, *v; + + e.get( i, &s, &v ); + + if ( ! strcmp( ":t", s ) ) + { + int i; + sscanf( v, "%X", &i ); + Track *t = (Track*)Loggable::find( i ); + + assert( t ); + + t->add( this ); + } + } +} + +void +Control_Sequence::draw ( void ) +{ + + if ( ! fl_not_clipped( x(), y(), w(), h() ) ) + return; + + fl_push_clip( x(), y(), w(), h() ); + + draw_box(); + + int X, Y, W, H; + + fl_clip_box( x(), y(), w(), h(), X, Y, W, H ); + + fl_line_style( FL_SOLID, 4 ); + + fl_color( fl_color_average( selection_color(), color(), 0.90f ) ); + + fl_begin_complex_polygon(); + + list ::const_iterator e = _widgets.end(); + e--; + + if ( _widgets.size() ) + for ( list ::const_iterator r = _widgets.begin(); ; r++ ) + { + if ( r == _widgets.begin() ) + { + fl_vertex( x(), y() + h() ); + fl_vertex( x(), (*r)->y() ); + } + + fl_vertex( (*r)->x(), (*r)->y() ); + + if ( r == e ) + { + fl_vertex( x() + w(), (*r)->y() ); + fl_vertex( x() + w(), y() + h() ); + break; + } + + } + + fl_end_complex_polygon(); + + fl_line_style( FL_SOLID, 0 ); + + timeline->draw_measure_lines( x(), y(), w(), h(), color() ); + + for ( list ::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) + (*r)->draw_box(); + + fl_pop_clip(); +} + +int +Control_Sequence::handle ( int m ) +{ + int r = Sequence::handle( m ); + + if ( r ) + return r; + + switch ( m ) + { + case FL_PUSH: + { + if ( Fl::event_button1() ) + { + Control_Point *r = new Control_Point( this, timeline->xoffset + timeline->x_to_ts( Fl::event_x() - x() ), (float)(Fl::event_y() - y()) / h() ); + + add( r ); + } + + return 1; + } + default: + return 0; + } +} diff --git a/Timeline/Control_Sequence.H b/Timeline/Control_Sequence.H index b35273c..c2296bc 100644 --- a/Timeline/Control_Sequence.H +++ b/Timeline/Control_Sequence.H @@ -25,6 +25,12 @@ class Control_Sequence : public Sequence { +protected: + + + void get ( Log_Entry &e ); + void set ( Log_Entry &e ); + Control_Sequence ( ) : Sequence( 0, 0, 1, 1 ) { @@ -34,7 +40,7 @@ public: LOG_CREATE_FUNC( Control_Sequence ); - Control_Sequence ( int X, int Y, int W, int H ) : Sequence( X, Y, W, H ) + Control_Sequence ( Track *track ) : Sequence( 0, 0, 0, 0, track ) { color( fl_darker( FL_GREEN ) ); @@ -48,85 +54,7 @@ public: const char *class_name ( void ) { return "Control_Sequence"; } - void - draw ( void ) - { + void draw ( void ); + int handle ( int m ); - if ( ! fl_not_clipped( x(), y(), w(), h() ) ) - return; - - fl_push_clip( x(), y(), w(), h() ); - - draw_box(); - - int X, Y, W, H; - - fl_clip_box( x(), y(), w(), h(), X, Y, W, H ); - - fl_line_style( FL_SOLID, 4 ); - - fl_color( fl_color_average( selection_color(), color(), 0.90f ) ); - - fl_begin_complex_polygon(); - - list ::const_iterator e = _widgets.end(); - e--; - - if ( _widgets.size() ) - for ( list ::const_iterator r = _widgets.begin(); ; r++ ) - { - if ( r == _widgets.begin() ) - { - fl_vertex( x(), y() + h() ); - fl_vertex( x(), (*r)->y() ); - } - - fl_vertex( (*r)->x(), (*r)->y() ); - - if ( r == e ) - { - fl_vertex( x() + w(), (*r)->y() ); - fl_vertex( x() + w(), y() + h() ); - break; - } - - } - - fl_end_complex_polygon(); - - fl_line_style( FL_SOLID, 0 ); - - timeline->draw_measure_lines( x(), y(), w(), h(), color() ); - - for ( list ::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) - (*r)->draw_box(); - - fl_pop_clip(); - } - - int - handle ( int m ) - { - int r = Sequence::handle( m ); - - if ( r ) - return r; - - switch ( m ) - { - case FL_PUSH: - { - if ( Fl::event_button1() ) - { - Control_Point *r = new Control_Point( this, timeline->xoffset + timeline->x_to_ts( Fl::event_x() - x() ), (float)(Fl::event_y() - y()) / h() ); - - add( r ); - } - - return 1; - } - default: - return 0; - } - } }; diff --git a/Timeline/Loggable.C b/Timeline/Loggable.C index 7c0cb26..5fe712e 100644 --- a/Timeline/Loggable.C +++ b/Timeline/Loggable.C @@ -46,15 +46,20 @@ Loggable::open ( const char *filename ) return false; } - /* TODO: replay log here */ - /* FIXME: handle transactions!!! */ + /* replay log */ { char buf[BUFSIZ]; while ( fscanf( fp, "%[^\n]\n", buf ) == 1 ) { - do_this( buf, false ); + if ( ! ( ! strcmp( buf, "{" ) || ! strcmp( buf, "}" ) ) ) + { + if ( *buf == '\t' ) + do_this( buf + 1, false ); + else + do_this( buf, false ); + } } } @@ -113,8 +118,10 @@ parse_alist( const char *s ) if ( *v == '"' ) { - v++; +// v++; v[ strlen( v ) - 2 ] = '\0'; + memmove( v, v + 1, strlen( v ) + 1 ); + } } @@ -191,13 +198,19 @@ Loggable::do_this ( const char *s, bool reverse ) } else if ( ! strcmp( command, create ) ) { - char **sa = parse_alist( arguments ); + char **sa = NULL; + + if ( arguments ) + sa = parse_alist( arguments ); Log_Entry e( sa ); - if ( ! _class_map[ string( classname ) ] ) - printf( "error class %s is unregistered!\n", classname ); - else + assert( _class_map[ string( classname ) ] ); + +/* if ( ! _class_map[ string( classname ) ] ) */ +/* printf( "error class %s is unregistered!\n", classname ); */ +/* else */ + { /* create */ Loggable *l = _class_map[ string( classname ) ]( e ); diff --git a/Timeline/Loggable.H b/Timeline/Loggable.H index 8b4e4a7..2fc74cd 100644 --- a/Timeline/Loggable.H +++ b/Timeline/Loggable.H @@ -136,9 +136,11 @@ public: { assert( _id == _log_id ); + assert( _loggables[ _id - 1 ] == this ); + _loggables[ _id - 1 ] = NULL; - --_log_id; +// --_log_id; _id = id; @@ -250,6 +252,7 @@ public: if ( _sa ) while ( _sa[ _i ] ) ++_i; + } ~Log_Entry ( ) diff --git a/Timeline/Makefile b/Timeline/Makefile index 8c1238e..180f006 100644 --- a/Timeline/Makefile +++ b/Timeline/Makefile @@ -5,6 +5,7 @@ SRCS= \ main.C \ Sequence.C \ Audio_Sequence.C \ + Control_Sequence.C \ Timeline.C \ Track.C \ Sequence_Widget.C \ diff --git a/Timeline/Sequence.C b/Timeline/Sequence.C index 54530b4..d384ada 100644 --- a/Timeline/Sequence.C +++ b/Timeline/Sequence.C @@ -24,6 +24,7 @@ #include +#include "Track.H" queue Sequence::_delete_queue; @@ -32,6 +33,9 @@ Sequence::Sequence ( int X, int Y, int W, int H, Track *track ) : Fl_Widget( X, _name = NULL; _track = track; + if ( track ) + track->add( this ); + box( FL_DOWN_BOX ); color( fl_darker( FL_GRAY ) ); align( FL_ALIGN_LEFT ); diff --git a/Timeline/Sequence.H b/Timeline/Sequence.H index fe59fc4..16ebafd 100644 --- a/Timeline/Sequence.H +++ b/Timeline/Sequence.H @@ -43,24 +43,40 @@ class Sequence_Widget; class Sequence : public Fl_Widget, public Loggable { - Track *_track; /* track this sequence belongs to */ - - char *_name; static queue _delete_queue; protected: + Track *_track; /* track this sequence belongs to */ + + char *_name; + std::list _widgets; Sequence_Widget *event_widget ( void ); virtual const char *class_name ( void ) { return "Sequence"; } - virtual void set ( Log_Entry &e ) { return; } + virtual void set ( Log_Entry &e ) + { + for ( int i = 0; i < e.size(); ++i ) + { + const char *s, *v; + + e.get( i, &s, &v ); + + if ( ! strcmp( ":n", s ) ) + { + name( strdup( v ) ); + } + } + } virtual void get ( Log_Entry &e ) { + e.add( ":n", name() ); +// e.add( ":t", _track ); /* s += sprintf( s, ":items " ); */ /* for ( list ::const_iterator i = _widgets.begin(); i != _widgets.end(); i++ ) */ @@ -81,10 +97,18 @@ public: virtual ~Sequence ( ); const char * name ( void ) const { return _name; } - void name ( char *s ) { if ( _name ) free( _name ); _name = s; label( _name ); } + void name ( const char *s ) + { + if ( _name ) free( _name ); + _name = strdup( s ); + label( _name ); + } void sort ( void ); + Track *track ( void ) const { return _track; } + void track ( Track *t ) { _track = t; } + void remove ( Sequence_Widget *r ); void add ( Sequence_Widget *r ); diff --git a/Timeline/Sequence_Widget.H b/Timeline/Sequence_Widget.H index 0cfa3bd..301287c 100644 --- a/Timeline/Sequence_Widget.H +++ b/Timeline/Sequence_Widget.H @@ -109,7 +109,7 @@ protected: else deselect(); } - else if ( ! strcmp( s, ":track" ) ) + else if ( ! strcmp( s, ":t" ) ) { int i; sscanf( v, "%X", &i ); diff --git a/Timeline/Timeline.C b/Timeline/Timeline.C index a7ee9d8..788c38e 100644 --- a/Timeline/Timeline.C +++ b/Timeline/Timeline.C @@ -115,8 +115,8 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : Fl_Overlay_Wi o->color( FL_RED ); - o->add( new Tempo_Point( 0, 120 ) ); - o->add( new Tempo_Point( 56000, 250 ) ); +/* o->add( new Tempo_Point( 0, 120 ) ); */ +/* o->add( new Tempo_Point( 56000, 250 ) ); */ o->label( "Tempo" ); o->align( FL_ALIGN_LEFT ); @@ -131,8 +131,8 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : Fl_Overlay_Wi o->color( fl_color_average( FL_RED, FL_WHITE, 0.50f ) ); - o->add( new Time_Point( 0, 4, 4 ) ); - o->add( new Time_Point( 345344, 6, 8 ) ); +/* o->add( new Time_Point( 0, 4, 4 ) ); */ +/* o->add( new Time_Point( 345344, 6, 8 ) ); */ o->label( "Time" ); o->align( FL_ALIGN_LEFT ); @@ -748,21 +748,25 @@ Timeline::handle ( int m ) { /* FIXME: prompt for I/O config? */ + Loggable::block_start(); + /* add audio track */ char *name = get_unique_track_name( "Audio" ); - Track *t = new Track( 0, 0, tracks->w(), 30, name ); + Track *t = new Track( name ); add_track( t ); - Sequence *o = new Audio_Sequence( 0, 0, 1, 100 ); + Sequence *o = new Audio_Sequence( t ); + new Control_Sequence( t ); t->track( o ); -// t->add( new Audio_Sequence( 0, 0, 1, 100 ) ); -// t->add( new Audio_Sequence( 0, 0, 1, 100 ) ); - t->add_control( new Control_Sequence( 0, 0, 1, 100 ) ); + +/* t->add( new Control_Sequence( t ); */ + t->color( (Fl_Color)rand() ); + Loggable::block_end(); } } @@ -809,18 +813,18 @@ Timeline::handle ( int m ) -bool -Timeline::track_name_exists ( const char *name ) +Track * +Timeline::track_by_name ( const char *name ) { for ( int i = tracks->children(); i-- ; ) { Track *t = (Track*)tracks->child( i ); if ( ! strcmp( name, t->name() ) ) - return true; + return t; } - return false; + return NULL; } char * @@ -830,7 +834,7 @@ Timeline::get_unique_track_name ( const char *name ) strcpy( pat, name ); - for ( int i = 1; track_name_exists( pat ); ++i ) + for ( int i = 1; track_by_name( pat ); ++i ) snprintf( pat, sizeof( pat ), "%s.%d", name, i ); return strdup( pat ); diff --git a/Timeline/Timeline.H b/Timeline/Timeline.H index 887c1b0..f65ecfc 100644 --- a/Timeline/Timeline.H +++ b/Timeline/Timeline.H @@ -157,7 +157,7 @@ private: friend class Engine; // FIXME: only Engine::process() needs to be friended.x - bool track_name_exists ( const char *name ); + Track * track_by_name ( const char *name ); char * get_unique_track_name ( const char *name ); /* Engine */ diff --git a/Timeline/Track.C b/Timeline/Track.C index cfb4292..0c825f9 100644 --- a/Timeline/Track.C +++ b/Timeline/Track.C @@ -96,8 +96,8 @@ Track::cb_button ( Fl_Widget *w ) } } -Track::Track ( int X, int Y, int W, int H, const char *L ) : - Fl_Group ( X, Y, W, H, L ) +void +Track::init ( void ) { _capture = NULL; _track = NULL; @@ -108,8 +108,7 @@ Track::Track ( int X, int Y, int W, int H, const char *L ) : labeltype( FL_NO_LABEL ); - - Fl_Group::size( w(), height() ); + Fl_Group::size( timeline->w(), height() ); Track *o = this; o->box( FL_THIN_UP_BOX ); @@ -204,15 +203,23 @@ Track::Track ( int X, int Y, int W, int H, const char *L ) : } end(); - if ( L ) - name( L ); - /* FIXME: should be configurable, but where? */ create_outputs( 2 ); create_inputs( 2 ); playback_ds = new Playback_DS( this, engine->frame_rate(), engine->nframes(), output.size() ); record_ds = new Record_DS( this, engine->frame_rate(), engine->nframes(), input.size() ); +} + + +Track::Track ( const char *L ) : + Fl_Group ( 0, 0, 0, 0, L ) +{ + + init(); + + if ( L ) + name( L ); log_create(); } @@ -278,14 +285,13 @@ Track::size ( int v ) } void -Track::track( Sequence * t ) +Track::track ( Sequence * t ) { -// t->size( 1, h() ); + t->track( this ); + if ( track() ) add( track() ); -// takes->insert( *track(), 0 ); - _track = t; pack->insert( *t, 0 ); @@ -293,14 +299,71 @@ Track::track( Sequence * t ) } void -Track::add_control( Sequence *t ) +Track::add ( Control_Sequence *t ) { + t->track( this ); + control->add( t ); resize(); } +void +Track::draw ( void ) +{ + if ( _selected ) + { + Fl_Color c = color(); + + color( FL_RED ); + + Fl_Group::draw(); + + color( c ); + } + else + Fl_Group::draw(); + + if ( ! name_field->visible() ) + { + fl_color( FL_WHITE ); + fl_font( FL_HELVETICA, 14 ); + fl_draw( name_field->value(), name_field->x(), name_field->y(), name_field->w(), name_field->h(), FL_ALIGN_CENTER ); + } +} + +int +Track::handle ( int m ) +{ + Logger log( this ); + + switch ( m ) + { + case FL_MOUSEWHEEL: + { + + if ( ! Fl::event_shift() ) + return 0; + + int d = Fl::event_dy(); + + printf( "%d\n", d ); + + if ( d < 0 ) + size( size() - 1 ); + else + size( size() + 1 ); + + return 1; + } + default: + return Fl_Group::handle( m ); + + } +} + + /**********/ /* Engine */ /**********/ diff --git a/Timeline/Track.H b/Timeline/Track.H index 9a71ae3..de01e2f 100644 --- a/Timeline/Track.H +++ b/Timeline/Track.H @@ -38,6 +38,9 @@ using std::vector; #include "Port.H" +#include "Timeline.H" +#include "Control_Sequence.H" + class Playback_DS; class Record_DS; class Port; @@ -48,7 +51,7 @@ class Track : public Fl_Group, public Loggable public: - Track ( int X, int Y, int W, int H, const char *L = 0 ); + Track ( const char *L ); ~Track ( ); private: @@ -75,34 +78,38 @@ private: Track ( ) : Fl_Group( 0, 0, 1, 1 ) { + init(); + timeline->add_track( this ); } + void init ( void ); + public: - Fl_Input * name_field; - Fl_Button *record_button; - Fl_Button *mute_button; - Fl_Button *solo_button; + Fl_Input *name_field; + Fl_Button *record_button; + Fl_Button *mute_button; + Fl_Button *solo_button; Fl_Menu_Button *take_menu; - Fl_Group *controls; + Fl_Group *controls; - Fl_Pack *pack; - Fl_Pack *control; - Fl_Pack *takes; + Fl_Pack *pack; + Fl_Pack *control; + Fl_Pack *takes; - vector input; - vector output; /* output ports... */ + vector input; /* input ports... */ + vector output; /* output ports... */ - Playback_DS *playback_ds; - Record_DS *record_ds; + Playback_DS *playback_ds; + Record_DS *record_ds; const char *class_name ( void ) { return "Track"; } void set ( Log_Entry &e ) { - for ( int i = 0; e.size(); ++i ) + for ( int i = 0; i < e.size(); ++i ) { const char *s, *v; @@ -120,7 +127,9 @@ public: else if ( ! strcmp( s, ":n" ) ) { _name = strdup( v ); - name_field->value( _name ); + /* FIXME: bogus */ + if ( name_field ) + name_field->value( _name ); } else if ( ! strcmp( s, ":t" ) ) { @@ -152,31 +161,7 @@ public: /* for loggable */ LOG_CREATE_FUNC( Track ); - void - draw ( void ) - { - if ( _selected ) - { - Fl_Color c = color(); - - color( FL_RED ); - - Fl_Group::draw(); - - color( c ); - } - else - Fl_Group::draw(); - - if ( ! name_field->visible() ) - { - fl_color( FL_WHITE ); - fl_font( FL_HELVETICA, 14 ); - fl_draw( name_field->value(), name_field->x(), name_field->y(), name_field->w(), name_field->h(), FL_ALIGN_CENTER ); - } - } - - void add_control( Sequence *t ); + void add ( Control_Sequence *t ); int size ( void ) const { return _size; } @@ -239,32 +224,9 @@ public: // take_menu->remove( t->name() ); } - int handle ( int m ) - { - switch ( m ) - { - case FL_MOUSEWHEEL: - { - if ( ! Fl::event_shift() ) - return 0; - - int d = Fl::event_dy(); - - printf( "%d\n", d ); - - if ( d < 0 ) - size( size() - 1 ); - else - size( size() + 1 ); - - return 1; - } - default: - return Fl_Group::handle( m ); - - } - } + void draw ( void ); + int handle ( int m ); /* Engine */ nframes_t process ( nframes_t nframes );