From b82774dcf3fa1b071b00668afed32f78ced088dc Mon Sep 17 00:00:00 2001 From: Jonathan Moore Liles Date: Thu, 23 Feb 2012 20:53:51 -0800 Subject: [PATCH] Timeline: Add interpolation mode choice of Linear and None to Control Sequences. --- timeline/src/Control_Sequence.C | 176 +++++++++++++------------ timeline/src/Control_Sequence.H | 9 +- timeline/src/Engine/Control_Sequence.C | 17 ++- 3 files changed, 107 insertions(+), 95 deletions(-) diff --git a/timeline/src/Control_Sequence.C b/timeline/src/Control_Sequence.C index 451fdd9..171eaca 100644 --- a/timeline/src/Control_Sequence.C +++ b/timeline/src/Control_Sequence.C @@ -67,6 +67,8 @@ Control_Sequence::Control_Sequence ( Track *track ) : Sequence( 0 ) if ( track ) track->add( this ); + interpolation( Linear ); + log_create(); } @@ -74,6 +76,7 @@ Control_Sequence::Control_Sequence ( Track *track ) : Sequence( 0 ) Control_Sequence::~Control_Sequence ( ) { + Fl::remove_timeout( &Control_Sequence::process_osc, this ); Loggable::block_start(); @@ -117,6 +120,12 @@ Control_Sequence::get ( Log_Entry &e ) const e.add( ":name", name() ); } +void +Control_Sequence::get_unjournaled ( Log_Entry &e ) const +{ + e.add( ":interpolation", _interpolation ); +} + void Control_Sequence::set ( Log_Entry &e ) { @@ -145,6 +154,8 @@ Control_Sequence::set ( Log_Entry &e ) } else if ( ! strcmp( ":name", s ) ) name( v ); + else if ( ! strcmp( ":interpolation", s ) ) + interpolation( (curve_type_e)atoi( v ) ); } } @@ -207,7 +218,6 @@ Control_Sequence::draw_curve ( bool flip, bool filled ) void Control_Sequence::draw ( void ) { - if ( ! fl_not_clipped( x(), y(), w(), h() ) ) return; @@ -230,64 +240,67 @@ Control_Sequence::draw ( void ) const Fl_Color color = active ? this->color() : fl_inactive( this->color() ); const Fl_Color selection_color = active ? this->selection_color() : fl_inactive( this->selection_color() ); - if ( draw_with_gradient ) - { + + if ( draw_with_gradient ) + { /* const Fl_Color c2 = fl_color_average( selection_color, FL_WHITE, 0.90f ); */ /* const Fl_Color c1 = fl_color_average( color, c2, 0.60f ); */ - const Fl_Color c1 = fl_color_average( selection_color, FL_WHITE, 0.90f ); - const Fl_Color c2 = fl_color_average( color, c1, 0.60f ); + const Fl_Color c1 = fl_color_average( selection_color, FL_WHITE, 0.90f ); + const Fl_Color c2 = fl_color_average( color, c1, 0.60f ); - for ( int gy = 0; gy < bh; gy++ ) - { - fl_color( fl_color_average( c1, c2, gy / (float)bh) ); - fl_line( X, by + gy, X + W, by + gy ); - } - } - - if ( draw_with_grid ) - { - fl_color( fl_darker( color ) ); - - const int inc = bh / 10; - if ( inc ) - for ( int gy = 0; gy < bh; gy += inc ) + for ( int gy = 0; gy < bh; gy++ ) + { + fl_color( fl_color_average( c1, c2, gy / (float)bh) ); fl_line( X, by + gy, X + W, by + gy ); + } + } - } + if ( draw_with_grid ) + { + fl_color( fl_darker( color ) ); + const int inc = bh / 10; + if ( inc ) + for ( int gy = 0; gy < bh; gy += inc ) + fl_line( X, by + gy, X + W, by + gy ); - if ( draw_with_polygon ) + } + + if ( interpolation() != None ) { - fl_color( draw_with_gradient ? color : fl_color_average( color, selection_color, 0.45f ) ); + if ( draw_with_polygon ) + { + fl_color( draw_with_gradient ? color : fl_color_average( color, selection_color, 0.45f ) ); - fl_begin_complex_polygon(); - draw_curve( draw_with_gradient, true ); - fl_end_complex_polygon(); + fl_begin_complex_polygon(); + draw_curve( draw_with_gradient, true ); + fl_end_complex_polygon(); - fl_color( selection_color ); - fl_line_style( FL_SOLID, 2 ); + fl_color( selection_color ); + fl_line_style( FL_SOLID, 2 ); - fl_begin_line(); - draw_curve( draw_with_gradient, false ); - fl_end_line(); - } - else - { + fl_begin_line(); + draw_curve( draw_with_gradient, false ); + fl_end_line(); + } + else + { // fl_color( fl_color_average( selection_color, color, 0.70f ) ); - fl_color( selection_color ); - fl_line_style( FL_SOLID, 2 ); + fl_color( selection_color ); + fl_line_style( FL_SOLID, 2 ); - fl_begin_line(); - draw_curve( draw_with_gradient, false ); - fl_end_line(); + fl_begin_line(); + draw_curve( draw_with_gradient, false ); + fl_end_line(); + } + + fl_line_style( FL_SOLID, 0 ); } - fl_line_style( FL_SOLID, 0 ); - timeline->draw_measure_lines( x(), y(), w(), h(), color ); - if ( _highlighted || Fl::focus() == this ) + if ( interpolation() == None || _highlighted || Fl::focus() == this ) for ( list ::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) (*r)->draw_box(); else @@ -316,27 +329,44 @@ Control_Sequence::menu_cb ( const Fl_Menu_ *m ) m->item_pathname( picked, sizeof( picked ), m->mvalue() ); - // DMESSAGE( "Picked: %s (%s)", picked, m->mvalue()->label() ); - - - if ( ! _osc_output ) - { - char *path; - asprintf( &path, "/non/daw/%s/control/%i", track()->name(), track()->ncontrols() ); + if ( ! strncmp( picked, "Connect To/", strlen( "Connect To/" ) ) ) + { + if ( ! _osc_output ) + { + char *path; + asprintf( &path, "/non/daw/%s/control/%i", track()->name(), track()->ncontrols() ); - _osc_output = timeline->osc->add_signal( path, OSC::Signal::Output, NULL, NULL ); + _osc_output = timeline->osc->add_signal( path, OSC::Signal::Output, NULL, NULL ); - free( path ); - } + free( path ); + } - /* FIXME: somebody has to free these unsigned longs */ - unsigned long id = *(unsigned long*)m->mvalue()->user_data(); + /* FIXME: somebody has to free these unsigned longs */ + unsigned long id = *(unsigned long*)m->mvalue()->user_data(); - char *peer_name = index( picked, '/' ) + 1; + char *peer_name = index( picked, '/' ) + 1; - *index( peer_name, '/' ) = 0; + *index( peer_name, '/' ) = 0; - timeline->osc->connect_signal( _osc_output, peer_name, id ); + timeline->osc->connect_signal( _osc_output, peer_name, id ); + } + else if ( ! strcmp( picked, "Interpolation/Linear" ) ) + interpolation( Linear ); + else if ( ! strcmp( picked, "Interpolation/None" ) ) + interpolation( None ); + else if ( ! strcmp( picked, "/Rename" ) ) + { + const char *s = fl_input( "Input new name for control sequence:", name() ); + + if ( s ) + name( s ); + + redraw(); + } + else if ( !strcmp( picked, "/Remove" ) ) + { + Fl::delete_widget( this ); + } } @@ -354,9 +384,8 @@ Control_Sequence::process_osc ( void ) if ( _osc_output && _osc_output->connected() ) { sample_t buf[1]; - - play( buf, (nframes_t)transport->frame, (nframes_t) 1 ); + play( buf, (nframes_t)transport->frame, (nframes_t) 1 ); _osc_output->value( (float)buf[0] ); } } @@ -412,42 +441,15 @@ Control_Sequence::handle ( int m ) /* menu.add( "Connect To", 0, 0, 0); */ /* menu.add( "Connect To", 0, 0, const_cast< Fl_Menu_Item *>( con->menu() ), FL_SUBMENU_POINTER ); */ + 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( "Rename", 0, 0, 0 ); menu.add( "Remove", 0, 0, 0 ); - menu.callback( &Control_Sequence::menu_cb, (void*)this); - /* Fl_Menu_Item menu[] = */ - /* { */ - /* { "Rename" }, */ - /* { "Remove" }, */ - /* { "Connect To" }, */ - - /* { 0 } */ - /* }; */ menu_popup( &menu, x(), y() ); -// const Fl_Menu_Item *r = menu.popup( Fl::event_x(), Fl::event_y(), "Control Sequence" ); - - /* if ( r ) */ - /* { */ - /* if ( r == &menu[ 0 ] ) */ - /* { */ - /* const char *s = fl_input( "Input new name for control sequence:", name() ); */ - - /* if ( s ) */ - /* name( s ); */ - - /* redraw(); */ - /* } */ - /* else if ( r == &menu[ 1 ] ) */ - /* { */ - /* Fl::delete_widget( this ); */ - /* } */ - - /* } */ - return 1; } diff --git a/timeline/src/Control_Sequence.H b/timeline/src/Control_Sequence.H index f4cc110..cbaa9e8 100644 --- a/timeline/src/Control_Sequence.H +++ b/timeline/src/Control_Sequence.H @@ -36,7 +36,7 @@ class Control_Sequence : public Sequence public: - enum curve_type_e { Linear, Quadratic }; + enum curve_type_e { None, Linear, Quadratic }; private: @@ -46,7 +46,7 @@ private: bool _highlighted; - curve_type_e _type; + curve_type_e _interpolation; void init ( void ); @@ -58,11 +58,13 @@ private: static void process_osc ( void *v ); void process_osc ( void ); + float _rate; protected: virtual void get ( Log_Entry &e ) const; + virtual void get_unjournaled ( Log_Entry &e ) const; void set ( Log_Entry &e ); Control_Sequence ( ) : Sequence( 0 ) @@ -87,6 +89,9 @@ public: Fl_Cursor cursor ( void ) const { return FL_CURSOR_CROSS; } + curve_type_e interpolation ( void ) const { return _interpolation; } + void interpolation ( curve_type_e v ) { _interpolation = v; } + /* Engine */ void output ( JACK::Port *p ) { _output = p; } nframes_t play ( sample_t *buf, nframes_t frame, nframes_t nframes ); diff --git a/timeline/src/Engine/Control_Sequence.C b/timeline/src/Engine/Control_Sequence.C index e88419e..4b78602 100644 --- a/timeline/src/Engine/Control_Sequence.C +++ b/timeline/src/Engine/Control_Sequence.C @@ -71,18 +71,23 @@ Control_Sequence::play ( sample_t *buf, nframes_t frame, nframes_t nframes ) /* do incremental linear interpolation */ const nframes_t len = p2->when() - p1->when(); - + const float y1 = 1.0f - p1->control(); const float y2 = 1.0f - p2->control(); - + const nframes_t start = frame - p1->when(); - const float incr = ( y2 - y1 ) / (float)len; - + + float incr; + + if ( interpolation() != None ) + incr = ( y2 - y1 ) / (float)len; + else + incr = 0.0f; + float v = y1 + start * incr; - + for ( nframes_t i = start; i < len && n--; ++i, v += incr ) *(buf++) = v; - } return nframes - n;