From fd9497f04449f9145539b4047c5dbb0b4f2a110b Mon Sep 17 00:00:00 2001 From: Jonathan Moore Liles Date: Thu, 29 May 2008 17:45:04 -0500 Subject: [PATCH] Implement move playhead by beat. --- Timeline/Timeline.C | 75 +++++++++++++++++++++++++++++++++++++++++---- Timeline/Timeline.H | 2 ++ 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/Timeline/Timeline.C b/Timeline/Timeline.C index b8846ac..936306f 100644 --- a/Timeline/Timeline.C +++ b/Timeline/Timeline.C @@ -239,11 +239,17 @@ Timeline::menu_cb ( Fl_Menu_ *m ) } else if ( ! strcmp( picked, "Playhead left" ) ) { -#warning unimplemented + nframes_t f = transport->frame; + + if ( prev_line( &f ) ) + transport->locate( f ); } else if ( ! strcmp( picked, "Playhead right" ) ) { -#warning unimplemented + nframes_t f = transport->frame; + + if ( next_line( &f ) ) + transport->locate( f ); } else if ( ! strcmp( picked, "Swap P1 and playhead" ) ) { @@ -440,7 +446,7 @@ abs_diff ( nframes_t n1, nframes_t n2 ) return n1 > n2 ? n1 - n2 : n2 - n1; } -void +static void nearest_line_cb ( nframes_t frame, const BBT &bbt, void *arg ) { nearest_line_arg *n = (nearest_line_arg *)arg; @@ -456,6 +462,15 @@ nearest_line_cb ( nframes_t frame, const BBT &bbt, void *arg ) n->closest = frame; } +static void +prev_next_line_cb ( nframes_t frame, const BBT &, void *arg ) +{ + nearest_line_arg *n = (nearest_line_arg *)arg; + + if ( abs_diff( frame, n->original ) < abs_diff( n->original, n->closest ) ) + n->closest = frame; +} + /** Set the value pointed to by /frame/ to the frame number of the of the nearest measure line to /when/. Returns true if the new value of *frame is valid, false otherwise. */ @@ -480,6 +495,51 @@ Timeline::nearest_line ( nframes_t *frame ) const } } +/** Set the value pointed to by /frame/ to the frame number of the of + the nearest measure line to *greater than* /when/. Returns true if + the new value of *frame is valid, false otherwise. */ +bool +Timeline::next_line ( nframes_t *frame ) const +{ + nframes_t when = *frame + 1; + + nearest_line_arg n = { when, -1 }; + + render_tempomap( when, x_to_ts( w() ), prev_next_line_cb, &n ); + + if ( n.closest == (nframes_t)-1 ) + return false; + else + { + *frame = n.closest; + return true; + } +} + + +/** Set the value pointed to by /frame/ to the frame number of the of + the nearest measure line to *less than* /when/. Returns true if + the new value of *frame is valid, false otherwise. */ +bool +Timeline::prev_line ( nframes_t *frame ) const +{ + nframes_t when = *frame - 1; + + nearest_line_arg n = { when, -1 }; + + render_tempomap( xoffset, when - xoffset, prev_next_line_cb, &n ); + + if ( n.closest == (nframes_t)-1 ) + return false; + else + { + *frame = n.closest; + return true; + } +} + + + nframes_t @@ -986,12 +1046,15 @@ Timeline::track_under ( int Y ) #include "FL/event_name.H" #include "FL/test_press.H" -/** give the scrollbars a shot at events */ +/** a bit of a hack to keep FLTK's focus navigation stuff from + * stealing the arrow keys from us */ int Timeline::handle_scroll ( int m ) { - if ( m == FL_KEYBOARD && Fl::event_key() != FL_Home && Fl::event_key() != FL_End ) - return hscroll->handle( m ) || vscroll->handle( m ); + if ( m == FL_KEYBOARD && + Fl::event_key() != FL_Home && + Fl::event_key() != FL_End ) + return menu->test_shortcut() || hscroll->handle( m ) || vscroll->handle( m ); else return 0; } diff --git a/Timeline/Timeline.H b/Timeline/Timeline.H index a08af26..0060c8e 100644 --- a/Timeline/Timeline.H +++ b/Timeline/Timeline.H @@ -155,6 +155,8 @@ public: void beats_per_minute ( nframes_t when, float bpm ); void time ( nframes_t when, int bpb, int beat_type ); bool nearest_line ( nframes_t *f ) const; + bool next_line ( nframes_t *f ) const; + bool prev_line ( nframes_t *f ) const; typedef void (measure_line_callback)( nframes_t frame, const BBT & bbt, void *arg );