diff --git a/Timeline/Clock.H b/Timeline/Clock.H index 3d8e141..b4ffb78 100644 --- a/Timeline/Clock.H +++ b/Timeline/Clock.H @@ -32,6 +32,7 @@ const float CLOCK_UPDATE_FREQ = 0.06f; /* TODO: frames per second? */ +#include "Sequence_Widget.H" class Clock : public Fl_Widget { @@ -93,7 +94,9 @@ public: static void frame_to_BBT ( char *dst, int n, nframes_t frame ) { - snprintf( dst, n, "unimplemented" ); + struct BBT bbt = timeline->solve_tempomap( frame ); + + snprintf( dst, n, "%03d:%1d:%04d", bbt.bar + 1, bbt.beat + 1 , bbt.tick ); } diff --git a/Timeline/Sequence_Widget.H b/Timeline/Sequence_Widget.H index ca3306e..b9aeeb2 100644 --- a/Timeline/Sequence_Widget.H +++ b/Timeline/Sequence_Widget.H @@ -61,6 +61,10 @@ struct Range { length += n; } + + Range ( ) : start( 0 ), offset( 0 ), length( 0 ) + { + } }; /* Used by time/tempo points or any other child of Sequence_Widget @@ -71,6 +75,10 @@ struct BBT unsigned short bar; unsigned char beat; unsigned short tick; + + BBT ( ) : bar( 0 ), beat( 0 ), tick( 0 ) + { + } }; @@ -242,31 +250,31 @@ public: _drag = NULL; } - void - start ( nframes_t where ) - { +/* void */ +/* start ( nframes_t where ) */ +/* { */ - if ( ! selected() ) - { - redraw(); - _r->start = where; - } - else - { - long d = where - _r->start; +/* if ( ! selected() ) */ +/* { */ +/* redraw(); */ +/* _r->start = where; */ +/* } */ +/* else */ +/* { */ +/* long d = where - _r->start; */ - for ( list ::iterator i = _selection.begin(); i != _selection.end(); i++ ) - { - (*i)->redraw(); +/* for ( list ::iterator i = _selection.begin(); i != _selection.end(); i++ ) */ +/* { */ +/* (*i)->redraw(); */ - if ( d < 0 ) - (*i)->_r->start -= 0 - d; - else - (*i)->_r->start += d; +/* if ( d < 0 ) */ +/* (*i)->_r->start -= 0 - d; */ +/* else */ +/* (*i)->_r->start += d; */ - } - } - } +/* } */ +/* } */ +/* } */ int dispatch ( int m ); @@ -317,7 +325,7 @@ public: void sequence ( Sequence *t ) { _sequence = t; } nframes_t start ( void ) const { return _r->start; } -// void start ( nframes_t o ) { _r->start = o; } + void start ( nframes_t o ) { _r->start = o; } void length ( nframes_t v ) { _r->length = v; } virtual nframes_t length ( void ) const { return _r->length; } diff --git a/Timeline/Tempo_Point.H b/Timeline/Tempo_Point.H index b11dac0..03578e0 100644 --- a/Timeline/Tempo_Point.H +++ b/Timeline/Tempo_Point.H @@ -26,6 +26,8 @@ class Tempo_Point : public Sequence_Point { float _tempo; + BBT _bbt; + void _make_label ( void ) { @@ -51,6 +53,8 @@ public: static bool edit ( float *tempo ); + const BBT * bbt ( void ) const { return &_bbt; } + Tempo_Point ( nframes_t when, float bpm ); ~Tempo_Point ( ); @@ -58,6 +62,7 @@ public: Tempo_Point ( const Tempo_Point &rhs ) : Sequence_Point( rhs ) { _tempo = rhs._tempo; + _bbt = rhs._bbt; log_create(); } diff --git a/Timeline/Time_Point.H b/Timeline/Time_Point.H index f287acc..c3198d5 100644 --- a/Timeline/Time_Point.H +++ b/Timeline/Time_Point.H @@ -27,16 +27,12 @@ struct time_sig int beats_per_bar; int beat_type; - time_sig ( ) + time_sig ( ) : beats_per_bar( 0 ), beat_type( 0 ) { - beats_per_bar = 0; - beat_type = 0; } - time_sig ( int bpb, int note ) + time_sig ( int bpb, int note ) : beats_per_bar( bpb ), beat_type( note ) { - beats_per_bar = bpb; - beat_type = note; } }; diff --git a/Timeline/Timeline.C b/Timeline/Timeline.C index 8a58e47..b205a21 100644 --- a/Timeline/Timeline.C +++ b/Timeline/Timeline.C @@ -313,10 +313,9 @@ Timeline::nearest_line ( nframes_t when, nframes_t *frame ) const nearest_line_arg n = { when, -1 }; /* FIXME: handle snap to bar */ - draw_measure( when - x_to_ts( 10 ), 0, 20, 0, (Fl_Color)0, nearest_line_cb, &n, false ); + draw_measure( when - x_to_ts( 10 ), 0, 20, 0, (Fl_Color)0, nearest_line_cb, frame ); *frame = n.closest; - return *frame != (nframes_t)-1; } @@ -340,9 +339,102 @@ draw_measure_cb ( nframes_t frame, int X, int Y, int H, void *arg ) fl_line( X, Y, X, Y + H ); } +#if 0 +/* we cache measure lines by rendering them to these structures. */ +struct Measure_Line +{ + /* it's easier to use this than a pixel coord, because the snapping + * code requires a frame number to be precise. */ + nframes_t frame; + + bool bar; /* is this a bar line, or just a beat? */ +}; +#endif + +BBT +Timeline::solve_tempomap ( nframes_t when ) +{ + +/* if ( ! tempo_track->_widgets.size() || ! time_track->_widgets.size() ) */ +/* { */ +/* DWARNING( "No tempo/time points" ); */ +/* return; */ +/* } */ + + const nframes_t samples_per_minute = sample_rate() * 60; + + list tempo_map; + + /* merge time and tempo maps into one list for convenience */ + + for ( list ::iterator i = tempo_track->_widgets.begin(); + i != tempo_track->_widgets.end(); ++i ) + tempo_map.push_back( *i ); + + for ( list ::iterator i = time_track->_widgets.begin(); + i != time_track->_widgets.end(); ++i ) + tempo_map.push_back( *i ); + + tempo_map.sort( Sequence_Widget::sort_func ); + + float bpm = 120.0f; + + time_sig sig; + + sig.beats_per_bar = 4; + sig.beat_type = 4; + + BBT bbt; + + nframes_t f = 0; + + nframes_t beat_inc = samples_per_minute / bpm; + + for ( list ::iterator i = tempo_map.begin(); + i != tempo_map.end(); ++i ) + { + nframes_t next; + + { + list ::iterator n = i; + ++n; + + next = n != tempo_map.end() ? (*n)->start() : when; + } + + if ( ! strcmp( (*i)->class_name(), "Tempo_Point" ) ) + { + const Tempo_Point *p = (Tempo_Point*)(*i); + + bpm = p->tempo(); + beat_inc = samples_per_minute / bpm; + } + else + { + const Time_Point *p = (Time_Point*)(*i); + + sig = p->time(); + } + + for ( ; f < next; f += beat_inc ) + { + if ( ++bbt.beat == sig.beats_per_bar ) + { + bbt.beat = 0; + ++bbt.bar; + } + } + +// const int x = ts_to_x( f - xoffset ) + Track::width(); + if ( f >= when ) + return bbt; + } +} + + /** draw appropriate measure lines inside the given bounding box */ void -Timeline::draw_measure ( nframes_t when, int Y, int W, int H, Fl_Color color, measure_line_callback * cb, void *arg, bool BBT ) const +Timeline::draw_measure ( nframes_t when, int Y, int W, int H, Fl_Color color, measure_line_callback * cb, void *arg ) const { if ( ! draw_with_measure_lines ) return; @@ -368,35 +460,39 @@ Timeline::draw_measure ( nframes_t when, int Y, int W, int H, Fl_Color color, me /* W += 40; */ /* } */ - list ::const_iterator tpi; list ::const_iterator mpi; /* find the first points before our range */ - for ( list ::const_reverse_iterator i = tempo_track->_widgets.rbegin(); - i != tempo_track->_widgets.rend(); i++ ) - if ( (*i)->start() <= when ) - { - tpi = i.base(); - break; - } +/* for ( list ::const_reverse_iterator i = tempo_track->_widgets.rbegin(); */ +/* i != tempo_track->_widgets.rend(); i++ ) */ +/* if ( (*i)->start() <= when ) */ +/* { */ +/* tpi = i.base(); */ +/* break; */ +/* } */ - for ( list ::const_reverse_iterator i = time_track->_widgets.rbegin(); - i != time_track->_widgets.rend(); i++ ) - if ( (*i)->start() <= when ) - { - mpi = i.base(); - break; - } +/* for ( list ::const_reverse_iterator i = time_track->_widgets.rbegin(); */ +/* i != time_track->_widgets.rend(); i++ ) */ +/* if ( (*i)->start() <= when ) */ +/* { */ +/* mpi = i.base(); */ +/* break; */ +/* } */ - --tpi; +/* --tpi; */ + + /* start from the beginnnig */ + /* FIXME: find a closer place to start */ + list ::const_iterator tpi = tempo_track->_widgets.begin(); /* start on the next beat */ const Tempo_Point *tp = (Tempo_Point*)(*tpi); nframes_t beat_inc = samples_per_minute / tp->tempo(); - nframes_t f = when - ( ( when - tp->start() ) % beat_inc ); + nframes_t f = 0; +/* nframes_t f = when - ( ( when - tp->start() ) % beat_inc ); */ for ( ; tpi != tempo_track->_widgets.end(); ++tpi ) { @@ -422,6 +518,13 @@ Timeline::draw_measure ( nframes_t when, int Y, int W, int H, Fl_Color color, me const int x = ts_to_x( f - xoffset ) + Track::width(); cb( f, x, Y, H, arg ); + +/* BBT bbt; */ + +/* bbt = const_cast< Timeline* >(this)->solve_tempomap( f ); */ + +/* printf( "%d:%d:%d\n", bbt.bar, bbt.beat, bbt.tick ); */ + } } @@ -431,7 +534,7 @@ Timeline::draw_measure ( nframes_t when, int Y, int W, int H, Fl_Color color, me void Timeline::draw_measure_lines ( int X, int Y, int W, int H, Fl_Color color ) { - draw_measure( x_to_offset( X ), Y, W, H, color, draw_measure_cb, 0, false ); + draw_measure( x_to_offset( X ), Y, W, H, color, draw_measure_cb, 0 ); } /** just like draw mesure lines except that it also draws the BBT values. */ diff --git a/Timeline/Timeline.H b/Timeline/Timeline.H index de3f8ab..38edef6 100644 --- a/Timeline/Timeline.H +++ b/Timeline/Timeline.H @@ -42,6 +42,7 @@ extern Timeline *timeline; #include "Sequence.H" +struct BBT; class Tempo_Sequence; class Time_Sequence; class Annotation_Sequence; @@ -149,9 +150,10 @@ public: typedef void (measure_line_callback)( nframes_t frame, int X, int Y, int H, void *arg ); + BBT solve_tempomap ( nframes_t when ); void draw_measure_lines ( int X, int Y, int W, int H, Fl_Color color ); void draw_measure_BBT ( int X, int Y, int W, int H, Fl_Color color ); - void draw_measure ( nframes_t when, int Y, int W, int H, Fl_Color color, measure_line_callback *cb, void *arg, bool BBT ) const; + void draw_measure ( nframes_t when, int Y, int W, int H, Fl_Color color, measure_line_callback *cb, void *arg ) const; void xposition ( int X ); void yposition ( int Y );