diff --git a/gui/ui.fl b/gui/ui.fl index 2cb7d2e..28af73a 100644 --- a/gui/ui.fl +++ b/gui/ui.fl @@ -55,6 +55,8 @@ handle_midi_input(); lash.process(); +ui->progress_group->do_callback(); + ui->vmetro_widget->update(); if ( transport.rolling ) @@ -134,7 +136,7 @@ if ( Fl::event() == FL_SHORTCUT && Fl::event_key() == FL_Escape ) if ( maybe_save_song() ) quit();} open - xywh {635 48 869 801} type Single box PLASTIC_UP_BOX color 37 resizable xclass non size_range {869 801 0 0} visible + xywh {790 38 869 801} type Single box PLASTIC_UP_BOX color 37 resizable xclass non size_range {869 801 0 0} visible } { Fl_Menu_Bar {} {open xywh {0 0 869 30} color 37 @@ -381,11 +383,11 @@ if ( o->value() == pattern_tab ) } { Fl_Group sequence_tab { label Sequence open - xywh {0 98 868 674} color 37 hide resizable + xywh {0 98 868 674} color 37 resizable code0 {update_sequence_widgets();} } { Fl_Group {} {open - xywh {10 125 233 502} + xywh {10 125 233 502} labelsize 12 } { Fl_Browser playlist_browser { label Playlist @@ -449,7 +451,7 @@ else Fl_Input sequence_name_field { label {name:} callback {playlist->name( o->value() );} - xywh {9 635 151 26} color 36 align 20 when 1 textcolor 32 + xywh {91 740 158 26} color 36 align 20 when 1 textcolor 32 } Fl_Light_Button detach_button { label Detach @@ -466,12 +468,12 @@ else tabs->insert( (Fl_Widget&)*sequence_tab, 0 ); sequence_tab->resize( pattern_tab->x(), pattern_tab->y(), pattern_tab->w(), pattern_tab->h() ); }} - xywh {165 639 78 26} + xywh {7 740 78 26} } Fl_Text_Editor sequence_notes_edit { label {Notes:} callback {playlist->notes( o->buffer()->text() );} - xywh {16 686 844 78} selection_color 48 labelsize 12 align 5 textcolor 94 + xywh {254 691 606 73} selection_color 48 labelsize 12 align 5 textcolor 94 code0 {o->buffer( sequence_notes_buffer = new Fl_Text_Buffer );} } Fl_Box triggers_widget { @@ -480,6 +482,29 @@ else code0 {o->box( FL_NO_BOX );} class Triggers } + Fl_Group progress_group { + callback {if ( ! o->visible_r() ) + return; + +phrase *p = phrase::phrase_by_number( playlist->playing() ); + +if ( p ) + phrase_progress->value( p->index() / (double)p->length() ); + +if ( playlist->length() ) + sequence_progress->value( playlist->index() / (double)playlist->length() );} open + xywh {10 656 233 66} + } { + Fl_Slider phrase_progress { + label Phrase + xywh {10 656 233 24} type Horizontal labelsize 12 align 1 + } + Fl_Slider sequence_progress { + label Sequence + callback {transport.locate( (tick_t)((double)playlist->length() * o->value()) );} selected + xywh {10 698 233 24} type Horizontal labelsize 12 align 1 + } + } } Fl_Group phrase_tab { label Phrase open @@ -531,7 +556,7 @@ o->maximum( phrase::phrases() );} } Fl_Group pattern_tab { label Pattern open - xywh {0 98 868 674} color 37 + xywh {0 98 868 674} color 37 hide code0 {update_pattern_widgets();} } { Fl_Box pattern_canvas_widget { @@ -636,7 +661,7 @@ if ( 0 == strncmp( picked, "Scale", strlen( "Scale" ) ) ) pattern_c->changed_mapping(); pattern_key_combo->activate(); -}} open selected +}} open xywh {609 734 30 24} labeltype NO_LABEL code0 {update_mapping_menu();} } { @@ -1074,7 +1099,8 @@ if ( g->notes() ) else phrase_notes_buffer->text( strdup( "" ) );} {} } - Function {update_sequence_widgets()} {} { + Function {update_sequence_widgets()} {open + } { code {if ( playlist->notes() ) sequence_notes_buffer->text( playlist->notes() ); else diff --git a/sequence.C b/sequence.C index 4922eff..100bd34 100644 --- a/sequence.C +++ b/sequence.C @@ -112,8 +112,9 @@ sequence::remove ( int n ) unlock(); } +/** return the number of phrases in this sequence */ int -sequence::length ( void ) const +sequence::phrases ( void ) const { return _rd->num; } @@ -204,6 +205,10 @@ sequence::play ( tick_t start, tick_t end ) const if ( pend > start ) { // FIXME: don't really need to trigger more than once! + _playing = p->number(); + + _index = start; + p->trigger( pstart, pend ); p->play( start, end ); break; @@ -216,6 +221,39 @@ sequence::play ( tick_t start, tick_t end ) const } } +/** return the number of the currently playing phrase, or 0 if none. */ +int +sequence::playing ( void ) const +{ + return _playing; +} + +/** return the location of the playhead for this sequence */ +tick_t +sequence::index ( void ) const +{ + return _index; +} + +/** return the total length of the sequence in ticks */ +tick_t +sequence::length ( void ) const +{ + tick_t l = 0; + + for ( int i = 0; i < _rd->num; i++ ) + { + phrase *p = phrase::phrase_by_number( _rd->phrases[ i ] ); + + if ( ! p ) + break; + + l += p->length(); + } + + return l; +} + /** return to a blank slate */ void sequence::reset ( void ) diff --git a/sequence.H b/sequence.H index 38c9942..322535a 100644 --- a/sequence.H +++ b/sequence.H @@ -47,6 +47,9 @@ class sequence : public trackable { char * _name; char * _notes; + mutable volatile int _playing; + mutable volatile tick_t _index; + void lock ( void ); void unlock ( void ); @@ -65,11 +68,14 @@ public: void insert ( unsigned int n, int pn ); void remove ( int n ); void move ( int n, int dir ); - int length ( void ) const; + int phrases ( void ) const; char * dump ( void ); bool load ( const char *name ); void save ( const char *name ) const; void play ( tick_t start, tick_t end ) const; + int playing ( void ) const; + tick_t index ( void ) const; + tick_t length ( void ) const; char * name ( void ) const; void name ( const char *s ); diff --git a/transport.C b/transport.C index cc71b4f..19eac03 100644 --- a/transport.C +++ b/transport.C @@ -21,6 +21,8 @@ #include #include +#include + #include "transport.H" #include "common.h" #include "const.h" @@ -47,6 +49,9 @@ Transport::timebase ( jack_transport_state_t state, jack_nframes_t nframes, jack pos->beats_per_minute = transport._master_beats_per_minute; + + // FIXME: there's some problem with relocation when we're the master... + if ( new_pos || ! _done ) { double wallclock = pos->frame / (pos->frame_rate * 60); @@ -168,8 +173,11 @@ Transport::toggle ( void ) void Transport::locate ( tick_t ticks ) { - MESSAGE( "Relocating transport" ); - jack_transport_locate( client, ticks ); + jack_nframes_t frame = trunc( ticks * transport.frames_per_tick ); + + MESSAGE( "Relocating transport to %lu, %lu", ticks, frame ); + + jack_transport_locate( client, frame ); } void