2021-11-01 14:28:44 +00:00
# include "cwCommon.h"
# include "cwLog.h"
# include "cwCommonImpl.h"
# include "cwMem.h"
# include "cwObject.h"
# include "cwText.h"
# include "cwFileSys.h"
# include "cwFile.h"
# include "cwTime.h"
# include "cwMidiDecls.h"
# include "cwMidi.h"
# include "cwUiDecls.h"
# include "cwIo.h"
# include "cwIoMidiRecordPlay.h"
# include "cwIoPresetSelApp.h"
# include "cwPianoScore.h"
2021-12-11 20:21:03 +00:00
# include "cwIoFlow.h"
2021-11-06 02:28:38 +00:00
# include "cwPresetSel.h"
2021-11-01 14:28:44 +00:00
namespace cw
{
namespace preset_sel_app
{
// Application Id's for UI elements
enum
{
// Resource Based elements
kPanelDivId = 1000 ,
kQuitBtnId ,
kIoReportBtnId ,
kReportBtnId ,
kStartBtnId ,
kStopBtnId ,
kMidiThruCheckId ,
kCurMidiEvtCntId ,
kTotalMidiEvtCntId ,
kCurAudioSecsId ,
kTotalAudioSecsId ,
kSaveBtnId ,
kLoadBtnId ,
kFnStringId ,
2021-11-14 18:11:11 +00:00
kBegPlayLocNumbId ,
kEndPlayLocNumbId ,
2021-11-06 02:28:38 +00:00
kInsertLocId ,
kInsertBtnId ,
kDeleteBtnId ,
kFragListId ,
kFragPanelId ,
kFragEndLocId ,
kFragPresetRowId ,
kFragPresetSelId ,
kFragPresetOrderId ,
kFragGainId ,
kFragWetDryGainId ,
kFragFadeOutMsId
2021-11-01 14:28:44 +00:00
} ;
enum
{
kAmMidiTimerId
} ;
// Application Id's for the resource based UI elements.
ui : : appIdMap_t mapA [ ] =
{
{ ui : : kRootAppId , kPanelDivId , " panelDivId " } ,
{ kPanelDivId , kQuitBtnId , " quitBtnId " } ,
{ kPanelDivId , kIoReportBtnId , " ioReportBtnId " } ,
{ kPanelDivId , kReportBtnId , " reportBtnId " } ,
{ kPanelDivId , kStartBtnId , " startBtnId " } ,
{ kPanelDivId , kStopBtnId , " stopBtnId " } ,
{ kPanelDivId , kMidiThruCheckId , " midiThruCheckId " } ,
{ kPanelDivId , kCurMidiEvtCntId , " curMidiEvtCntId " } ,
{ kPanelDivId , kTotalMidiEvtCntId , " totalMidiEvtCntId " } ,
{ kPanelDivId , kCurAudioSecsId , " curAudioSecsId " } ,
{ kPanelDivId , kTotalAudioSecsId , " totalAudioSecsId " } ,
{ kPanelDivId , kSaveBtnId , " saveBtnId " } ,
{ kPanelDivId , kLoadBtnId , " loadBtnId " } ,
{ kPanelDivId , kFnStringId , " filenameId " } ,
2021-11-14 18:11:11 +00:00
{ kPanelDivId , kBegPlayLocNumbId , " begLocNumbId " } ,
{ kPanelDivId , kEndPlayLocNumbId , " endLocNumbId " } ,
2021-11-06 02:28:38 +00:00
{ kPanelDivId , kInsertLocId , " insertLocId " } ,
{ kPanelDivId , kInsertBtnId , " insertBtnId " } ,
2021-11-14 18:11:11 +00:00
{ kPanelDivId , kDeleteBtnId , " deleteBtnId " } ,
2021-11-06 02:28:38 +00:00
{ kPanelDivId , kFragListId , " fragListId " } ,
{ kFragListId , kFragPanelId , " fragPanelId " } ,
{ kFragPanelId , kFragEndLocId , " fragEndLocId " } ,
{ kFragPanelId , kFragPresetRowId , " fragPresetRowId " } ,
{ kFragPanelId , kFragGainId , " fragGainId " } ,
{ kFragPanelId , kFragWetDryGainId , " fragWetDryGainId " } ,
{ kFragPanelId , kFragFadeOutMsId , " fragFadeOutMsId " }
2021-11-01 14:28:44 +00:00
} ;
unsigned mapN = sizeof ( mapA ) / sizeof ( mapA [ 0 ] ) ;
typedef struct loc_map_str
{
unsigned loc ;
time : : spec_t timestamp ;
} loc_map_t ;
2021-11-14 18:11:11 +00:00
typedef struct ui_blob_str
{
unsigned fragId ;
unsigned varId ;
unsigned presetId ;
} ui_blob_t ;
2021-11-01 14:28:44 +00:00
typedef struct app_str
{
2021-11-06 02:28:38 +00:00
io : : handle_t ioH ;
2021-11-01 14:28:44 +00:00
2021-11-06 02:28:38 +00:00
const char * record_dir ;
2021-12-19 17:18:22 +00:00
const char * record_fn ;
2021-11-06 02:28:38 +00:00
const char * record_fn_ext ;
char * directory ;
const char * scoreFn ;
const object_t * frag_panel_cfg ;
const object_t * presets_cfg ;
2021-12-11 20:21:03 +00:00
const object_t * flow_cfg ;
2021-11-01 14:28:44 +00:00
midi_record_play : : handle_t mrpH ;
score : : handle_t scoreH ;
loc_map_t * locMap ;
unsigned locMapN ;
2021-11-06 02:28:38 +00:00
2021-12-12 21:47:41 +00:00
unsigned insertLoc ; // last valid insert location id received from the GUI
2021-11-06 02:28:38 +00:00
2021-12-12 21:47:41 +00:00
time : : spec_t beg_play_timestamp ;
time : : spec_t end_play_timestamp ;
2021-11-14 18:11:11 +00:00
2021-11-06 02:28:38 +00:00
preset_sel : : handle_t psH ;
2021-12-12 21:47:41 +00:00
io_flow : : handle_t ioFlowH ;
2021-12-19 17:18:22 +00:00
unsigned tmp ;
double crossFadeSrate ;
unsigned crossFadeCnt ;
2021-11-01 14:28:44 +00:00
} app_t ;
2021-11-03 15:09:07 +00:00
rc_t _parseCfg ( app_t * app , const object_t * cfg , const object_t * & params_cfgRef )
2021-11-01 14:28:44 +00:00
{
rc_t rc = kOkRC ;
2021-12-11 20:21:03 +00:00
if ( ( rc = cfg - > getv ( " params " , params_cfgRef ,
" flow " , app - > flow_cfg ) ) ! = kOkRC )
2021-11-01 14:28:44 +00:00
{
rc = cwLogError ( kSyntaxErrorRC , " Preset Select App 'params' cfg record not found. " ) ;
goto errLabel ;
}
2021-11-03 15:09:07 +00:00
if ( ( rc = params_cfgRef - > getv ( " record_dir " , app - > record_dir ,
2021-12-19 17:18:22 +00:00
" record_fn " , app - > record_fn ,
2021-11-06 02:28:38 +00:00
" record_fn_ext " , app - > record_fn_ext ,
" score_fn " , app - > scoreFn ,
" frag_panel " , app - > frag_panel_cfg ,
2021-12-19 17:18:22 +00:00
" presets " , app - > presets_cfg ,
" crossFadeSrate " , app - > crossFadeSrate ,
" crossFadeCount " , app - > crossFadeCnt ) ) ! = kOkRC )
2021-11-01 14:28:44 +00:00
{
rc = cwLogError ( kSyntaxErrorRC , " Preset Select App configuration parse failed. " ) ;
}
// verify that the output directory exists
if ( ( rc = filesys : : isDir ( app - > record_dir ) ) ! = kOkRC )
if ( ( rc = filesys : : makeDir ( app - > record_dir ) ) ! = kOkRC )
rc = cwLogError ( rc , " Unable to create the base output directory:%s. " , cwStringNullGuard ( app - > record_dir ) ) ;
2021-11-06 02:28:38 +00:00
app - > insertLoc = kInvalidId ; // initialize 'insertLoc' to be invalid
2021-11-01 14:28:44 +00:00
errLabel :
return rc ;
}
rc_t _free ( app_t & app )
{
2021-11-06 02:28:38 +00:00
preset_sel : : destroy ( app . psH ) ;
2021-12-11 20:21:03 +00:00
io_flow : : destroy ( app . ioFlowH ) ;
2021-11-01 14:28:44 +00:00
mem : : release ( app . locMap ) ;
mem : : release ( app . directory ) ;
return kOkRC ;
}
2021-12-12 21:47:41 +00:00
rc_t _apply_preset ( app_t * app , const time : : spec_t & ts , const preset_sel : : frag_t * frag = nullptr )
{
if ( frag = = nullptr )
preset_sel : : track_timestamp ( app - > psH , ts , frag ) ;
if ( frag = = nullptr )
cwLogInfo ( " No preset fragment was found for the requested timestamp. " ) ;
else
{
unsigned preset_idx = fragment_play_preset_index ( frag ) ;
2021-12-19 17:18:22 +00:00
const char * preset_label = preset_sel : : preset_label ( app - > psH , preset_idx ) ;
printf ( " Apply preset: '%s'. \n " , preset_idx = = kInvalidIdx ? " <invalid> " : preset_label ) ;
2021-12-12 21:47:41 +00:00
2021-12-19 17:18:22 +00:00
if ( preset_label ! = nullptr )
io_flow : : apply_preset ( app - > ioFlowH , frag - > fadeOutMs , preset_label ) ;
2021-12-12 21:47:41 +00:00
}
return kOkRC ;
}
2021-11-01 14:28:44 +00:00
void _midi_play_callback ( void * arg , unsigned id , const time : : spec_t timestamp , uint8_t ch , uint8_t status , uint8_t d0 , uint8_t d1 )
{
app_t * app = ( app_t * ) arg ;
if ( id ! = kInvalidId )
{
2021-12-12 21:47:41 +00:00
const unsigned buf_byte_cnt = 256 ;
char buf [ buf_byte_cnt ] ;
2021-11-01 14:28:44 +00:00
event_to_string ( app - > scoreH , id , buf , buf_byte_cnt ) ;
printf ( " %s \n " , buf ) ;
2021-12-12 21:47:41 +00:00
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 ) ;
}
2021-11-01 14:28:44 +00:00
}
}
2021-11-06 02:28:38 +00:00
void _update_event_ui ( app_t * app )
{
io : : uiSendValue ( app - > ioH , uiFindElementUuId ( app - > ioH , kCurMidiEvtCntId ) , midi_record_play : : event_index ( app - > mrpH ) ) ;
io : : uiSendValue ( app - > ioH , uiFindElementUuId ( app - > ioH , kTotalMidiEvtCntId ) , midi_record_play : : event_count ( app - > mrpH ) ) ;
}
2021-12-19 17:18:22 +00:00
// Update the UI with the value from the the fragment data record.
2021-11-06 02:28:38 +00:00
template < typename T >
rc_t _update_frag_ui ( app_t * app , unsigned fragId , unsigned psVarId , unsigned psPresetId , unsigned uiParentUuId , unsigned uiVarAppId , unsigned uiChanId , T & valRef )
{
rc_t rc = kOkRC ;
unsigned uuid = kInvalidId ;
// Get the value from the data record
if ( ( rc = preset_sel : : get_value ( app - > psH , fragId , psVarId , psPresetId , valRef ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Unable to locate the preset value for var:5i preset:%i. " , psVarId , psPresetId ) ;
goto errLabel ;
}
// Get the UI uuId
if ( ( uuid = io : : uiFindElementUuId ( app - > ioH , uiParentUuId , uiVarAppId , uiChanId ) ) = = kInvalidId )
{
rc = cwLogError ( rc , " Unable to locate the UI uuid for appid:%i chanId:%i. " , uiVarAppId , uiChanId ) ;
goto errLabel ;
}
// Send the value to the UI
if ( ( rc = io : : uiSendValue ( app - > ioH , uuid , valRef ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Transmission of fragment value failed. " ) ;
goto errLabel ;
}
errLabel :
return rc ;
}
2021-11-14 18:11:11 +00:00
// Get the endLoc associated with this fragment id
rc_t _frag_id_to_endloc ( app_t * app , unsigned fragId , unsigned & endLocRef )
{
rc_t rc = kOkRC ;
endLocRef = kInvalidId ;
if ( ( rc = get_value ( app - > psH , fragId , preset_sel : : kEndLocVarId , kInvalidId , endLocRef ) ) ! = kOkRC )
rc = cwLogError ( rc , " Unable to get the 'end loc' value for fragment id:%i. " , fragId ) ;
return rc ;
}
// Update the preset select check boxes on a fragment panel
rc_t _update_frag_select_flags ( app_t * app , unsigned fragId , unsigned fragEndLoc = kInvalidId )
{
rc_t rc = kOkRC ;
// if
if ( fragEndLoc = = kInvalidId )
{
// get the endLoc associated with this fragment
rc = _frag_id_to_endloc ( app , fragId , fragEndLoc ) ;
}
if ( rc = = kOkRC )
{
bool bValue ;
unsigned uValue ;
// The uiChan is the fragment endLoc
unsigned uiChanId = fragEndLoc ;
// The fragPanelUUid is the same as the fragId
unsigned fragPanelUuId = fragId ;
// uuid of the frag preset row
unsigned fragPresetRowUuId = io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragPresetRowId , uiChanId ) ;
// Update each fragment preset control UI by getting it's current value from the fragment data record
for ( unsigned preset_idx = 0 ; preset_idx < preset_sel : : preset_count ( app - > psH ) ; + + preset_idx )
{
_update_frag_ui ( app , fragId , preset_sel : : kPresetSelectVarId , preset_idx , fragPresetRowUuId , kFragPresetSelId , preset_idx , bValue ) ;
_update_frag_ui ( app , fragId , preset_sel : : kPresetOrderVarId , preset_idx , fragPresetRowUuId , kFragPresetOrderId , preset_idx , uValue ) ;
}
}
return rc ;
}
// Update the fragment UI withh the fragment record associated with 'fragId'
2021-11-06 02:28:38 +00:00
rc_t _update_frag_ui ( app_t * app , unsigned fragId )
{
// Notes: fragId == fragPanelUuId
// uiChanId = endLoc for panel values
// or uiChanId = preset_index for preset values
rc_t rc = kOkRC ;
unsigned endLoc ;
2021-11-14 18:11:11 +00:00
// get the endLoc for this fragment
if ( ( rc = _frag_id_to_endloc ( app , fragId , endLoc ) ) = = kOkRC )
2021-11-06 02:28:38 +00:00
{
unsigned uValue ;
double dValue ;
2021-11-14 18:11:11 +00:00
unsigned uiChanId = endLoc ;
unsigned fragPanelUuId = fragId ;
2021-11-06 02:28:38 +00:00
_update_frag_ui ( app , fragId , preset_sel : : kEndLocVarId , kInvalidId , fragPanelUuId , kFragEndLocId , uiChanId , uValue ) ;
_update_frag_ui ( app , fragId , preset_sel : : kGainVarId , kInvalidId , fragPanelUuId , kFragGainId , uiChanId , dValue ) ;
_update_frag_ui ( app , fragId , preset_sel : : kFadeOutMsVarId , kInvalidId , fragPanelUuId , kFragFadeOutMsId , uiChanId , dValue ) ;
_update_frag_ui ( app , fragId , preset_sel : : kWetGainVarId , kInvalidId , fragPanelUuId , kFragWetDryGainId , uiChanId , dValue ) ;
2021-11-14 18:11:11 +00:00
_update_frag_select_flags ( app , fragId , endLoc ) ;
2021-11-06 02:28:38 +00:00
}
return rc ;
}
2021-12-19 17:18:22 +00:00
// Called when a UI value is changed in a fragment panel (e.g. gain, fadeMs, ...)
2021-11-06 02:28:38 +00:00
template < typename T >
2021-11-14 18:11:11 +00:00
rc_t _on_ui_frag_value ( app_t * app , unsigned uuId , const T & value )
2021-11-06 02:28:38 +00:00
{
2021-11-14 18:11:11 +00:00
rc_t rc = kOkRC ;
unsigned blobByteN = 0 ;
ui_blob_t * blob = nullptr ;
if ( ( blob = ( ui_blob_t * ) io : : uiGetBlob ( app - > ioH , uuId , blobByteN ) ) = = nullptr | | blobByteN ! = sizeof ( ui_blob_t ) )
return cwLogError ( kInvalidStateRC , " A fragment UI blob was missing or corrupt. " ) ;
rc = preset_sel : : set_value ( app - > psH , blob - > fragId , blob - > varId , blob - > presetId , value ) ;
if ( rc ! = kOkRC )
{
// TODO: Set the error indicator on the GUI
}
else
{
// TODO: Clear the error indicator on the GUI
}
//
if ( blob - > varId = = preset_sel : : kPresetSelectVarId )
_update_frag_select_flags ( app , blob - > fragId ) ;
2021-11-06 02:28:38 +00:00
return rc ;
}
2021-12-19 17:18:22 +00:00
rc_t _frag_set_ui_blob ( app_t * app , unsigned uuId , unsigned fragId , unsigned varId , unsigned presetId )
{
ui_blob_t blob = { . fragId = fragId , . varId = varId , . presetId = presetId } ;
return io : : uiSetBlob ( app - > ioH , uuId , & blob , sizeof ( blob ) ) ;
}
2021-11-06 02:28:38 +00:00
2021-12-19 17:18:22 +00:00
rc_t _create_frag_preset_ctl ( app_t * app , unsigned fragId , unsigned fragPresetRowUuId , unsigned presetN , unsigned preset_idx )
{
rc_t rc = kOkRC ;
unsigned colUuId = kInvalidId ;
unsigned uuId = kInvalidId ;
const char * nullEleName = nullptr ;
const char * nullClass = nullptr ;
unsigned invalidAppId = kInvalidId ;
unsigned chanId = preset_idx ; // chanId is the preset id
const char * presetLabel = preset_sel : : preset_label ( app - > psH , preset_idx ) ;
assert ( presetLabel ! = nullptr ) ;
// preset control column container
if ( ( rc = io : : uiCreateDiv ( app - > ioH , colUuId , fragPresetRowUuId , nullEleName , invalidAppId , chanId , " col fragPresetCtl " , nullptr ) ) ! = kOkRC )
goto errLabel ;
// preset select check
if ( ( rc = io : : uiCreateCheck ( app - > ioH , uuId , colUuId , nullEleName , kFragPresetSelId , chanId , nullClass , presetLabel ) ) ! = kOkRC )
goto errLabel ;
// store a connection for the select control back to the fragment record
_frag_set_ui_blob ( app , uuId , fragId , preset_sel : : kPresetSelectVarId , preset_idx ) ;
// preset order number
if ( ( rc = io : : uiCreateNumb ( app - > ioH , uuId , colUuId , nullEleName , kFragPresetOrderId , chanId , nullClass , nullptr , 0 , presetN , 1 , 0 ) ) ! = kOkRC )
goto errLabel ;
// store a connection for the select control back to the fragment record
_frag_set_ui_blob ( app , uuId , fragId , preset_sel : : kPresetOrderVarId , preset_idx ) ;
errLabel :
if ( rc ! = kOkRC )
rc = cwLogError ( rc , " Preset control index '%i' create failed. " ) ;
return rc ;
}
rc_t _create_frag_ui ( app_t * app , unsigned endLoc , unsigned & fragIdRef )
2021-11-01 14:28:44 +00:00
{
2021-12-19 17:18:22 +00:00
rc_t rc = kOkRC ;
unsigned fragListUuId = io : : uiFindElementUuId ( app - > ioH , kFragListId ) ;
unsigned fragChanId = endLoc ; // use the frag. endLoc as the channel id
unsigned fragPanelUuId = kInvalidId ;
unsigned fragEndLocUuId = kInvalidId ;
unsigned fragPresetRowUuId = kInvalidId ;
unsigned presetN = preset_sel : : preset_count ( app - > psH ) ;
// create the UI object
if ( ( rc = io : : uiCreateFromObject ( app - > ioH , app - > frag_panel_cfg , fragListUuId , fragChanId ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " The fragments UI object creation failed. " ) ;
goto errLabel ;
}
// get the uuid's of the new fragment panel and the endloc number display
fragPanelUuId = io : : uiFindElementUuId ( app - > ioH , fragListUuId , kFragPanelId , fragChanId ) ;
fragEndLocUuId = io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragEndLocId , fragChanId ) ;
fragPresetRowUuId = io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragPresetRowId , fragChanId ) ;
assert ( fragPanelUuId ! = kInvalidId ) ;
assert ( fragEndLocUuId ! = kInvalidId ) ;
assert ( fragPresetRowUuId ! = kInvalidId ) ;
// Make the fragment panel clickable
io : : uiSetClickable ( app - > ioH , fragPanelUuId ) ;
// Set the fragment panel order
io : : uiSetOrderKey ( app - > ioH , fragPanelUuId , endLoc ) ;
// The fragment id is the same as the frag panel UUId
fragIdRef = fragPanelUuId ;
// Attach blobs to the UI to allow convenient access back to the prese_sel data record
_frag_set_ui_blob ( app , io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragGainId , fragChanId ) , fragIdRef , preset_sel : : kGainVarId , kInvalidId ) ;
_frag_set_ui_blob ( app , io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragWetDryGainId , fragChanId ) , fragIdRef , preset_sel : : kWetGainVarId , kInvalidId ) ;
_frag_set_ui_blob ( app , io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragFadeOutMsId , fragChanId ) , fragIdRef , preset_sel : : kFadeOutMsVarId , kInvalidId ) ;
2021-11-01 14:28:44 +00:00
2021-12-19 17:18:22 +00:00
// create each of the preset controls
for ( unsigned preset_idx = 0 ; preset_idx < presetN ; + + preset_idx )
if ( ( rc = _create_frag_preset_ctl ( app , fragIdRef , fragPresetRowUuId , presetN , preset_idx ) ) ! = kOkRC )
goto errLabel ;
errLabel :
return rc ;
}
rc_t _restore ( app_t * app )
{
rc_t rc = kOkRC ;
char * fn = nullptr ;
const preset_sel : : frag_t * f = nullptr ;
// form the output file name
if ( ( fn = filesys : : makeFn ( app - > record_dir , app - > record_fn , app - > record_fn_ext , NULL ) ) = = nullptr )
{
rc = cwLogError ( kOpFailRC , " The preset select filename could not formed. " ) ;
goto errLabel ;
}
if ( ! filesys : : isFile ( fn ) )
{
cwLogInfo ( " The preset selection data file: '%s' does not exist. " , cwStringNullGuard ( fn ) ) ;
goto errLabel ;
}
// read the preset data file
if ( ( rc = preset_sel : : read ( app - > psH , fn ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " File write failed on preset select. " ) ;
goto errLabel ;
}
preset_sel : : report ( app - > psH ) ;
2021-11-01 14:28:44 +00:00
2021-12-19 17:18:22 +00:00
f = preset_sel : : get_fragment_base ( app - > psH ) ;
for ( ; f ! = nullptr ; f = f - > link )
{
unsigned fragId = kInvalidId ;
if ( ( rc = _create_frag_ui ( app , f - > endLoc , fragId ) ) ! = kOkRC )
2021-11-01 14:28:44 +00:00
{
2021-12-19 17:18:22 +00:00
cwLogError ( rc , " Frag UI create failed. " ) ;
2021-11-01 14:28:44 +00:00
goto errLabel ;
}
2021-12-19 17:18:22 +00:00
// update the fragment id
// TODO:
// BUG BUG BUG: there is nothing to prevent the new fragment id from conflicting with the existing fragment id's
// The correct way to handle this is to reset all the fragment id's in a single operation after the UI is created
preset_sel : : set_value ( app - > psH , f - > fragId , preset_sel : : kFragIdVarId , kInvalidId , fragId ) ;
_update_frag_ui ( app , fragId ) ;
2021-11-01 14:28:44 +00:00
}
2021-12-19 17:18:22 +00:00
errLabel :
mem : : release ( fn ) ;
return rc ;
}
rc_t _on_ui_save ( app_t * app )
{
rc_t rc = kOkRC ;
char * fn = nullptr ;
// form the output file name
if ( ( fn = filesys : : makeFn ( app - > record_dir , app - > record_fn , app - > record_fn_ext , NULL ) ) = = nullptr )
{
rc = cwLogError ( kOpFailRC , " The preset select filename could not formed. " ) ;
goto errLabel ;
}
// write the preset data file
if ( ( rc = preset_sel : : write ( app - > psH , fn ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " File write failed on preset select. " ) ;
goto errLabel ;
2021-11-01 14:28:44 +00:00
}
errLabel :
2021-12-19 17:18:22 +00:00
mem : : release ( fn ) ;
return rc ;
2021-11-01 14:28:44 +00:00
}
rc_t _on_ui_load ( app_t * app )
{
rc_t rc = kOkRC ;
const score : : event_t * e = nullptr ;
unsigned midiEventN = 0 ;
midi_record_play : : midi_msg_t * m = nullptr ;
printf ( " Loading \n " ) ;
// create the score
if ( ( rc = score : : create ( app - > scoreH , app - > scoreFn ) ) ! = kOkRC )
{
cwLogError ( rc , " Score create failed on '%s'. " , app - > scoreFn ) ;
goto errLabel ;
}
// get the count of MIDI events
if ( ( e = score : : base_event ( app - > scoreH ) ) ! = nullptr )
for ( ; e ! = nullptr ; e = e - > link )
if ( e - > status ! = 0 )
midiEventN + = 1 ;
// copy the MIDI events
if ( ( e = score : : base_event ( app - > scoreH ) ) ! = nullptr )
{
// allocate the locMap[]
mem : : free ( app - > locMap ) ;
app - > locMap = mem : : allocZ < loc_map_t > ( midiEventN ) ;
app - > locMapN = midiEventN ;
// allocate the the player msg array
m = mem : : allocZ < midi_record_play : : midi_msg_t > ( midiEventN ) ;
// load the player msg array
for ( unsigned i = 0 ; e ! = nullptr & & i < midiEventN ; e = e - > link )
if ( e - > status ! = 0 )
{
time : : millisecondsToSpec ( m [ i ] . timestamp , ( unsigned ) ( e - > sec * 1000 ) ) ;
m [ i ] . ch = e - > status & 0x0f ;
m [ i ] . status = e - > status & 0xf0 ;
m [ i ] . d0 = e - > d0 ;
m [ i ] . d1 = e - > d1 ;
m [ i ] . id = e - > uid ;
app - > locMap [ i ] . loc = e - > loc ;
app - > locMap [ i ] . timestamp = m [ i ] . timestamp ;
+ + i ;
}
// load the player with the msg list
if ( ( rc = midi_record_play : : load ( app - > mrpH , m , midiEventN ) ) ! = kOkRC )
{
cwLogError ( rc , " MIDI player load failed. " ) ;
goto errLabel ;
}
mem : : free ( m ) ;
}
2021-11-06 02:28:38 +00:00
// enable the 'End Loc' number box since the score is loaded
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kInsertLocId ) , true ) ;
// update the current event and event count
_update_event_ui ( app ) ;
2021-11-14 18:11:11 +00:00
// enable the start/stop buttons
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kStartBtnId ) , true ) ;
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kStopBtnId ) , true ) ;
2021-12-19 17:18:22 +00:00
// restore the fragment records
if ( ( rc = _restore ( app ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Restore failed. " ) ;
goto errLabel ;
}
2021-11-01 14:28:44 +00:00
cwLogInfo ( " '%s' loaded. " , app - > scoreFn ) ;
errLabel :
2021-11-06 02:28:38 +00:00
_update_event_ui ( app ) ;
2021-11-01 14:28:44 +00:00
return rc ;
}
rc_t _on_ui_start ( app_t * app )
{
rc_t rc = kOkRC ;
2021-11-14 18:11:11 +00:00
bool rewindFl = true ;
if ( ! time : : isZero ( app - > beg_play_timestamp ) )
{
// seek the player to the requested loc
if ( ( rc = midi_record_play : : seek ( app - > mrpH , app - > beg_play_timestamp ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " MIDI seek failed. " ) ;
goto errLabel ;
}
rewindFl = false ;
}
2021-12-12 21:47:41 +00:00
// apply the preset which is active at the start time
if ( ( rc = _apply_preset ( app , app - > beg_play_timestamp ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Preset application failed prior to MIDI start. " ) ;
goto errLabel ;
}
// start the MIDI playback
2021-11-14 18:11:11 +00:00
if ( ( rc = midi_record_play : : start ( app - > mrpH , rewindFl , & app - > end_play_timestamp ) ) ! = kOkRC )
2021-11-01 14:28:44 +00:00
{
rc = cwLogError ( rc , " MIDI start failed. " ) ;
goto errLabel ;
}
2021-11-14 18:11:11 +00:00
2021-11-03 15:09:07 +00:00
io : : uiSendValue ( app - > ioH , uiFindElementUuId ( app - > ioH , kCurMidiEvtCntId ) , midi_record_play : : event_index ( app - > mrpH ) ) ;
2021-11-01 14:28:44 +00:00
//io::uiSendValue( app->ioH, kInvalidId, uiFindElementUuId(app->ioH,kCurAudioSecsId), audio_record_play::current_loc_seconds(app->arpH) );
errLabel :
return rc ;
}
rc_t _on_ui_stop ( app_t * app )
{
rc_t rc = kOkRC ;
if ( ( rc = midi_record_play : : stop ( app - > mrpH ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " MIDI start failed. " ) ;
goto errLabel ;
}
//if((rc = audio_record_play::stop(app->arpH)) != kOkRC )
//{
// rc = cwLogError(rc,"Audio start failed.");
// goto errLabel;
//}
errLabel :
return rc ;
}
rc_t _set_midi_thru_state ( app_t * app , bool thru_fl )
{
rc_t rc = kOkRC ;
if ( ( rc = midi_record_play : : set_thru_state ( app - > mrpH , thru_fl ) ) ! = kOkRC )
rc = cwLogError ( rc , " %s MIDI thru state failed. " , thru_fl ? " Enable " : " Disable " ) ;
return rc ;
}
2021-11-06 02:28:38 +00:00
loc_map_t * _find_loc ( app_t * app , unsigned loc )
{
unsigned i = 0 ;
for ( ; i < app - > locMapN ; + + i )
if ( app - > locMap [ i ] . loc = = loc )
return app - > locMap + i ;
return nullptr ;
}
2021-11-14 18:11:11 +00:00
bool _is_valid_insert_loc ( app_t * app , unsigned loc )
{
bool fl0 = _find_loc ( app , loc ) ! = nullptr ;
bool fl1 = preset_sel : : is_fragment_loc ( app - > psH , loc ) = = false ;
return fl0 & & fl1 ;
}
2021-11-06 02:28:38 +00:00
2021-11-01 14:28:44 +00:00
2021-11-14 18:11:11 +00:00
rc_t _on_ui_play_loc ( app_t * app , unsigned appId , unsigned loc )
2021-11-01 14:28:44 +00:00
{
2021-11-14 18:11:11 +00:00
rc_t rc = kOkRC ;
2021-11-06 02:28:38 +00:00
loc_map_t * map ;
// locate the map record
if ( ( map = _find_loc ( app , loc ) ) = = nullptr )
2021-11-01 14:28:44 +00:00
{
2021-11-06 02:28:38 +00:00
rc = cwLogError ( kOpFailRC , " The location '%i' could not be found. " , loc ) ;
goto errLabel ;
}
2021-11-14 18:11:11 +00:00
switch ( appId )
2021-11-06 02:28:38 +00:00
{
2021-11-14 18:11:11 +00:00
case kBegPlayLocNumbId :
app - > beg_play_timestamp = map - > timestamp ;
break ;
case kEndPlayLocNumbId :
app - > end_play_timestamp = map - > timestamp ;
break ;
2021-11-06 02:28:38 +00:00
}
2021-11-14 18:11:11 +00:00
errLabel :
return rc ;
}
2021-11-06 02:28:38 +00:00
2021-11-14 18:11:11 +00:00
rc_t _on_ui_insert_loc ( app_t * app , unsigned insertLoc )
{
rc_t rc = kOkRC ;
bool enableFl = _is_valid_insert_loc ( app , insertLoc ) ;
unsigned insertBtnUuId = io : : uiFindElementUuId ( app - > ioH , kInsertBtnId ) ;
io : : uiSetEnable ( app - > ioH , insertBtnUuId , enableFl ) ;
if ( enableFl )
{
app - > insertLoc = insertLoc ;
// TODO: Clear GUI error indicator
2021-11-06 02:28:38 +00:00
2021-11-14 18:11:11 +00:00
}
else
{
app - > insertLoc = kInvalidId ;
cwLogWarning ( " Location '%i' is not valid. " , insertLoc ) ;
// TODO: Set GUI error indicator
}
2021-11-06 02:28:38 +00:00
return rc ;
}
rc_t _on_ui_insert_btn ( app_t * app )
{
2021-12-12 21:47:41 +00:00
rc_t rc = kOkRC ;
unsigned fragId = kInvalidId ;
loc_map_t * loc_ts = nullptr ;
2021-11-06 02:28:38 +00:00
// verify that frag panel resource object is initiailized
if ( app - > frag_panel_cfg = = nullptr )
{
rc = cwLogError ( kInvalidStateRC , " The fragment UI resource was not initialized. " ) ;
goto errLabel ;
}
// verify that the insertion location is valid
if ( app - > insertLoc = = kInvalidId )
{
rc = cwLogError ( kInvalidIdRC , " The new fragment's 'End Loc' is not valid. " ) ;
goto errLabel ;
}
2021-12-12 21:47:41 +00:00
// verify that the end-loc is not already in use - this shouldn't be possible because the 'insert' btn should be disabled if the 'insertLoc' is not valid
if ( preset_sel : : is_fragment_loc ( app - > psH , app - > insertLoc ) )
{
rc = cwLogError ( kInvalidIdRC , " The new fragment's 'End Loc' is already in use. " ) ;
goto errLabel ;
}
// get the timestamp assoc'd with the the 'end-loc'
if ( ( loc_ts = _find_loc ( app , app - > insertLoc ) ) = = nullptr )
{
rc = cwLogError ( kOpFailRC , " The time stamp associated with the 'End Loc' '%i' could not be found. " , app - > insertLoc ) ;
goto errLabel ;
}
2021-12-19 17:18:22 +00:00
// create the fragment UI panel
if ( ( rc = _create_frag_ui ( app , app - > insertLoc , fragId ) ) ! = kOkRC )
2021-11-06 02:28:38 +00:00
{
2021-12-19 17:18:22 +00:00
rc = cwLogError ( rc , " Fragment UI panel create failed. " ) ;
2021-11-06 02:28:38 +00:00
goto errLabel ;
2021-11-01 14:28:44 +00:00
}
2021-11-06 02:28:38 +00:00
// create the data record associated with the new fragment.
2021-12-12 21:47:41 +00:00
if ( ( rc = preset_sel : : create_fragment ( app - > psH , fragId , app - > insertLoc , loc_ts - > timestamp ) ) ! = kOkRC )
2021-11-06 02:28:38 +00:00
{
rc = cwLogError ( rc , " Fragment data record create failed. " ) ;
goto errLabel ;
}
2021-11-14 18:11:11 +00:00
2021-11-06 02:28:38 +00:00
// update the fragment UI
2021-12-19 17:18:22 +00:00
_update_frag_ui ( app , fragId ) ;
2021-11-06 02:28:38 +00:00
errLabel :
2021-11-01 14:28:44 +00:00
return rc ;
2021-11-06 02:28:38 +00:00
2021-11-01 14:28:44 +00:00
}
2021-11-14 18:11:11 +00:00
rc_t _on_ui_delete_btn ( app_t * app )
{
rc_t rc = kOkRC ;
unsigned fragId = kInvalidId ;
// get the fragment id (uuid) of the selected fragment
if ( ( fragId = preset_sel : : ui_select_fragment_id ( app - > psH ) ) = = kInvalidId )
{
rc = cwLogError ( kInvalidStateRC , " There is no selected fragment to delete. " ) ;
goto errLabel ;
}
// delete the fragment data record
2021-12-19 17:18:22 +00:00
if ( ( rc = preset_sel : : delete_fragment ( app - > psH , fragId ) ) ! = kOkRC )
2021-11-14 18:11:11 +00:00
goto errLabel ;
// delete the fragment UI element
if ( ( rc = io : : uiDestroyElement ( app - > ioH , fragId ) ) ! = kOkRC )
goto errLabel ;
errLabel :
if ( rc ! = kOkRC )
rc = cwLogError ( rc , " Fragment delete failed. " ) ;
return rc ;
}
2021-11-01 14:28:44 +00:00
rc_t _onUiInit ( app_t * app , const io : : ui_msg_t & m )
{
rc_t rc = kOkRC ;
2021-11-06 02:28:38 +00:00
_update_event_ui ( app ) ;
2021-11-14 18:11:11 +00:00
// 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 , kStopBtnId ) , false ) ;
2021-11-06 02:28:38 +00:00
const preset_sel : : frag_t * f = preset_sel : : get_fragment_base ( app - > psH ) ;
for ( ; f ! = nullptr ; f = f - > link )
_update_frag_ui ( app , f - > fragId ) ;
2021-11-14 18:11:11 +00:00
2021-11-01 14:28:44 +00:00
return rc ;
}
2021-11-14 18:11:11 +00:00
2021-11-01 14:28:44 +00:00
rc_t _onUiValue ( app_t * app , const io : : ui_msg_t & m )
{
rc_t rc = kOkRC ;
switch ( m . appId )
{
case kQuitBtnId :
io : : stop ( app - > ioH ) ;
break ;
case kIoReportBtnId :
io : : report ( app - > ioH ) ;
break ;
case kReportBtnId :
2021-12-19 17:18:22 +00:00
//preset_sel::report( app->psH );
io_flow : : apply_preset ( app - > ioFlowH , 2000.0 , app - > tmp = = 0 ? " a " : " b " ) ;
app - > tmp = ! app - > tmp ;
2021-11-01 14:28:44 +00:00
break ;
case kSaveBtnId :
_on_ui_save ( app ) ;
break ;
case kLoadBtnId :
_on_ui_load ( app ) ;
break ;
case kMidiThruCheckId :
cwLogInfo ( " MIDI thru:%i " , m . value - > u . b ) ;
_set_midi_thru_state ( app , m . value - > u . b ) ;
break ;
case kStartBtnId :
_on_ui_start ( app ) ;
break ;
case kStopBtnId :
_on_ui_stop ( app ) ;
break ;
case kFnStringId :
mem : : release ( app - > directory ) ;
app - > directory = mem : : duplStr ( m . value - > u . s ) ;
2021-11-14 18:11:11 +00:00
//rintf("filename:%s\n",app->directory);
2021-11-01 14:28:44 +00:00
break ;
2021-11-14 18:11:11 +00:00
case kBegPlayLocNumbId :
_on_ui_play_loc ( app , m . appId , m . value - > u . i ) ;
break ;
case kEndPlayLocNumbId :
_on_ui_play_loc ( app , m . appId , m . value - > u . i ) ;
2021-11-01 14:28:44 +00:00
break ;
2021-11-06 02:28:38 +00:00
case kInsertLocId :
2021-11-14 18:11:11 +00:00
_on_ui_insert_loc ( app , m . value - > u . u ) ;
2021-11-06 02:28:38 +00:00
break ;
case kInsertBtnId :
_on_ui_insert_btn ( app ) ;
break ;
case kDeleteBtnId :
2021-11-14 18:11:11 +00:00
_on_ui_delete_btn ( app ) ;
2021-11-06 02:28:38 +00:00
break ;
case kFragGainId :
2021-11-14 18:11:11 +00:00
_on_ui_frag_value ( app , m . uuId , m . value - > u . d ) ;
2021-11-06 02:28:38 +00:00
break ;
case kFragWetDryGainId :
2021-11-14 18:11:11 +00:00
_on_ui_frag_value ( app , m . uuId , m . value - > u . d ) ;
2021-11-06 02:28:38 +00:00
break ;
case kFragFadeOutMsId :
2021-12-19 17:18:22 +00:00
_on_ui_frag_value ( app , m . uuId , m . value - > u . u ) ;
2021-11-06 02:28:38 +00:00
break ;
case kFragPresetOrderId :
2021-11-14 18:11:11 +00:00
_on_ui_frag_value ( app , m . uuId , m . value - > u . u ) ;
2021-11-06 02:28:38 +00:00
break ;
case kFragPresetSelId :
2021-11-14 18:11:11 +00:00
_on_ui_frag_value ( app , m . uuId , m . value - > u . b ) ;
2021-11-06 02:28:38 +00:00
break ;
2021-11-01 14:28:44 +00:00
}
return rc ;
}
2021-11-14 18:11:11 +00:00
rc_t _onUiClick ( app_t * app , const io : : ui_msg_t & m )
{
rc_t rc = kOkRC ;
// get the last selected fragment
unsigned uuId = preset_sel : : ui_select_fragment_id ( app - > psH ) ;
// is the last selected fragment the same as the clicked fragment
bool reclickFl = uuId = = m . uuId ;
// if a different fragment was clicked then deselect the last fragment in the UI
if ( ! reclickFl & & uuId ! = kInvalidId )
uiSetSelect ( app - > ioH , uuId , false ) ;
// select or deselect the clicked fragment
uiSetSelect ( app - > ioH , m . uuId , ! reclickFl ) ;
// Note: calls to uiSetSelect() produce callbacks to _onUiSelect().
return rc ;
}
rc_t _onUiSelect ( app_t * app , const io : : ui_msg_t & m )
{
rc_t rc = kOkRC ;
bool selectFl = m . value - > u . b ; // True/False if the fragment is being selected/deselected
// track the currently selected fragment.
preset_sel : : ui_select_fragment ( app - > psH , m . uuId , selectFl ) ;
// enable/disable the delete fragment button
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kDeleteBtnId ) , selectFl ) ;
return rc ;
}
2021-11-01 14:28:44 +00:00
rc_t _onUiEcho ( app_t * app , const io : : ui_msg_t & m )
{
rc_t rc = kOkRC ;
return rc ;
}
rc_t _ui_callback ( app_t * app , const io : : ui_msg_t & m )
{
rc_t rc = kOkRC ;
switch ( m . opId )
{
case ui : : kConnectOpId :
cwLogInfo ( " UI Connected: wsSessId:%i. " , m . wsSessId ) ;
break ;
case ui : : kDisconnectOpId :
cwLogInfo ( " UI Disconnected: wsSessId:%i. " , m . wsSessId ) ;
break ;
case ui : : kInitOpId :
_onUiInit ( app , m ) ;
break ;
case ui : : kValueOpId :
_onUiValue ( app , m ) ;
break ;
2021-11-14 18:11:11 +00:00
case ui : : kClickOpId :
_onUiClick ( app , m ) ;
break ;
case ui : : kSelectOpId :
_onUiSelect ( app , m ) ;
break ;
2021-11-01 14:28:44 +00:00
case ui : : kEchoOpId :
_onUiEcho ( app , m ) ;
break ;
case ui : : kIdleOpId :
break ;
case ui : : kInvalidOpId :
// fall through
default :
assert ( 0 ) ;
break ;
}
return rc ;
}
// The main application callback
rc_t _io_callback ( void * arg , const io : : msg_t * m )
{
rc_t rc = kOkRC ;
app_t * app = reinterpret_cast < app_t * > ( arg ) ;
if ( app - > mrpH . isValid ( ) )
{
midi_record_play : : exec ( app - > mrpH , * m ) ;
if ( midi_record_play : : is_started ( app - > mrpH ) )
2021-11-03 15:09:07 +00:00
io : : uiSendValue ( app - > ioH , uiFindElementUuId ( app - > ioH , kCurMidiEvtCntId ) , midi_record_play : : event_index ( app - > mrpH ) ) ;
2021-11-01 14:28:44 +00:00
}
2021-12-11 20:21:03 +00:00
if ( app - > ioFlowH . isValid ( ) )
{
io_flow : : exec ( app - > ioFlowH , * m ) ;
}
2021-11-01 14:28:44 +00:00
/*
if ( app - > arpH . isValid ( ) )
{
audio_record_play : : exec ( app - > arpH , * m ) ;
if ( audio_record_play : : is_started ( app - > arpH ) )
io : : uiSendValue ( app - > ioH , kInvalidId , uiFindElementUuId ( app - > ioH , kCurAudioSecsId ) , audio_record_play : : current_loc_seconds ( app - > arpH ) ) ;
}
*/
switch ( m - > tid )
{
case io : : kTimerTId :
break ;
case io : : kSerialTId :
break ;
case io : : kMidiTId :
break ;
case io : : kAudioTId :
break ;
case io : : kAudioMeterTId :
break ;
case io : : kSockTId :
break ;
case io : : kWebSockTId :
break ;
case io : : kUiTId :
rc = _ui_callback ( app , m - > u . ui ) ;
break ;
default :
assert ( 0 ) ;
}
return rc ;
}
}
}
2021-12-11 20:21:03 +00:00
cw : : rc_t cw : : preset_sel_app : : main ( const object_t * cfg , const object_t * flow_proc_dict )
2021-11-01 14:28:44 +00:00
{
rc_t rc ;
2021-11-06 02:28:38 +00:00
app_t app = { } ;
2021-11-03 15:09:07 +00:00
const object_t * params_cfg = nullptr ;
2021-11-01 14:28:44 +00:00
// Parse the configuration
2021-11-03 15:09:07 +00:00
if ( ( rc = _parseCfg ( & app , cfg , params_cfg ) ) ! = kOkRC )
2021-11-01 14:28:44 +00:00
goto errLabel ;
// create the io framework instance
if ( ( rc = io : : create ( app . ioH , cfg , _io_callback , & app , mapA , mapN ) ) ! = kOkRC )
{
rc = cwLogError ( kOpFailRC , " IO Framework create failed. " ) ;
goto errLabel ;
}
2021-11-06 02:28:38 +00:00
// create the preset selection state object
if ( ( rc = create ( app . psH , app . presets_cfg ) ) ! = kOkRC )
{
rc = cwLogError ( kOpFailRC , " Preset state control object create failed. " ) ;
goto errLabel ;
}
2021-11-01 14:28:44 +00:00
// create the MIDI record-play object
2021-11-03 15:09:07 +00:00
if ( ( rc = midi_record_play : : create ( app . mrpH , app . ioH , * params_cfg , _midi_play_callback , & app ) ) ! = kOkRC )
2021-11-01 14:28:44 +00:00
{
rc = cwLogError ( rc , " MIDI record-play object create failed. " ) ;
goto errLabel ;
}
2021-12-11 20:21:03 +00:00
// create the IO Flow controller
2021-12-19 17:18:22 +00:00
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 )
2021-12-11 20:21:03 +00:00
{
rc = cwLogError ( rc , " The IO Flow controller create failed. " ) ;
goto errLabel ;
}
2021-11-01 14:28:44 +00:00
/*
// create the audio record-play object
if ( ( rc = audio_record_play : : create ( app . arpH , app . ioH , * cfg ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Audio record-play object create failed. " ) ;
goto errLabel ;
}
*/
// start the io framework instance
if ( ( rc = io : : start ( app . ioH ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Preset-select app start failed. " ) ;
goto errLabel ;
}
// execute the io framework
while ( ! isShuttingDown ( app . ioH ) )
{
exec ( app . ioH ) ;
sleepMs ( 50 ) ;
}
2021-12-19 17:18:22 +00:00
if ( ( rc = io : : stop ( app . ioH ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " IO API stop failed. " ) ;
goto errLabel ;
}
2021-11-01 14:28:44 +00:00
errLabel :
2021-12-19 17:18:22 +00:00
2021-11-01 14:28:44 +00:00
_free ( app ) ;
io : : destroy ( app . ioH ) ;
printf ( " Preset-select Done. \n " ) ;
return rc ;
}