diff --git a/timeline/src/Annotation_Sequence.H b/timeline/src/Annotation_Sequence.H index ae3fed6..d2d925c 100644 --- a/timeline/src/Annotation_Sequence.H +++ b/timeline/src/Annotation_Sequence.H @@ -60,7 +60,7 @@ protected: Annotation_Sequence ( ) : Sequence ( 0 ) { - color( fl_darker( FL_GREEN ) ); + color( FL_DARK1 ); } public: @@ -72,16 +72,12 @@ public: Annotation_Sequence ( Track *track ) : Sequence( track ) { - color( fl_darker( FL_GREEN ) ); + color( FL_DARK1 ); log_create(); } -/* Annotation_Sequence ( int X, int Y, int W, int H ) : Sequence ( 0 ) */ -/* { */ -/* } */ - - ~Annotation_Sequence ( ) + virtual ~Annotation_Sequence ( ) { Loggable::block_start(); @@ -108,12 +104,12 @@ public: if ( Fl::event_button1() ) { - add( new Annotation_Point( this, x_to_offset( Fl::event_x() ), "mark" ) ); + add( new Annotation_Point( this, x_to_offset( Fl::event_x() - drawable_x() ), "mark" ) ); redraw(); } if ( Fl::event_button3() && Fl::event_shift() ) { - Annotation_Region *r = new Annotation_Region( this, x_to_offset( Fl::event_x() ), "mark" ); + Annotation_Region *r = new Annotation_Region( this, x_to_offset( Fl::event_x() - drawable_x() ), "mark" ); add( r ); diff --git a/timeline/src/Audio_Sequence.C b/timeline/src/Audio_Sequence.C index 15316f2..64ec3e3 100644 --- a/timeline/src/Audio_Sequence.C +++ b/timeline/src/Audio_Sequence.C @@ -35,7 +35,7 @@ using namespace std; #include "Engine/Audio_File.H" // for ::from_file() #include "Transport.H" // for locate() - +#include "Track_Header.H" #include #include // for symlink() @@ -44,10 +44,67 @@ using namespace std; +const char * +Audio_Sequence::name ( void ) const +{ + return Sequence::name(); +} + +void +Audio_Sequence::name ( const char *s ) +{ + Sequence::name( s ); + header()->name_input->value( s ); +} + +void +Audio_Sequence::cb_button ( Fl_Widget *w, void *v ) +{ + ((Audio_Sequence*)v)->cb_button( w ); +} + +void +Audio_Sequence::cb_button ( Fl_Widget *w ) +{ + Logger log(this); + + if ( w == header()->name_input ) + { + Sequence::name( header()->name_input->value() ); + } + else if ( w == header()->delete_button ) + { + track()->remove( this ); + } + else if ( w == header()->promote_button ) + { + track()->sequence( this ); + } +} + +void +Audio_Sequence::init ( void ) +{ + labeltype( FL_NO_LABEL ); + { + Audio_Sequence_Header *o = new Audio_Sequence_Header( x(), y(), Track::width(), 52 ); + + o->name_input->callback( cb_button, this ); + o->delete_button->callback( cb_button, this ); + o->promote_button->callback( cb_button, this ); + + Fl_Group::add( o ); + } + + resizable(0); +} + Audio_Sequence::Audio_Sequence ( Track *track, const char *name ) : Sequence( track ) { _track = track; + init(); + if ( name ) Audio_Sequence::name( name ); else @@ -71,10 +128,6 @@ Audio_Sequence::Audio_Sequence ( Track *track, const char *name ) : Sequence( tr track->add( this ); log_create(); - - /* FIXME: temporary */ - labeltype( FL_NO_LABEL ); - } @@ -155,7 +208,7 @@ Audio_Sequence::draw ( void ) int xfades = 0; - fl_push_clip( x(), y(), w(), h() ); + fl_push_clip( drawable_x(), y(), drawable_w(), h() ); /* draw crossfades */ for ( list ::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) diff --git a/timeline/src/Audio_Sequence.H b/timeline/src/Audio_Sequence.H index f7beea6..b2fe976 100644 --- a/timeline/src/Audio_Sequence.H +++ b/timeline/src/Audio_Sequence.H @@ -24,6 +24,7 @@ #include "Audio_Region.H" #include +class Audio_Sequence_Header; class Audio_Sequence : public Sequence { @@ -36,18 +37,25 @@ protected: Audio_Sequence ( ) : Sequence( 0 ) { + init(); } - void handle_widget_change ( nframes_t start, nframes_t length ); void draw ( void ); int handle ( int m ); + static void cb_button ( Fl_Widget *w, void *v ); + void cb_button ( Fl_Widget *w ); + + void init ( void ); + public: LOG_CREATE_FUNC( Audio_Sequence ); + Audio_Sequence_Header * header ( void ) { return (Audio_Sequence_Header*)child(0); } + Audio_Sequence ( Track *track, const char *name = 0 ); ~Audio_Sequence ( ); @@ -67,6 +75,9 @@ public: return t; } + virtual void name ( const char *s ); + virtual const char *name ( void ) const; + const Audio_Region *capture_region ( void ) const; nframes_t play ( sample_t *buf, nframes_t frame, nframes_t nframes, int channels ); diff --git a/timeline/src/Control_Point.C b/timeline/src/Control_Point.C index 2d385d5..ef7b513 100644 --- a/timeline/src/Control_Point.C +++ b/timeline/src/Control_Point.C @@ -72,14 +72,11 @@ void Control_Point::draw_box ( void ) { if ( selected() ) - { fl_color( selection_color() ); - fl_pie( x(), y(), w(), h(), 0, 360 ); - } + else + fl_color( box_color() ); - fl_color( box_color() ); - - fl_arc( x(), y(), w(), h(), 0, 360 ); + fl_pie( x() - w() / 2, y() - h() / 2, w(), h(), 0, 360 ); if ( this == Sequence_Widget::belowmouse() || this == Sequence_Widget::pushed() ) @@ -111,25 +108,17 @@ Control_Point::handle ( int m ) switch ( m ) { - case FL_RELEASE: - sequence()->sort(); - redraw(); - break; - case FL_ENTER: - case FL_LEAVE: redraw(); break; case FL_DRAG: { - sequence()->sort(); - if ( nselected() > 1 ) // only allow horizontal movement when part of a selection... break; int Y = Fl::event_y() - parent()->y(); - + if ( Y >= 0 && Y < parent()->h() ) { _y = (float)Y / parent()->h(); diff --git a/timeline/src/Control_Sequence.C b/timeline/src/Control_Sequence.C index 1f27564..c041f84 100644 --- a/timeline/src/Control_Sequence.C +++ b/timeline/src/Control_Sequence.C @@ -28,6 +28,8 @@ #include "Engine/Engine.H" // for lock() +#include "Track_Header.H" + #include using std::list; @@ -37,14 +39,26 @@ using std::list; #include "string_util.h" +#include "FL/event_name.H" +#include "FL/test_press.H" + +#define DAMAGE_SEQUENCE FL_DAMAGE_USER1 +#define DAMAGE_HEADER FL_DAMAGE_USER2 + bool Control_Sequence::draw_with_grid = true; bool Control_Sequence::draw_with_polygon = true; +Fl_Widget * Control_Sequence::_highlighted = 0; + +Control_Sequence::Control_Sequence ( ) : Sequence( 0 ) +{ + init(); +} -Control_Sequence::Control_Sequence ( Track *track ) : Sequence( 0 ) +Control_Sequence::Control_Sequence ( Track *track, const char *name ) : Sequence( 0 ) { init(); @@ -52,6 +66,8 @@ Control_Sequence::Control_Sequence ( Track *track ) : Sequence( 0 ) mode( OSC ); + this->name( name ); + if ( track ) track->add( this ); @@ -61,8 +77,6 @@ Control_Sequence::Control_Sequence ( Track *track ) : Sequence( 0 ) Control_Sequence::~Control_Sequence ( ) { -// Fl::remove_timeout( &Control_Sequence::process_osc, this ); - Loggable::block_start(); clear(); @@ -84,11 +98,13 @@ Control_Sequence::~Control_Sequence ( ) _output = NULL; } - if ( _osc_output ) + if ( _osc_output() ) { - delete _osc_output; + OSC::Signal *t = _osc_output(); - _osc_output = NULL; + _osc_output( NULL ); + + delete t; } for ( list::iterator i = _persistent_osc_connections.begin(); @@ -103,13 +119,103 @@ Control_Sequence::~Control_Sequence ( ) Loggable::block_end(); } +const char * +Control_Sequence::name ( void ) const +{ + return Sequence::name(); +} + +void +Control_Sequence::name ( const char *s ) +{ + char *n = track()->get_unique_control_name( s ); + + Sequence::name( n ); + header()->name_input->value( n ); + + if ( mode() == CV ) + update_port_name(); + + redraw(); +} + +void +Control_Sequence::update_port_name ( void ) +{ + engine->lock(); + + bool needs_activation = false; + if ( ! _output ) + { + _output = new JACK::Port( engine, JACK::Port::Output, track()->name(), track()->ncontrols(), "cv" ); + needs_activation = true; + } + + if ( name() ) + { + char n[1024]; + snprintf( n, sizeof(n), "%s/%s-cv", track()->name(), name() ); + + _output->name( n ); + } + + if ( needs_activation ) + { + if ( ! _output->activate() ) + { + fl_alert( "Could not create JACK port for control output on track \"%s\"", track()->name() ); + delete _output; + _output = NULL; + } + } + + engine->unlock(); +} + +void +Control_Sequence::cb_button ( Fl_Widget *w, void *v ) +{ + ((Control_Sequence*)v)->cb_button( w ); +} + +void +Control_Sequence::cb_button ( Fl_Widget *w ) +{ + Logger log(this); + + if ( w == header()->name_input ) + { + name( header()->name_input->value() ); + } + else if ( w == header()->delete_button ) + { + Fl::delete_widget( this ); + } + /* else if ( w == header()->promote_button ) */ + /* { */ + /* track()->sequence( this ); */ + /* } */ +} + void Control_Sequence::init ( void ) { + labeltype( FL_NO_LABEL ); + { + Control_Sequence_Header *o = new Control_Sequence_Header( x(), y(), Track::width(), 52 ); + + o->name_input->callback( cb_button, this ); + o->delete_button->callback( cb_button, this ); + /* o->promote_button->callback( cb_button, this ); */ + Fl_Group::add( o ); + } + resizable(0); + + box( FL_NO_BOX ); + _track = NULL; - _highlighted = false; _output = NULL; - _osc_output = NULL; + __osc_output = NULL; _mode = (Mode)-1; interpolation( Linear ); @@ -130,15 +236,15 @@ Control_Sequence::get_unjournaled ( Log_Entry &e ) const { e.add( ":interpolation", _interpolation ); - if ( _osc_output && _osc_output->connected() ) + if ( _osc_output() && _osc_output()->connected() ) { - DMESSAGE( "OSC Output connections: %i", _osc_output->noutput_connections() ); + DMESSAGE( "OSC Output connections: %i", _osc_output()->noutput_connections() ); - for ( int i = 0; i < _osc_output->noutput_connections(); ++i ) + for ( int i = 0; i < _osc_output()->noutput_connections(); ++i ) { char *s; - s = _osc_output->get_output_connection_peer_name_and_path(i); + s = _osc_output()->get_output_connection_peer_name_and_path(i); e.add( ":osc-output", s ); @@ -166,13 +272,6 @@ Control_Sequence::set ( Log_Entry &e ) assert( t ); - _output = new JACK::Port( engine, JACK::Port::Output, t->name(), t->ncontrols(), "cv" ); - - if ( ! _output->activate() ) - { - FATAL( "could not create JACK port" ); - } - t->add( this ); } else if ( ! strcmp( ":name", s ) ) @@ -205,34 +304,34 @@ Control_Sequence::mode ( Mode m ) { _output->shutdown(); - delete _output; - + JACK::Port *t = _output; + _output = NULL; + + delete t; } } else if ( OSC != m && mode() == OSC ) { - if ( _osc_output ) + if ( _osc_output() ) { - delete _osc_output; - - _osc_output = NULL; + OSC::Signal *t = _osc_output(); + + _osc_output( NULL ); + + delete t; } } if ( CV == m && mode() != CV ) { - _output = new JACK::Port( engine, JACK::Port::Output, track()->name(), track()->ncontrols(), "cv" ); - - if ( ! _output->activate() ) - { - fl_alert( "Could not create JACK port for control output on %s", track()->name() ); - delete _output; - _output = NULL; - } + update_port_name(); + + header()->outputs_indicator->label( "cv" ); } else if ( OSC == m && mode() != OSC ) { + /* FIXME: use name here... */ char *path; asprintf( &path, "/track/%s/control/%i", track()->name(), track()->ncontrols() ); @@ -242,11 +341,17 @@ Control_Sequence::mode ( Mode m ) path = s; - _osc_output = timeline->osc->add_signal( path, OSC::Signal::Output, 0, 1, 0, NULL, NULL ); + OSC::Signal *t = timeline->osc->add_signal( path, OSC::Signal::Output, 0, 1, 0, NULL, NULL ); free( path ); + _osc_output( t ); + + DMESSAGE( "osc_output: %p", _osc_output() ); + connect_osc(); + + header()->outputs_indicator->label( "osc" ); } _mode = m; @@ -255,27 +360,37 @@ Control_Sequence::mode ( Mode m ) void Control_Sequence::draw_curve ( bool filled ) { - const int bx = x(); + const int bx = drawable_x(); const int by = y() + Fl::box_dy( box() ); - const int bw = w(); + const int bw = drawable_w(); const int bh = h() - Fl::box_dh( box() ); - list ::const_iterator e = _widgets.end(); + /* make a copy of the list for drawing and sort it... */ + list wl; + + std::copy( _widgets.begin(), _widgets.end(), std::back_inserter( wl ) ); + +//= new list (_widgets); + + wl.sort( Sequence_Widget::sort_func ); + + list ::const_iterator e = wl.end(); e--; - if ( _widgets.size() ) - for ( list ::const_iterator r = _widgets.begin(); ; r++ ) + if ( wl.size() ) + for ( list ::const_iterator r = wl.begin(); ; r++ ) { const int ry = (*r)->y(); + const int rx = (*r)->line_x(); - if ( r == _widgets.begin() ) + if ( r == wl.begin() ) { if ( filled ) fl_vertex( bx, bh + by ); fl_vertex( bx, ry ); } - fl_vertex( (*r)->line_x(), ry ); + fl_vertex( rx, ry ); if ( r == e ) { @@ -291,9 +406,9 @@ Control_Sequence::draw_curve ( bool filled ) void Control_Sequence::draw_box ( void ) { - const int bx = x(); + const int bx = drawable_x(); const int by = y(); - const int bw = w(); + const int bw = drawable_w(); const int bh = h(); int X, Y, W, H; @@ -301,7 +416,9 @@ Control_Sequence::draw_box ( void ) fl_clip_box( bx, by, bw, bh, X, Y, W, H ); // fl_rectf( X, Y, W, H, fl_color_average( FL_BLACK, FL_BACKGROUND_COLOR, 0.3 ) ); - fl_rectf( X,Y,W,H, fl_color_average( FL_BLACK, FL_WHITE, 0.90 ) ); +// fl_rectf( X,Y,W,H, fl_color_average( FL_BLACK, FL_WHITE, 0.90 ) ); + fl_rectf( X,Y,W,H, FL_DARK1 ); + if ( draw_with_grid ) { @@ -315,16 +432,12 @@ Control_Sequence::draw_box ( void ) } timeline->draw_measure_lines( X, Y, W, H ); - - fl_color( FL_BLACK ); - fl_line( x(), y(), x() + w(), y() ); - fl_line( x(), y() + h() - 1, w(), y() + h() - 1 ); } void Control_Sequence::draw ( void ) { - fl_push_clip( x(), y(), w(), h() ); + fl_push_clip( drawable_x(), y(), drawable_w(), h() ); const int bx = x(); const int by = y() + Fl::box_dy( box() ); @@ -356,7 +469,7 @@ Control_Sequence::draw ( void ) } fl_color( fl_color_average( FL_WHITE, color, 0.5 ) ); - fl_line_style( FL_SOLID, 3 ); + fl_line_style( FL_SOLID, 2 ); fl_begin_line(); draw_curve( false ); @@ -365,15 +478,24 @@ Control_Sequence::draw ( void ) fl_line_style( FL_SOLID, 0 ); } - if ( interpolation() == None || _highlighted || Fl::focus() == this ) + if ( interpolation() == None || _highlighted == this || Fl::focus() == this ) for ( list ::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) - (*r)->draw_box(); + if ( (*r)->x() + (*r)->w() >= bx && + (*r)->x() <= bw + bw ) + (*r)->draw_box(); else for ( list ::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) if ( (*r)->selected() ) - (*r)->draw_box(); + if ( (*r)->x() + (*r)->w() >= bx && + (*r)->x() <= bw + bw ) + (*r)->draw_box(); fl_pop_clip(); + + if ( damage() & ~DAMAGE_SEQUENCE ) + { + Fl_Group::draw_children(); + } } #include "FL/menu_popup.H" @@ -389,6 +511,8 @@ Control_Sequence::menu_cb ( const Fl_Menu_ *m ) { char picked[1024]; + DMESSAGE( "Control_Sequence: menu_cb" ); + if ( ! m->mvalue() ) // || m->mvalue()->flags & FL_SUBMENU_POINTER || m->mvalue()->flags & FL_SUBMENU ) return; @@ -406,7 +530,7 @@ Control_Sequence::menu_cb ( const Fl_Menu_ *m ) char *peer_and_path; asprintf( &peer_and_path, "%s:%s", peer_name, path ); - if ( ! _osc_output->is_connected_to( ((OSC::Signal*)m->mvalue()->user_data()) ) ) + if ( ! _osc_output()->is_connected_to( ((OSC::Signal*)m->mvalue()->user_data()) ) ) { _persistent_osc_connections.push_back( peer_and_path ); @@ -414,7 +538,7 @@ Control_Sequence::menu_cb ( const Fl_Menu_ *m ) } else { - timeline->osc->disconnect_signal( _osc_output, peer_name, path ); + timeline->osc->disconnect_signal( _osc_output(), peer_name, path ); for ( std::list::iterator i = _persistent_osc_connections.begin(); i != _persistent_osc_connections.end(); @@ -443,12 +567,7 @@ Control_Sequence::menu_cb ( const Fl_Menu_ *m ) else if ( ! strcmp( picked, "/Rename" ) ) { - const char *s = fl_input( "Input new name for control sequence:", name() ); - - if ( s ) - name( s ); - - redraw(); + ((Fl_Sometimes_Input*)header()->name_input)->take_focus(); } else if ( !strcmp( picked, "/Remove" ) ) { @@ -478,35 +597,33 @@ Control_Sequence::connect_osc ( void ) i != _persistent_osc_connections.end(); ++i ) { - if ( ! timeline->osc->connect_signal( _osc_output, *i ) ) + if ( ! timeline->osc->connect_signal( _osc_output(), *i ) ) { // MESSAGE( "Failed to connect output %s to ", _osc_output->path(), *i ); } else { - MESSAGE( "Connected output %s to %s", _osc_output->path(), *i ); - + MESSAGE( "Connected output %s to %s", _osc_output()->path(), *i ); // tooltip( _osc_connected_path ); } } } } -void -Control_Sequence::process_osc ( void *v ) -{ - ((Control_Sequence*)v)->process_osc(); -} - void Control_Sequence::process_osc ( void ) { - if ( _osc_output && _osc_output->connected() ) + if ( mode() != OSC ) + return; + + header()->outputs_indicator->value( _osc_output() && _osc_output()->connected() ); + + if ( _osc_output() && _osc_output()->connected() ) { sample_t buf[1]; play( buf, (nframes_t)transport->frame, (nframes_t) 1 ); - _osc_output->value( (float)buf[0] ); + _osc_output()->value( (float)buf[0] ); } } @@ -544,7 +661,7 @@ Control_Sequence::peer_callback( const char *name, const OSC::Signal *sig ) peer_menu->add( s, 0, NULL, (void*)( sig ), FL_MENU_TOGGLE | - ( _osc_output->is_connected_to( sig ) ? FL_MENU_VALUE : 0 ) ); + ( _osc_output()->is_connected_to( sig ) ? FL_MENU_VALUE : 0 ) ); free( path ); @@ -568,18 +685,38 @@ Control_Sequence::handle ( int m ) switch ( m ) { case FL_ENTER: - _highlighted = true; - fl_cursor( cursor() ); - redraw(); - return 1; + break; case FL_LEAVE: - _highlighted = false; - redraw(); - return 1; + _highlighted = 0; + damage( DAMAGE_SEQUENCE ); + fl_cursor( FL_CURSOR_DEFAULT ); + break; + case FL_MOVE: + if ( Fl::event_x() > drawable_x() ) + { + if ( _highlighted != this ) + { + _highlighted = this; + damage( DAMAGE_SEQUENCE ); + fl_cursor( FL_CURSOR_CROSS ); + } + } + else + { + if ( _highlighted == this ) + { + _highlighted = 0; + damage( DAMAGE_SEQUENCE ); + fl_cursor( FL_CURSOR_DEFAULT ); + } + } default: break; } + Logger log(this); + + int r = Sequence::handle( m ); if ( r ) @@ -589,43 +726,52 @@ Control_Sequence::handle ( int m ) { case FL_PUSH: { - Logger log( this ); - - if ( Fl::event_button1() ) + if ( test_press( FL_BUTTON1 ) && + Fl::event_x() >= Track::width() ) { - Control_Point *r = new Control_Point( this, timeline->xoffset + timeline->x_to_ts( Fl::event_x() - x() ), (float)(Fl::event_y() - y()) / h() ); + timeline->wrlock(); + + Control_Point *r = new Control_Point( this, timeline->xoffset + timeline->x_to_ts( Fl::event_x() - drawable_x() ), (float)(Fl::event_y() - y()) / h() ); add( r ); + + timeline->unlock(); + + return 1; } - else if ( Fl::event_button3() && ! ( Fl::event_state() & ( FL_ALT | FL_SHIFT | FL_CTRL ) ) ) + else if ( test_press( FL_BUTTON3 ) && + Fl::event_x() < Track::width() ) { + Fl_Menu_Button *menu = new Fl_Menu_Button( 0, 0, 0, 0, "Control Sequence" ); - Fl_Menu_Button menu( 0, 0, 0, 0, "Control Sequence" ); - - menu.clear(); + menu->clear(); if ( mode() == OSC ) { - add_osc_peers_to_menu( &menu, "Connect To" ); + add_osc_peers_to_menu( menu, "Connect To" ); } - menu.add( "Interpolation/None", 0, 0, 0, FL_MENU_RADIO | ( interpolation() == None ? FL_MENU_VALUE : 0 ) ); - menu.add( "Interpolation/Linear", 0, 0, 0, FL_MENU_RADIO | ( interpolation() == Linear ? FL_MENU_VALUE : 0 ) ); - menu.add( "Mode/Control Voltage (JACK)", 0, 0, 0 ,FL_MENU_RADIO | ( mode() == CV ? FL_MENU_VALUE : 0 ) ); - menu.add( "Mode/Control Signal (OSC)", 0, 0, 0 , FL_MENU_RADIO | ( mode() == OSC ? FL_MENU_VALUE : 0 ) ); + menu->add( "Interpolation/None", 0, 0, 0, FL_MENU_RADIO | ( interpolation() == None ? FL_MENU_VALUE : 0 ) ); + menu->add( "Interpolation/Linear", 0, 0, 0, FL_MENU_RADIO | ( interpolation() == Linear ? FL_MENU_VALUE : 0 ) ); + menu->add( "Mode/Control Voltage (JACK)", 0, 0, 0 ,FL_MENU_RADIO | ( mode() == CV ? FL_MENU_VALUE : 0 ) ); + menu->add( "Mode/Control Signal (OSC)", 0, 0, 0 , FL_MENU_RADIO | ( mode() == OSC ? FL_MENU_VALUE : 0 ) ); - menu.add( "Rename", 0, 0, 0 ); - menu.add( "Color", 0, 0, 0 ); - menu.add( "Remove", 0, 0, 0 ); + menu->add( "Rename", 0, 0, 0 ); + menu->add( "Color", 0, 0, 0 ); + menu->add( "Remove", 0, 0, 0 ); - menu.callback( &Control_Sequence::menu_cb, (void*)this); + menu->callback( &Control_Sequence::menu_cb, (void*)this); - menu_popup( &menu, x(), y() ); + menu_popup( menu ); + + delete menu; + +// redraw(); return 1; } - return 1; + return 0; } default: return 0; diff --git a/timeline/src/Control_Sequence.H b/timeline/src/Control_Sequence.H index 8fee564..e86ab4a 100644 --- a/timeline/src/Control_Sequence.H +++ b/timeline/src/Control_Sequence.H @@ -28,6 +28,8 @@ // class JACK::Port; #include "OSC/Endpoint.H" +class Control_Sequence_Header; + class Control_Sequence : public Sequence { /* not permitted */ @@ -44,22 +46,35 @@ public: MIDI }; - private: + static void cb_button ( Fl_Widget *w, void *v ); + void cb_button ( Fl_Widget *w ); + JACK::Port *_output; /* these are used to cache the saved osc connection until the * session is loaded, at which time we will reconnect */ std::list _persistent_osc_connections; /* osc output port */ - OSC::Signal *_osc_output; + volatile void *__osc_output; + + OSC::Signal *_osc_output ( void ) const + { + return (OSC::Signal *)__osc_output; + } + + void _osc_output ( OSC::Signal * s) + { + __osc_output = s; + } + static void peer_callback( const char *name, const OSC::Signal *sig, void *v ); void peer_callback( const char *name, const OSC::Signal *sig ); void add_osc_peers_to_menu ( Fl_Menu_Button *m, const char *prefix ); - bool _highlighted; + static Fl_Widget *_highlighted; Curve_Type _interpolation; @@ -75,28 +90,27 @@ private: float _rate; protected: - + + Control_Sequence ( ); virtual void get ( Log_Entry &e ) const; virtual void get_unjournaled ( Log_Entry &e ) const; void set ( Log_Entry &e ); - Control_Sequence ( ) : Sequence( 0 ) - { - init(); - } - - void draw_box ( void ); void draw ( void ); int handle ( int m ); + void update_port_name ( void ); + public: + Control_Sequence_Header * header ( void ) { return (Control_Sequence_Header*)child(0); } + + virtual void name ( const char *s ); + virtual const char *name ( void ) const; - static void process_osc ( void *v ); void process_osc ( void ); - void connect_osc ( void ); static bool draw_with_polygon; @@ -104,14 +118,18 @@ public: LOG_CREATE_FUNC( Control_Sequence ); - Control_Sequence ( Track * ); + Control_Sequence ( Track *, const char *name = 0 ); ~Control_Sequence ( ); Fl_Cursor cursor ( void ) const { return FL_CURSOR_CROSS; } Curve_Type interpolation ( void ) const { return _interpolation; } - void interpolation ( Curve_Type v ) { _interpolation = v; } - + void interpolation ( Curve_Type v ) + { + _interpolation = v; + damage( FL_DAMAGE_USER1 ); + } + Mode mode ( void ) const { return _mode; } void mode ( Mode v ); diff --git a/timeline/src/Cursor_Sequence.C b/timeline/src/Cursor_Sequence.C index 94bdf98..e420b40 100644 --- a/timeline/src/Cursor_Sequence.C +++ b/timeline/src/Cursor_Sequence.C @@ -20,6 +20,40 @@ #include "Cursor_Sequence.H" #include "Cursor_Point.H" #include "Timeline.H" +#include "Track.H" + +Cursor_Sequence::Cursor_Sequence( int X, int Y, int W, int H ) : Sequence ( X, Y, W, H ) +{ + _cursor_color = FL_CYAN; + + labeltype(FL_NO_LABEL); + + box( FL_FLAT_BOX ); + + { Fl_Box *o = new Fl_Box( X, Y, Track::width(), H ); + o->align( FL_ALIGN_RIGHT | FL_ALIGN_INSIDE ); + o->labelsize( 12 ); + o->labeltype( FL_NORMAL_LABEL ); + Fl_Group::add( o ); + } + + resizable(0); +} + + + +void +Cursor_Sequence::label ( const char *s ) +{ + Sequence::label(s); + child(0)->label(s); +} + +const char * +Cursor_Sequence::label ( void ) const +{ + return Sequence::label(); +} void Cursor_Sequence::handle_widget_change ( nframes_t start, nframes_t length ) diff --git a/timeline/src/Cursor_Sequence.H b/timeline/src/Cursor_Sequence.H index 472386c..57fe5f7 100644 --- a/timeline/src/Cursor_Sequence.H +++ b/timeline/src/Cursor_Sequence.H @@ -36,6 +36,9 @@ protected: public: + void label ( const char * s ); + const char *label ( void ) const; + Sequence_Widget *active_cursor ( void ); Fl_Color cursor_color ( void ) const { return _cursor_color; } @@ -43,11 +46,7 @@ public: Fl_Cursor cursor ( void ) const { return FL_CURSOR_DEFAULT; } - Cursor_Sequence ( int X, int Y, int W, int H ) : Sequence ( X, Y, W, H ) - { - _cursor_color = FL_CYAN; - } - + Cursor_Sequence ( int X, int Y, int W, int H ); void handle_widget_change ( nframes_t start, nframes_t length ); int handle ( int m ); diff --git a/timeline/src/OSC_Thread.C b/timeline/src/OSC_Thread.C index a04aa81..016dda5 100644 --- a/timeline/src/OSC_Thread.C +++ b/timeline/src/OSC_Thread.C @@ -66,7 +66,9 @@ OSC_Thread::process ( void ) { usleep( 100 * 1000 ); + /* lock(); */ timeline->process_osc(); + /* unlock(); */ } DMESSAGE( "OSC Thread stopping." ); diff --git a/timeline/src/Project.C b/timeline/src/Project.C index 7cd1f6f..a72286b 100644 --- a/timeline/src/Project.C +++ b/timeline/src/Project.C @@ -128,6 +128,14 @@ Project::write_info ( void ) return true; } +void +Project::undo ( void ) +{ + timeline->wrlock(); + Loggable::undo(); + timeline->unlock(); +} + bool Project::read_info ( int *version, nframes_t *sample_rate, char **creation_date, char **created_by ) { @@ -194,8 +202,11 @@ Project::close ( void ) if ( ! save() ) return false; - + + timeline->wrlock(); Loggable::close(); + timeline->unlock(); + // write_info(); _is_open = false; @@ -300,11 +311,13 @@ Project::open ( const char *name ) if ( ! engine ) make_engine(); + timeline->wrlock(); { Block_Timer timer( "Replayed journal" ); if ( ! Loggable::open( "history" ) ) return E_INVALID; } + timeline->unlock(); /* /\* really a good idea? *\/ */ /* timeline->sample_rate( rate ); */ diff --git a/timeline/src/Project.H b/timeline/src/Project.H index 9abe4e6..a1a67a4 100644 --- a/timeline/src/Project.H +++ b/timeline/src/Project.H @@ -36,6 +36,7 @@ class Project static const char *_errstr[]; static void make_engine ( void ); + public: enum @@ -60,6 +61,6 @@ public: static int open ( const char *name ); static bool open ( void ) { return _is_open; } static bool create ( const char *name, const char *template_name ); - + static void undo ( void ); static const char *created_on ( void ) { return _created_on; } }; diff --git a/timeline/src/Sequence.C b/timeline/src/Sequence.C index 9997187..83f3cd9 100644 --- a/timeline/src/Sequence.C +++ b/timeline/src/Sequence.C @@ -39,7 +39,7 @@ queue Sequence::_delete_queue; -Sequence::Sequence ( Track *track, const char *name ) : Fl_Widget( 0, 0, 0, 0 ), Loggable( true ) +Sequence::Sequence ( Track *track, const char *name ) : Fl_Group( 0, 0, 0, 0 ), Loggable( true ) { init(); @@ -51,7 +51,7 @@ Sequence::Sequence ( Track *track, const char *name ) : Fl_Widget( 0, 0, 0, 0 ), // log_create(); } -Sequence::Sequence ( int X, int Y, int W, int H ) : Fl_Widget( X, Y, W, H ), Loggable( false ) +Sequence::Sequence ( int X, int Y, int W, int H ) : Fl_Group( X, Y, W, H ), Loggable( false ) { init(); } @@ -67,9 +67,11 @@ Sequence::init ( void ) color( FL_BACKGROUND_COLOR ); align( FL_ALIGN_LEFT ); + end(); // clear_visible_focus(); } + Sequence::~Sequence ( ) { DMESSAGE( "destroying sequence" ); @@ -86,6 +88,18 @@ Sequence::~Sequence ( ) +int +Sequence::drawable_w ( void ) const +{ + return w() - Track::width(); +} + +int +Sequence::drawable_x ( void ) const +{ + return x() + Track::width(); +} + void Sequence::log_children ( void ) const { @@ -120,11 +134,7 @@ Sequence::x_to_offset ( int X ) void Sequence::sort ( void ) { - timeline->wrlock(); - _widgets.sort( Sequence_Widget::sort_func ); - - timeline->unlock(); } /** return a pointer to the widget that /r/ overlaps, or NULL if none. */ @@ -145,6 +155,7 @@ void Sequence::handle_widget_change ( nframes_t start, nframes_t length ) { sort(); + timeline->damage_sequence(); // timeline->update_length( start + length ); } @@ -164,7 +175,7 @@ Sequence::widget_at ( nframes_t ts, int Y ) Sequence_Widget * Sequence::event_widget ( void ) { - nframes_t ets = timeline->xoffset + timeline->x_to_ts( Fl::event_x() - x() ); + nframes_t ets = timeline->xoffset + timeline->x_to_ts( Fl::event_x() - drawable_x() ); return widget_at( ets, Fl::event_y() ); } @@ -180,12 +191,9 @@ Sequence::add ( Sequence_Widget *r ) // r->track()->redraw(); } - timeline->wrlock(); - r->sequence( this ); - _widgets.push_back( r ); - timeline->unlock(); + _widgets.push_back( r ); handle_widget_change( r->start(), r->length() ); } @@ -193,12 +201,8 @@ Sequence::add ( Sequence_Widget *r ) void Sequence::remove ( Sequence_Widget *r ) { - timeline->wrlock(); - _widgets.remove( r ); - timeline->unlock(); - handle_widget_change( r->start(), r->length() ); } @@ -259,13 +263,23 @@ void Sequence::draw_box ( void ) { /* draw the box with the ends cut off. */ - Fl_Widget::draw_box( box(), x() - Fl::box_dx( box() ) - 1, y(), w() + Fl::box_dw( box() ) + 2, h(), color() ); + Fl_Group::draw_box( box(), x() - Fl::box_dx( box() ) - 1, y(), w() + Fl::box_dw( box() ) + 2, h(), color() ); } void Sequence::draw ( void ) { - fl_push_clip( x(), y(), w(), h() ); + if ( damage() & ~FL_DAMAGE_USER1 ) + { + Fl_Boxtype b = box(); + box( FL_NO_BOX ); + + Fl_Group::draw(); + + box( b ); + } + + fl_push_clip( drawable_x(), y(), drawable_w(), h() ); draw_box(); @@ -353,17 +367,17 @@ Sequence::handle ( int m ) /* garbage from overlay window */ return 0; case FL_FOCUS: - Fl_Widget::handle( m ); + Fl_Group::handle( m ); redraw(); return 1; case FL_UNFOCUS: - Fl_Widget::handle( m ); + Fl_Group::handle( m ); redraw(); return 1; case FL_LEAVE: // DMESSAGE( "leave" ); fl_cursor( FL_CURSOR_DEFAULT ); - Fl_Widget::handle( m ); + Fl_Group::handle( m ); return 1; case FL_DND_DRAG: return 1; @@ -374,19 +388,25 @@ Sequence::handle ( int m ) if ( Sequence_Widget::pushed()->sequence()->class_name() == class_name() ) { /* accept objects dragged from other sequences of this type */ + + timeline->wrlock(); + add( Sequence_Widget::pushed() ); - redraw(); + + timeline->unlock(); + + damage( FL_DAMAGE_USER1 ); fl_cursor( FL_CURSOR_MOVE ); } else - fl_cursor( (Fl_Cursor)1 ); + fl_cursor( FL_CURSOR_DEFAULT ); } else if ( ! event_widget() ) fl_cursor( cursor() ); - Fl_Widget::handle( m ); + Fl_Group::handle( m ); return 1; case FL_DND_ENTER: @@ -443,6 +463,8 @@ Sequence::handle ( int m ) Loggable::block_start(); + timeline->wrlock(); + while ( _delete_queue.size() ) { @@ -460,6 +482,8 @@ Sequence::handle ( int m ) delete t; } + timeline->unlock(); + Loggable::block_end(); if ( m == FL_PUSH ) @@ -475,7 +499,7 @@ Sequence::handle ( int m ) Sequence_Widget::select_none(); } - return Fl_Widget::handle( m ); + return Fl_Group::handle( m ); } } } diff --git a/timeline/src/Sequence.H b/timeline/src/Sequence.H index 10b7d66..c07b4f9 100644 --- a/timeline/src/Sequence.H +++ b/timeline/src/Sequence.H @@ -40,7 +40,7 @@ class Sequence_Widget; /* This is the base class for all track types. */ -class Sequence : public Fl_Widget, public Loggable +class Sequence : public Fl_Group, public Loggable { /* not permitted */ @@ -100,6 +100,9 @@ public: void sort ( void ); void clear ( void ); + int drawable_x ( void ) const; + int drawable_w ( void ) const; + const Sequence_Widget *next ( nframes_t from ) const; const Sequence_Widget *prev ( nframes_t from ) const; diff --git a/timeline/src/Sequence_Widget.C b/timeline/src/Sequence_Widget.C index 307f3d0..0503ed5 100644 --- a/timeline/src/Sequence_Widget.C +++ b/timeline/src/Sequence_Widget.C @@ -65,6 +65,7 @@ Sequence_Widget::Sequence_Widget ( const Sequence_Widget &rhs ) : Loggable( rhs _sequence = rhs._sequence; _range = rhs._range; + _dragging_range = rhs._dragging_range; _r = &_range; _color = rhs._color; @@ -79,6 +80,7 @@ Sequence_Widget::operator= ( const Sequence_Widget &rhs ) _r = &_range; _range = rhs._range; + _dragging_range = rhs._dragging_range; _sequence = rhs._sequence; _box_color = rhs._box_color; _color = rhs._color; @@ -157,7 +159,7 @@ Sequence_Widget::set ( Log_Entry &e ) if ( _sequence ) { _sequence->handle_widget_change( _r->start, _r->length ); - _sequence->redraw(); + _sequence->damage( FL_DAMAGE_USER1 ); } } @@ -168,7 +170,12 @@ Sequence_Widget::begin_drag ( const Drag &d ) timeline->rdlock(); - _r = new Range( _range ); + /* copy current values */ + + _dragging_range = _range; + + /* tell display to use temporary */ + _r = &_dragging_range; timeline->unlock(); } @@ -176,20 +183,21 @@ Sequence_Widget::begin_drag ( const Drag &d ) void Sequence_Widget::end_drag ( void ) { + /* swap in the new value */ + /* go back to playback and display using same values */ + timeline->wrlock(); - /* swap in the new value */ - _range = *_r; - - timeline->unlock(); - - delete _r; + _range = _dragging_range; _r = &_range; delete _drag; _drag = NULL; + /* this will result in a sort */ sequence()->handle_widget_change( _r->start, _r->length ); + + timeline->unlock(); } /** set position of widget on the timeline. */ @@ -392,7 +400,10 @@ Sequence_Widget::handle ( int m ) /* deletion */ if ( test_press( FL_BUTTON3 + FL_CTRL ) ) { + timeline->wrlock(); remove(); + timeline->unlock(); + return 1; } else if ( test_press( FL_BUTTON1 ) || test_press( FL_BUTTON1 + FL_CTRL ) ) @@ -476,18 +487,17 @@ Sequence_Widget::handle ( int m ) // timeline->update_length( start() + length() ); - /* FIXME: why isn't this enough? */ - sequence()->redraw(); + sequence()->damage( FL_DAMAGE_USER1 ); } if ( ! selected() || _selection.size() == 1 ) { /* track jumping */ - if ( Y > y() + h() || Y < y() ) + if ( Y > _sequence->y() + _sequence->h() || Y < _sequence->y() ) { Track *t = timeline->track_under( Y ); - fl_cursor( (Fl_Cursor)1 ); + fl_cursor( FL_CURSOR_HAND ); if ( t ) t->handle( FL_ENTER ); diff --git a/timeline/src/Sequence_Widget.H b/timeline/src/Sequence_Widget.H index 1f9ee85..e9db7ad 100644 --- a/timeline/src/Sequence_Widget.H +++ b/timeline/src/Sequence_Widget.H @@ -140,8 +140,10 @@ protected: char *_label; Sequence *_sequence; /* track this region belongs to */ + + Range _range; /* always used by RT/osc threads */ + Range _dragging_range; /* used when dragging */ - Range _range; /* range for playback */ Range *_r; /* range for editing / display (points to the same thing as above, except for when dragging etc) */ Fl_Color _color; /* color of waveform */ @@ -199,8 +201,9 @@ public: int get_x( nframes_t frame ) const { - return frame < timeline->xoffset ? _sequence->x() : min( _sequence->x() + _sequence->w(), _sequence->x() + timeline->ts_to_x( frame - timeline->xoffset ) ); - + return frame < timeline->xoffset ? + _sequence->drawable_x() : + min( _sequence->drawable_x() + _sequence->drawable_w(), _sequence->drawable_x() + timeline->ts_to_x( frame - timeline->xoffset ) ); } virtual int x ( void ) const @@ -211,7 +214,9 @@ public: /* use this as x() when you need to draw lines between widgets */ int line_x ( void ) const { - return _r->start < timeline->xoffset ? max( -32767, _sequence->x() - timeline->ts_to_x( timeline->xoffset - _r->start )) : min( 32767, _sequence->x() + timeline->ts_to_x( _r->start - timeline->xoffset ) ); + return _r->start < timeline->xoffset ? + max( -32767, _sequence->drawable_x() - timeline->ts_to_x( timeline->xoffset - _r->start )) : + min( 32767, _sequence->drawable_x() + timeline->ts_to_x( _r->start - timeline->xoffset ) ); } virtual int w ( void ) const @@ -224,7 +229,7 @@ public: else rw = abs_w(); - return min( rw, _sequence->w() ); + return min( rw, _sequence->drawable_w() ); } int abs_x ( void ) const { return timeline->ts_to_x( _r->start ); } @@ -271,7 +276,7 @@ public: /** convert a screen x coord into an start into the region */ nframes_t x_to_offset ( int X ) { - return timeline->x_to_ts( scroll_x() + ( X - _sequence->x() ) ) - _r->start; + return timeline->x_to_ts( scroll_x() + ( X - _sequence->drawable_x() ) ) - _r->start; } int active_r ( void ) const { return _sequence->active_r(); } @@ -299,11 +304,11 @@ public: if ( ! (align() & FL_ALIGN_INSIDE) ) { - // FIXME: to better.. - _sequence->redraw(); + // FIXME: do better.. + _sequence->damage( FL_DAMAGE_USER1 ); } else - _sequence->damage( FL_DAMAGE_ALL, x(), y(), w(), h() ); + _sequence->damage( FL_DAMAGE_USER1, x(), y(), w(), h() ); } virtual void draw_box ( void ); diff --git a/timeline/src/TLE.fl b/timeline/src/TLE.fl index 23a7476..d20253f 100644 --- a/timeline/src/TLE.fl +++ b/timeline/src/TLE.fl @@ -249,7 +249,7 @@ Loggable::progress_callback( &TLE::progress_cb, this );} {} label {Non DAW : Timeline} callback {if ( Fl::event_key() != FL_Escape ) timeline->command_quit();} open - xywh {559 209 1025 770} type Double resizable + xywh {262 208 1025 770} type Double resizable class TLE_Window xclass Non_DAW size_range {900 300 0 0} visible } { Fl_Group {} { @@ -396,7 +396,7 @@ Project::compact();} } { MenuItem {} { label Undo - callback {Loggable::undo();} + callback {Project::undo();} xywh {5 5 40 25} shortcut 0x4007a divider } MenuItem {} { @@ -719,34 +719,38 @@ ab.run();} } { Fl_Button solo_blinker { label SOLO selected - xywh {800 33 50 15} box BORDER_BOX down_box BORDER_BOX color 74 selection_color 92 labelfont 1 labelsize 11 labelcolor 32 deactivate + xywh {800 33 50 15} box BORDER_BOX down_box BORDER_BOX color 74 selection_color 92 labelfont 1 labelsize 11 labelcolor 32 code0 {\#include "FL/Fl_Blink_Button.H"} code1 {o->box( FL_ASYM_BOX );} code2 {o->down_box( FL_ASYM_BOX );} + code3 {o->ignore_input( true );} class Fl_Blink_Button } Fl_Button rec_blinker { label REC selected - xywh {800 53 50 15} box BORDER_BOX down_box BORDER_BOX color 72 selection_color 88 labelfont 1 labelsize 11 labelcolor 32 deactivate + xywh {800 53 50 15} box BORDER_BOX down_box BORDER_BOX color 72 selection_color 88 labelfont 1 labelsize 11 labelcolor 32 code0 {\#include "FL/Fl_Blink_Button.H"} code1 {o->box( FL_ASYM_BOX );} code2 {o->down_box( FL_ASYM_BOX );} + code3 {o->ignore_input( true );} class Fl_Blink_Button } Fl_Button selected_blinker { label SEL selected - xywh {745 53 50 15} box BORDER_BOX down_box BORDER_BOX color 13 selection_color 5 labelfont 1 labelsize 11 labelcolor 32 deactivate + xywh {745 53 50 15} box BORDER_BOX down_box BORDER_BOX color 13 selection_color 5 labelfont 1 labelsize 11 labelcolor 32 code0 {\#include "FL/Fl_Blink_Button.H"} code1 {o->box( FL_ASYM_BOX );} code2 {o->down_box( FL_ASYM_BOX );} + code3 {o->ignore_input( true );} class Fl_Blink_Button } Fl_Button seek_blinker { label SEEK selected - xywh {745 33 50 15} box BORDER_BOX down_box BORDER_BOX color 10 selection_color 2 labelfont 1 labelsize 11 labelcolor 32 deactivate + xywh {745 33 50 15} box BORDER_BOX down_box BORDER_BOX color 10 selection_color 2 labelfont 1 labelsize 11 labelcolor 32 code0 {\#include "FL/Fl_Blink_Button.H"} code1 {o->box( FL_ASYM_BOX );} code2 {o->down_box( FL_ASYM_BOX );} + code3 {o->ignore_input( true );} class Fl_Blink_Button } } @@ -995,7 +999,7 @@ if ( logo_box->image() ) ((Fl_Shared_Image*)logo_box->image())->release(); logo_box->image( NULL ); }} open - private xywh {1240 261 520 775} type Double modal visible + private xywh {1242 261 520 775} type Double modal visible } { Fl_Value_Output {} { label {Sample Rate} diff --git a/timeline/src/Tempo_Sequence.C b/timeline/src/Tempo_Sequence.C index a90c4a1..a81fa08 100644 --- a/timeline/src/Tempo_Sequence.C +++ b/timeline/src/Tempo_Sequence.C @@ -18,6 +18,22 @@ /*******************************************************************************/ #include "Tempo_Sequence.H" +#include "Track.H" + +Tempo_Sequence::Tempo_Sequence ( int X, int Y, int W, int H ) : Sequence ( X, Y, W, H ) +{ + box( FL_FLAT_BOX ); + + { Fl_Box *o = new Fl_Box( X, Y, Track::width(), H ); + o->align( FL_ALIGN_RIGHT | FL_ALIGN_INSIDE ); + o->labelsize( 12 ); + o->labeltype( FL_NORMAL_LABEL ); + o->label( "Tempo" ); + Fl_Group::add( o ); + } + + resizable(0); +} void Tempo_Sequence::handle_widget_change ( nframes_t start, nframes_t length ) diff --git a/timeline/src/Tempo_Sequence.H b/timeline/src/Tempo_Sequence.H index d74b9d3..61f6498 100644 --- a/timeline/src/Tempo_Sequence.H +++ b/timeline/src/Tempo_Sequence.H @@ -35,10 +35,7 @@ public: Fl_Cursor cursor ( void ) const { return FL_CURSOR_DEFAULT; } - Tempo_Sequence ( int X, int Y, int W, int H ) : Sequence ( X, Y, W, H ) - { -// box( FL_DOWN_BOX ); - } + Tempo_Sequence ( int X, int Y, int W, int H ); void handle_widget_change ( nframes_t start, nframes_t length ); int handle ( int m ); diff --git a/timeline/src/Time_Sequence.C b/timeline/src/Time_Sequence.C index 51e52df..39461a0 100644 --- a/timeline/src/Time_Sequence.C +++ b/timeline/src/Time_Sequence.C @@ -18,6 +18,25 @@ /*******************************************************************************/ #include "Time_Sequence.H" +#include "Track.H" +#include + +Time_Sequence::Time_Sequence ( int X, int Y, int W, int H ) : Sequence ( X, Y, W, H ) +{ + box( FL_FLAT_BOX ); + + { Fl_Box *o = new Fl_Box( X, Y, Track::width(), H ); + o->align( FL_ALIGN_RIGHT | FL_ALIGN_INSIDE ); + o->labelsize( 12 ); + o->labeltype( FL_NORMAL_LABEL ); + o->label( "Time" ); + Fl_Group::add( o ); + } + + resizable(0); +} + + void Time_Sequence::handle_widget_change ( nframes_t start, nframes_t length ) diff --git a/timeline/src/Time_Sequence.H b/timeline/src/Time_Sequence.H index 9686455..4e71a71 100644 --- a/timeline/src/Time_Sequence.H +++ b/timeline/src/Time_Sequence.H @@ -39,10 +39,7 @@ public: Fl_Cursor cursor ( void ) const { return FL_CURSOR_DEFAULT; } - Time_Sequence ( int X, int Y, int W, int H ) : Sequence ( X, Y, W, H ) - { -// box( FL_UP_BOX ); - } + Time_Sequence ( int X, int Y, int W, int H ); time_sig time ( nframes_t when ) diff --git a/timeline/src/Timeline.C b/timeline/src/Timeline.C index 4e62eb5..86e0a7c 100644 --- a/timeline/src/Timeline.C +++ b/timeline/src/Timeline.C @@ -321,7 +321,7 @@ Timeline::cb_scroll ( Fl_Widget *w ) if ( _old_yposition != panzoomer->y_value() ) { - tracks->position( tracks->x(), (rulers->y() + rulers->h()) - panzoomer->y_value() ); + tracks->position( tracks->x(), track_window->y() - (int)panzoomer->y_value() ); damage( FL_DAMAGE_SCROLL ); } @@ -615,6 +615,8 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W /* menu->add( "Add Track", 0, 0, 0 ); */ + int ruler_height = 0; + menu->add( "Add audio track", 'a', 0, 0 ); menu->add( "Tempo from edit (beat)", 't', 0, 0 ); menu->add( "Tempo from edit (bar)", FL_CTRL + 't', 0, 0 ); @@ -637,17 +639,15 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W { - Fl_Pack *o = new Fl_Pack( X + Track::width(), Y, (W - Track::width()), 1, "rulers" ); + Fl_Pack *o = new Fl_Pack( X, Y, W, 1, "rulers" ); o->type( Fl_Pack::VERTICAL ); { Tempo_Sequence *o = new Tempo_Sequence( 0, 0, 800, 18 ); - o->color( FL_GRAY ); + o->color( FL_DARK1 ); - o->labelsize( 12 ); - o->label( "Tempo" ); - o->align( FL_ALIGN_LEFT ); + /* o->label( "Tempo" ); */ tempo_track = o; } @@ -655,11 +655,9 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W { Time_Sequence *o = new Time_Sequence( 0, 24, 800, 18 ); - o->color( fl_lighter( FL_GRAY ) ); + o->color( FL_DARK2 ); - o->labelsize( 12 ); - o->label( "Time" ); - o->align( FL_ALIGN_LEFT ); + /* o->name( "Time" ); */ time_track = o; } @@ -667,11 +665,9 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W { Cursor_Sequence *o = new Cursor_Sequence( 0, 24, 800, 18 ); - o->color( FL_GRAY ); + o->color( FL_DARK1 ); - o->labelsize( 12 ); o->label( "Edit" ); - o->align( FL_ALIGN_LEFT ); o->cursor_color( FL_YELLOW ); edit_cursor_track = o; @@ -680,11 +676,9 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W { Cursor_Sequence *o = new Cursor_Sequence( 0, 24, 800, 18 ); - o->color( fl_lighter( FL_GRAY ) ); + o->color( FL_DARK2 ); - o->labelsize( 12 ); o->label( "Punch" ); - o->align( FL_ALIGN_LEFT ); o->cursor_color( FL_RED ); punch_cursor_track = o; @@ -693,11 +687,9 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W { Cursor_Sequence *o = new Cursor_Sequence( 0, 24, 800, 18 ); - o->color( FL_GRAY ); + o->color( FL_DARK1 ); - o->labelsize( 12 ); o->label( "Playback" ); - o->align( FL_ALIGN_LEFT ); o->cursor_color( FL_GREEN ); play_cursor_track = o; @@ -715,16 +707,22 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W /* } */ rulers = o; - o->size( o->w(), o->child( 0 )->h() * o->children() ); o->end(); + + ruler_height = o->child( 0 )->h() * o->children(); + + DMESSAGE( "Ruler height: %i", ruler_height ); + + o->size( o->w(), ruler_height ); } { - Fl_Tile *o = new Fl_Tile( X, rulers->y() + rulers->h(), W, H - rulers->h() ); + Fl_Tile *o = new Fl_Tile( X, rulers->y() + ruler_height, W, H - rulers->h() ); o->box(FL_FLAT_BOX); o->when( FL_WHEN_RELEASE ); { Fl_Group *o = new Fl_Group( X, rulers->y() + rulers->h(), W, ( H - rulers->h() ) - 50 ); + o->box(FL_FLAT_BOX); { _fpp = 8; Fl_Pack *o = new Fl_Pack( X, rulers->y() + rulers->h(), W, 1 ); @@ -733,7 +731,7 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W tracks = o; o->end(); - resizable( o ); + /* Fl_Group::current()->resizable( o ); */ } o->end(); @@ -753,14 +751,13 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W o->type( FL_HORIZONTAL ); o->callback( cb_scroll, this ); - //resizable(o); panzoomer = o; } Fl_Box *spacebox = new Fl_Box( 0,0,1,1 ); o->end(); - o->resizable( spacebox); + o->resizable( spacebox ); spacebox->resize( X, rulers->y() + ( ( H - rulers->h() ) - 50 ), W, 125 ); @@ -768,19 +765,14 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W o->position( panzoomer->x(), panzoomer->y(), panzoomer->x(), track_window->y() + track_window->h() ); - resizable(o); tile = o; + resizable(o); } /* rulers go above tracks... */ add( rulers ); - /* make sure scrollbars are on top */ - /* add( panzoomer ); */ - -// vscroll->range( 0, tracks->h() ); - - redraw(); + /* redraw(); */ end(); @@ -1112,7 +1104,7 @@ Timeline::draw_measure_lines ( int X, int Y, int W, int H ) } void -Timeline::draw_clip ( void * v, int X, int Y, int W, int H ) +Timeline::draw_clip_rulers ( void * v, int X, int Y, int W, int H ) { Timeline *tl = (Timeline *)v; @@ -1120,9 +1112,25 @@ Timeline::draw_clip ( void * v, int X, int Y, int W, int H ) tl->draw_box(); + tl->draw_child( *tl->rulers ); + + fl_pop_clip(); +} + +void +Timeline::draw_clip_tracks ( void * v, int X, int Y, int W, int H ) +{ + Timeline *tl = (Timeline *)v; + + fl_push_clip( X, Y, W, H ); + + tl->draw_box(); + + fl_damage_t pzd = tl->panzoomer->damage(); + tl->draw_child( *tl->tile ); - tl->draw_child( *tl->rulers ); + tl->panzoomer->damage( pzd ); tl->draw_cursors(); @@ -1137,25 +1145,25 @@ Timeline::resize ( int X, int Y, int W, int H ) tile->resizable()->resize( X, tile->y() + tile->h() - 150, - W, 125 ); - + W, 125 ); + /* why is THIS necessary? */ - panzoomer->resize( X, + panzoomer->resize( X, tile->y() + tile->h() - 50, W, 50 ); - track_window->resize( X, + track_window->resize( X, tile->y(), W, tile->h() - 50); - rulers->resize( X + Track::width(), - rulers->y(), - W - Track::width(), - rulers->h() ); + /* /\* rulers->resize( X, *\/ */ + /* /\* rulers->y(), *\/ */ + /* /\* W, *\/ */ + /* /\* rulers->h() ); *\/ */ - tile->redraw(); + /* tile->redraw(); */ } @@ -1245,7 +1253,7 @@ Timeline::draw ( void ) adjust_panzoomer(); int dx = ts_to_x( _old_xposition ) - ts_to_x( xoffset ); - int dy = _old_yposition - panzoomer->y_value(); + int dy = _old_yposition - (int)panzoomer->y_value(); int c = damage(); @@ -1253,30 +1261,37 @@ Timeline::draw ( void ) if ( c & FL_DAMAGE_SCROLL ) { - /* if ( dx && dy ) */ - /* { */ - /* /\* FIXME: scrolling both at once is... problematic *\/ */ - - /* c |= FL_DAMAGE_ALL; */ - /* } */ - /* else */ { /* draw_child( *rulers ); */ Y = track_window->y(); H = track_window->h(); - if ( dy ) - fl_scroll( X, Y, Track::width(), H, 0, dy, draw_clip, this ); if ( dx ) - fl_scroll( rulers->x(), rulers->y(), rulers->w(), rulers->h(), dx, 0, draw_clip, this ); - - fl_scroll( X + Track::width(), Y, W - Track::width(), H, dx, dy, draw_clip, this ); + /* when scrolling horizontally, scroll rulers */ + fl_scroll( rulers->x() + Track::width(), + rulers->y(), + rulers->w(), + rulers->h(), dx, 0, draw_clip_rulers, this ); + + if ( dy ) + /* when scrolling vertically, also scroll track headers */ + fl_scroll( + X, + Y, + Track::width(), + H, 0, dy, draw_clip_tracks, this ); + + /* scroll sequences */ + fl_scroll( X + Track::width(), + Y, + W - Track::width(), + H, dx, dy, draw_clip_tracks, this ); } } - panzoomer->redraw(); +// panzoomer->redraw(); if ( c & FL_DAMAGE_ALL ) { @@ -1311,6 +1326,10 @@ Timeline::draw ( void ) tile->w(), tile->h() ); + /* redraw the panzoomer preview whenever tracks change */ + /* if ( tracks->damage() ) */ + /* panzoomer->redraw(); */ + update_child(*tile); draw_cursors(); @@ -1329,6 +1348,12 @@ done: _old_yposition = panzoomer->y_value(); } +void +Timeline::damage_sequence ( void ) +{ + panzoomer->redraw(); +} + /** draw a single cursor line at /frame/ with color /color/ using symbol routine /symbol/ for the cap */ void Timeline::draw_cursor ( nframes_t frame, Fl_Color color, void (*symbol)(Fl_Color) ) const @@ -1726,7 +1751,7 @@ Timeline::track_by_name ( const char *name ) { Track *t = (Track*)tracks->child( i ); - if ( ! strcmp( name, t->name() ) ) + if ( name && t->name() && ! strcmp( name, t->name() ) ) return t; } @@ -1831,8 +1856,6 @@ Timeline::add_track ( Track *track ) { DMESSAGE( "added new track to the timeline" ); - wrlock(); - engine->lock(); tracks->add( track ); @@ -1841,8 +1864,6 @@ Timeline::add_track ( Track *track ) engine->unlock(); - unlock(); - /* FIXME: why is this necessary? doesn't the above add do DAMAGE_CHILD? */ redraw(); @@ -1854,8 +1875,6 @@ Timeline::insert_track ( Track *track, int n ) if ( n > tracks->children() || n < 0 ) return; - wrlock(); - engine->lock(); tracks->insert( *track, n ); @@ -1866,8 +1885,6 @@ Timeline::insert_track ( Track *track, int n ) engine->unlock(); - unlock(); - /* FIXME: why is this necessary? doesn't the above add do DAMAGE_CHILD? */ // redraw(); } @@ -1882,8 +1899,6 @@ compare_tracks ( Track *a, Track *b ) void Timeline::apply_track_order ( void ) { - wrlock(); - engine->lock(); std::list tl; @@ -1904,8 +1919,6 @@ Timeline::apply_track_order ( void ) update_track_order(); engine->unlock(); - - unlock(); } void @@ -1939,8 +1952,6 @@ Timeline::remove_track ( Track *track ) { DMESSAGE( "removed track from the timeline" ); - wrlock(); - engine->lock(); /* FIXME: what to do about track contents? */ @@ -1950,9 +1961,6 @@ Timeline::remove_track ( Track *track ) engine->unlock(); - unlock(); - - /* FIXME: why is this necessary? doesn't the above add do DAMAGE_CHILD? */ redraw(); } @@ -2124,6 +2132,8 @@ Timeline::handle_peer_scan_complete ( void *o ) void Timeline::connect_osc ( void ) { + wrlock(); + /* try to (re)connect OSC signals */ for ( int i = tracks->children(); i-- ; ) { @@ -2131,6 +2141,8 @@ Timeline::connect_osc ( void ) t->connect_osc(); } + + unlock(); } void @@ -2158,6 +2170,7 @@ Timeline::process_osc ( void ) { THREAD_ASSERT( OSC ); + /* FIXME: is holding this lock a problem for recording? */ rdlock(); /* reconnect OSC signals */ @@ -2167,7 +2180,7 @@ Timeline::process_osc ( void ) t->process_osc(); } - + unlock(); } diff --git a/timeline/src/Timeline.H b/timeline/src/Timeline.H index 976609d..d46c7db 100644 --- a/timeline/src/Timeline.H +++ b/timeline/src/Timeline.H @@ -100,7 +100,8 @@ class Timeline : public Fl_Single_Window, public RWLock class Timeline_Panzoomer; - static void draw_clip ( void * v, int X, int Y, int W, int H ); + static void draw_clip_rulers ( void * v, int X, int Y, int W, int H ); + static void draw_clip_tracks ( void * v, int X, int Y, int W, int H ); nframes_t _old_xposition; int _old_yposition; @@ -110,8 +111,8 @@ class Timeline : public Fl_Single_Window, public RWLock Fl_Group *track_window; Fl_Pack *tracks; Fl_Pack *rulers; - Fl_Panzoomer *panzoomer; Fl_Tile *tile; + Fl_Panzoomer *panzoomer; void adjust_panzoomer ( void ); static void cb_scroll ( Fl_Widget *w, void *v ); @@ -139,6 +140,9 @@ class Timeline : public Fl_Single_Window, public RWLock public: + /* called when widgets are moved etc */ + void damage_sequence ( void ); + OSC::Endpoint *osc; OSC_Thread *osc_thread; @@ -305,6 +309,9 @@ public: void add_cursor ( Cursor_Region *o ); void add_cursor ( Cursor_Point *o ); + char * get_unique_track_name ( const char *name ); + Track * track_by_name ( const char *name ); + private: void add_take_for_armed_tracks(); @@ -315,8 +322,6 @@ private: friend class Engine; // FIXME: only Engine::process() needs to be friended.x - Track * track_by_name ( const char *name ); - char * get_unique_track_name ( const char *name ); /* Engine */ void resize_buffers ( nframes_t nframes ); diff --git a/timeline/src/Track.C b/timeline/src/Track.C index a81dcd4..6db5ca9 100644 --- a/timeline/src/Track.C +++ b/timeline/src/Track.C @@ -29,6 +29,7 @@ #include "Transport.H" #include "../FL/Fl_Sometimes_Input.H" +#include "../FL/Fl_Sometimes_Pack.H" #include #include #include @@ -54,70 +55,6 @@ random_color ( void ) static Fl_Menu_Button _menu( 0, 0, 0, 0, "Track" ); -class Fl_Sometimes_Pack : public Fl_Pack -{ - bool _pack; - -public: - - Fl_Sometimes_Pack ( int X, int Y, int W, int H, const char *L=0 ) : Fl_Pack(X,Y,W,H,L) - { - _pack = true; - } - - virtual ~Fl_Sometimes_Pack ( ) - { - } - - void pack ( bool b ) - { - if ( b != _pack ) - redraw(); - - _pack = b; - } - - bool pack ( void ) const - { - return _pack; - } - - virtual void draw ( void ) - { - /* draw_box(); */ - - if ( _pack ) - { - for ( int i = 0; i < children(); i++ ) - { - Fl_Widget *o = child( i ); - - o->box( FL_FLAT_BOX ); - } - - Fl_Pack::draw(); - } - else - { - if ( children() ) - { - for ( int i = 0; i < children(); i++ ) - { - Fl_Widget *o = child( i ); - - if ( i != 0 ) - o->box( FL_NO_BOX ); - - o->resize( x(),y(),w(), o->h() ); - } - resize( x(), y(), w(), child(0)->h() ); - } - - Fl_Group::draw(); - } - } -}; - int Track::_soloing = 0; @@ -206,7 +143,7 @@ Track::init ( void ) o->box( FL_FLAT_BOX ); { - Track_Header *o = new Track_Header( x(), y(), 200, 80 ); + Track_Header *o = new Track_Header( x(), y(), w(), h() ); name_field = o->name_input; record_button = o->rec_button; @@ -224,18 +161,12 @@ Track::init ( void ) overlay_controls_button->callback( cb_button, this ); resizable( o ); - o->color( (Fl_Color)53 ); +// o->color( (Fl_Color)53 ); } - - /* { */ - /* Fl_Box *o = new Fl_Box( 0, 72, 149, 38 ); */ - /* o->box( FL_NO_BOX ); */ - /* Fl_Group::current()->resizable( o ); */ - /* } */ - + { /* this pack holds the active sequence, annotation sequence, control sequences and takes */ - Fl_Pack *o = pack = new Fl_Pack( x() + width(), y(), w() - width(), h() ); + Fl_Pack *o = pack = new Fl_Pack( x(), y(), w(), h() ); o->type( Fl_Pack::VERTICAL ); o->labeltype( FL_NO_LABEL ); /* o->resize( x() + width(), y(), w() - width(), h() ); */ @@ -243,25 +174,66 @@ Track::init ( void ) /* resizable( o ); */ { - Fl_Pack *o = annotation = new Fl_Pack( width(), 0, pack->w(), 1 ); + Fl_Pack *o = annotation = new Fl_Pack( 0, 0, pack->w(), 1 ); o->type( Fl_Pack::VERTICAL ); o->end(); } { - Fl_Sometimes_Pack *o = control = new Fl_Sometimes_Pack( width(), 0, pack->w(), 1 ); - o->box( FL_NO_BOX ); - o->color( FL_BACKGROUND_COLOR ); - o->type( Fl_Pack::VERTICAL ); - o->pack( true ); - o->end(); + { + Fl_Group *o = controls_heading = new Fl_Group( 0, 0, pack->w(), 10 ); + o->box( FL_FLAT_BOX ); + o->color( fl_color_add_alpha( fl_rgb_color( 1,1,1 ), 127 ) ); + + { + Fl_Box *o = new Fl_Box( 0,0, Track::width(), 10 ); + o->label( "Controls" ); + o->align( FL_ALIGN_RIGHT | FL_ALIGN_INSIDE ); + o->labelsize( 10 ); + } + + o->hide(); + o->end(); + o->resizable( 0 ); + } + + { + Fl_Sometimes_Pack *o = control = new Fl_Sometimes_Pack( 0, 0, pack->w(), 1 ); + o->spacing( 1 ); + o->box( FL_NO_BOX ); + o->color( FL_BACKGROUND_COLOR ); + o->type( Fl_Pack::VERTICAL ); + o->pack( true ); + o->hide(); + o->align( FL_ALIGN_TOP | FL_ALIGN_LEFT ); + o->end(); + } } { - Fl_Pack *o = takes = new Fl_Pack( width(), 0, pack->w(), 1 ); + { + Fl_Group *o = takes_heading = new Fl_Group( 0, 0, pack->w(), 10 ); + o->box( FL_FLAT_BOX ); + o->color( fl_color_add_alpha( fl_rgb_color( 1,1,1 ), 127 ) ); + + { + Fl_Box *o = new Fl_Box( 0,0, Track::width(), 10 ); + o->label( "Takes" ); + o->align( FL_ALIGN_RIGHT | FL_ALIGN_INSIDE ); + o->labelsize( 10 ); + } + o->hide(); + o->end(); + o->resizable( 0 ); + } + + { + Fl_Pack *o = takes = new Fl_Pack( 0, 0, pack->w(), 1 ); o->type( Fl_Pack::VERTICAL ); o->end(); o->hide(); + o->align( FL_ALIGN_TOP | FL_ALIGN_LEFT ); + } } o->end(); @@ -464,62 +436,131 @@ Track::adjust_size ( void ) for ( int i = control->children(); i--; ) control->child( i )->size( w(), height() ); - control->pack( ! overlay_controls() ); - - int TH = height(); - - if ( show_all_takes() ) + if ( overlay_controls() ) { - takes->show(); - TH += height() * takes->children(); - } - else - takes->hide(); + for ( int i = 0; i < control->children(); i++ ) + { + Control_Sequence *o = (Control_Sequence*)control->child(i); - if ( control->children() ) - { - control->show(); - - if ( overlay_controls() ) - TH += height() * (control->children() ? 1 : 0); - else - TH += height() * pack_visible( control ); - } + if ( i != 0 ) + o->box( FL_NO_BOX ); + + o->header()->hide(); + } + + control->pack( false ); + } else - control->hide(); - + { + for ( int i = 0; i < control->children(); i++ ) + { + Control_Sequence *o = (Control_Sequence*)control->child(i); + + o->box( FL_FLAT_BOX ); + + o->header()->show(); + } + + control->pack( true ); + } + + + int TY = 0; + if ( annotation->children() ) { annotation->show(); - TH += 24 * pack_visible( annotation ); + TY += 24 * pack_visible( annotation ); } else annotation->hide(); + /* height of the sequence */ + TY += height(); + + if ( control->children() ) + { + int TH; + + /* calculate height of control pack */ + if ( overlay_controls() ) + TH = height() * (control->children() ? 1 : 0); + else + TH = height() * pack_visible( control ); + + TY += TH; + + control->show(); + controls_heading->show(); + } + else + { + control->hide(); + controls_heading->hide(); + } + + if ( show_all_takes() ) + { + /* calculate height of takes pack */ + const int TH = height() * takes->children(); + + TY += TH; + + takes->show(); + takes_heading->show(); + } + else + { + takes_heading->hide(); + takes->hide(); + } + + if ( takes_heading->visible() ) + TY += takes_heading->h(); + if ( controls_heading->visible() ) + TY += controls_heading->h(); + + int TH; + if ( ! size() ) { takes->hide(); control->hide(); - Fl_Group::size( w(), height() ); + TH = height(); } else - Fl_Group::size( w(), TH ); + TH = TY; + Fl_Group::size( w(), TH ); + if ( sequence() ) sequence()->size( w(), height() ); - /* if ( controls->y() + controls->h() > y() + h() ) */ - /* controls->hide(); */ - /* else */ - /* controls->show(); */ - - - /* FIXME: why is this necessary? */ if ( parent() ) parent()->parent()->redraw(); } +void +Track::name ( const char *name ) +{ + if ( _name ) + free( _name ); + + _name = timeline->get_unique_track_name(name); + + if ( name_field ) + name_field->value( _name ); + + update_port_names(); +} + +const char * +Track::name ( void ) const +{ + return _name; +} + void Track::size ( int v ) { @@ -535,8 +576,13 @@ Track::size ( int v ) void Track::add ( Audio_Sequence * t ) { + t->track( this ); + takes->insert( *t, 0 ); + /* show the take header */ + t->child(0)->show(); + t->color( fl_color_average( FL_BLACK, FL_GRAY, 0.25f ) ); t->labeltype( FL_ENGRAVED_LABEL ); @@ -548,8 +594,6 @@ Track::remove ( Audio_Sequence *t ) if ( ! takes ) return; - timeline->wrlock(); - if ( sequence() == t ) { pack->remove( t ); @@ -565,8 +609,6 @@ Track::remove ( Audio_Sequence *t ) /* delete t; */ - timeline->unlock(); - adjust_size(); } @@ -587,16 +629,12 @@ Track::remove ( Control_Sequence *t ) if ( ! control ) return; - timeline->wrlock(); - engine->lock(); control->remove( t ); engine->unlock(); - timeline->unlock(); - adjust_size(); } @@ -618,6 +656,9 @@ Track::sequence ( Audio_Sequence * t ) /* insert following the annotation pack */ pack->insert( *t, 1 ); + /* hide the take header */ + t->child(0)->hide(); + t->color( FL_GRAY ); t->labeltype( FL_NO_LABEL ); @@ -735,7 +776,10 @@ Track::menu_cb ( const Fl_Menu_ *m ) } else if ( ! strcmp( picked, "/Add Control" ) ) { - new Control_Sequence( this ); + /* add audio track */ + char *name = get_unique_control_name( "Control" ); + + new Control_Sequence( this, name ); } else if ( ! strcmp( picked, "/Overlay controls" ) ) { @@ -850,6 +894,36 @@ Track::menu_cb ( const Fl_Menu_ *m ) } } +/** retrun a pointer to the control sequence named /name/, or NULL if no control sequence is named /name/ */ +Control_Sequence * +Track::control_by_name ( const char *name ) +{ + for ( int i = control->children(); i-- ; ) + { + Control_Sequence *t = (Control_Sequence*)control->child( i ); + + if ( t->name() && name && ! strcmp( name, t->name() ) ) + return t; + } + + return NULL; +} + +/** return a malloc'd string representing a unique name for a new control sequence */ +char * +Track::get_unique_control_name ( const char *name ) +{ + char pat[256]; + + strcpy( pat, name ); + + for ( int i = 1; control_by_name( pat ); ++i ) + snprintf( pat, sizeof( pat ), "%s.%d", name, i ); + + return strdup( pat ); +} + + #include "FL/menu_popup.H" /** build the context menu */ @@ -909,61 +983,11 @@ Track::menu ( void ) const #include "FL/event_name.H" #include "FL/test_press.H" -void -Track::internal_draw ( void ) -{ - draw_box(); - - pack->resize( x() + Track::width(), y(), w() - Track::width(), h() ); - - /* we have to do this first because the pack(s) size isn't known until draw() */ - draw_child( *pack ); - - - { - Track_Header *o = (Track_Header *)child( 0 ); - - o->controls_header_group->resize( x(), control->y(), o->controls_header_group->w(), control->h() ); - o->takes_header_group->resize( x(), takes->y(), o->takes_header_group->w(), takes->h() ); - - if ( takes->visible() ) - o->takes_header_group->show(); - else - o->takes_header_group->hide(); - - if ( control->visible() ) - o->controls_header_group->show(); - else - o->controls_header_group->hide(); - - /* override stupid group resize effect. */ - o->takes_header_group->child(0)->size( 195, 12 ); - o->controls_header_group->child(0)->size( 195, 12 ); - - } - - child(0)->size( Track::width(), h() ); - - draw_child( *child(0)); - - if ( takes->visible() ) - for ( int i = 0; i < takes->children(); i++ ) - draw_outside_label( *takes->child( i ) ); - - if ( control->visible() ) - for ( int i = 0; i < control->children(); i++ ) - draw_outside_label( *control->child( i ) ); -} - void Track::draw ( void ) { - int X, Y, W, H; - fl_push_clip( x(), y(), w(), h() ); - fl_clip_box( x(), y(), w(), h(), X, Y, W, H ); - Fl_Color saved_color = color(); if ( ! Track::colored_tracks ) @@ -975,12 +999,12 @@ Track::draw ( void ) color( FL_RED ); - internal_draw(); + Fl_Group::draw(); color( c ); } else - internal_draw(); + Fl_Group::draw(); if ( ! Track::colored_tracks ) color( saved_color ); diff --git a/timeline/src/Track.H b/timeline/src/Track.H index a8394af..362a806 100644 --- a/timeline/src/Track.H +++ b/timeline/src/Track.H @@ -85,8 +85,8 @@ public: } }; - Fl_Color color ( void ) const { return child(0)->color(); } - void color ( Fl_Color c ) { child(0)->color( c ); } + virtual Fl_Color color ( void ) const { return child(0)->color(); } + virtual void color ( Fl_Color c ) { child(0)->color( c ); } bool operator< ( const Track &rhs ) const { @@ -118,8 +118,6 @@ private: Track ( ); void init ( void ); - void internal_draw ( void ); - protected: void get ( Log_Entry &e ) const; @@ -130,6 +128,8 @@ protected: Fl_Sometimes_Pack *control; Fl_Blink_Button *connected_indicator; + Fl_Group *controls_heading; + Fl_Group *takes_heading; public: @@ -156,6 +156,9 @@ public: /* for loggable */ LOG_CREATE_FUNC( Track ); + Control_Sequence * control_by_name ( const char *name ); + char * get_unique_control_name ( const char *name ); + void add ( Annotation_Sequence *t ); void remove ( Annotation_Sequence *t ); @@ -175,7 +178,7 @@ public: int height ( void ) const { - static int table[] = { 27, 54, 80, 150, 300 }; + static int table[] = { 25, 54, 80, 150, 300 }; return table[ _size ]; } @@ -201,20 +204,9 @@ public: return overlay_controls_button->value(); } - void name ( const char *name ) - { - if ( _name ) - free( _name ); + void name ( const char *name ); + const char * name ( void ) const; - _name = strdup( name ); - - if ( name_field ) - name_field->value( _name ); - - update_port_names(); - } - - const char * name ( void ) const { return _name; } bool mute ( void ) const { return mute_button->value(); } void mute ( bool b ) { mute_button->value( b ); } bool solo ( void ) const { return solo_button->value(); } diff --git a/timeline/src/Track_Header.fl b/timeline/src/Track_Header.fl index 86ac2f7..8b378e2 100644 --- a/timeline/src/Track_Header.fl +++ b/timeline/src/Track_Header.fl @@ -5,116 +5,114 @@ code_name {.cxx} decl {\#include "FL/Fl_Sometimes_Input.H"} {public global } +decl {\#include "FL/Fl_Blink_Button.H"} {public global +} + widget_class Track_Header {open - xywh {384 728 200 210} type Double box THIN_UP_BOX resizable visible + xywh {635 603 525 60} type Double box NO_BOX resizable visible } { - Fl_Group {} {open - xywh {5 3 192 48} + Fl_Group box_group {open + private xywh {0 0 200 60} box THIN_UP_BOX color 63 + code0 {o->resizable(0);} } { - Fl_Input name_input { - label {input:} - xywh {5 3 192 22} labeltype NO_LABEL align 20 when 8 - class Fl_Sometimes_Input - } - Fl_Button track_inputs_indicator { - label in - tooltip {lit if inputs are connected} xywh {5 27 24 16} box BORDER_BOX color 48 selection_color 90 labelfont 5 labelsize 10 labelcolor 53 hide - } - Fl_Button track_outputs_indicator { - label out - tooltip {lit if outputs are connected} xywh {31 27 24 16} box BORDER_BOX color 48 selection_color 90 labelfont 5 labelsize 10 labelcolor 53 hide - } - Fl_Button overlay_controls_button { - label {c-} selected - tooltip {Expand controls} xywh {5 26 24 24} type Toggle selection_color 3 labelfont 5 labelsize 12 - } - Fl_Button show_all_takes_button { - label {t+} selected - tooltip {Show all takes} xywh {32 26 24 24} type Toggle selection_color 3 labelfont 5 labelsize 12 - } - Fl_Button rec_button { - label r - tooltip {arm for recording} xywh {118 26 24 24} type Toggle selection_color 88 labelfont 5 labelsize 12 - } - Fl_Button mute_button { - label m - tooltip mute xywh {145 26 24 24} type Toggle selection_color 63 labelfont 5 labelsize 12 - } - Fl_Button solo_button { - label s - tooltip solo xywh {172 26 24 24} type Toggle selection_color 91 labelfont 5 labelsize 12 - } - } - Fl_Group controls_header_group {open - xywh {5 53 195 64} labelsize 11 align 25 - } { - Fl_Box {} { - label Controls - xywh {5 53 195 12} box FLAT_BOX color 47 labelsize 9 align 24 - code0 {o->color( fl_color_add_alpha( o->color(), 127 ) );} - } - Fl_Box {} { - label spacer - xywh {5 63 195 53} labeltype NO_LABEL resizable - } - } - Fl_Group takes_header_group {open - xywh {5 115 195 55} labelsize 11 align 25 - } { - Fl_Box {} { - label Takes - xywh {5 115 195 12} box FLAT_BOX color 47 labelsize 9 align 24 - code0 {o->color( fl_color_add_alpha( o->color(), 127 ) );} - } - Fl_Box {} { - label spacer - xywh {5 126 195 40} labeltype NO_LABEL resizable + Fl_Group {} {open + xywh {0 0 200 50} + code0 {o->resizable(0);} + } { + Fl_Input name_input { + label {input:} + xywh {0 2 200 23} labeltype NO_LABEL align 20 when 8 + class Fl_Sometimes_Input + } + Fl_Button track_inputs_indicator { + label in + tooltip {lit if inputs are connected} xywh {0 27 29 16} box BORDER_BOX color 48 selection_color 90 labelfont 5 labelsize 10 labelcolor 53 hide + } + Fl_Button track_outputs_indicator { + label out + tooltip {lit if outputs are connected} xywh {31 27 24 16} box BORDER_BOX color 48 selection_color 90 labelfont 5 labelsize 10 labelcolor 53 hide + } + Fl_Button overlay_controls_button { + label {c-} + tooltip {Expand controls} xywh {5 26 24 24} type Toggle selection_color 3 labelfont 5 labelsize 12 + } + Fl_Button show_all_takes_button { + label {t+} + tooltip {Show all takes} xywh {32 26 24 24} type Toggle selection_color 3 labelfont 5 labelsize 12 + } + Fl_Button rec_button { + label r + tooltip {arm for recording} xywh {118 26 24 24} type Toggle selection_color 88 labelfont 5 labelsize 12 + } + Fl_Button mute_button { + label m + tooltip mute xywh {145 26 24 24} type Toggle selection_color 63 labelfont 5 labelsize 12 + } + Fl_Button solo_button { + label s + tooltip solo xywh {172 26 24 24} type Toggle selection_color 91 labelfont 5 labelsize 12 + } } } Fl_Box {} { - label spacer - xywh {0 165 200 45} labeltype NO_LABEL resizable + label {} + xywh {200 0 325 60} resizable + code0 {o->labeltype(FL_NO_LABEL);} + } + Function {draw()} {open return_type {virtual void} + } { + code {box_group->color( color() ); + +Fl_Group::draw();} {} } } widget_class Control_Sequence_Header {open - xywh {390 981 200 55} type Double visible + xywh {309 702 200 55} type Double box NO_BOX visible } { - Fl_Input take_name_input { - label {input:} - xywh {5 3 192 22} labeltype NO_LABEL align 20 when 8 + Fl_Input name_input { + label {input:} selected + xywh {5 3 192 22} labeltype NO_LABEL align 20 when 8 textsize 12 class Fl_Sometimes_Input } Fl_Button outputs_indicator { label out - tooltip {lit if outputs are connected} xywh {33 26 24 16} box BORDER_BOX color 48 selection_color 90 labelfont 5 labelsize 10 + tooltip {lit if outputs are connected} xywh {33 26 24 16} box BORDER_BOX down_box BORDER_BOX color 48 selection_color 90 labelfont 5 labelsize 10 + code0 {o->ignore_input( true );} + code1 {o->blink( false );} + class Fl_Blink_Button } - Fl_Output {} { - xywh {60 26 92 24} color 32 labeltype NO_LABEL align 20 textsize 9 + Fl_Output osc_name_output { + xywh {60 26 92 24} color 32 labeltype NO_LABEL align 20 textsize 9 hide } - Fl_Menu_Button {} {open - xywh {147 26 24 24} color 52 + Fl_Menu_Button osc_connect_menu {open + xywh {147 26 24 24} color 52 hide } {} - Fl_Button delete_control_button { + Fl_Button delete_button { label X - tooltip {Expand controls} xywh {172 26 24 24} color 52 labelfont 5 labelsize 12 + tooltip {Expand controls} xywh {172 26 24 24} labelfont 5 labelsize 12 } } -widget_class Take_Header {open - xywh {868 986 200 50} type Double visible +widget_class Audio_Sequence_Header {open + xywh {326 544 200 50} type Double box NO_BOX resizable visible } { - Fl_Input take_name_input { - label {input:} - xywh {5 3 193 22} labeltype NO_LABEL align 20 when 8 - class Fl_Sometimes_Input - } - Fl_Button delete_take_button { - label X - tooltip {Expand controls} xywh {172 26 24 24} color 52 labelfont 5 labelsize 12 - } - Fl_Button set_active_take_button { - label {@2} - tooltip {select this take as active sequence} xywh {147 26 24 24} color 52 labelfont 5 labelsize 12 + Fl_Group {} {open + xywh {0 0 200 55} + code0 {o->resizable(0);} + } { + Fl_Input name_input { + label {input:} selected + xywh {0 3 193 22} labeltype NO_LABEL align 20 when 8 textsize 12 + class Fl_Sometimes_Input + } + Fl_Button delete_button { + label X + tooltip {Expand controls} xywh {167 26 24 24} labelfont 5 labelsize 12 + } + Fl_Button promote_button { + label {@2} + tooltip {select this take as active sequence} xywh {142 26 24 24} labelfont 5 labelsize 12 + } } }