cwIoPresetSelApp.h/cpp : 'flow_proc_dict' is now read from an external file. Added 'live' option to select a preset while streaming live audio.

This commit is contained in:
kevin 2022-10-26 08:49:20 -04:00
parent d8e4109baf
commit 714817bfb6
3 changed files with 84 additions and 16 deletions

View File

@ -40,6 +40,7 @@ namespace cw
kStartBtnId, kStartBtnId,
kStopBtnId, kStopBtnId,
kLiveCheckId,
kPrintMidiCheckId, kPrintMidiCheckId,
kPianoMidiCheckId, kPianoMidiCheckId,
@ -105,8 +106,8 @@ namespace cw
enum enum
{ {
kPiano_MRP_DevIdx = 0, kPiano_MRP_DevIdx = 1,
kSampler_MRP_DevIdx = 1 kSampler_MRP_DevIdx = 0
}; };
enum enum
@ -126,6 +127,7 @@ namespace cw
{ kPanelDivId, kStartBtnId, "startBtnId" }, { kPanelDivId, kStartBtnId, "startBtnId" },
{ kPanelDivId, kStopBtnId, "stopBtnId" }, { kPanelDivId, kStopBtnId, "stopBtnId" },
{ kPanelDivId, kLiveCheckId, "liveCheckId" },
{ kPanelDivId, kPrintMidiCheckId, "printMidiCheckId" }, { kPanelDivId, kPrintMidiCheckId, "printMidiCheckId" },
{ kPanelDivId, kPianoMidiCheckId, "pianoMidiCheckId" }, { kPanelDivId, kPianoMidiCheckId, "pianoMidiCheckId" },
@ -209,6 +211,7 @@ namespace cw
const object_t* midi_play_record_cfg; const object_t* midi_play_record_cfg;
const object_t* frag_panel_cfg; const object_t* frag_panel_cfg;
const object_t* presets_cfg; const object_t* presets_cfg;
object_t* flow_proc_dict;
const object_t* flow_cfg; const object_t* flow_cfg;
midi_record_play::handle_t mrpH; midi_record_play::handle_t mrpH;
@ -250,12 +253,15 @@ namespace cw
unsigned seqFragId; // unsigned seqFragId; //
unsigned seqPresetIdx; // unsigned seqPresetIdx; //
bool useLiveMidiFl;
} app_t; } app_t;
rc_t _parseCfg(app_t* app, const object_t* cfg, const object_t*& params_cfgRef ) rc_t _parseCfg(app_t* app, const object_t* cfg, const object_t*& params_cfgRef )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
const char* flow_proc_dict_fn = nullptr;
if((rc = cfg->getv( "params", params_cfgRef, if((rc = cfg->getv( "params", params_cfgRef,
"flow", app->flow_cfg)) != kOkRC ) "flow", app->flow_cfg)) != kOkRC )
@ -268,6 +274,7 @@ namespace cw
"record_fn", app->record_fn, "record_fn", app->record_fn,
"record_fn_ext", app->record_fn_ext, "record_fn_ext", app->record_fn_ext,
"score_fn", app->scoreFn, "score_fn", app->scoreFn,
"flow_proc_dict_fn",flow_proc_dict_fn,
"midi_play_record", app->midi_play_record_cfg, "midi_play_record", app->midi_play_record_cfg,
"frag_panel", app->frag_panel_cfg, "frag_panel", app->frag_panel_cfg,
"presets", app->presets_cfg, "presets", app->presets_cfg,
@ -291,6 +298,12 @@ namespace cw
goto errLabel; goto errLabel;
} }
if((rc = objectFromFile( flow_proc_dict_fn, app->flow_proc_dict )) != kOkRC )
{
rc = cwLogError(kInvalidArgRC,"The flow proc file '%s' parse failed.",app->flow_proc_dict);
goto errLabel;
}
// verify that the output directory exists // verify that the output directory exists
if((rc = filesys::isDir(app->record_dir)) != kOkRC ) if((rc = filesys::isDir(app->record_dir)) != kOkRC )
if((rc = filesys::makeDir(app->record_dir)) != kOkRC ) if((rc = filesys::makeDir(app->record_dir)) != kOkRC )
@ -338,6 +351,9 @@ namespace cw
rc_t _free( app_t& app ) rc_t _free( app_t& app )
{ {
if( app.flow_proc_dict != nullptr )
app.flow_proc_dict->free();
mem::release((char*&)app.record_dir); mem::release((char*&)app.record_dir);
mem::release((char*&)app.scoreFn); mem::release((char*&)app.scoreFn);
preset_sel::destroy(app.psH); preset_sel::destroy(app.psH);
@ -475,6 +491,46 @@ namespace cw
} }
} }
rc_t _on_live_midi( app_t* app, const io::msg_t& msg )
{
rc_t rc = kOkRC;
if( msg.u.midi != nullptr )
{
const io::midi_msg_t& m = *msg.u.midi;
const midi::packet_t* pkt = m.pkt;
// for each midi msg
for(unsigned j=0; j<pkt->msgCnt; ++j)
{
// if this is a sys-ex msg
if( pkt->msgArray == NULL )
{
cwLogError(kNotImplementedRC,"Sys-ex recording not implemented.");
}
else // this is a triple
{
midi::msg_t* mm = pkt->msgArray + j;
time::spec_t timestamp;
unsigned id = kInvalidId;
unsigned loc = app->beg_play_loc;
time::get(timestamp);
if( midi::isChStatus(mm->status) )
{
if(midi_record_play::send_midi_msg( app->mrpH, kSampler_MRP_DevIdx, mm->status & 0x0f, mm->status & 0xf0, mm->d0, mm->d1 ) == kOkRC )
_midi_play_callback( app, midi_record_play::kMidiEventActionId, id, timestamp, loc, mm->status & 0x0f, mm->status & 0xf0, mm->d0, mm->d1 );
}
}
}
}
return rc;
}
// Find the closest locMap equal to or after 'loc' // Find the closest locMap equal to or after 'loc'
loc_map_t* _find_loc( app_t* app, unsigned loc ) loc_map_t* _find_loc( app_t* app, unsigned loc )
{ {
@ -542,7 +598,7 @@ namespace cw
app->end_play_timestamp = endMap->timestamp; app->end_play_timestamp = endMap->timestamp;
if( !time::isZero(app->beg_play_timestamp) ) if( !time::isZero(app->beg_play_timestamp) && !app->useLiveMidiFl )
{ {
// seek the player to the requested loc // seek the player to the requested loc
if((rc = midi_record_play::seek( app->mrpH, app->beg_play_timestamp )) != kOkRC ) if((rc = midi_record_play::seek( app->mrpH, app->beg_play_timestamp )) != kOkRC )
@ -561,15 +617,18 @@ namespace cw
} }
// start the MIDI playback // start the MIDI playback
if((rc = midi_record_play::start(app->mrpH,rewindFl,&app->end_play_timestamp)) != kOkRC ) if( !app->useLiveMidiFl )
{ {
rc = cwLogError(rc,"MIDI start failed."); if((rc = midi_record_play::start(app->mrpH,rewindFl,&app->end_play_timestamp)) != kOkRC )
goto errLabel; {
} rc = cwLogError(rc,"MIDI start failed.");
goto errLabel;
}
if((cur_loc = midi_record_play::event_loc(app->mrpH)) > 0 ) if((cur_loc = midi_record_play::event_loc(app->mrpH)) > 0 )
{ {
io::uiSendValue( app->ioH, uiFindElementUuId(app->ioH,kCurMidiEvtCntId), cur_loc ); io::uiSendValue( app->ioH, uiFindElementUuId(app->ioH,kCurMidiEvtCntId), cur_loc );
}
} }
errLabel: errLabel:
@ -1236,6 +1295,7 @@ namespace cw
// enable the start/stop buttons // enable the start/stop buttons
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStartBtnId ), true ); io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStartBtnId ), true );
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStopBtnId ), true ); io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStopBtnId ), true );
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kLiveCheckId ), true );
// restore the fragment records // restore the fragment records
if( firstLoadFl ) if( firstLoadFl )
@ -1570,6 +1630,7 @@ namespace cw
// disable start and stop buttons until a score is loaded // disable start and stop buttons until a score is loaded
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStartBtnId ), false ); io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStartBtnId ), false );
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStopBtnId ), false ); io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStopBtnId ), false );
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kLiveCheckId ), false );
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kSaveBtnId ), false ); io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kSaveBtnId ), false );
const preset_sel::frag_t* f = preset_sel::get_fragment_base( app->psH ); const preset_sel::frag_t* f = preset_sel::get_fragment_base( app->psH );
@ -1628,6 +1689,10 @@ namespace cw
_do_stop_play(app); _do_stop_play(app);
break; break;
case kLiveCheckId:
app->useLiveMidiFl = m.value->u.b;
break;
case kPrintMidiCheckId: case kPrintMidiCheckId:
app->printMidiFl = m.value->u.b; app->printMidiFl = m.value->u.b;
break; break;
@ -1899,7 +1964,7 @@ namespace cw
rc_t rc = kOkRC; rc_t rc = kOkRC;
app_t* app = reinterpret_cast<app_t*>(arg); app_t* app = reinterpret_cast<app_t*>(arg);
if( app->mrpH.isValid() ) if( app->mrpH.isValid() && !app->useLiveMidiFl )
{ {
midi_record_play::exec( app->mrpH, *m ); midi_record_play::exec( app->mrpH, *m );
if( midi_record_play::is_started(app->mrpH) ) if( midi_record_play::is_started(app->mrpH) )
@ -1928,6 +1993,8 @@ namespace cw
break; break;
case io::kMidiTId: case io::kMidiTId:
if( app->useLiveMidiFl && app->mrpH.isValid() )
_on_live_midi( app, *m );
break; break;
case io::kAudioTId: case io::kAudioTId:
@ -1959,7 +2026,7 @@ namespace cw
} }
cw::rc_t cw::preset_sel_app::main( const object_t* cfg, const object_t* flow_proc_dict ) cw::rc_t cw::preset_sel_app::main( const object_t* cfg )
{ {
rc_t rc; rc_t rc;
@ -1994,7 +2061,7 @@ cw::rc_t cw::preset_sel_app::main( const object_t* cfg, const object_t* flow_pro
} }
// create the IO Flow controller // create the IO Flow controller
if(app.flow_cfg==nullptr || flow_proc_dict==nullptr || (rc = io_flow::create(app.ioFlowH,app.ioH,app.crossFadeSrate,app.crossFadeCnt,*flow_proc_dict,*app.flow_cfg)) != kOkRC ) if(app.flow_cfg==nullptr || app.flow_proc_dict==nullptr || (rc = io_flow::create(app.ioFlowH,app.ioH,app.crossFadeSrate,app.crossFadeCnt,*app.flow_proc_dict,*app.flow_cfg)) != kOkRC )
{ {
rc = cwLogError(rc,"The IO Flow controller create failed."); rc = cwLogError(rc,"The IO Flow controller create failed.");
goto errLabel; goto errLabel;

View File

@ -5,7 +5,7 @@ namespace cw
{ {
namespace preset_sel_app namespace preset_sel_app
{ {
rc_t main( const object_t* cfg, const object_t* flow_proc_dict ); rc_t main( const object_t* cfg );
} }
} }

View File

@ -34,6 +34,7 @@
button:{ name: stopBtnId, title:"Stop" }, button:{ name: stopBtnId, title:"Stop" },
number:{ name: begLocNumbId, title:"Loc:", min:0, max:100000, step:1, decpl:0 }, number:{ name: begLocNumbId, title:"Loc:", min:0, max:100000, step:1, decpl:0 },
number:{ name: endLocNumbId, title:"End:", min:0, max:100000, step:1, decpl:0 }, number:{ name: endLocNumbId, title:"End:", min:0, max:100000, step:1, decpl:0 },
check: { name: liveCheckId, title:"Live" },
}, },
row: { row: {