diff --git a/cwIoMidiRecordPlay.cpp b/cwIoMidiRecordPlay.cpp index 780c3f9..b8db1a2 100644 --- a/cwIoMidiRecordPlay.cpp +++ b/cwIoMidiRecordPlay.cpp @@ -281,7 +281,7 @@ namespace cw rc_t _event_callback( midi_record_play_t* p, unsigned id, const time::spec_t timestamp, unsigned loc, uint8_t ch, uint8_t status, uint8_t d0, uint8_t d1, bool log_fl=true ) { rc_t rc = kOkRC; - + bool quiet_flag = true; // if we have arrived at the stop time bool after_stop_time_fl = !time::isZero(p->end_play_event_timestamp) && time::isGT(timestamp,p->end_play_event_timestamp); bool after_all_off_fl = after_stop_time_fl && time::isGT(timestamp,p->all_off_timestamp); @@ -331,8 +331,11 @@ namespace cw else if( d1 == p->midiDevA[i].pedalDownHalfVelId ) out_d1 = p->midiDevA[i].pedalDownHalfVel; - else - cwLogError(kInvalidIdRC,"Unexpected pedal down velocity (%i) during pedal velocity mapping.",d1); + else + { + if(!quiet_flag) + cwLogError(kInvalidIdRC,"Unexpected pedal down velocity (%i) during pedal velocity mapping.",d1); + } } } diff --git a/cwIoPresetSelApp.cpp b/cwIoPresetSelApp.cpp index 0c546e5..484707d 100644 --- a/cwIoPresetSelApp.cpp +++ b/cwIoPresetSelApp.cpp @@ -218,7 +218,8 @@ namespace cw unsigned locMapN; unsigned insertLoc; // last valid insert location id received from the GUI - + unsigned lastPlayedLoc; + unsigned minLoc; unsigned maxLoc; @@ -346,11 +347,14 @@ namespace cw return kOkRC; } - rc_t _apply_preset( app_t* app, const time::spec_t& ts, const preset_sel::frag_t* frag=nullptr ) + rc_t _apply_preset( app_t* app, const time::spec_t& ts, unsigned loc, const preset_sel::frag_t* frag=nullptr ) { if( frag == nullptr ) - preset_sel::track_timestamp( app->psH, ts, frag); - + { + //preset_sel::track_timestamp( app->psH, ts, frag); + preset_sel::track_loc( app->psH, loc, frag); + } + if( frag == nullptr ) cwLogInfo("No preset fragment was found for the requested timestamp."); else @@ -445,13 +449,21 @@ namespace cw if( midi_record_play::is_started(app->mrpH) ) { const preset_sel::frag_t* f = nullptr; - if( preset_sel::track_timestamp( app->psH, timestamp, f ) ) - { - //printf("NEW FRAG: id:%i loc:%i\n", f->fragId, f->endLoc ); - _apply_preset( app, timestamp, f ); + //if( preset_sel::track_timestamp( app->psH, timestamp, f ) ) - if( f != nullptr ) - _do_select_frag( app, f->guiUuId ); + + // ZERO SHOULD BE A VALID LOC VALUE - MAKE -1 THE INVALID LOC VALUE + + if( loc != 0 ) + { + if( preset_sel::track_loc( app->psH, loc, f ) ) + { + //printf("NEW FRAG: id:%i loc:%i\n", f->fragId, f->endLoc ); + _apply_preset( app, timestamp, loc, f ); + + if( f != nullptr ) + _do_select_frag( app, f->guiUuId ); + } } } break; @@ -498,6 +510,7 @@ namespace cw bool rewindFl = true; loc_map_t* begMap = nullptr; loc_map_t* endMap = nullptr; + unsigned cur_loc = 0; // if the player is already playing then stop it if( midi_record_play::is_started(app->mrpH) ) @@ -537,7 +550,7 @@ namespace cw } // apply the preset which is active at the start time - if((rc = _apply_preset( app, app->beg_play_timestamp )) != kOkRC ) + if((rc = _apply_preset( app, app->beg_play_timestamp, app->beg_play_loc )) != kOkRC ) { rc = cwLogError(rc,"Preset application failed prior to MIDI start."); goto errLabel; @@ -550,8 +563,11 @@ namespace cw goto errLabel; } - - io::uiSendValue( app->ioH, uiFindElementUuId(app->ioH,kCurMidiEvtCntId), midi_record_play::event_loc(app->mrpH) ); + if((cur_loc = midi_record_play::event_loc(app->mrpH)) > app->lastPlayedLoc ) + { + io::uiSendValue( app->ioH, uiFindElementUuId(app->ioH,kCurMidiEvtCntId), cur_loc ); + app->lastPlayedLoc = cur_loc; + } errLabel: return rc; @@ -1878,7 +1894,15 @@ namespace cw { midi_record_play::exec( app->mrpH, *m ); if( midi_record_play::is_started(app->mrpH) ) - io::uiSendValue( app->ioH, uiFindElementUuId(app->ioH,kCurMidiEvtCntId), midi_record_play::event_loc(app->mrpH) ); + { + unsigned cur_loc = midi_record_play::event_loc(app->mrpH); + if( cur_loc > app->lastPlayedLoc ) + { + io::uiSendValue( app->ioH, uiFindElementUuId(app->ioH,kCurMidiEvtCntId), cur_loc ); + app->lastPlayedLoc = cur_loc; + } + + } } if( app->ioFlowH.isValid() ) diff --git a/cwPresetSel.cpp b/cwPresetSel.cpp index d5a7b55..7c468c5 100644 --- a/cwPresetSel.cpp +++ b/cwPresetSel.cpp @@ -200,6 +200,56 @@ namespace cw return nullptr; } + + + + + bool _loc_is_in_frag( const frag_t* f, unsigned loc ) + { + // if f is the earliest fragment + if( f->prev == nullptr ) + return loc <= f->endLoc; + + // else f->prev->end_loc < loc && loc <= f->end_loc + return f->prev->endLoc < loc && loc <= f->endLoc; + } + + bool _loc_is_before_frag( const frag_t* f, unsigned loc ) + { + // if loc is past f + if( loc > f->endLoc ) + return false; + + // loc may now only be inside or before f + + // if f is the first frag then loc must be inside it + if( f->prev == nullptr ) + return false; + + // is loc before f + return loc <= f->prev->endLoc; + } + + bool _loc_is_after_frag( const frag_t* f, unsigned loc ) + { + return loc > f->endLoc; + } + + // Scan from through the fragment list to find the fragment containing loc. + frag_t* _fast_loc_to_frag( preset_sel_t* p, unsigned loc, frag_t* init_frag=nullptr ) + { + frag_t* f = init_frag==nullptr ? p->fragL : init_frag; + for(; f!=nullptr; f=f->link) + if( _loc_is_in_frag(f,loc) ) + return f; + + return nullptr; + } + + + + + rc_t _validate_preset_id( const frag_t* frag, unsigned preset_id ) @@ -826,6 +876,51 @@ bool cw::preset_sel::track_timestamp( handle_t h, const time::spec_t& ts, const return frag_changed_fl; } + +void cw::preset_sel::track_loc_reset( handle_t h ) +{ + preset_sel_t* p = _handleToPtr(h); + p->last_ts_frag = nullptr; +} + +bool cw::preset_sel::track_loc( handle_t h, unsigned loc, const cw::preset_sel::frag_t*& frag_Ref ) +{ + preset_sel_t* p = _handleToPtr(h); + frag_t* f = nullptr; + bool frag_changed_fl = false; + + + // if this is the first call to 'track_timestamp()'. + if( p->last_ts_frag == nullptr ) + f = _fast_loc_to_frag(p,loc); + else + // if the 'ts' is in the same frag as previous call. + if( _loc_is_in_frag(p->last_ts_frag,loc) ) + f = p->last_ts_frag; + else + // if 'ts' is in a later frag + if( _loc_is_after_frag(p->last_ts_frag,loc) ) + f = _fast_loc_to_frag(p,loc,p->last_ts_frag); + else // ts is prior to 'last_ts_frag' + f = _fast_loc_to_frag(p,loc); + + // 'f' will be null at this point if 'ts' is past the last preset. + // In this case we should leave 'last_ts_frag' unchanged. + + // if 'f' is valid but different from 'last_ts_frag' + if( f != nullptr && f != p->last_ts_frag ) + { + p->last_ts_frag = f; + frag_changed_fl = true; + } + + frag_Ref = p->last_ts_frag; + + return frag_changed_fl; +} + + + unsigned cw::preset_sel::fragment_play_preset_index( const frag_t* frag, unsigned preset_seq_idx ) { unsigned n = 0; diff --git a/cwPresetSel.h b/cwPresetSel.h index c9131b9..e99f0cb 100644 --- a/cwPresetSel.h +++ b/cwPresetSel.h @@ -115,6 +115,9 @@ namespace cw void track_timestamp_reset( handle_t h ); bool track_timestamp( handle_t h, const time::spec_t& ts, const cw::preset_sel::frag_t*& frag_Ref ); + void track_loc_reset( handle_t h ); + bool track_loc( handle_t h, unsigned loc, const cw::preset_sel::frag_t*& frag_Ref ); + // Return the preset index marked to play on this fragment. unsigned fragment_play_preset_index( const frag_t* frag, unsigned preset_seq_idx=kInvalidIdx );