2021-11-01 14:28:44 +00:00
# include "cwCommon.h"
# include "cwLog.h"
# include "cwCommonImpl.h"
# include "cwMem.h"
# include "cwText.h"
2022-12-17 22:54:39 +00:00
# include "cwNumericConvert.h"
# include "cwObject.h"
2021-11-01 14:28:44 +00:00
# include "cwFileSys.h"
# include "cwFile.h"
# include "cwTime.h"
# include "cwMidiDecls.h"
# include "cwMidi.h"
2023-11-26 20:43:52 +00:00
# include "cwMidiFile.h"
2021-11-01 14:28:44 +00:00
# include "cwUiDecls.h"
# include "cwIo.h"
2023-05-25 20:16:21 +00:00
# include "cwScoreFollowerPerf.h"
2021-11-01 14:28:44 +00:00
# include "cwIoMidiRecordPlay.h"
# include "cwIoPresetSelApp.h"
2021-12-28 01:32:56 +00:00
# include "cwVectOps.h"
# include "cwMath.h"
# include "cwDspTypes.h"
# include "cwMtx.h"
2024-01-13 15:21:06 +00:00
# include "cwFlowDecl.h"
2021-12-28 01:32:56 +00:00
# include "cwFlow.h"
# include "cwFlowTypes.h"
# include "cwFlowCross.h"
2021-12-11 20:21:03 +00:00
# include "cwIoFlow.h"
2021-11-06 02:28:38 +00:00
# include "cwPresetSel.h"
2023-03-20 23:41:58 +00:00
# include "cwVelTableTuner.h"
2023-09-13 00:32:38 +00:00
# include "cwDynRefTbl.h"
# include "cwScoreParse.h"
# include "cwSfScore.h"
# include "cwSfTrack.h"
2024-02-08 16:25:38 +00:00
# include "cwPerfMeas.h"
# include "cwPianoScore.h"
2023-05-01 01:22:49 +00:00
# include "cwScoreFollower.h"
2021-11-01 14:28:44 +00:00
2023-02-26 18:44:54 +00:00
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 ,
2022-01-22 14:55:17 +00:00
kNetPrintBtnId ,
2021-11-01 14:28:44 +00:00
kReportBtnId ,
2024-02-10 16:34:06 +00:00
kLatencyBtnId ,
2024-02-18 13:41:19 +00:00
2021-11-01 14:28:44 +00:00
kStartBtnId ,
kStopBtnId ,
2024-03-09 20:12:56 +00:00
kBegPlayLocNumbId ,
kEndPlayLocNumbId ,
kLockLoctnCheckId ,
2022-10-26 12:49:20 +00:00
kLiveCheckId ,
2023-01-05 12:31:49 +00:00
kTrackMidiCheckId ,
2022-01-22 14:55:17 +00:00
kPrintMidiCheckId ,
kPianoMidiCheckId ,
kSamplerMidiCheckId ,
kSyncDelayMsId ,
kWetInGainId ,
kWetOutGainId ,
kDryGainId ,
2021-11-01 14:28:44 +00:00
kMidiThruCheckId ,
kCurMidiEvtCntId ,
kTotalMidiEvtCntId ,
kCurAudioSecsId ,
kTotalAudioSecsId ,
kSaveBtnId ,
kLoadBtnId ,
2023-05-16 22:22:56 +00:00
kPerfSelId ,
2023-12-03 16:20:38 +00:00
kAltSelId ,
2024-02-18 13:41:19 +00:00
kPriPresetProbCheckId ,
kSecPresetProbCheckId ,
kPresetInterpCheckId ,
2024-03-09 20:12:56 +00:00
kPresetAllowAllCheckId ,
2021-11-01 14:28:44 +00:00
2024-02-18 13:41:19 +00:00
2023-05-25 20:16:21 +00:00
kEnaRecordCheckId ,
kMidiSaveBtnId ,
kMidiLoadBtnId ,
kMidiLoadFnameId ,
kSfResetBtnId ,
kSfResetLocNumbId ,
2021-11-06 02:28:38 +00:00
kInsertLocId ,
kInsertBtnId ,
kDeleteBtnId ,
2021-12-28 01:32:56 +00:00
kStatusId ,
2023-01-05 12:31:49 +00:00
kPvWndSmpCntId ,
kSdBypassId ,
kSdInGainId ,
kSdCeilingId ,
kSdExpoId ,
kSdThreshId ,
kSdUprId ,
kSdLwrId ,
kSdMixId ,
kCmpBypassId ,
kAMtrIn0Id ,
kAMtrIn1Id ,
kAMtrOut0Id ,
kAMtrOut1Id ,
2021-12-30 02:57:04 +00:00
kLogId ,
2021-11-06 02:28:38 +00:00
kFragListId ,
kFragPanelId ,
2022-12-05 22:25:59 +00:00
kFragMeasId ,
2021-12-28 01:32:56 +00:00
kFragBegLocId ,
2021-11-06 02:28:38 +00:00
kFragEndLocId ,
kFragPresetRowId ,
kFragPresetSelId ,
2022-05-21 15:22:53 +00:00
kFragPresetSeqSelId ,
2021-11-06 02:28:38 +00:00
kFragPresetOrderId ,
2023-12-03 16:20:38 +00:00
kFragPresetAltId ,
2021-11-06 02:28:38 +00:00
2021-12-28 01:32:56 +00:00
kFragInGainId ,
kFragOutGainId ,
2021-11-06 02:28:38 +00:00
kFragWetDryGainId ,
2021-12-28 01:32:56 +00:00
kFragFadeOutMsId ,
kFragBegPlayLocId ,
kFragEndPlayLocId ,
kFragPlayBtnId ,
2022-05-21 13:29:03 +00:00
kFragPlaySeqBtnId ,
2022-05-21 15:22:53 +00:00
kFragPlayAllBtnId ,
2023-03-20 23:41:58 +00:00
kFragNoteId ,
2021-11-01 14:28:44 +00:00
2023-03-20 23:41:58 +00:00
kVelTblMinId = vtbl : : kVtMinId ,
2023-05-16 22:22:56 +00:00
kVelTblMaxId = vtbl : : kVtMaxId ,
kPerfOptionBaseId = kVelTblMaxId + 1 ,
2022-01-22 14:55:17 +00:00
} ;
2021-11-01 14:28:44 +00:00
// Application Id's for the resource based UI elements.
ui : : appIdMap_t mapA [ ] =
{
{ ui : : kRootAppId , kPanelDivId , " panelDivId " } ,
{ kPanelDivId , kQuitBtnId , " quitBtnId " } ,
{ kPanelDivId , kIoReportBtnId , " ioReportBtnId " } ,
2022-01-22 14:55:17 +00:00
{ kPanelDivId , kNetPrintBtnId , " netPrintBtnId " } ,
2021-11-01 14:28:44 +00:00
{ kPanelDivId , kReportBtnId , " reportBtnId " } ,
2024-02-10 16:34:06 +00:00
{ kPanelDivId , kLatencyBtnId , " latencyBtnId " } ,
2021-11-01 14:28:44 +00:00
{ kPanelDivId , kStartBtnId , " startBtnId " } ,
{ kPanelDivId , kStopBtnId , " stopBtnId " } ,
2024-03-09 20:12:56 +00:00
{ kPanelDivId , kBegPlayLocNumbId , " begLocNumbId " } ,
{ kPanelDivId , kEndPlayLocNumbId , " endLocNumbId " } ,
{ kPanelDivId , kLockLoctnCheckId , " locLoctnCheckId " } ,
2022-10-26 12:49:20 +00:00
{ kPanelDivId , kLiveCheckId , " liveCheckId " } ,
2023-01-05 12:31:49 +00:00
{ kPanelDivId , kTrackMidiCheckId , " trackMidiCheckId " } ,
2022-01-22 14:55:17 +00:00
{ kPanelDivId , kPrintMidiCheckId , " printMidiCheckId " } ,
{ kPanelDivId , kPianoMidiCheckId , " pianoMidiCheckId " } ,
{ kPanelDivId , kSamplerMidiCheckId , " samplerMidiCheckId " } ,
{ kPanelDivId , kSyncDelayMsId , " syncDelayMsId " } ,
{ kPanelDivId , kWetInGainId , " wetInGainId " } ,
{ kPanelDivId , kWetOutGainId , " wetOutGainId " } ,
{ kPanelDivId , kDryGainId , " dryGainId " } ,
2021-11-01 14:28:44 +00:00
{ kPanelDivId , kMidiThruCheckId , " midiThruCheckId " } ,
{ kPanelDivId , kCurMidiEvtCntId , " curMidiEvtCntId " } ,
{ kPanelDivId , kTotalMidiEvtCntId , " totalMidiEvtCntId " } ,
{ kPanelDivId , kCurAudioSecsId , " curAudioSecsId " } ,
{ kPanelDivId , kTotalAudioSecsId , " totalAudioSecsId " } ,
{ kPanelDivId , kSaveBtnId , " saveBtnId " } ,
{ kPanelDivId , kLoadBtnId , " loadBtnId " } ,
2023-05-16 22:22:56 +00:00
{ kPanelDivId , kPerfSelId , " perfSelId " } ,
2023-12-03 16:20:38 +00:00
{ kPanelDivId , kAltSelId , " altSelId " } ,
2024-03-09 20:12:56 +00:00
{ kPanelDivId , kPriPresetProbCheckId , " presetProbPriCheckId " } ,
{ kPanelDivId , kSecPresetProbCheckId , " presetProbSecCheckId " } ,
{ kPanelDivId , kPresetInterpCheckId , " presetInterpCheckId " } ,
{ kPanelDivId , kPresetAllowAllCheckId , " presetAllowAllCheckId " } ,
2021-11-01 14:28:44 +00:00
2023-05-25 20:16:21 +00:00
{ kPanelDivId , kEnaRecordCheckId , " enaRecordCheckId " } ,
{ kPanelDivId , kMidiSaveBtnId , " midiSaveBtnId " } ,
{ kPanelDivId , kMidiLoadBtnId , " midiLoadBtnId " } ,
{ kPanelDivId , kMidiLoadFnameId , " midiLoadFnameId " } ,
{ kPanelDivId , kSfResetBtnId , " sfResetBtnId " } ,
{ kPanelDivId , kSfResetLocNumbId , " sfResetLocNumbId " } ,
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 " } ,
2022-03-20 14:27:46 +00:00
2023-01-05 12:31:49 +00:00
{ kPanelDivId , kPvWndSmpCntId , " pvWndSmpCntId " } ,
{ kPanelDivId , kSdBypassId , " sdBypassId " } ,
{ kPanelDivId , kSdInGainId , " sdInGainId " } ,
{ kPanelDivId , kSdCeilingId , " sdCeilingId " } ,
{ kPanelDivId , kSdExpoId , " sdExpoId " } ,
{ kPanelDivId , kSdThreshId , " sdThreshId " } ,
{ kPanelDivId , kSdUprId , " sdUprId " } ,
{ kPanelDivId , kSdLwrId , " sdLwrId " } ,
{ kPanelDivId , kSdMixId , " sdMixId " } ,
{ kPanelDivId , kCmpBypassId , " cmpBypassId " } ,
{ kPanelDivId , kStatusId , " statusId " } ,
{ kPanelDivId , kAMtrIn0Id , " aMtrIn0 " } ,
{ kPanelDivId , kAMtrIn1Id , " aMtrIn1 " } ,
{ kPanelDivId , kAMtrOut0Id , " aMtrOut0 " } ,
{ kPanelDivId , kAMtrOut1Id , " aMtrOut1 " } ,
2022-03-20 14:27:46 +00:00
2021-12-30 02:57:04 +00:00
{ kPanelDivId , kLogId , " logId " } ,
2021-11-06 02:28:38 +00:00
2023-03-20 23:41:58 +00:00
2021-12-28 01:32:56 +00:00
{ kPanelDivId , kFragListId , " fragListId " } ,
{ kFragListId , kFragPanelId , " fragPanelId " } ,
2022-12-05 22:25:59 +00:00
{ kFragPanelId , kFragMeasId , " fragMeasId " } ,
2021-12-28 01:32:56 +00:00
{ kFragPanelId , kFragBegLocId , " fragBegLocId " } ,
2021-11-06 02:28:38 +00:00
{ kFragPanelId , kFragEndLocId , " fragEndLocId " } ,
{ kFragPanelId , kFragPresetRowId , " fragPresetRowId " } ,
2021-12-28 01:32:56 +00:00
{ kFragPanelId , kFragInGainId , " fragInGainId " } ,
{ kFragPanelId , kFragOutGainId , " fragOutGainId " } ,
2021-11-06 02:28:38 +00:00
{ kFragPanelId , kFragWetDryGainId , " fragWetDryGainId " } ,
2021-12-28 01:32:56 +00:00
{ kFragPanelId , kFragFadeOutMsId , " fragFadeOutMsId " } ,
{ kFragPanelId , kFragBegPlayLocId , " fragBegPlayLocId " } ,
{ kFragPanelId , kFragEndPlayLocId , " fragEndPlayLocId " } ,
{ kFragPanelId , kFragPlayBtnId , " fragPlayBtnId " } ,
2022-05-21 15:22:53 +00:00
{ kFragPanelId , kFragPlaySeqBtnId , " fragPlaySeqBtnId " } ,
{ kFragPanelId , kFragPlayAllBtnId , " fragPlayAllBtnId " } ,
{ kFragPanelId , kFragNoteId , " fragNoteId " } ,
2023-03-20 23:41:58 +00:00
2021-11-06 02:28:38 +00:00
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 ;
2023-05-27 20:01:17 +00:00
2023-06-27 21:53:04 +00:00
typedef struct vel_tbl_str
{
const char * name ;
const char * device ;
} vel_tbl_t ;
2023-05-27 20:01:17 +00:00
typedef struct perf_recording_str
{
2023-06-27 21:53:04 +00:00
char * fname ; // perf recording
2023-11-26 20:43:52 +00:00
unsigned sess_numb ;
unsigned take_numb ;
unsigned beg_loc ;
unsigned end_loc ;
2023-06-27 21:53:04 +00:00
char * label ; // menu label
unsigned id ; // menu appId
unsigned uuId ; // menu uuid
vel_tbl_t * vel_tblA ; // vel_tblA[ velTblN ]
unsigned vel_tblN ; //
2023-05-27 20:01:17 +00:00
struct perf_recording_str * link ;
} perf_recording_t ;
2021-11-01 14:28:44 +00:00
typedef struct app_str
{
2023-06-27 21:53:04 +00:00
io : : handle_t ioH ;
// path components for reading/writing the preset assignments
const char * record_dir ;
const char * record_fn ;
const char * record_fn_ext ;
const char * record_backup_dir ;
2021-11-01 14:28:44 +00:00
2021-11-06 02:28:38 +00:00
const char * scoreFn ;
2023-05-27 20:01:17 +00:00
const object_t * perfDirL ;
2023-03-20 23:41:58 +00:00
const char * velTableFname ;
const char * velTableBackupDir ;
2022-01-22 14:55:17 +00:00
const object_t * midi_play_record_cfg ;
2021-11-06 02:28:38 +00:00
const object_t * presets_cfg ;
2023-01-05 12:31:49 +00:00
object_t * flow_proc_dict ;
2021-12-11 20:21:03 +00:00
const object_t * flow_cfg ;
2023-05-01 01:22:49 +00:00
const object_t * score_follower_cfg ;
2023-02-19 19:18:53 +00:00
const char * in_audio_dev_file ;
unsigned in_audio_dev_idx ;
2023-02-26 18:44:54 +00:00
unsigned in_audio_begin_loc ;
double in_audio_offset_sec ;
2023-05-01 01:22:49 +00:00
2023-06-27 21:53:04 +00:00
score_follower : : handle_t sfH ;
midi_record_play : : handle_t mrpH ;
2021-11-01 14:28:44 +00:00
2024-02-08 16:25:38 +00:00
perf_score : : handle_t perfScoreH ;
2023-06-27 21:53:04 +00:00
loc_map_t * locMap ;
2021-11-01 14:28:44 +00:00
unsigned locMapN ;
2021-11-06 02:28:38 +00:00
2023-06-27 21:53:04 +00:00
unsigned insertLoc ; // last valid insert location id received from the GUI
2021-12-30 02:57:04 +00:00
2023-12-05 20:34:25 +00:00
unsigned minScoreLoc ; // min/max locations of the currently loaded score
unsigned maxScoreLoc ; //
unsigned minPerfLoc ; // min/max locations of the currently loaded performance
unsigned maxPerfLoc ;
2022-10-15 13:23:58 +00:00
2023-06-27 21:53:04 +00:00
unsigned beg_play_loc ; // beg/end play loc's from the UI
unsigned end_play_loc ;
2024-03-09 20:12:56 +00:00
bool lockLoctnFl ;
2021-11-14 18:11:11 +00:00
2023-06-27 21:53:04 +00:00
preset_sel : : handle_t psH ;
const preset_sel : : frag_t * psNextFrag ;
time : : spec_t psLoadT0 ;
2023-05-25 20:16:21 +00:00
2023-06-27 21:53:04 +00:00
vtbl : : handle_t vtH ;
io_flow : : handle_t ioFlowH ;
2021-12-28 01:32:56 +00:00
2021-12-19 17:18:22 +00:00
double crossFadeSrate ;
unsigned crossFadeCnt ;
2022-01-22 14:55:17 +00:00
2023-06-27 21:53:04 +00:00
bool printMidiFl ;
2022-03-20 14:27:46 +00:00
2024-02-18 13:41:19 +00:00
unsigned multiPresetFlags ;
2023-06-27 21:53:04 +00:00
bool seqActiveFl ; // true if the sequence is currently active (set by 'Play Seq' btn)
unsigned seqStartedFl ; // set by the first seq idle callback
unsigned seqFragId ; //
unsigned seqPresetIdx ; //
2022-10-26 12:49:20 +00:00
2023-06-27 21:53:04 +00:00
bool useLiveMidiFl ; // use incoming MIDI to drive program (otherwise use score file)
bool trackMidiFl ; // apply presets based on MIDI location (otherwise respond only to direct manipulation of fragment control)
2023-05-25 20:16:21 +00:00
2023-06-27 21:53:04 +00:00
bool enableRecordFl ; // enable recording of incoming MIDI
2023-05-25 20:16:21 +00:00
char * midiRecordDir ;
const char * midiRecordFolder ;
char * midiLoadFname ;
2023-01-05 12:31:49 +00:00
2023-05-25 20:16:21 +00:00
unsigned sfResetLoc ;
2023-05-01 01:22:49 +00:00
2023-01-21 16:49:07 +00:00
unsigned pvWndSmpCnt ;
bool sdBypassFl ;
double sdInGain ;
double sdCeiling ;
double sdExpo ;
double sdThresh ;
double sdUpr ;
double sdLwr ;
double sdMix ;
bool cmpBypassFl ;
2023-05-27 20:01:17 +00:00
unsigned dfltSyncDelayMs ;
perf_recording_t * perfRecordingBeg ;
perf_recording_t * perfRecordingEnd ;
2024-03-09 20:12:56 +00:00
const char * dflt_perf_label ;
unsigned dflt_perf_app_id ;
2024-03-28 23:48:46 +00:00
unsigned run_dur_secs ;
2024-03-09 20:12:56 +00:00
2022-05-21 13:29:03 +00:00
2021-11-01 14:28:44 +00:00
} app_t ;
2022-12-17 22:54:39 +00:00
rc_t _apply_command_line_args ( app_t * app , int argc , const char * argv [ ] )
{
rc_t rc = kOkRC ;
for ( int i = 0 ; i < argc ; i + = 2 )
{
2023-03-20 23:41:58 +00:00
if ( textCompare ( argv [ i ] , " record_fn " ) = = 0 )
2022-12-17 22:54:39 +00:00
{
app - > record_fn = argv [ i + 1 ] ;
goto found_fl ;
}
2023-03-20 23:41:58 +00:00
if ( textCompare ( argv [ i ] , " score_fn " ) = = 0 )
2022-12-17 22:54:39 +00:00
{
app - > scoreFn = argv [ i + 1 ] ;
goto found_fl ;
}
2023-03-20 23:41:58 +00:00
if ( textCompare ( argv [ i ] , " beg_play_loc " ) = = 0 )
2022-12-17 22:54:39 +00:00
{
string_to_number ( argv [ i + 1 ] , app - > beg_play_loc ) ;
goto found_fl ;
}
2023-03-20 23:41:58 +00:00
if ( textCompare ( argv [ i ] , " end_play_loc " ) = = 0 )
2022-12-17 22:54:39 +00:00
{
string_to_number ( argv [ i + 1 ] , app - > end_play_loc ) ;
goto found_fl ;
}
rc = cwLogError ( kSyntaxErrorRC , " The command line argument: '%s' was not recognized. " , argv [ i ] ) ;
goto errLabel ;
found_fl :
printf ( " Command line override '%s=%s' . \n " , argv [ i ] , argv [ i + 1 ] ) ;
}
errLabel :
return rc ;
}
rc_t _parseCfg ( app_t * app , const object_t * cfg , const object_t * & params_cfgRef , int argc , const char * argv [ ] )
2021-11-01 14:28:44 +00:00
{
2023-03-20 23:41:58 +00:00
rc_t rc = kOkRC ;
2022-10-26 12:49:20 +00:00
const char * flow_proc_dict_fn = nullptr ;
2023-05-25 20:16:21 +00:00
const char * midi_record_dir ;
2023-09-13 00:32:38 +00:00
if ( ( rc = cfg - > getv ( " params " , params_cfgRef ,
2021-12-11 20:21:03 +00:00
" 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 ;
}
2023-09-13 00:32:38 +00:00
if ( ( rc = params_cfgRef - > getv ( " record_dir " , app - > record_dir ,
2023-03-20 23:41:58 +00:00
" record_fn " , app - > record_fn ,
" record_fn_ext " , app - > record_fn_ext ,
" score_fn " , app - > scoreFn ,
2023-05-27 20:01:17 +00:00
" perfDirL " , app - > perfDirL ,
2023-05-25 20:16:21 +00:00
" flow_proc_dict_fn " , flow_proc_dict_fn ,
2023-03-20 23:41:58 +00:00
" midi_play_record " , app - > midi_play_record_cfg ,
" vel_table_fname " , app - > velTableFname ,
" vel_table_backup_dir " , app - > velTableBackupDir ,
" presets " , app - > presets_cfg ,
" crossFadeCount " , app - > crossFadeCnt ,
" beg_play_loc " , app - > beg_play_loc ,
2023-05-01 01:22:49 +00:00
" end_play_loc " , app - > end_play_loc ,
2024-03-25 14:46:45 +00:00
" dflt_perf_label " , app - > dflt_perf_label ,
2024-03-28 23:48:46 +00:00
" run_dur_secs " , app - > run_dur_secs ,
2023-05-25 20:16:21 +00:00
" live_mode_fl " , app - > useLiveMidiFl ,
" enable_recording_fl " , app - > enableRecordFl ,
" midi_record_dir " , midi_record_dir ,
" midi_record_folder " , app - > midiRecordFolder ,
" sf_reset_loc " , app - > sfResetLoc ,
2023-05-01 01:22:49 +00:00
" score_follower " , app - > score_follower_cfg ) ) ! = kOkRC )
2021-11-01 14:28:44 +00:00
{
rc = cwLogError ( kSyntaxErrorRC , " Preset Select App configuration parse failed. " ) ;
2022-12-17 13:18:05 +00:00
goto errLabel ;
2021-11-01 14:28:44 +00:00
}
2023-02-26 18:44:54 +00:00
if ( ( rc = params_cfgRef - > getv_opt ( " in_audio_dev_file " , app - > in_audio_dev_file ,
" in_audio_file_begin_loc " , app - > in_audio_begin_loc ,
" in_audio_file_offset_sec " , app - > in_audio_offset_sec ) ) ! = kOkRC )
2023-02-19 19:18:53 +00:00
{
rc = cwLogError ( rc , " Parse of optional cfg. params failed.. " ) ;
goto errLabel ;
}
2022-12-17 22:54:39 +00:00
_apply_command_line_args ( app , argc , argv ) ;
2023-05-25 20:16:21 +00:00
2022-05-14 14:19:18 +00:00
if ( ( app - > scoreFn = filesys : : expandPath ( app - > scoreFn ) ) = = nullptr )
{
rc = cwLogError ( kInvalidArgRC , " The score file name is invalid. " ) ;
goto errLabel ;
}
if ( ( app - > record_dir = filesys : : expandPath ( app - > record_dir ) ) = = nullptr )
{
rc = cwLogError ( kInvalidArgRC , " The record directory path is invalid. " ) ;
goto errLabel ;
}
2022-10-26 12:49:20 +00:00
2023-05-25 20:16:21 +00:00
if ( ( app - > midiRecordDir = filesys : : expandPath ( midi_record_dir ) ) = = nullptr )
{
rc = cwLogError ( kInvalidArgRC , " The midi record path is invalid. " ) ;
goto errLabel ;
}
2022-12-17 13:18:05 +00:00
if ( ( app - > record_backup_dir = filesys : : makeFn ( app - > record_dir , " backup " , nullptr , nullptr ) ) = = nullptr )
{
rc = cwLogError ( kInvalidArgRC , " The record backup directory path is invalid. " ) ;
goto errLabel ;
}
2022-10-26 12:49:20 +00:00
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 ;
}
2022-12-17 13:18:05 +00:00
2021-11-01 14:28:44 +00:00
// verify that the output directory exists
2022-12-17 13:18:05 +00:00
if ( ( rc = filesys : : makeDir ( app - > record_dir ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Unable to create the base output directory:%s. " , cwStringNullGuard ( app - > record_dir ) ) ;
goto errLabel ;
}
2021-11-01 14:28:44 +00:00
2023-05-25 20:16:21 +00:00
// verify that the midi record directory exists
if ( ( rc = filesys : : makeDir ( app - > midiRecordDir ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Unable to create the MIDI recording directory:%s. " , cwStringNullGuard ( app - > midiRecordDir ) ) ;
goto errLabel ;
}
2022-12-17 13:18:05 +00:00
// verify that the output backup directory exists
if ( ( rc = filesys : : makeDir ( app - > record_backup_dir ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Unable to create the output backup directory:%s. " , cwStringNullGuard ( app - > record_backup_dir ) ) ;
}
2021-11-06 02:28:38 +00:00
2022-12-17 22:54:39 +00:00
app - > insertLoc = kInvalidId ; // initialize 'insertLoc' to be invalid
2021-11-01 14:28:44 +00:00
2023-02-19 19:18:53 +00:00
errLabel :
2021-11-01 14:28:44 +00:00
return rc ;
}
2023-11-26 20:43:52 +00:00
void _set_statusv ( app_t * app , const char * fmt , va_list vl )
{
const int sN = 128 ;
char s [ sN ] ;
vsnprintf ( s , sN , fmt , vl ) ;
uiSendValue ( app - > ioH , uiFindElementUuId ( app - > ioH , kStatusId ) , s ) ;
//printf("Status:%s\n",s);
}
void _set_status ( app_t * app , const char * fmt , . . . )
{
va_list vl ;
va_start ( vl , fmt ) ;
_set_statusv ( app , fmt , vl ) ;
va_end ( vl ) ;
}
void _clear_status ( app_t * app )
{
_set_status ( app , " Ok " ) ;
}
void _log_output_func ( void * arg , unsigned level , const char * text )
{
app_t * app = ( app_t * ) arg ;
unsigned logUuId = uiFindElementUuId ( app - > ioH , kLogId ) ;
2024-03-28 23:48:46 +00:00
//uiSetLogLine( app->ioH, logUuId, text );
2023-11-26 20:43:52 +00:00
log : : defaultOutput ( nullptr , level , text ) ;
}
void _free_perf_recording_recd ( perf_recording_t * prp )
{
if ( prp ! = nullptr )
{
mem : : release ( prp - > label ) ;
mem : : release ( prp - > fname ) ;
mem : : release ( prp - > vel_tblA ) ;
mem : : release ( prp ) ;
}
}
rc_t _free ( app_t & app )
{
if ( app . flow_proc_dict ! = nullptr )
app . flow_proc_dict - > free ( ) ;
perf_recording_t * prp = app . perfRecordingBeg ;
while ( prp ! = nullptr )
{
perf_recording_t * tmp = prp - > link ;
_free_perf_recording_recd ( prp ) ;
prp = tmp ;
}
mem : : release ( ( char * & ) app . record_backup_dir ) ;
mem : : release ( ( char * & ) app . record_dir ) ;
mem : : release ( ( char * & ) app . scoreFn ) ;
mem : : release ( app . midiRecordDir ) ;
mem : : release ( app . midiLoadFname ) ;
vtbl : : destroy ( app . vtH ) ;
destroy ( app . sfH ) ;
preset_sel : : destroy ( app . psH ) ;
io_flow : : destroy ( app . ioFlowH ) ;
midi_record_play : : destroy ( app . mrpH ) ;
2024-02-08 16:25:38 +00:00
perf_score : : destroy ( app . perfScoreH ) ;
2023-11-26 20:43:52 +00:00
mem : : release ( app . locMap ) ;
return kOkRC ;
}
2021-11-01 14:28:44 +00:00
2023-05-27 20:01:17 +00:00
rc_t _load_perf_recording_menu ( app_t * app )
{
rc_t rc = kOkRC ;
perf_recording_t * prp = nullptr ;
unsigned id = 0 ;
2023-06-27 21:53:04 +00:00
unsigned selectUuId = kInvalidId ;
2023-05-27 20:01:17 +00:00
// get the peformance menu UI uuid
if ( ( selectUuId = io : : uiFindElementUuId ( app - > ioH , kPerfSelId ) ) = = kInvalidId )
{
rc = cwLogError ( rc , " The performance list base UI element does not exist. " ) ;
goto errLabel ;
}
// for each performance recording
2023-06-27 21:53:04 +00:00
for ( prp = app - > perfRecordingBeg ; prp ! = nullptr ; prp = prp - > link )
2023-05-27 20:01:17 +00:00
{
// create an option entry in the selection ui
if ( ( rc = uiCreateOption ( app - > ioH , prp - > uuId , selectUuId , nullptr , kPerfOptionBaseId + id , kInvalidId , " optClass " , prp - > label ) ) ! = kOkRC )
{
rc = cwLogError ( kSyntaxErrorRC , " The performance recording menu create failed on %s. " , prp - > label ) ;
goto errLabel ;
}
2024-03-09 20:12:56 +00:00
if ( app - > dflt_perf_label )
if ( textIsEqual ( prp - > label , app - > dflt_perf_label ) )
{
app - > dflt_perf_app_id = kPerfOptionBaseId + id ;
cwLogInfo ( " The default performance '%s' was found. " , prp - > label ) ;
}
2023-05-27 20:01:17 +00:00
prp - > id = id ;
id + = 1 ;
}
errLabel :
return rc ;
}
2023-12-03 16:20:38 +00:00
rc_t _load_alt_menu ( app_t * app )
{
rc_t rc = kOkRC ;
unsigned uuid ;
unsigned selectUuId = kInvalidId ;
// get the peformance menu UI uuid
if ( ( selectUuId = io : : uiFindElementUuId ( app - > ioH , kAltSelId ) ) = = kInvalidId )
{
rc = cwLogError ( rc , " The 'alt' list base UI element does not exist. " ) ;
goto errLabel ;
}
for ( unsigned altId = 0 ; altId < alt_count ( app - > psH ) ; + + altId )
{
const char * label = alt_label ( app - > psH , altId ) ;
assert ( label ! = nullptr ) ;
// create an option entry in the selection ui
if ( ( rc = uiCreateOption ( app - > ioH , uuid , selectUuId , nullptr , altId , kInvalidId , " optClass " , label ) ) ! = kOkRC )
{
rc = cwLogError ( kSyntaxErrorRC , " The 'alt' menu create failed on %s. " , cwStringNullGuard ( label ) ) ;
goto errLabel ;
}
}
errLabel :
return rc ;
}
2023-11-26 20:43:52 +00:00
2023-06-27 21:53:04 +00:00
rc_t _parse_perf_recording_vel_tbl ( app_t * app , const object_t * velTblCfg , vel_tbl_t * & velTblA_Ref , unsigned & velTblN_Ref )
2023-05-27 20:01:17 +00:00
{
2023-06-27 21:53:04 +00:00
rc_t rc = kOkRC ;
velTblA_Ref = nullptr ;
velTblN_Ref = 0 ;
unsigned velTblN = velTblCfg - > child_count ( ) ;
vel_tbl_t * velTblA = nullptr ;
if ( velTblN > 0 )
{
velTblA = mem : : allocZ < vel_tbl_t > ( velTblN ) ;
for ( unsigned i = 0 ; i < velTblN ; + + i )
{
if ( ( rc = velTblCfg - > child_ele ( i ) - > getv ( " name " , velTblA [ i ] . name ,
" device " , velTblA [ i ] . device ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " The vel table at index '%i' parse failed. " , i ) ;
goto errLabel ;
}
}
}
velTblA_Ref = velTblA ;
velTblN_Ref = velTblN ;
errLabel :
return rc ;
}
2023-11-26 20:43:52 +00:00
rc_t _create_perf_recording_recd ( app_t * app , const char * dir , const char * recording_folder , const char * fname , const object_t * velTblCfg )
{
rc_t rc = kOkRC ;
perf_recording_t * prp = nullptr ;
object_t * meta_cfg = nullptr ;
const char * take_label = nullptr ;
char * perf_fname = nullptr ;
char * meta_fname = nullptr ;
bool skip_fl = false ;
2024-03-28 23:48:46 +00:00
2023-11-26 20:43:52 +00:00
// create the performance recording file path
if ( ( perf_fname = filesys : : makeFn ( dir , fname , nullptr , recording_folder , nullptr ) ) = = nullptr )
{
rc = cwLogError ( kOpFailRC , " The performance file name formation failed on directory '%s'. " , cwStringNullGuard ( recording_folder ) ) ;
goto errLabel ;
}
// if path does not identify an existing file - skip it
if ( ! filesys : : isFile ( perf_fname ) )
goto errLabel ;
if ( ( meta_fname = filesys : : makeFn ( dir , " meta " , " cfg " , recording_folder , nullptr ) ) = = nullptr )
{
rc = cwLogError ( kOpFailRC , " The performance meta file name formation failed on directory '%s'. " , cwStringNullGuard ( recording_folder ) ) ;
goto errLabel ;
}
// parse the perf. meta file
if ( ( rc = objectFromFile ( meta_fname , meta_cfg ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Performance meta file '%s' parse failed. " , cwStringNullGuard ( meta_fname ) ) ;
goto errLabel ;
}
// allocate the perf_recording_t recd
prp = mem : : allocZ < perf_recording_t > ( ) ;
// read the meta file values
if ( ( rc = meta_cfg - > getv ( " take_label " , take_label ,
" session_number " , prp - > sess_numb ,
" take_number " , prp - > take_numb ,
" beg_loc " , prp - > beg_loc ,
" end_loc " , prp - > end_loc ,
" skip_score_follow_fl " , skip_fl ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Performance meta file '%s' parse failed. " , cwStringNullGuard ( meta_fname ) ) ;
goto errLabel ;
}
if ( skip_fl )
{
cwLogWarning ( " 'Skip score follow flag' set.Skipping recorded performance '%s'. " , cwStringNullGuard ( take_label ) ) ;
goto errLabel ;
}
prp - > label = mem : : duplStr ( take_label ) ;
prp - > fname = mem : : duplStr ( perf_fname ) ;
if ( ( rc = _parse_perf_recording_vel_tbl ( app , velTblCfg , prp - > vel_tblA , prp - > vel_tblN ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Parse failed on vel table entry for the recorded performance in '%s'. " , cwStringNullGuard ( dir ) ) ;
goto errLabel ;
}
if ( app - > perfRecordingEnd = = nullptr )
{
app - > perfRecordingBeg = prp ;
app - > perfRecordingEnd = prp ;
}
else
{
app - > perfRecordingEnd - > link = prp ;
app - > perfRecordingEnd = prp ;
}
errLabel :
if ( rc ! = kOkRC | | skip_fl )
_free_perf_recording_recd ( prp ) ;
mem : : release ( meta_fname ) ;
mem : : release ( perf_fname ) ;
2024-03-28 23:48:46 +00:00
if ( meta_cfg ! = nullptr )
meta_cfg - > free ( ) ;
2023-11-26 20:43:52 +00:00
2024-03-28 23:48:46 +00:00
return rc ;
2023-11-26 20:43:52 +00:00
}
2023-06-27 21:53:04 +00:00
rc_t _parse_perf_recording_dir ( app_t * app , const char * dir , const char * fname , const object_t * velTblCfg )
{
rc_t rc = kOkRC ;
2023-05-27 20:01:17 +00:00
filesys : : dirEntry_t * deA = nullptr ;
2023-06-27 21:53:04 +00:00
unsigned deN = 0 ;
2023-11-26 20:43:52 +00:00
2023-05-27 20:01:17 +00:00
// get the directory entries based on 'dir'
if ( ( deA = filesys : : dirEntries ( dir , filesys : : kDirFsFl , & deN ) ) = = nullptr )
{
rc = cwLogError ( kOpFailRC , " The attempt to get the performance directory at '%s' failed. " , cwStringNullGuard ( dir ) ) ;
goto errLabel ;
}
if ( deN = = 0 )
cwLogWarning ( " The performance recording directory '%s' was found to be empty. " , cwStringNullGuard ( dir ) ) ;
// for each directory entry
2023-11-26 20:43:52 +00:00
for ( unsigned i = 0 ; i < deN ; + + i )
if ( ( rc = _create_perf_recording_recd ( app , dir , deA [ i ] . name , fname , velTblCfg ) ) ! = kOkRC )
2023-05-27 20:01:17 +00:00
goto errLabel ;
2023-11-26 20:43:52 +00:00
2023-05-27 20:01:17 +00:00
errLabel :
mem : : release ( deA ) ;
return rc ;
}
rc_t _load_perf_dir_selection_menu ( app_t * app )
{
rc_t rc = kOkRC ;
// verify that a performance list was given
if ( app - > perfDirL = = nullptr | | app - > perfDirL - > child_count ( ) = = 0 )
{
rc = cwLogError ( rc , " The performance directorty list is missing or empty. " ) ;
goto errLabel ;
}
// for each performance directory
for ( unsigned i = 0 ; i < app - > perfDirL - > child_count ( ) ; + + i )
{
2023-06-27 21:53:04 +00:00
const object_t * d = nullptr ; ;
const char * dir = nullptr ;
const char * fname = nullptr ;
const object_t * velTblCfg = nullptr ;
2023-05-27 20:01:17 +00:00
// get the directory dict. from the cfg file
if ( ( d = app - > perfDirL - > child_ele ( i ) ) = = nullptr | | ! d - > is_dict ( ) )
{
rc = cwLogError ( kSyntaxErrorRC , " The performance directory entry at index '%i' is malformed. " , i ) ;
goto errLabel ;
}
// get the directory
2023-06-27 21:53:04 +00:00
if ( ( rc = d - > getv ( " dir " , dir ,
" fname " , fname ,
" vel_table " , velTblCfg ) ) ! = kOkRC )
2023-05-27 20:01:17 +00:00
{
rc = cwLogError ( rc , " Error parsing the performance directory entry at index '%i'. " , i ) ;
goto errLabel ;
}
// create the performance records from this directory
2023-06-27 21:53:04 +00:00
if ( ( rc = _parse_perf_recording_dir ( app , dir , fname , velTblCfg ) ) ! = kOkRC )
2023-05-27 20:01:17 +00:00
{
rc = cwLogError ( rc , " Error creating the performance directory entry at index '%i'. " , i ) ;
goto errLabel ;
2023-11-26 20:43:52 +00:00
}
}
2023-05-27 20:01:17 +00:00
if ( ( rc = _load_perf_recording_menu ( app ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " The performance menu creation failed. " ) ;
goto errLabel ;
}
2023-12-03 16:20:38 +00:00
2023-05-27 20:01:17 +00:00
errLabel :
if ( rc ! = kOkRC )
rc = cwLogError ( rc , " An error occured while creating the recorded performance list. " ) ;
return rc ;
}
2023-05-01 01:22:49 +00:00
double _get_system_sample_rate ( app_t * app , const char * groupLabel )
{
unsigned groupIdx = kInvalidIdx ;
double srate = 0 ;
if ( ( groupIdx = audioGroupLabelToIndex ( app - > ioH , groupLabel ) ) = = kInvalidIdx )
{
cwLogError ( kOpFailRC , " The audio group '%s' could not be found. " , cwStringNullGuard ( groupLabel ) ) ;
goto errLabel ;
}
if ( ( srate = audioGroupSampleRate ( app - > ioH , groupIdx ) ) = = 0 )
{
cwLogError ( kOpFailRC , " The sample rate could not be determined for the audio group: '%s'. " , cwStringNullGuard ( groupLabel ) ) ;
goto errLabel ;
}
errLabel :
return srate ;
}
2024-01-13 15:21:06 +00:00
rc_t _apply_preset ( app_t * app , unsigned loc , const perf_score : : event_t * score_evt = nullptr , const preset_sel : : frag_t * frag = nullptr )
2021-12-12 21:47:41 +00:00
{
2022-10-15 13:23:58 +00:00
// if frag is NULL this is the beginning of a play session
2021-12-12 21:47:41 +00:00
if ( frag = = nullptr )
2022-10-01 22:54:06 +00:00
{
2023-01-21 16:49:07 +00:00
preset_sel : : track_loc_reset ( app - > psH ) ;
2022-10-01 22:54:06 +00:00
preset_sel : : track_loc ( app - > psH , loc , frag ) ;
}
2021-12-12 21:47:41 +00:00
if ( frag = = nullptr )
cwLogInfo ( " No preset fragment was found for the requested timestamp. " ) ;
else
{
2024-01-13 15:21:06 +00:00
unsigned preset_idx = kInvalidIdx ;
const char * preset_label = nullptr ;
const char * preset_type_label = " <None> " ;
rc_t apply_rc = kOkRC ;
2022-05-21 15:22:53 +00:00
// if the preset sequence player is active then apply the next selected seq. preset
// otherwise select the next primary preset for ths fragment
unsigned seq_idx_n = app - > seqActiveFl ? app - > seqPresetIdx : kInvalidIdx ;
2023-02-26 18:44:54 +00:00
2024-02-08 16:25:38 +00:00
if ( score_evt ! = nullptr )
{
//printf("Meas:e:%f d:%f t:%f c:%f\n",score_evt->even,score_evt->dyn,score_evt->tempo,score_evt->cost);
printf ( " Meas:e:%f d:%f t:%f c:%f \n " , score_evt - > featV [ perf_meas : : kEvenValIdx ] , score_evt - > featV [ perf_meas : : kDynValIdx ] , score_evt - > featV [ perf_meas : : kTempoValIdx ] , score_evt - > featV [ perf_meas : : kMatchCostValIdx ] ) ;
}
2023-02-26 18:44:54 +00:00
2024-01-13 15:21:06 +00:00
// if we are not automatically sequencing through the presets and a score event was given
if ( seq_idx_n = = kInvalidIdx & & score_evt ! = nullptr & & frag - > multiPresetN > 0 )
{
2024-02-08 16:25:38 +00:00
//double coeffV[] = { score_evt->even, score_evt->dyn, score_evt->tempo, score_evt->cost };
//unsigned coeffN = sizeof(coeffV)/sizeof(coeffV[0]);
2024-01-13 15:21:06 +00:00
2024-02-08 16:25:38 +00:00
flow : : multi_preset_selector_t mp_sel =
2024-02-18 13:41:19 +00:00
{ . flags = app - > multiPresetFlags ,
. coeffV = score_evt - > featV ,
. coeffMinV = score_evt - > featMinV ,
. coeffMaxV = score_evt - > featMaxV ,
. coeffN = perf_meas : : kValCnt ,
2024-03-09 20:12:56 +00:00
. presetA = cwIsFlag ( app - > multiPresetFlags , flow : : kAllowAllPresetFl ) ? preset_order_array ( app - > psH ) : frag - > multiPresetA ,
. presetN = cwIsFlag ( app - > multiPresetFlags , flow : : kAllowAllPresetFl ) ? preset_count ( app - > psH ) : frag - > multiPresetN
2024-02-08 16:25:38 +00:00
} ;
2024-01-13 15:21:06 +00:00
2024-02-08 16:25:38 +00:00
if ( app - > ioFlowH . isValid ( ) )
apply_rc = io_flow : : apply_preset ( app - > ioFlowH , flow_cross : : kNextDestId , mp_sel ) ;
2023-11-26 20:43:52 +00:00
2024-03-09 20:12:56 +00:00
preset_label = " (multi) " ; //mp_sel.presetN>0 && mp_sel.presetA[0].preset_label!=nullptr ? mp_sel.presetA[0].preset_label : nullptr;
2023-11-26 20:43:52 +00:00
2024-01-13 15:21:06 +00:00
preset_type_label = " multi " ;
}
else
{
// get the preset index to play for this fragment
if ( ( preset_idx = fragment_play_preset_index ( app - > psH , frag , seq_idx_n ) ) = = kInvalidIdx )
cwLogInfo ( " No preset has been assigned to the fragment at end loc. '%i'. " , frag - > endLoc ) ;
else
preset_label = preset_sel : : preset_label ( app - > psH , preset_idx ) ;
2024-02-08 16:25:38 +00:00
if ( preset_label ! = nullptr )
2021-12-28 01:32:56 +00:00
{
2024-02-08 16:25:38 +00:00
if ( app - > ioFlowH . isValid ( ) )
apply_rc = io_flow : : apply_preset ( app - > ioFlowH , flow_cross : : kNextDestId , preset_label ) ;
2021-12-12 21:47:41 +00:00
2024-01-13 15:21:06 +00:00
preset_type_label = " single " ;
2021-12-28 01:32:56 +00:00
}
2024-01-13 15:21:06 +00:00
// don't display preset updates unless the score is actually loaded
printf ( " Apply %s preset: '%s' : loc:%i status:%i \n " , preset_type_label , preset_label = = nullptr ? " <invalid> " : preset_label , loc , apply_rc ) ;
}
2024-03-09 20:12:56 +00:00
_set_status ( app , " Apply %s preset: '%s'. " , preset_type_label , preset_label = = nullptr ? " <invalid> " : preset_label ) ;
2024-01-13 15:21:06 +00:00
// apply the fragment defined gain settings
if ( app - > ioFlowH . isValid ( ) )
{
io_flow : : set_variable_value ( app - > ioFlowH , flow_cross : : kNextDestId , " wet_in_gain " , " gain " , flow : : kAnyChIdx , ( dsp : : real_t ) frag - > igain ) ;
io_flow : : set_variable_value ( app - > ioFlowH , flow_cross : : kNextDestId , " wet_out_gain " , " gain " , flow : : kAnyChIdx , ( dsp : : real_t ) frag - > ogain ) ;
io_flow : : set_variable_value ( app - > ioFlowH , flow_cross : : kNextDestId , " wd_bal " , " in " , flow : : kAnyChIdx , ( dsp : : real_t ) frag - > wetDryGain ) ;
// activate the cross-fade
io_flow : : begin_cross_fade ( app - > ioFlowH , frag - > fadeOutMs ) ;
2021-12-28 01:32:56 +00:00
}
2021-12-12 21:47:41 +00:00
}
return kOkRC ;
}
2022-01-22 14:55:17 +00:00
// Turn on the selection border for the clicked fragment
rc_t _do_select_frag ( app_t * app , unsigned clickedUuId )
{
rc_t rc = kOkRC ;
// get the last selected fragment
unsigned prevFragId = preset_sel : : ui_select_fragment_id ( app - > psH ) ;
2023-03-20 23:41:58 +00:00
unsigned prevUuId = preset_sel : : frag_to_gui_id ( app - > psH , prevFragId , false ) ;
2022-01-22 14:55:17 +00:00
// is the last selected fragment the same as the clicked fragment
bool reclickFl = prevUuId = = clickedUuId ;
// if a different fragment was clicked then deselect the last fragment in the UI
if ( ! reclickFl )
{
if ( prevUuId ! = kInvalidId )
io : : uiSetSelect ( app - > ioH , prevUuId , false ) ;
// select or deselect the clicked fragment
io : : uiSetSelect ( app - > ioH , clickedUuId , ! reclickFl ) ;
}
// Note: calls to uiSetSelect() produce callbacks to _onUiSelect().
return rc ;
}
2023-02-26 18:44:54 +00:00
rc_t _do_stop_play ( app_t * app )
{
rc_t rc = kOkRC ;
2023-05-25 20:16:21 +00:00
unsigned evt_cnt = 0 ;
2023-02-26 18:44:54 +00:00
if ( app - > in_audio_dev_idx ! = kInvalidIdx )
{
if ( ( rc = audioDeviceEnable ( app - > ioH , app - > in_audio_dev_idx , true , false ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Enable failed on audio device input file. " ) ;
goto errLabel ;
}
}
2023-05-25 20:16:21 +00:00
2023-02-26 18:44:54 +00:00
if ( ( rc = midi_record_play : : stop ( app - > mrpH ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " MIDI stop failed. " ) ;
goto errLabel ;
}
2023-05-25 20:16:21 +00:00
if ( app - > enableRecordFl & & ( evt_cnt = midi_record_play : : event_count ( app - > mrpH ) ) > 0 )
{
io : : uiSendValue ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kTotalMidiEvtCntId ) , evt_cnt ) ;
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kMidiSaveBtnId ) , true ) ;
}
2023-02-26 18:44:54 +00:00
errLabel :
return rc ;
}
2023-05-25 20:16:21 +00:00
unsigned _get_loc_from_score_follower ( app_t * app , double secs , unsigned muid , uint8_t status , uint8_t d0 , uint8_t d1 )
2023-05-09 12:24:46 +00:00
{
2023-12-17 13:51:46 +00:00
unsigned loc = score_parse : : kInvalidLocId ;
2023-05-09 12:24:46 +00:00
// if this is a MIDI note-on event - then udpate the score follower
2023-05-25 20:16:21 +00:00
if ( midi : : isNoteOn ( status , d1 ) & & muid ! = kInvalidIdx )
2023-05-09 12:24:46 +00:00
{
unsigned smpIdx = 0 ; // not functional - used to associate input with score follower output
bool newMatchOccurredFl = false ;
if ( exec ( app - > sfH , secs , smpIdx , muid , status , d0 , d1 , newMatchOccurredFl ) ! = kOkRC )
{
cwLogWarning ( " Score follower exec error. " ) ;
}
else
{
if ( newMatchOccurredFl )
{
unsigned matchLocN = 0 ;
2023-09-13 00:32:38 +00:00
const unsigned * matchLocA = current_result_index_array ( app - > sfH , matchLocN ) ;
2023-05-09 12:24:46 +00:00
unsigned maxLocId = 0 ;
2023-05-27 20:01:17 +00:00
printf ( " SF: " ) ;
for ( unsigned i = 0 ; i < matchLocN ; + + i )
2023-05-09 12:24:46 +00:00
{
2023-05-27 20:01:17 +00:00
if ( matchLocA [ i ] > maxLocId )
maxLocId = matchLocA [ i ] ;
printf ( " %i " , matchLocA [ i ] ) ;
}
2023-06-27 21:53:04 +00:00
printf ( " \n " ) ;
2023-05-09 12:24:46 +00:00
2023-05-27 20:01:17 +00:00
2023-06-27 21:53:04 +00:00
loc = maxLocId ;
2023-05-27 20:01:17 +00:00
2023-09-13 00:32:38 +00:00
clear_result_index_array ( app - > sfH ) ;
2023-05-09 12:24:46 +00:00
}
}
}
return loc ;
}
2023-02-26 18:44:54 +00:00
2023-11-26 20:43:52 +00:00
void _midi_play_callback ( void * arg , unsigned actionId , unsigned id , const time : : spec_t timestamp , unsigned loc , const void * msg_arg , uint8_t ch , uint8_t status , uint8_t d0 , uint8_t d1 )
2021-11-01 14:28:44 +00:00
{
app_t * app = ( app_t * ) arg ;
2022-05-21 13:29:03 +00:00
switch ( actionId )
{
case midi_record_play : : kPlayerStoppedActionId :
2023-03-20 23:41:58 +00:00
app - > seqStartedFl = false ;
2023-02-26 18:44:54 +00:00
_do_stop_play ( app ) ;
2022-05-21 15:22:53 +00:00
_set_status ( app , " Done " ) ;
2022-05-21 13:29:03 +00:00
break ;
2022-03-20 14:27:46 +00:00
2022-05-21 13:29:03 +00:00
case midi_record_play : : kMidiEventActionId :
{
if ( app - > printMidiFl )
2022-03-20 14:27:46 +00:00
{
2022-05-21 13:29:03 +00:00
const unsigned buf_byte_cnt = 256 ;
2023-03-20 23:41:58 +00:00
char buf [ buf_byte_cnt ] ;
2022-05-21 13:29:03 +00:00
// if this event is not in the score
if ( id = = kInvalidId )
{
// TODO: print this out in the same format as event_to_string()
snprintf ( buf , buf_byte_cnt , " ch:%i status:0x%02x d0:%i d1:%i " , ch , status , d0 , d1 ) ;
}
else
2024-02-08 16:25:38 +00:00
perf_score : : event_to_string ( app - > perfScoreH , id , buf , buf_byte_cnt ) ;
2022-05-21 13:29:03 +00:00
printf ( " %s \n " , buf ) ;
2022-03-20 14:27:46 +00:00
}
2022-05-14 14:19:18 +00:00
2022-05-21 13:29:03 +00:00
if ( midi_record_play : : is_started ( app - > mrpH ) )
{
const preset_sel : : frag_t * f = nullptr ;
2022-10-01 22:54:06 +00:00
2023-05-09 12:24:46 +00:00
double sec = time : : specToSeconds ( timestamp ) ;
2023-05-01 01:22:49 +00:00
2023-05-25 20:16:21 +00:00
// call the score follower
2023-06-27 21:53:04 +00:00
if ( score_follower : : is_enabled ( app - > sfH ) )
loc = _get_loc_from_score_follower ( app , sec , id , status , d0 , d1 ) ;
2023-05-01 01:22:49 +00:00
2023-05-09 12:24:46 +00:00
// TODO: ZERO SHOULD BE A VALID LOC VALUE - MAKE -1 THE INVALID LOC VALUE
2022-10-01 22:54:06 +00:00
2023-12-17 13:51:46 +00:00
if ( loc ! = score_parse : : kInvalidLocId & & app - > trackMidiFl )
2023-05-27 20:01:17 +00:00
{
2022-10-01 22:54:06 +00:00
if ( preset_sel : : track_loc ( app - > psH , loc , f ) )
2023-11-26 20:43:52 +00:00
{
_apply_preset ( app , loc , ( const perf_score : : event_t * ) msg_arg , f ) ;
2022-10-01 22:54:06 +00:00
if ( f ! = nullptr )
_do_select_frag ( app , f - > guiUuId ) ;
}
2022-05-21 13:29:03 +00:00
}
2023-02-26 18:44:54 +00:00
2022-05-14 14:19:18 +00:00
}
2022-05-21 13:29:03 +00:00
break ;
2021-12-12 21:47:41 +00:00
}
2022-05-21 13:29:03 +00:00
}
2021-11-01 14:28:44 +00:00
}
2021-11-06 02:28:38 +00:00
2024-02-08 16:25:38 +00:00
rc_t _on_live_midi_event ( app_t * app , const io : : msg_t & msg )
2022-10-26 12:49:20 +00:00
{
rc_t rc = kOkRC ;
if ( msg . u . midi ! = nullptr )
2024-02-10 16:34:06 +00:00
{
const io : : midi_msg_t & m = * msg . u . midi ;
2022-10-26 12:49:20 +00:00
const midi : : packet_t * pkt = m . pkt ;
2024-02-10 16:34:06 +00:00
2022-10-26 12:49:20 +00:00
// for each midi msg
2023-05-25 20:16:21 +00:00
for ( unsigned j = 0 ; j < pkt - > msgCnt ; + + j )
2022-10-26 12:49:20 +00:00
{
// if this is a sys-ex msg
if ( pkt - > msgArray = = NULL )
{
cwLogError ( kNotImplementedRC , " Sys-ex recording not implemented. " ) ;
}
2023-03-20 23:41:58 +00:00
else // this is a triple
2022-10-26 12:49:20 +00:00
{
2023-03-20 23:41:58 +00:00
time : : spec_t timestamp ;
2024-02-10 16:34:06 +00:00
midi : : msg_t * mm = pkt - > msgArray + j ;
2023-05-25 20:16:21 +00:00
unsigned id = app - > enableRecordFl ? last_store_index ( app - > mrpH ) : kInvalidId ;
2023-03-20 23:41:58 +00:00
unsigned loc = app - > beg_play_loc ;
2022-10-26 12:49:20 +00:00
time : : get ( timestamp ) ;
if ( midi : : isChStatus ( mm - > status ) )
{
2024-02-14 15:56:44 +00:00
if ( midi_record_play : : send_midi_msg ( app - > mrpH , midi_record_play : : kSampler_MRP_DevIdx , mm - > ch , mm - > status , mm - > d0 , mm - > d1 ) = = kOkRC )
_midi_play_callback ( app , midi_record_play : : kMidiEventActionId , id , timestamp , loc , nullptr , mm - > ch , mm - > status , mm - > d0 , mm - > d1 ) ;
2022-10-26 12:49:20 +00:00
}
}
}
}
return rc ;
}
2022-05-06 20:11:51 +00:00
// Find the closest locMap equal to or after 'loc'
2021-12-28 01:32:56 +00:00
loc_map_t * _find_loc ( app_t * app , unsigned loc )
{
2023-03-20 23:41:58 +00:00
unsigned i = 0 ;
2022-05-06 20:11:51 +00:00
loc_map_t * pre_loc_map = nullptr ;
2021-12-28 01:32:56 +00:00
for ( ; i < app - > locMapN ; + + i )
2022-05-06 20:11:51 +00:00
{
if ( app - > locMap [ i ] . loc > = loc )
return app - > locMap + i ;
pre_loc_map = app - > locMap + i ;
}
return pre_loc_map ;
2021-12-28 01:32:56 +00:00
}
2022-01-22 14:55:17 +00:00
2023-02-26 18:44:54 +00:00
rc_t _loc_to_frame_index ( app_t * app , unsigned loc , unsigned & frameIdxRef )
2022-01-22 14:55:17 +00:00
{
2023-03-20 23:41:58 +00:00
rc_t rc = kOkRC ;
2023-09-13 00:32:38 +00:00
const perf_score : : event_t * e0 = nullptr ;
const perf_score : : event_t * e1 = nullptr ;
2023-02-26 18:44:54 +00:00
double srate = 0 ;
2023-03-20 23:41:58 +00:00
double secs = 0 ;
2022-01-22 14:55:17 +00:00
2023-02-26 18:44:54 +00:00
frameIdxRef = kInvalidIdx ;
2023-12-17 13:51:46 +00:00
if ( app - > in_audio_begin_loc ! = score_parse : : kInvalidLocId )
2023-01-05 12:31:49 +00:00
{
2024-02-08 16:25:38 +00:00
if ( ( e0 = loc_to_event ( app - > perfScoreH , app - > in_audio_begin_loc ) ) = = nullptr )
2023-01-05 12:31:49 +00:00
{
2023-02-26 18:44:54 +00:00
rc = cwLogError ( kInvalidArgRC , " The score event associated with the 'in_audio_beg_loc' loc:%i could not be found. " , loc ) ;
2023-01-05 12:31:49 +00:00
goto errLabel ;
}
}
2024-02-08 16:25:38 +00:00
if ( ( e1 = loc_to_event ( app - > perfScoreH , loc ) ) = = nullptr )
2022-01-22 14:55:17 +00:00
{
2023-02-26 18:44:54 +00:00
rc = cwLogError ( kInvalidArgRC , " The score event associated with the begin play loc:%i could not be found. " , loc ) ;
2022-01-22 14:55:17 +00:00
goto errLabel ;
}
2023-02-26 18:44:54 +00:00
if ( ( srate = audioDeviceSampleRate ( app - > ioH , app - > in_audio_dev_idx ) ) = = 0 )
{
rc = cwLogError ( kInvalidArgRC , " Audio device file sample rate could not be accessed. " ) ;
goto errLabel ;
}
if ( e1 - > sec < e0 - > sec )
cwLogWarning ( " The audio file start time ('in_audio_beg_sec') (%f sec) is prior to the start play location %f sec. " , e1 - > sec , e0 - > sec ) ;
else
{
secs = ( e1 - > sec - e0 - > sec ) + app - > in_audio_offset_sec ;
cwLogInfo ( " File offset %f seconds. %f %f " , secs ) ;
}
frameIdxRef = ( unsigned ) ( secs * srate ) ;
2022-01-22 14:55:17 +00:00
errLabel :
2023-02-26 18:44:54 +00:00
2022-01-22 14:55:17 +00:00
return rc ;
}
2023-05-25 20:16:21 +00:00
bool _is_performance_loaded ( app_t * app )
2021-12-28 01:32:56 +00:00
{
2024-02-08 16:25:38 +00:00
return app - > perfScoreH . isValid ( ) and event_count ( app - > perfScoreH ) > 0 ;
2023-05-25 20:16:21 +00:00
}
2023-05-27 20:01:17 +00:00
rc_t _do_sf_reset ( app_t * app , unsigned loc )
{
rc_t rc = kOkRC ;
track_loc_reset ( app - > psH ) ;
score_follower : : reset ( app - > sfH , app - > sfResetLoc ) ;
cwLogInfo ( " SF reset loc: %i " , app - > sfResetLoc ) ;
return rc ;
}
2023-05-25 20:16:21 +00:00
rc_t _do_start ( app_t * app , unsigned begLoc , unsigned endLoc )
{
rc_t rc = kOkRC ;
bool rewindFl = true ;
loc_map_t * begMap = nullptr ;
loc_map_t * endMap = nullptr ;
unsigned score_loc = app - > sfResetLoc ;
unsigned preset_loc = app - > sfResetLoc ;
2021-12-28 01:32:56 +00:00
2022-01-22 14:55:17 +00:00
// if the player is already playing then stop it
if ( midi_record_play : : is_started ( app - > mrpH ) )
{
rc = _do_stop_play ( app ) ;
goto errLabel ;
}
2022-03-20 14:27:46 +00:00
2023-05-25 20:16:21 +00:00
// if we are using and audio file as the source
2023-02-19 19:18:53 +00:00
if ( app - > in_audio_dev_idx ! = kInvalidIdx )
2023-01-05 12:31:49 +00:00
{
2023-02-26 18:44:54 +00:00
unsigned frameIdx = 0 ;
if ( ( rc = _loc_to_frame_index ( app , begLoc , frameIdx ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Frame index could not be calculated. " ) ;
goto errLabel ;
}
if ( ( rc = audioDeviceSeek ( app - > ioH , app - > in_audio_dev_idx , true , frameIdx ) ) ! = kOkRC )
2023-01-05 12:31:49 +00:00
{
2023-02-19 19:18:53 +00:00
rc = cwLogError ( rc , " Seek failed on audio device input file. " ) ;
2023-01-05 12:31:49 +00:00
goto errLabel ;
}
2023-02-19 19:18:53 +00:00
if ( ( rc = audioDeviceEnable ( app - > ioH , app - > in_audio_dev_idx , true , true ) ) ! = kOkRC )
2023-01-05 12:31:49 +00:00
{
2023-02-19 19:18:53 +00:00
rc = cwLogError ( rc , " Enable failed on audio device input file. " ) ;
2023-01-05 12:31:49 +00:00
goto errLabel ;
}
}
2023-02-19 19:18:53 +00:00
2023-05-25 20:16:21 +00:00
// if a performance is loaded
if ( _is_performance_loaded ( app ) )
2021-12-28 01:32:56 +00:00
{
2023-05-25 20:16:21 +00:00
if ( ( begMap = _find_loc ( app , begLoc ) ) = = nullptr )
{
rc = cwLogError ( kInvalidArgRC , " The begin play location (%i) is not valid. " , begLoc ) ;
2021-12-28 01:32:56 +00:00
goto errLabel ;
2023-05-25 20:16:21 +00:00
}
if ( ( endMap = _find_loc ( app , endLoc ) ) = = nullptr )
{
rc = cwLogError ( kInvalidArgRC , " The end play location (%i) is not valid. " , endLoc ) ;
goto errLabel ;
}
2023-06-27 21:53:04 +00:00
if ( ! time : : isZero ( begMap - > timestamp ) )
2023-05-25 20:16:21 +00:00
{
// seek the player to the requested loc
2023-06-27 21:53:04 +00:00
if ( ( rc = midi_record_play : : seek ( app - > mrpH , begMap - > timestamp ) ) ! = kOkRC )
2023-05-25 20:16:21 +00:00
{
rc = cwLogError ( rc , " MIDI seek failed. " ) ;
goto errLabel ;
}
rewindFl = false ;
}
score_loc = begLoc ;
preset_loc = begMap - > loc ;
2021-12-28 01:32:56 +00:00
}
2023-05-25 20:16:21 +00:00
// if recording - empty the recording buffer
if ( app - > enableRecordFl )
2021-12-28 01:32:56 +00:00
{
2023-05-25 20:16:21 +00:00
midi_record_play : : set_record_state ( app - > mrpH , app - > enableRecordFl ) ;
midi_record_play : : clear ( app - > mrpH ) ;
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kMidiSaveBtnId ) , false ) ;
2021-12-28 01:32:56 +00:00
}
2023-05-27 20:01:17 +00:00
2023-05-25 20:16:21 +00:00
// reset the score follower
2023-05-27 20:01:17 +00:00
if ( ( rc = _do_sf_reset ( app , score_loc ) ) ! = kOkRC )
2023-05-01 01:22:49 +00:00
{
rc = cwLogError ( rc , " Score follower reset failed. " ) ;
goto errLabel ;
}
2021-12-28 01:32:56 +00:00
// apply the preset which is active at the start time
2023-05-25 20:16:21 +00:00
if ( ( rc = _apply_preset ( app , preset_loc ) ) ! = kOkRC )
2021-12-28 01:32:56 +00:00
{
rc = cwLogError ( rc , " Preset application failed prior to MIDI start. " ) ;
goto errLabel ;
}
2023-05-25 20:16:21 +00:00
// start the MIDI record/play unit
if ( _is_performance_loaded ( app ) | | app - > enableRecordFl )
2021-12-28 01:32:56 +00:00
{
2023-05-25 20:16:21 +00:00
unsigned evt_cnt = 0 ;
2023-06-27 21:53:04 +00:00
if ( ( rc = midi_record_play : : start ( app - > mrpH , rewindFl , & endMap - > timestamp ) ) ! = kOkRC )
2022-10-26 12:49:20 +00:00
{
rc = cwLogError ( rc , " MIDI start failed. " ) ;
goto errLabel ;
}
2021-12-28 01:32:56 +00:00
2023-05-25 20:16:21 +00:00
// update the current event loc/count
if ( _is_performance_loaded ( app ) )
evt_cnt = midi_record_play : : event_loc ( app - > mrpH ) ;
else
if ( app - > enableRecordFl )
evt_cnt = midi_record_play : : event_count ( app - > mrpH ) ;
io : : uiSendValue ( app - > ioH , uiFindElementUuId ( app - > ioH , kCurMidiEvtCntId ) , evt_cnt ) ;
2022-10-01 22:54:06 +00:00
}
2022-10-26 12:49:20 +00:00
2021-12-28 01:32:56 +00:00
errLabel :
return rc ;
}
2023-01-21 16:49:07 +00:00
// This function is used to apply the selected (checked) preset immediately.
2023-01-05 12:31:49 +00:00
rc_t _apply_current_preset ( app_t * app , unsigned fragId )
{
2023-01-21 16:49:07 +00:00
rc_t rc = kOkRC ;
const preset_sel : : frag_t * frag = nullptr ;
bool orig_seqActiveFl = app - > seqActiveFl ;
2023-01-05 12:31:49 +00:00
2023-01-21 16:49:07 +00:00
// temporarily turn of the preset sequencer (if it is active)
2023-01-05 12:31:49 +00:00
app - > seqActiveFl = false ;
if ( ( frag = preset_sel : : get_fragment ( app - > psH , fragId ) ) = = nullptr )
{
rc = cwLogError ( rc , " The fragment at id '%i' could not be accessed. " , fragId ) ;
goto errLabel ;
}
// apply the preset which is active at the start time
2023-11-26 20:43:52 +00:00
if ( ( rc = _apply_preset ( app , frag - > begPlayLoc , nullptr , frag ) ) ! = kOkRC )
2023-01-05 12:31:49 +00:00
{
rc = cwLogError ( rc , " Preset application failed on fragment at id '%i'. " , fragId ) ;
goto errLabel ;
}
errLabel :
app - > seqActiveFl = orig_seqActiveFl ;
return rc ;
}
2021-12-28 01:32:56 +00:00
rc_t _do_play_fragment ( app_t * app , unsigned fragId )
{
2023-03-20 23:41:58 +00:00
rc_t rc ;
2021-12-28 01:32:56 +00:00
unsigned begLoc = 0 ;
unsigned endLoc = 0 ;
2023-01-21 16:49:07 +00:00
// get the fragment starting location as currently set in the UI
// (this may be different from the fragment begin location)
2021-12-28 01:32:56 +00:00
if ( ( rc = get_value ( app - > psH , fragId , preset_sel : : kBegPlayLocVarId , kInvalidId , begLoc ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Could not retrieve the begin play location for fragment id:%i. " , fragId ) ;
goto errLabel ;
}
2023-01-21 16:49:07 +00:00
// get the fragment ending location as currently set in the UI
// (this may be different from the fragment end location)
2021-12-28 01:32:56 +00:00
if ( ( rc = get_value ( app - > psH , fragId , preset_sel : : kEndPlayLocVarId , kInvalidId , endLoc ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Could not retrieve the begin play location for fragment id:%i. " , fragId ) ;
goto errLabel ;
}
2023-05-25 20:16:21 +00:00
rc = _do_start ( app , begLoc , endLoc ) ;
2021-12-28 01:32:56 +00:00
errLabel :
return rc ;
}
2022-05-21 13:29:03 +00:00
rc_t _do_seq_play_fragment ( app_t * app , unsigned fragId )
{
rc_t rc = kOkRC ;
if ( app - > seqActiveFl )
{
app - > seqActiveFl = false ;
}
else
{
app - > seqFragId = fragId ;
app - > seqPresetIdx = 0 ;
2022-05-21 15:22:53 +00:00
app - > seqStartedFl = true ;
app - > seqActiveFl = true ;
2022-05-21 13:29:03 +00:00
}
// Note that if the MIDI player is already playing
// calling '_do_play_fragment()' here will stop the player
_do_play_fragment ( app , app - > seqFragId ) ;
return rc ;
}
rc_t _do_seq_exec ( app_t * app )
{
rc_t rc = kOkRC ;
2022-05-21 15:22:53 +00:00
// if the seq player is active but currently stopped
2023-03-20 23:41:58 +00:00
if ( app - > seqActiveFl & & app - > seqStartedFl = = false )
2022-05-21 13:29:03 +00:00
{
2022-05-21 15:22:53 +00:00
app - > seqPresetIdx + = 1 ;
2023-03-20 23:41:58 +00:00
app - > seqStartedFl = app - > seqPresetIdx < preset_sel : : fragment_seq_count ( app - > psH , app - > seqFragId ) ;
app - > seqActiveFl = app - > seqStartedFl ;
2022-05-21 15:22:53 +00:00
if ( app - > seqStartedFl )
_do_play_fragment ( app , app - > seqFragId ) ;
2022-05-21 13:29:03 +00:00
}
return rc ;
}
2021-12-28 01:32:56 +00:00
2021-11-06 02:28:38 +00:00
void _update_event_ui ( app_t * app )
{
2022-05-06 20:11:51 +00:00
//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) );
2023-12-05 20:34:25 +00:00
io : : uiSendValue ( app - > ioH , uiFindElementUuId ( app - > ioH , kTotalMidiEvtCntId ) , app - > maxPerfLoc - app - > minPerfLoc ) ;
2021-11-06 02:28:38 +00:00
}
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 )
{
2021-12-28 01:32:56 +00:00
rc = cwLogError ( rc , " Unable to locate the preset value for var:%i preset:%i. " , psVarId , psPresetId ) ;
2021-11-06 02:28:38 +00:00
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 ;
2023-03-20 23:41:58 +00:00
endLocRef = kInvalidId ;
2021-11-14 18:11:11 +00:00
if ( ( rc = get_value ( app - > psH , fragId , preset_sel : : kEndLocVarId , kInvalidId , endLocRef ) ) ! = kOkRC )
2023-03-20 23:41:58 +00:00
rc = cwLogError ( rc , " Unable to get the 'end loc' value for fragment id:%i. " , fragId ) ;
2021-11-14 18:11:11 +00:00
return rc ;
}
// Update the preset select check boxes on a fragment panel
2023-05-01 01:22:49 +00:00
rc_t _update_frag_select_flags ( app_t * app , unsigned fragId , unsigned fragEndLoc = kInvalidId , bool apply_preset_fl = true )
2021-11-14 18:11:11 +00:00
{
2023-03-20 23:41:58 +00:00
rc_t rc = kOkRC ;
2021-11-14 18:11:11 +00:00
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 ;
2023-12-03 16:20:38 +00:00
const char * sValue ;
2021-12-28 01:32:56 +00:00
unsigned fragPanelUuId ;
2021-11-14 18:11:11 +00:00
// The uiChan is the fragment endLoc
2022-12-12 17:28:27 +00:00
unsigned uiChanId = fragId ; //fragEndLoc;
2021-11-14 18:11:11 +00:00
2021-12-28 01:32:56 +00:00
// Get the fragPanelUUid
get_value ( app - > psH , fragId , preset_sel : : kGuiUuIdVarId , kInvalidId , fragPanelUuId ) ;
2021-11-14 18:11:11 +00:00
// uuid of the frag preset row
unsigned fragPresetRowUuId = io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragPresetRowId , uiChanId ) ;
2021-12-28 01:32:56 +00:00
2021-11-14 18:11:11 +00:00
// 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 )
{
2022-05-21 15:22:53 +00:00
_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 ) ;
2023-12-03 16:20:38 +00:00
_update_frag_ui ( app , fragId , preset_sel : : kPresetAltVarId , preset_idx , fragPresetRowUuId , kFragPresetAltId , preset_idx , sValue ) ;
2022-05-21 15:22:53 +00:00
_update_frag_ui ( app , fragId , preset_sel : : kPresetSeqSelectVarId , preset_idx , fragPresetRowUuId , kFragPresetSeqSelId , preset_idx , bValue ) ;
2021-11-14 18:11:11 +00:00
}
2023-01-05 12:31:49 +00:00
2023-05-01 01:22:49 +00:00
if ( apply_preset_fl )
_apply_current_preset ( app , fragId ) ;
2021-11-14 18:11:11 +00:00
}
return rc ;
}
// Update the fragment UI withh the fragment record associated with 'fragId'
2023-05-01 01:22:49 +00:00
rc_t _update_frag_ui ( app_t * app , unsigned fragId , bool apply_preset_fl = true )
2021-11-06 02:28:38 +00:00
{
2021-12-28 01:32:56 +00:00
// Notes:
2023-01-31 00:35:28 +00:00
// uiChanId = fragId for panel values or uiChanId = preset_index for preset values
2023-03-20 23:41:58 +00:00
rc_t rc = kOkRC ;
2021-11-06 02:28:38 +00:00
unsigned endLoc ;
2021-11-14 18:11:11 +00:00
2023-01-31 00:35:28 +00:00
// Get the endLoc for this fragment
2021-11-14 18:11:11 +00:00
if ( ( rc = _frag_id_to_endloc ( app , fragId , endLoc ) ) = = kOkRC )
2021-11-06 02:28:38 +00:00
{
2023-03-20 23:41:58 +00:00
unsigned uValue ;
double dValue ;
2021-12-28 01:32:56 +00:00
const char * sValue ;
2023-03-20 23:41:58 +00:00
unsigned uiChanId = fragId ; //endLoc;
unsigned fragPanelUuId = kInvalidId ;
2021-11-06 02:28:38 +00:00
2021-12-28 01:32:56 +00:00
get_value ( app - > psH , fragId , preset_sel : : kGuiUuIdVarId , kInvalidId , fragPanelUuId ) ;
2021-11-06 02:28:38 +00:00
2021-12-28 01:32:56 +00:00
_update_frag_ui ( app , fragId , preset_sel : : kBegLocVarId , kInvalidId , fragPanelUuId , kFragBegLocId , uiChanId , uValue ) ;
_update_frag_ui ( app , fragId , preset_sel : : kEndLocVarId , kInvalidId , fragPanelUuId , kFragEndLocId , uiChanId , uValue ) ;
_update_frag_ui ( app , fragId , preset_sel : : kInGainVarId , kInvalidId , fragPanelUuId , kFragInGainId , uiChanId , dValue ) ;
_update_frag_ui ( app , fragId , preset_sel : : kInGainVarId , kInvalidId , fragPanelUuId , kFragOutGainId , 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 ) ;
_update_frag_ui ( app , fragId , preset_sel : : kBegPlayLocVarId , kInvalidId , fragPanelUuId , kFragBegPlayLocId , uiChanId , uValue ) ;
_update_frag_ui ( app , fragId , preset_sel : : kEndPlayLocVarId , kInvalidId , fragPanelUuId , kFragEndPlayLocId , uiChanId , uValue ) ;
_update_frag_ui ( app , fragId , preset_sel : : kNoteVarId , kInvalidId , fragPanelUuId , kFragNoteId , uiChanId , sValue ) ;
2023-05-01 01:22:49 +00:00
_update_frag_select_flags ( app , fragId , endLoc , apply_preset_fl ) ;
2021-11-14 18:11:11 +00:00
2021-11-06 02:28:38 +00:00
}
return rc ;
}
2021-12-30 02:57:04 +00:00
rc_t _frag_uuid_to_blob ( app_t * app , unsigned uuId , ui_blob_t * & blobRef )
{
2023-03-20 23:41:58 +00:00
unsigned blobByteN = 0 ;
2021-12-30 02:57:04 +00:00
if ( ( blobRef = ( 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 for GUI uuid:%i. " , uuId ) ;
return kOkRC ;
}
void _enable_global_play_btn ( app_t * app , bool enableFl )
{
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kStartBtnId ) , enableFl ) ;
//io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStopBtnId ), enableFl );
}
void _enable_frag_play_btn ( app_t * app , ui_blob_t * blob , unsigned , const char * ) { }
void _enable_frag_play_btn ( app_t * app , ui_blob_t * blob , const char * , unsigned ) { }
void _enable_frag_play_btn ( app_t * app , ui_blob_t * blob , unsigned begPlayLoc , unsigned endPlayLoc )
{
2023-03-20 23:41:58 +00:00
bool enableFl = begPlayLoc < endPlayLoc ;
unsigned fragUuId = kInvalidId ;
2021-12-30 02:57:04 +00:00
if ( ( fragUuId = frag_to_gui_id ( app - > psH , blob - > fragId ) ) ! = kInvalidId )
2022-05-21 16:35:28 +00:00
{
unsigned btnIdA [ ] = { kFragPlayBtnId , kFragPlaySeqBtnId , kFragPlayAllBtnId } ;
2023-03-20 23:41:58 +00:00
unsigned btnIdN = sizeof ( btnIdA ) / sizeof ( btnIdA [ 0 ] ) ;
2022-05-21 16:35:28 +00:00
2023-03-20 23:41:58 +00:00
for ( unsigned i = 0 ; i < btnIdN ; + + i )
2021-12-30 02:57:04 +00:00
{
2022-05-21 16:35:28 +00:00
unsigned btnUuId ;
2023-03-20 23:41:58 +00:00
if ( ( btnUuId = uiFindElementUuId ( app - > ioH , fragUuId , btnIdA [ i ] , blob - > presetId ) ) ! = kInvalidId )
2022-05-21 16:35:28 +00:00
uiSetEnable ( app - > ioH , btnUuId , enableFl ) ;
2021-12-30 02:57:04 +00:00
}
2022-05-21 16:35:28 +00:00
}
2023-05-27 20:01:17 +00:00
//if( enableFl )
// _clear_status(app);
//else
if ( ! enableFl )
2023-12-05 20:34:25 +00:00
{
2023-12-03 16:20:38 +00:00
_set_status ( app , " Invalid fragment play range. beg:%i end:%i " , begPlayLoc , endPlayLoc ) ;
2023-12-05 20:34:25 +00:00
cwLogError ( kInvalidArgRC , " Invalid fragment play range. beg:%i end:%i " , begPlayLoc , endPlayLoc ) ;
}
2022-05-21 16:35:28 +00:00
2021-12-30 02:57:04 +00:00
}
void _disable_frag_play_btn ( app_t * app , unsigned fragBegEndUuId )
{
2023-03-20 23:41:58 +00:00
ui_blob_t * blob = nullptr ;
2021-12-30 02:57:04 +00:00
if ( _frag_uuid_to_blob ( app , fragBegEndUuId , blob ) = = kOkRC )
_enable_frag_play_btn ( app , blob , 1 , ( unsigned ) 0 ) ;
}
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
{
2023-03-20 23:41:58 +00:00
rc_t rc = kOkRC ;
ui_blob_t * blob = nullptr ;
2021-11-14 18:11:11 +00:00
2021-12-30 02:57:04 +00:00
if ( ( rc = _frag_uuid_to_blob ( app , uuId , blob ) ) ! = kOkRC )
goto errLabel ;
2021-11-14 18:11:11 +00:00
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
}
2021-12-28 01:32:56 +00:00
//
switch ( blob - > varId )
{
case preset_sel : : kPresetSelectVarId :
_update_frag_select_flags ( app , blob - > fragId ) ;
break ;
2022-05-21 15:22:53 +00:00
2023-12-03 16:20:38 +00:00
case preset_sel : : kPresetAltVarId :
_update_frag_select_flags ( app , blob - > fragId ) ;
break ;
2022-05-21 15:22:53 +00:00
case preset_sel : : kPresetSeqSelectVarId :
_update_frag_select_flags ( app , blob - > fragId ) ;
break ;
2021-12-28 01:32:56 +00:00
case preset_sel : : kPlayBtnVarId :
_do_play_fragment ( app , blob - > fragId ) ;
break ;
2021-12-30 02:57:04 +00:00
2022-05-21 13:29:03 +00:00
case preset_sel : : kPlaySeqBtnVarId :
_do_seq_play_fragment ( app , blob - > fragId ) ;
break ;
2022-05-21 15:22:53 +00:00
case preset_sel : : kPlaySeqAllBtnVarId :
_do_seq_play_fragment ( app , blob - > fragId ) ;
break ;
2021-12-30 02:57:04 +00:00
case preset_sel : : kBegPlayLocVarId :
2023-01-31 00:35:28 +00:00
{
unsigned endPlayLoc ;
get_value ( app - > psH , blob - > fragId , preset_sel : : kEndPlayLocVarId , blob - > presetId , endPlayLoc ) ;
_enable_frag_play_btn ( app , blob , value , endPlayLoc ) ;
}
break ;
2021-12-30 02:57:04 +00:00
case preset_sel : : kEndPlayLocVarId :
2023-01-31 00:35:28 +00:00
{
unsigned begPlayLoc ;
get_value ( app - > psH , blob - > fragId , preset_sel : : kBegPlayLocVarId , blob - > presetId , begPlayLoc ) ;
_enable_frag_play_btn ( app , blob , begPlayLoc , value ) ;
}
break ;
2021-12-28 01:32:56 +00:00
}
2021-12-30 02:57:04 +00:00
errLabel :
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 )
{
2023-03-20 23:41:58 +00:00
ui_blob_t blob = { . fragId = fragId , . varId = varId , . presetId = presetId } ;
2021-12-19 17:18:22 +00:00
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 ) ;
2023-12-03 16:20:38 +00:00
/*
// order/alt row container
if ( ( rc = io : : uiCreateDiv ( app - > ioH , rowUuId , colUuId , nullEleName , invalidAppId , chanId , " uiRow " , nullptr ) ) ! = kOkRC )
goto errLabel ;
// preset order number
if ( ( rc = io : : uiCreateNumb ( app - > ioH , uuId , rowUuId , nullEleName , kFragPresetOrderId , chanId , " uiNumber fragLittleNumb " , nullptr , 0 , presetN , 1 , 0 ) ) ! = kOkRC )
goto errLabel ;
// store a connection for the order control back to the fragment record
_frag_set_ui_blob ( app , uuId , fragId , preset_sel : : kPresetOrderVarId , preset_idx ) ;
// preset alt letter
if ( ( rc = io : : uiCreateStr ( app - > ioH , uuId , rowUuId , nullEleName , kFragPresetAltId , chanId , " uiString fragLittleNumb " , nullptr ) ) ! = kOkRC )
goto errLabel ;
// store a connection for the order control back to the fragment record
_frag_set_ui_blob ( app , uuId , fragId , preset_sel : : kPresetAltVarId , preset_idx ) ;
*/
2021-12-19 17:18:22 +00:00
// preset order number
if ( ( rc = io : : uiCreateNumb ( app - > ioH , uuId , colUuId , nullEleName , kFragPresetOrderId , chanId , nullClass , nullptr , 0 , presetN , 1 , 0 ) ) ! = kOkRC )
goto errLabel ;
2022-05-21 15:22:53 +00:00
// store a connection for the order control back to the fragment record
2021-12-19 17:18:22 +00:00
_frag_set_ui_blob ( app , uuId , fragId , preset_sel : : kPresetOrderVarId , preset_idx ) ;
2023-12-03 16:20:38 +00:00
// preset alt letter
if ( ( rc = io : : uiCreateStr ( app - > ioH , uuId , colUuId , nullEleName , kFragPresetAltId , chanId , nullClass , nullptr ) ) ! = kOkRC )
goto errLabel ;
2021-12-19 17:18:22 +00:00
2023-12-03 16:20:38 +00:00
// store a connection for the order control back to the fragment record
_frag_set_ui_blob ( app , uuId , fragId , preset_sel : : kPresetAltVarId , preset_idx ) ;
2022-05-21 15:22:53 +00:00
// preset sequence select check
if ( ( rc = io : : uiCreateCheck ( app - > ioH , uuId , colUuId , nullEleName , kFragPresetSeqSelId , chanId , nullClass , nullptr ) ) ! = kOkRC )
goto errLabel ;
// store a connection for the sequence select control back to the fragment record
_frag_set_ui_blob ( app , uuId , fragId , preset_sel : : kPresetSeqSelectVarId , preset_idx ) ;
2021-12-19 17:18:22 +00:00
errLabel :
if ( rc ! = kOkRC )
2024-03-28 23:48:46 +00:00
rc = cwLogError ( rc , " Preset control index '%i' create failed. " , preset_idx ) ;
2021-12-19 17:18:22 +00:00
return rc ;
}
2021-12-28 01:32:56 +00:00
rc_t _create_frag_ui ( app_t * app , unsigned endLoc , unsigned fragId )
2021-11-01 14:28:44 +00:00
{
2023-03-20 23:41:58 +00:00
rc_t rc = kOkRC ;
unsigned fragListUuId = io : : uiFindElementUuId ( app - > ioH , kFragListId ) ;
2023-12-03 16:20:38 +00:00
unsigned fragChanId = fragId ; //endLoc; // use the frag. endLoc as the channel id
2023-03-20 23:41:58 +00:00
unsigned fragPanelUuId = kInvalidId ;
unsigned fragPresetRowUuId = kInvalidId ;
unsigned presetN = preset_sel : : preset_count ( app - > psH ) ;
unsigned fragBegLoc = 0 ;
2021-12-19 17:18:22 +00:00
// create the UI object
2022-12-14 01:58:06 +00:00
if ( ( rc = io : : uiCreateFromRsrc ( app - > ioH , " frag_panel " , fragListUuId , fragChanId ) ) ! = kOkRC )
2021-12-19 17:18:22 +00:00
{
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
2021-12-28 01:32:56 +00:00
fragPanelUuId = io : : uiFindElementUuId ( app - > ioH , fragListUuId , kFragPanelId , fragChanId ) ;
2021-12-19 17:18:22 +00:00
fragPresetRowUuId = io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragPresetRowId , fragChanId ) ;
assert ( fragPanelUuId ! = kInvalidId ) ;
assert ( fragPresetRowUuId ! = kInvalidId ) ;
// Make the fragment panel clickable
io : : uiSetClickable ( app - > ioH , fragPanelUuId ) ;
2023-01-31 00:35:28 +00:00
// Set the fragment panel order.
2021-12-19 17:18:22 +00:00
io : : uiSetOrderKey ( app - > ioH , fragPanelUuId , endLoc ) ;
2023-12-05 20:34:25 +00:00
2021-12-30 02:57:04 +00:00
// Set the fragment beg/end play range
get_value ( app - > psH , fragId , preset_sel : : kBegPlayLocVarId , kInvalidId , fragBegLoc ) ;
2023-12-05 20:34:25 +00:00
uiSetNumbRange ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragBegPlayLocId , fragChanId ) , app - > minScoreLoc , app - > maxScoreLoc , 1 , 0 , fragBegLoc ) ;
uiSetNumbRange ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragEndPlayLocId , fragChanId ) , app - > minScoreLoc , app - > maxScoreLoc , 1 , 0 , endLoc ) ;
2021-12-19 17:18:22 +00:00
// Attach blobs to the UI to allow convenient access back to the prese_sel data record
2022-05-21 15:22:53 +00:00
_frag_set_ui_blob ( app , io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragInGainId , fragChanId ) , fragId , preset_sel : : kInGainVarId , kInvalidId ) ;
_frag_set_ui_blob ( app , io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragOutGainId , fragChanId ) , fragId , preset_sel : : kOutGainVarId , kInvalidId ) ;
_frag_set_ui_blob ( app , io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragWetDryGainId , fragChanId ) , fragId , preset_sel : : kWetGainVarId , kInvalidId ) ;
_frag_set_ui_blob ( app , io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragFadeOutMsId , fragChanId ) , fragId , preset_sel : : kFadeOutMsVarId , kInvalidId ) ;
_frag_set_ui_blob ( app , io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragBegPlayLocId , fragChanId ) , fragId , preset_sel : : kBegPlayLocVarId , kInvalidId ) ;
_frag_set_ui_blob ( app , io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragEndPlayLocId , fragChanId ) , fragId , preset_sel : : kEndPlayLocVarId , kInvalidId ) ;
_frag_set_ui_blob ( app , io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragPlayBtnId , fragChanId ) , fragId , preset_sel : : kPlayBtnVarId , kInvalidId ) ;
_frag_set_ui_blob ( app , io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragPlaySeqBtnId , fragChanId ) , fragId , preset_sel : : kPlaySeqBtnVarId , kInvalidId ) ;
_frag_set_ui_blob ( app , io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragPlayAllBtnId , fragChanId ) , fragId , preset_sel : : kPlaySeqAllBtnVarId , kInvalidId ) ;
_frag_set_ui_blob ( app , io : : uiFindElementUuId ( app - > ioH , fragPanelUuId , kFragNoteId , fragChanId ) , fragId , preset_sel : : kNoteVarId , kInvalidId ) ;
2021-11-01 14:28:44 +00:00
2021-12-19 17:18:22 +00:00
// create each of the preset controls
2023-03-20 23:41:58 +00:00
for ( unsigned preset_idx = 0 ; preset_idx < presetN ; + + preset_idx )
2021-12-28 01:32:56 +00:00
if ( ( rc = _create_frag_preset_ctl ( app , fragId , fragPresetRowUuId , presetN , preset_idx ) ) ! = kOkRC )
2021-12-19 17:18:22 +00:00
goto errLabel ;
2021-12-30 02:57:04 +00:00
// set the uuid associated with this fragment
2021-12-28 01:32:56 +00:00
preset_sel : : set_value ( app - > psH , fragId , preset_sel : : kGuiUuIdVarId , kInvalidId , fragPanelUuId ) ;
2021-12-19 17:18:22 +00:00
errLabel :
return rc ;
}
2023-05-25 20:16:21 +00:00
rc_t _fragment_load_data ( 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 ;
}
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 )
{
2024-03-28 23:48:46 +00:00
rc = cwLogError ( rc , " File read failed on preset select. " ) ;
2023-05-25 20:16:21 +00:00
goto errLabel ;
}
2023-12-05 20:34:25 +00:00
get_loc_range ( app - > psH , app - > minScoreLoc , app - > maxScoreLoc ) ;
2023-05-25 20:16:21 +00:00
// Settting psNextFrag to a non-null value causes the
app - > psNextFrag = preset_sel : : get_fragment_base ( app - > psH ) ;
_set_status ( app , " Loaded fragment file. " ) ;
time : : get ( app - > psLoadT0 ) ;
errLabel :
mem : : release ( fn ) ;
return rc ;
}
2024-03-09 20:12:56 +00:00
rc_t _on_perf_select ( app_t * app , unsigned optionAppId ) ;
rc_t _on_ui_play_loc ( app_t * app , unsigned appId , unsigned loc ) ;
2021-12-19 17:18:22 +00:00
2023-05-25 20:16:21 +00:00
rc_t _fragment_restore_ui ( app_t * app )
{
rc_t rc = kOkRC ;
// if the fragment UI has not already been created
if ( app - > psNextFrag ! = nullptr )
{
unsigned fragId = app - > psNextFrag - > fragId ;
// create a fragment UI
if ( ( rc = _create_frag_ui ( app , app - > psNextFrag - > endLoc , fragId ) ) ! = kOkRC )
{
cwLogError ( rc , " Frag UI create failed. " ) ;
goto errLabel ;
}
// update the fragment UI
_update_frag_ui ( app , fragId , false ) ;
_set_status ( app , " Loaded fragment loc:%i. " , app - > psNextFrag - > endLoc ) ;
// prepare to create the next fragment UI
app - > psNextFrag = app - > psNextFrag - > link ;
// if all the fragment UI's have been created
if ( app - > psNextFrag = = nullptr )
{
2023-06-27 21:53:04 +00:00
2023-12-30 16:09:46 +00:00
io : : uiSendMsg ( app - > ioH , " { \" op \" : \" attach \" } " ) ;
2023-12-03 16:20:38 +00:00
// the fragments are loaded enable the 'load' and 'alt' menu
2023-05-27 20:01:17 +00:00
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kPerfSelId ) , true ) ;
2023-12-03 16:20:38 +00:00
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kAltSelId ) , true ) ;
2023-06-27 21:53:04 +00:00
cwLogInfo ( " Fragment restore complete: elapsed secs:%f " , time : : elapsedSecs ( app - > psLoadT0 ) ) ;
2023-12-03 16:20:38 +00:00
io : : uiRealTimeReport ( app - > ioH ) ;
2024-03-09 20:12:56 +00:00
/*
if ( app - > dflt_perf_app_id ! = kInvalidId )
{
uiSendValue ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kPerfSelId ) , app - > dflt_perf_app_id ) ;
_on_perf_select ( app , app - > dflt_perf_app_id ) ;
uiSendValue ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kBegPlayLocNumbId ) , 2538 ) ;
uiSendValue ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kEndPlayLocNumbId ) , 3517 ) ;
_on_ui_play_loc ( app , kBegPlayLocNumbId , 2538 ) ;
_on_ui_play_loc ( app , kBegPlayLocNumbId , 3517 ) ;
}
*/
2023-05-25 20:16:21 +00:00
}
}
errLabel :
if ( rc ! = kOkRC )
{
// TODO: HANDLE FAILURE
}
return rc ;
}
2023-12-05 20:34:25 +00:00
/*
2022-05-06 20:11:51 +00:00
rc_t _restore_fragment_data ( app_t * app )
2021-12-19 17:18:22 +00:00
{
2023-03-20 23:41:58 +00:00
rc_t rc = kOkRC ;
char * fn = nullptr ;
2021-12-19 17:18:22 +00:00
const preset_sel : : frag_t * f = nullptr ;
2023-05-25 20:16:21 +00:00
time : : spec_t t0 ;
time : : get ( t0 ) ;
2021-12-19 17:18:22 +00:00
// 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 ;
}
2023-12-05 20:34:25 +00:00
get_loc_range ( app - > psH , app - > minScoreLoc , app - > maxScoreLoc ) ;
2022-05-06 20:11:51 +00:00
//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 ) ;
2023-03-20 23:41:58 +00:00
for ( int i = 0 ; f ! = nullptr ; f = f - > link , + + i )
2021-12-19 17:18:22 +00:00
{
2021-12-28 01:32:56 +00:00
unsigned fragId = f - > fragId ;
2021-12-19 17:18:22 +00:00
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 ;
}
2023-05-01 01:22:49 +00:00
_update_frag_ui ( app , fragId , false ) ;
2022-05-06 20:11:51 +00:00
2021-11-01 14:28:44 +00:00
}
2021-12-19 17:18:22 +00:00
errLabel :
mem : : release ( fn ) ;
2023-05-25 20:16:21 +00:00
printf ( " ELAPSED SECS:%f \n " , time : : elapsedSecs ( t0 ) ) ;
2021-12-19 17:18:22 +00:00
return rc ;
}
2023-12-05 20:34:25 +00:00
*/
2021-12-19 17:18:22 +00:00
rc_t _on_ui_save ( app_t * app )
{
2023-03-20 23:41:58 +00:00
rc_t rc = kOkRC ;
2021-12-19 17:18:22 +00:00
char * fn = nullptr ;
2022-12-17 13:18:05 +00:00
2021-12-19 17:18:22 +00:00
// form the output file name
2022-12-17 13:18:05 +00:00
if ( ( fn = filesys : : makeFn ( app - > record_dir , app - > record_fn , app - > record_fn_ext , nullptr ) ) = = nullptr )
2021-12-19 17:18:22 +00:00
{
rc = cwLogError ( kOpFailRC , " The preset select filename could not formed. " ) ;
goto errLabel ;
}
2022-12-17 13:18:05 +00:00
// backup the current output file to versioned copy
if ( ( rc = file : : backup ( app - > record_dir , app - > record_fn , app - > record_fn_ext , app - > record_backup_dir ) ) ! = kOkRC )
{
rc = cwLogError ( kOpFailRC , " The preset select backup to '%s' failed. " , cwStringNullGuard ( app - > record_backup_dir ) ) ;
goto errLabel ;
}
2021-12-19 17:18:22 +00:00
// 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 ) ;
2021-12-30 02:57:04 +00:00
if ( rc = = kOkRC )
_clear_status ( app ) ;
else
_set_status ( app , " Save failed. " ) ;
2021-12-19 17:18:22 +00:00
return rc ;
2021-11-01 14:28:44 +00:00
}
2022-05-06 20:11:51 +00:00
int _compare_loc_map ( const void * m0 , const void * m1 )
{ return ( ( const loc_map_t * ) m0 ) - > loc - ( ( const loc_map_t * ) m1 ) - > loc ; }
2021-11-01 14:28:44 +00:00
2023-05-25 20:16:21 +00:00
rc_t _load_midi_player ( app_t * app , unsigned & midiEventCntRef )
2021-11-01 14:28:44 +00:00
{
rc_t rc = kOkRC ;
2023-11-26 20:43:52 +00:00
const perf_score : : event_t * e = nullptr ;
2021-11-01 14:28:44 +00:00
unsigned midiEventN = 0 ;
midi_record_play : : midi_msg_t * m = nullptr ;
2022-05-06 20:11:51 +00:00
midiEventCntRef = 0 ;
2021-11-01 14:28:44 +00:00
// get the count of MIDI events
2024-02-08 16:25:38 +00:00
if ( ( e = perf_score : : base_event ( app - > perfScoreH ) ) ! = nullptr )
2023-03-20 23:41:58 +00:00
for ( ; e ! = nullptr ; e = e - > link )
2021-11-01 14:28:44 +00:00
if ( e - > status ! = 0 )
2023-03-20 23:41:58 +00:00
midiEventN + = 1 ;
2021-11-01 14:28:44 +00:00
// copy the MIDI events
2024-02-08 16:25:38 +00:00
if ( ( e = perf_score : : base_event ( app - > perfScoreH ) ) ! = nullptr )
2021-11-01 14:28:44 +00:00
{
// allocate the locMap[]
2023-05-25 20:16:21 +00:00
app - > locMap = mem : : resizeZ < loc_map_t > ( app - > locMap , midiEventN ) ;
2021-11-01 14:28:44 +00:00
app - > locMapN = midiEventN ;
2023-12-17 13:51:46 +00:00
app - > minPerfLoc = score_parse : : kInvalidLocId ;
app - > maxPerfLoc = score_parse : : kInvalidLocId ;
2023-05-25 20:16:21 +00:00
2021-11-01 14:28:44 +00:00
// allocate the the player msg array
m = mem : : allocZ < midi_record_play : : midi_msg_t > ( midiEventN ) ;
// load the player msg array
2023-05-09 12:24:46 +00:00
for ( unsigned i = 0 ; e ! = nullptr & & i < midiEventN ; e = e - > link )
if ( e - > status ! = 0 )
2021-11-01 14:28:44 +00:00
{
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 ;
2023-05-25 20:16:21 +00:00
m [ i ] . id = e - > uid ;
2022-05-06 20:11:51 +00:00
m [ i ] . loc = e - > loc ;
2023-11-26 20:43:52 +00:00
m [ i ] . arg = e ;
2022-03-20 14:27:46 +00:00
2023-03-20 23:41:58 +00:00
app - > locMap [ i ] . loc = e - > loc ;
2021-11-01 14:28:44 +00:00
app - > locMap [ i ] . timestamp = m [ i ] . timestamp ;
2021-12-30 02:57:04 +00:00
2023-12-17 13:51:46 +00:00
if ( e - > loc ! = score_parse : : kInvalidLocId )
2023-05-25 20:16:21 +00:00
{
2023-12-17 13:51:46 +00:00
if ( app - > minPerfLoc = = score_parse : : kInvalidLocId )
2023-12-05 20:34:25 +00:00
app - > minPerfLoc = e - > loc ;
2023-05-25 20:16:21 +00:00
else
2023-12-05 20:34:25 +00:00
app - > minPerfLoc = std : : min ( app - > minPerfLoc , e - > loc ) ;
2023-05-25 20:16:21 +00:00
2023-12-17 13:51:46 +00:00
if ( app - > maxPerfLoc = = score_parse : : kInvalidLocId )
2023-12-05 20:34:25 +00:00
app - > maxPerfLoc = e - > loc ;
2023-05-25 20:16:21 +00:00
else
2023-12-05 20:34:25 +00:00
app - > maxPerfLoc = std : : max ( app - > maxPerfLoc , e - > loc ) ;
2023-05-25 20:16:21 +00:00
}
2021-11-01 14:28:44 +00:00
+ + i ;
}
2022-05-06 20:11:51 +00:00
qsort ( app - > locMap , app - > locMapN , sizeof ( loc_map_t ) , _compare_loc_map ) ;
2021-11-01 14:28:44 +00:00
// 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 ;
}
2023-05-25 20:16:21 +00:00
midiEventCntRef = midiEventN ;
2022-03-20 14:27:46 +00:00
2023-12-05 20:34:25 +00:00
cwLogInfo ( " %i MIDI events loaded from score. Loc Min:%i Max:%i " , midiEventN , app - > minPerfLoc , app - > maxPerfLoc ) ;
2021-11-01 14:28:44 +00:00
}
2022-05-06 20:11:51 +00:00
2023-05-25 20:16:21 +00:00
errLabel :
2022-05-06 20:11:51 +00:00
2023-05-25 20:16:21 +00:00
mem : : release ( m ) ;
return rc ;
2022-05-06 20:11:51 +00:00
}
2023-06-27 21:53:04 +00:00
rc_t _set_vel_table ( app_t * app , const vel_tbl_t * vtA , unsigned vtN )
{
rc_t rc ;
const uint8_t * tableA = nullptr ;
unsigned tableN = 0 ;
unsigned midiDevIdx = kInvalidIdx ;
unsigned assignN = 0 ;
if ( ( rc = vel_table_disable ( app - > mrpH ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Velocity table disable failed. " ) ;
goto errLabel ;
}
for ( unsigned i = 0 ; i < vtN ; + + i )
{
if ( ( midiDevIdx = label_to_device_index ( app - > mrpH , vtA [ i ] . device ) ) = = kInvalidIdx )
{
rc = cwLogError ( kInvalidArgRC , " The MIDI device '%s' could not be found. " , cwStringNullGuard ( vtA [ i ] . device ) ) ;
goto errLabel ;
}
if ( ( tableA = get_vel_table ( app - > vtH , vtA [ i ] . name , tableN ) ) = = nullptr )
{
rc = cwLogError ( kInvalidArgRC , " The MIDI velocity table '%s' could not be found. " , cwStringNullGuard ( vtA [ i ] . name ) ) ;
goto errLabel ;
}
if ( ( rc = vel_table_set ( app - > mrpH , midiDevIdx , tableA , tableN ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Velocity table device:%s name:%s assignment failed. " , cwStringNullGuard ( vtA [ i ] . device ) , cwStringNullGuard ( vtA [ i ] . name ) ) ;
goto errLabel ;
}
2023-12-03 16:20:38 +00:00
cwLogInfo ( " Applied velocity table: %s to dev: %s. " , cwStringNullGuard ( vtA [ i ] . name ) , cwStringNullGuard ( vtA [ i ] . device ) ) ;
2023-06-27 21:53:04 +00:00
assignN + = 1 ;
}
if ( assignN = = 0 )
cwLogWarning ( " All velocity tables disabled. " ) ;
errLabel :
if ( rc ! = kOkRC )
rc = cwLogError ( rc , " Velocity table assignment failed. " ) ;
return rc ;
}
2023-11-26 20:43:52 +00:00
2024-02-08 16:25:38 +00:00
rc_t _do_load_perf_score ( app_t * app , const char * perf_fn , const vel_tbl_t * vtA = nullptr , unsigned vtN = 0 )
2022-05-06 20:11:51 +00:00
{
2024-03-09 20:12:56 +00:00
rc_t rc = kOkRC ;
unsigned midiEventN = 0 ;
// only lock the current beg/end location settings if a valid perf. score is already loaded
bool lockLoctnFl = app - > perfScoreH . isValid ( ) & & app - > lockLoctnFl ;
2023-11-26 20:43:52 +00:00
2022-05-06 20:11:51 +00:00
cwLogInfo ( " Loading " ) ;
_set_status ( app , " Loading... " ) ;
2021-11-06 02:28:38 +00:00
2023-12-05 20:34:25 +00:00
// load the performance
2024-02-08 16:25:38 +00:00
if ( ( rc = perf_score : : create ( app - > perfScoreH , perf_fn ) ) ! = kOkRC )
2023-05-25 20:16:21 +00:00
{
2023-09-13 00:32:38 +00:00
cwLogError ( rc , " Score create failed on '%s'. " , perf_fn ) ;
2023-05-25 20:16:21 +00:00
goto errLabel ;
}
2022-05-06 20:11:51 +00:00
2023-06-27 21:53:04 +00:00
// load the midi player, create locMap[], set app->min/maxLoc
if ( ( rc = _load_midi_player ( app , midiEventN ) ) ! = kOkRC )
2022-05-06 20:11:51 +00:00
{
2023-06-27 21:53:04 +00:00
rc = cwLogError ( rc , " MIDI player load failed. " ) ;
goto errLabel ;
2022-05-06 20:11:51 +00:00
}
2023-05-27 20:01:17 +00:00
2023-06-27 21:53:04 +00:00
// assign the vel. table
if ( ( rc = _set_vel_table ( app , vtA , vtN ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Velocity table assignment failed. " ) ;
goto errLabel ;
}
2023-11-26 20:43:52 +00:00
2023-06-27 21:53:04 +00:00
// A performance is loaded so enable the UI
2021-11-14 18:11:11 +00:00
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kStartBtnId ) , true ) ;
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kStopBtnId ) , true ) ;
2024-03-09 20:12:56 +00:00
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kLockLoctnCheckId ) , true ) ;
2022-10-26 12:49:20 +00:00
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kLiveCheckId ) , true ) ;
2023-05-25 20:16:21 +00:00
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kEnaRecordCheckId ) , true ) ;
2023-01-05 12:31:49 +00:00
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kTrackMidiCheckId ) , true ) ;
2021-12-30 02:57:04 +00:00
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kSaveBtnId ) , true ) ;
2023-06-27 21:53:04 +00:00
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kInsertLocId ) , true ) ;
2021-11-01 14:28:44 +00:00
2023-06-27 21:53:04 +00:00
// set the UI begin/end play to the locations of the newly loaded performance
2024-03-09 20:12:56 +00:00
if ( ! lockLoctnFl )
{
app - > end_play_loc = app - > maxPerfLoc ;
app - > beg_play_loc = app - > minPerfLoc ;
}
2023-06-27 21:53:04 +00:00
// Update the master range of the play beg/end number widgets
2023-12-05 20:34:25 +00:00
io : : uiSetNumbRange ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kBegPlayLocNumbId ) , app - > minPerfLoc , app - > maxPerfLoc , 1 , 0 , app - > beg_play_loc ) ;
io : : uiSetNumbRange ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kEndPlayLocNumbId ) , app - > minPerfLoc , app - > maxPerfLoc , 1 , 0 , app - > end_play_loc ) ;
2023-06-27 21:53:04 +00:00
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kBegPlayLocNumbId ) , true ) ;
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kEndPlayLocNumbId ) , true ) ;
io : : uiSendValue ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kBegPlayLocNumbId ) , app - > beg_play_loc ) ;
io : : uiSendValue ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kEndPlayLocNumbId ) , app - > end_play_loc ) ;
// set the range of the SF reset number
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kSfResetBtnId ) , true ) ;
2023-11-26 20:43:52 +00:00
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kSfResetLocNumbId ) , true ) ;
2023-12-05 20:34:25 +00:00
io : : uiSetNumbRange ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kSfResetLocNumbId ) , app - > minPerfLoc , app - > maxPerfLoc , 1 , 0 , app - > beg_play_loc ) ;
io : : uiSendValue ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kSfResetLocNumbId ) , app - > minPerfLoc ) ;
2023-11-26 20:43:52 +00:00
2023-05-25 20:16:21 +00:00
cwLogInfo ( " '%s' loaded. " , perf_fn ) ;
2021-11-01 14:28:44 +00:00
2022-12-14 01:58:06 +00:00
errLabel :
2021-11-06 02:28:38 +00:00
_update_event_ui ( app ) ;
2021-12-30 02:57:04 +00:00
if ( rc ! = kOkRC )
_set_status ( app , " Load failed. " ) ;
else
_set_status ( app , " %i MIDI events loaded. " , midiEventN ) ;
2023-05-27 20:01:17 +00:00
//io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kLoadBtnId ), false );
2022-12-14 01:58:06 +00:00
2021-11-01 14:28:44 +00:00
return rc ;
}
2023-05-16 22:22:56 +00:00
rc_t _on_perf_select ( app_t * app , unsigned optionAppId )
{
2023-05-27 20:01:17 +00:00
rc_t rc = kOkRC ;
unsigned perf_idx = kInvalidIdx ;
perf_recording_t * prp = nullptr ;
2023-05-16 22:22:56 +00:00
// validate the selected menu id
2023-05-27 20:01:17 +00:00
if ( optionAppId < kPerfOptionBaseId )
2023-05-16 22:22:56 +00:00
{
rc = cwLogError ( kInvalidArgRC , " The performance request menu id is not valid. " ) ;
goto errLabel ;
}
perf_idx = optionAppId - kPerfOptionBaseId ;
2023-05-27 20:01:17 +00:00
// locate the selected performance record
for ( prp = app - > perfRecordingBeg ; prp ! = nullptr ; prp = prp - > link )
if ( prp - > id = = perf_idx )
break ;
2023-05-16 22:22:56 +00:00
2023-05-27 20:01:17 +00:00
// if the selected performance record was not found
if ( prp = = nullptr )
2023-05-16 22:22:56 +00:00
{
2023-05-27 20:01:17 +00:00
rc = cwLogError ( kSyntaxErrorRC , " The performance record with id:%i was not found. " , perf_idx ) ;
2023-05-16 22:22:56 +00:00
goto errLabel ;
}
2024-02-08 16:25:38 +00:00
printf ( " Loading:%s \n " , prp - > fname ) ;
2023-12-03 16:20:38 +00:00
2023-05-16 22:22:56 +00:00
// load the requested performance
2024-02-08 16:25:38 +00:00
if ( ( rc = _do_load_perf_score ( app , prp - > fname , prp - > vel_tblA , prp - > vel_tblN ) ) ! = kOkRC )
2023-05-16 22:22:56 +00:00
{
rc = cwLogError ( kSyntaxErrorRC , " The performance load failed. " ) ;
goto errLabel ;
}
errLabel :
return rc ;
}
2023-12-03 16:20:38 +00:00
rc_t _on_alt_select ( app_t * app , unsigned optionAppId )
{
rc_t rc = kOkRC ;
if ( optionAppId = = kInvalidId | | optionAppId > = alt_count ( app - > psH ) )
{
rc = cwLogError ( kInvalidArgRC , " The selected 'alt' id (%i) is invalid. " , optionAppId ) ;
goto errLabel ;
}
if ( ( rc = set_alternative ( app - > psH , optionAppId ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Alt selection failed. " ) ;
goto errLabel ;
}
cwLogInfo ( " Alt:%s selected. " , alt_label ( app - > psH , optionAppId ) ) ;
errLabel :
return rc ;
}
2023-05-16 22:22:56 +00:00
2021-11-01 14:28:44 +00:00
rc_t _on_ui_start ( app_t * app )
{
2023-05-25 20:16:21 +00:00
return _do_start ( app , app - > beg_play_loc , app - > end_play_loc ) ;
2021-11-01 14:28:44 +00:00
}
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 )
2023-03-20 23:41:58 +00:00
rc = cwLogError ( rc , " %s MIDI thru state failed. " , thru_fl ? " Enable " : " Disable " ) ;
2021-11-01 14:28:44 +00:00
return rc ;
}
2021-11-14 18:11:11 +00:00
bool _is_valid_insert_loc ( app_t * app , unsigned loc )
{
2022-12-17 22:54:39 +00:00
// the minimum possible value for the insert location is 1 because the previous end loc must be
// less than the insert location (BUT what if we are inserting location 0???? A: loc 0 is invalid
// ???? FIX the loc values1 ....
if ( loc < 1 )
return false ;
2023-05-25 20:16:21 +00:00
bool fl0 = _find_loc ( app , loc ) ! = nullptr ;
2023-03-20 23:41:58 +00:00
bool fl1 = preset_sel : : is_fragment_end_loc ( app - > psH , loc - 1 ) = = false ;
2021-11-14 18:11:11 +00:00
return fl0 & & fl1 ;
}
2021-11-06 02:28:38 +00:00
2021-12-30 02:57:04 +00:00
// Called when the global play locations change
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
{
2023-03-20 23:41:58 +00:00
rc_t rc = kOkRC ;
2021-11-06 02:28:38 +00:00
2022-01-22 14:55:17 +00:00
// verify that the location exists
if ( _find_loc ( app , loc ) = = nullptr )
_set_status ( app , " %i is an invalid location. " , loc ) ;
else
2021-11-06 02:28:38 +00:00
{
2022-01-22 14:55:17 +00:00
switch ( appId )
{
case kBegPlayLocNumbId :
app - > beg_play_loc = loc ;
break ;
2021-11-14 18:11:11 +00:00
2022-01-22 14:55:17 +00:00
case kEndPlayLocNumbId :
app - > end_play_loc = loc ;
break ;
}
bool enableFl = app - > beg_play_loc < app - > end_play_loc ;
2021-12-30 02:57:04 +00:00
2022-01-22 14:55:17 +00:00
_enable_global_play_btn ( app , enableFl ) ;
if ( enableFl )
_clear_status ( app ) ;
else
_set_status ( app , " Invalid play location range. " ) ;
}
2021-11-14 18:11:11 +00:00
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 ;
2021-12-30 02:57:04 +00:00
_clear_status ( app ) ;
2021-11-14 18:11:11 +00:00
}
else
{
app - > insertLoc = kInvalidId ;
2021-12-30 02:57:04 +00:00
_set_status ( app , " Location '%i' is not valid. " , insertLoc ) ;
2021-11-14 18:11:11 +00:00
}
2021-11-06 02:28:38 +00:00
return rc ;
}
rc_t _on_ui_insert_btn ( app_t * app )
{
2022-12-17 22:54:39 +00:00
rc_t rc = kOkRC ;
unsigned fragId = kInvalidId ;
loc_map_t * loc_ts = nullptr ;
const preset_sel : : frag_t * f = nullptr ;
unsigned end_loc = app - > insertLoc - 1 ;
2021-11-06 02:28:38 +00:00
// 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
2022-12-17 22:54:39 +00:00
if ( preset_sel : : is_fragment_end_loc ( app - > psH , end_loc ) )
2021-12-12 21:47:41 +00:00
{
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'
2022-12-17 22:54:39 +00:00
if ( ( loc_ts = _find_loc ( app , end_loc ) ) = = nullptr )
2021-12-12 21:47:41 +00:00
{
2022-12-17 22:54:39 +00:00
rc = cwLogError ( kOpFailRC , " The time stamp associated with the 'End Loc' '%i' could not be found. " , app - > insertLoc - 1 ) ;
2021-12-12 21:47:41 +00:00
goto errLabel ;
}
2021-12-28 01:32:56 +00:00
// create the data record associated with the new fragment.
2022-12-17 22:54:39 +00:00
if ( ( rc = preset_sel : : create_fragment ( app - > psH , end_loc , loc_ts - > timestamp , fragId ) ) ! = kOkRC )
2021-11-06 02:28:38 +00:00
{
2021-12-28 01:32:56 +00:00
rc = cwLogError ( rc , " Fragment data record create failed. " ) ;
2021-11-06 02:28:38 +00:00
goto errLabel ;
2021-11-01 14:28:44 +00:00
}
2021-12-28 01:32:56 +00:00
// create the fragment UI panel
2022-12-17 22:54:39 +00:00
if ( ( rc = _create_frag_ui ( app , end_loc , fragId ) ) ! = kOkRC )
2021-11-06 02:28:38 +00:00
{
2021-12-28 01:32:56 +00:00
rc = cwLogError ( rc , " Fragment UI panel create failed. " ) ;
2021-11-06 02:28:38 +00:00
goto errLabel ;
}
2021-11-14 18:11:11 +00:00
2021-12-28 01:32:56 +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
2021-12-30 02:57:04 +00:00
if ( ( f = get_fragment ( app - > psH , fragId ) ) ! = nullptr & & f - > link ! = nullptr )
_update_frag_ui ( app , f - > link - > 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 )
{
2023-03-20 23:41:58 +00:00
rc_t rc = kOkRC ;
2022-12-12 17:28:27 +00:00
unsigned fragId = kInvalidId ;
2023-03-20 23:41:58 +00:00
unsigned uuId = kInvalidId ;
2022-12-12 17:28:27 +00:00
const preset_sel : : frag_t * f = nullptr ; ;
2021-11-14 18:11:11 +00:00
2022-12-05 22:25:59 +00:00
// get the fragment id (uuid) of the selected (high-lighted) fragment
2021-11-14 18:11:11 +00:00
if ( ( fragId = preset_sel : : ui_select_fragment_id ( app - > psH ) ) = = kInvalidId )
{
2023-03-20 23:41:58 +00:00
rc = cwLogError ( kInvalidStateRC , " There is no selected fragment to delete. " ) ;
2021-11-14 18:11:11 +00:00
goto errLabel ;
}
2021-12-30 02:57:04 +00:00
// locate the uuid assocated with the specified fragid
if ( ( uuId = preset_sel : : frag_to_gui_id ( app - > psH , fragId ) ) = = kInvalidId )
{
rc = cwLogError ( kInvalidIdRC , " The uuId associated with the fragment id %i could not be found. " , fragId ) ;
goto errLabel ;
}
2022-12-12 17:28:27 +00:00
// get a pointer to the fragment prior to the one to be deleted
if ( ( f = get_fragment ( app - > psH , fragId ) ) ! = nullptr )
2023-03-20 23:41:58 +00:00
f = f - > prev ;
2022-12-12 17:28:27 +00:00
2021-11-14 18:11:11 +00:00
// 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
2021-12-30 02:57:04 +00:00
if ( ( rc = io : : uiDestroyElement ( app - > ioH , uuId ) ) ! = kOkRC )
2021-11-14 18:11:11 +00:00
goto errLabel ;
2022-12-12 17:28:27 +00:00
// update the fragment prior to deleted fragment
if ( f ! = nullptr )
_update_frag_ui ( app , f - > fragId ) ;
2023-01-31 00:35:28 +00:00
errLabel :
2021-11-14 18:11:11 +00:00
if ( rc ! = kOkRC )
rc = cwLogError ( rc , " Fragment delete failed. " ) ;
2022-01-22 14:55:17 +00:00
else
cwLogInfo ( " Fragment %i deleted. " , fragId ) ;
return rc ;
}
2023-05-25 20:16:21 +00:00
void _update_enable_midi_load_btn ( app_t * app )
{
bool enableBtnFl = ! app - > enableRecordFl & & filesys : : isFile ( app - > midiLoadFname ) ;
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kMidiLoadBtnId ) , enableBtnFl ) ;
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kMidiLoadFnameId ) , ! app - > enableRecordFl ) ;
}
rc_t _on_ui_record_check ( app_t * app , bool enableRecordFl )
{
app - > enableRecordFl = enableRecordFl ;
midi_record_play : : set_record_state ( app - > mrpH , app - > enableRecordFl ) ;
_update_enable_midi_load_btn ( app ) ;
return kOkRC ;
}
rc_t _save_midi_meta_data ( app_t * app , const char * dir )
{
rc_t rc = kOkRC ;
char * fname = nullptr ;
int bufCharN = 255 ;
unsigned bN = 0 ;
char buf [ bufCharN + 1 ] ;
// form the filename of the file to save
if ( ( fname = filesys : : makeFn ( dir , " meta " , " cfg " , nullptr , nullptr ) ) = = nullptr )
{
rc = cwLogError ( kOpFailRC , " The MIDI save filename formation failed. " ) ;
goto errLabel ;
}
if ( ( bN = snprintf ( buf , bufCharN , " { begLoc:%i } " , app - > sfResetLoc ) ) = = 0 )
{
rc = cwLogError ( kOpFailRC , " The meta data buffer formation failed. " ) ;
goto errLabel ;
}
if ( ( rc = file : : fnWrite ( fname , buf , bN ) ) ! = kOkRC )
goto errLabel ;
errLabel :
if ( rc ! = kOkRC )
rc = cwLogError ( rc , " MIDI meta data file save failed on %s. " , cwStringNullGuard ( fname ) ) ;
mem : : release ( fname ) ;
return rc ;
}
rc_t _on_midi_save_btn ( app_t * app )
{
rc_t rc = kOkRC ;
char * dir = nullptr ;
char * fname = nullptr ;
// create a versioned folder in the directory specified by app->midiRecordDir
if ( ( dir = filesys : : makeVersionedDirectory ( app - > midiRecordDir , app - > midiRecordFolder ) ) = = nullptr )
{
rc = cwLogError ( kOpFailRC , " The versioned directory creation failed on: '%s/%s'. " , cwStringNullGuard ( app - > midiRecordDir ) , cwStringNullGuard ( app - > midiRecordFolder ) ) ;
goto errLabel ;
}
// form the filename of the MIDI csv file to save
if ( ( fname = filesys : : makeFn ( dir , " midi " , " csv " , nullptr , nullptr ) ) = = nullptr )
{
rc = cwLogError ( kOpFailRC , " The MIDI save filename formation failed. " ) ;
goto errLabel ;
}
// save the MIDI data as a CSV
if ( ( rc = midi_record_play : : save_csv ( app - > mrpH , fname ) ) ! = kOkRC )
{
rc = cwLogError ( kOpFailRC , " The MIDI save failed on:. " , cwStringNullGuard ( fname ) ) ;
goto errLabel ;
}
mem : : release ( fname ) ;
// write the current score reset location as the meta data
if ( ( rc = _save_midi_meta_data ( app , dir ) ) ! = kOkRC )
goto errLabel ;
// form the filename of the MIDI SVG file to save
if ( ( fname = filesys : : makeFn ( dir , " midi_svg " , " html " , nullptr , nullptr ) ) = = nullptr )
{
rc = cwLogError ( kOpFailRC , " The MIDI SVG filename formation failed. " ) ;
goto errLabel ;
}
// write the MIDI data as an SVG file
if ( ( rc = midi_record_play : : write_svg ( app - > mrpH , fname ) ) ! = kOkRC )
{
rc = cwLogError ( kOpFailRC , " The MIDI save failed on:'%s'. " , cwStringNullGuard ( fname ) ) ;
goto errLabel ;
}
mem : : release ( fname ) ;
if ( has_stored_performance ( app - > sfH ) )
{
// form the filename of the MIDI csv file to save
if ( ( fname = filesys : : makeFn ( dir , " score_follow " , " html " , nullptr , nullptr ) ) = = nullptr )
{
rc = cwLogError ( kOpFailRC , " The score follower SVG filename formation failed. " ) ;
goto errLabel ;
}
// write the score follower SVG file
if ( ( rc = write_svg_file ( app - > sfH , fname ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Score follower SVG create failed on:'%s'. " , cwStringNullGuard ( fname ) ) ;
goto errLabel ;
}
mem : : release ( fname ) ;
// form the filename of the sync'd MIDI csv file to save
if ( ( fname = filesys : : makeFn ( dir , " play_score " , " csv " , nullptr , nullptr ) ) = = nullptr )
{
rc = cwLogError ( kOpFailRC , " The score follower SVG filename formation failed. " ) ;
goto errLabel ;
}
// sync the performance records to the score follow info
if ( ( rc = score_follower : : sync_perf_to_score ( app - > sfH ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " The score follower sync failed. " ) ;
goto errLabel ;
}
// write the sync'd CSV file
if ( ( rc = save_synced_csv ( app - > mrpH , fname , score_follower : : perf_base ( app - > sfH ) , score_follower : : perf_count ( app - > sfH ) ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Sync'd performance CSV write failed on '%s'. " , cwStringNullGuard ( fname ) ) ;
goto errLabel ;
}
// set the load filename to the name of 'play_score.csv'
io : : uiSendValue ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kMidiLoadFnameId ) , fname ) ;
}
_set_status ( app , " %i events saved to %s. SVG files updated. " , midi_record_play : : event_count ( app - > mrpH ) , cwStringNullGuard ( fname ) ) ;
errLabel :
mem : : release ( fname ) ;
mem : : release ( dir ) ;
return rc ;
}
2024-02-08 16:25:38 +00:00
/*
2023-05-25 20:16:21 +00:00
rc_t _on_midi_load_btn_0 ( app_t * app )
{
rc_t rc = kOkRC ;
filesys : : pathPart_t * pp = nullptr ;
char * fname = nullptr ;
object_t * cfg = nullptr ;
unsigned sfResetLoc ;
2024-02-08 16:25:38 +00:00
if ( ( rc = perf_score : : create_from_midi_csv ( app - > perfScoreH , app - > midiLoadFname ) ) ! = kOkRC )
2023-05-25 20:16:21 +00:00
{
rc = cwLogError ( rc , " Piano score performance load failed on '%s'. " , cwStringNullGuard ( app - > midiLoadFname ) ) ;
goto errLabel ;
}
2024-02-08 16:25:38 +00:00
if ( ( rc = _do_load_perf_score ( app , nullptr ) ) ! = kOkRC )
2023-05-25 20:16:21 +00:00
{
rc = cwLogError ( rc , " Performance load failed on '%s'. " , cwStringNullGuard ( app - > midiLoadFname ) ) ;
goto errLabel ;
}
if ( ( pp = filesys : : pathParts ( app - > midiLoadFname ) ) = = nullptr )
{
rc = cwLogError ( rc , " Splitting the path '%s' failed. " , cwStringNullGuard ( app - > midiLoadFname ) ) ;
goto errLabel ;
}
if ( ( fname = filesys : : makeFn ( pp - > dirStr , " meta " , " cfg " , nullptr , nullptr ) ) = = nullptr )
{
rc = cwLogError ( kOpFailRC , " Meta file name formation failed. " ) ;
goto errLabel ;
}
if ( ( rc = objectFromFile ( fname , cfg ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Meta file read failed on '%s'. " , cwStringNullGuard ( fname ) ) ;
goto errLabel ;
}
if ( ( rc = cfg - > getv ( " begLoc " , sfResetLoc ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Meta parse failed on '%s'. " , cwStringNullGuard ( fname ) ) ;
goto errLabel ;
}
io : : uiSendValue ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kSfResetLocNumbId ) , sfResetLoc ) ;
app - > sfResetLoc = sfResetLoc ;
errLabel :
mem : : release ( pp ) ;
mem : : release ( fname ) ;
return rc ;
}
2024-02-08 16:25:38 +00:00
*/
2023-05-25 20:16:21 +00:00
rc_t _on_midi_load_btn ( app_t * app )
{
rc_t rc = kOkRC ;
2024-02-08 16:25:38 +00:00
if ( ( rc = _do_load_perf_score ( app , app - > midiLoadFname ) ) ! = kOkRC )
2023-05-25 20:16:21 +00:00
{
rc = cwLogError ( rc , " Piano score performance load failed on '%s'. " , cwStringNullGuard ( app - > midiLoadFname ) ) ;
goto errLabel ;
}
errLabel :
return rc ;
}
rc_t _on_midi_load_fname ( app_t * app , const char * fname )
{
rc_t rc = kOkRC ;
app - > midiLoadFname = mem : : reallocStr ( app - > midiLoadFname , fname ) ;
_update_enable_midi_load_btn ( app ) ;
return rc ;
}
2022-01-22 14:55:17 +00:00
void _on_echo_midi_enable ( app_t * app , unsigned uuId , unsigned mrp_dev_idx )
{
if ( mrp_dev_idx < = midi_record_play : : device_count ( app - > mrpH ) )
{
2023-03-20 23:41:58 +00:00
bool enableFl = midi_record_play : : is_device_enabled ( app - > mrpH , mrp_dev_idx ) ;
2022-05-21 13:29:03 +00:00
2022-01-22 14:55:17 +00:00
io : : uiSendValue ( app - > ioH , uuId , enableFl ) ;
}
}
void _on_midi_enable ( app_t * app , unsigned checkAppId , unsigned mrp_dev_idx , bool enableFl )
{
unsigned midi_dev_n = midi_record_play : : device_count ( app - > mrpH ) ;
if ( mrp_dev_idx < midi_dev_n )
midi_record_play : : enable_device ( app - > mrpH , mrp_dev_idx , enableFl ) ;
else
cwLogError ( kInvalidArgRC , " %i is not a valid MIDI device index for device count:%i. " , mrp_dev_idx , midi_dev_n ) ;
}
rc_t _on_echo_master_value ( app_t * app , unsigned varId , unsigned uuId )
{
2023-03-20 23:41:58 +00:00
rc_t rc = kOkRC ;
2022-01-22 14:55:17 +00:00
double val = 0 ;
2023-03-20 23:41:58 +00:00
if ( ( rc = get_value ( app - > psH , kInvalidId , varId , kInvalidId , val ) ) ! = kOkRC )
2022-01-22 14:55:17 +00:00
rc = cwLogError ( rc , " Unable to get the master value for var id:%i. " , varId ) ;
else
io : : uiSendValue ( app - > ioH , uuId , val ) ;
return rc ;
}
rc_t _on_master_value ( app_t * app , const char * inst_label , const char * var_label , unsigned varId , double value )
{
rc_t rc = kOkRC ;
if ( ( rc = preset_sel : : set_value ( app - > psH , kInvalidId , varId , kInvalidId , value ) ) ! = kOkRC )
rc = cwLogError ( rc , " Master value set failed on varId:%i %s.%s. " , varId , cwStringNullGuard ( inst_label ) , cwStringNullGuard ( var_label ) ) ;
else
2023-12-30 16:09:46 +00:00
{
if ( app - > ioFlowH . isValid ( ) )
if ( ( rc = io_flow : : set_variable_value ( app - > ioFlowH , flow_cross : : kAllDestId , inst_label , var_label , flow : : kAnyChIdx , ( dsp : : real_t ) value ) ) ! = kOkRC )
rc = cwLogError ( rc , " Master value send failed on %s.%s. " , cwStringNullGuard ( inst_label ) , cwStringNullGuard ( var_label ) ) ;
}
2021-11-14 18:11:11 +00:00
return rc ;
}
2021-11-01 14:28:44 +00:00
2023-01-05 12:31:49 +00:00
rc_t _on_master_audio_meter ( app_t * app , const io : : msg_t & msg )
{
2023-03-20 23:41:58 +00:00
io : : audio_group_dev_t * agd = msg . u . audioGroupDev ;
unsigned n = std : : min ( agd - > chCnt , 2U ) ;
unsigned baseUiAppId = cwIsFlag ( agd - > flags , io : : kInFl ) ? kAMtrIn0Id : kAMtrOut0Id ;
2023-01-05 12:31:49 +00:00
2023-03-20 23:41:58 +00:00
for ( unsigned i = 0 ; i < n ; + + i )
2023-01-05 12:31:49 +00:00
{
2023-01-31 00:35:28 +00:00
unsigned uuid = io : : uiFindElementUuId ( app - > ioH , baseUiAppId + i ) ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
double lin_val = agd - > meterA [ i ] ;
unsigned meter_value = ( unsigned ) ( lin_val < 1e-5 ? 0 : ( 100.0 + 20 * log10 ( lin_val ) ) ) ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
io : : uiSendValue ( app - > ioH , uuid , meter_value ) ;
2023-01-05 12:31:49 +00:00
}
return kOkRC ;
}
rc_t _on_sd_control ( app_t * app , const io : : ui_msg_t & m )
{
2023-03-20 23:41:58 +00:00
rc_t rc = kOkRC ;
2023-05-25 20:16:21 +00:00
//unsigned uuid = io::uiFindElementUuId( app->ioH, m.appId );
2023-01-05 12:31:49 +00:00
const char * var_label = nullptr ;
2023-05-25 20:16:21 +00:00
//assert(uuid != kInvalidId);
2023-01-05 12:31:49 +00:00
switch ( m . appId )
{
2023-01-31 00:35:28 +00:00
case kPvWndSmpCntId :
2023-03-20 23:41:58 +00:00
var_label = " wndSmpN " ;
2023-01-31 00:35:28 +00:00
app - > pvWndSmpCnt = m . value - > u . u ;
2023-12-30 16:09:46 +00:00
if ( app - > ioFlowH . isValid ( ) )
rc = io_flow : : set_variable_value ( app - > ioFlowH , flow_cross : : kAllDestId , " pva " , var_label , flow : : kAnyChIdx , m . value - > u . u ) ;
2023-01-31 00:35:28 +00:00
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
case kSdBypassId :
2023-03-20 23:41:58 +00:00
var_label = " bypass " ;
2023-01-31 00:35:28 +00:00
app - > sdBypassFl = m . value - > u . b ;
2023-12-30 16:09:46 +00:00
if ( app - > ioFlowH . isValid ( ) )
rc = io_flow : : set_variable_value ( app - > ioFlowH , flow_cross : : kAllDestId , " sd " , var_label , flow : : kAnyChIdx , m . value - > u . b ) ;
2023-01-31 00:35:28 +00:00
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
case kSdInGainId :
2023-03-20 23:41:58 +00:00
var_label = " igain " ;
2023-01-31 00:35:28 +00:00
app - > sdInGain = m . value - > u . d ;
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
case kSdCeilingId :
2023-03-20 23:41:58 +00:00
var_label = " ceiling " ;
2023-01-31 00:35:28 +00:00
app - > sdCeiling = m . value - > u . d ;
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
case kSdExpoId :
2023-03-20 23:41:58 +00:00
var_label = " expo " ;
2023-01-31 00:35:28 +00:00
app - > sdExpo = m . value - > u . d ;
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
case kSdThreshId :
2023-03-20 23:41:58 +00:00
var_label = " thresh " ;
2023-01-31 00:35:28 +00:00
app - > sdThresh = m . value - > u . d ;
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
case kSdUprId :
2023-03-20 23:41:58 +00:00
var_label = " upr " ;
2023-01-31 00:35:28 +00:00
app - > sdUpr = m . value - > u . d ;
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
case kSdLwrId :
2023-03-20 23:41:58 +00:00
var_label = " lwr " ;
2023-01-31 00:35:28 +00:00
app - > sdLwr = m . value - > u . d ;
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
case kSdMixId :
2023-03-20 23:41:58 +00:00
var_label = " mix " ;
2023-01-31 00:35:28 +00:00
app - > sdMix = m . value - > u . d ;
break ;
case kCmpBypassId :
2023-03-20 23:41:58 +00:00
var_label = " cmp-bypass " ;
2023-01-31 00:35:28 +00:00
app - > cmpBypassFl = m . value - > u . b ;
2023-12-30 16:09:46 +00:00
if ( app - > ioFlowH . isValid ( ) )
rc = io_flow : : set_variable_value ( app - > ioFlowH , flow_cross : : kAllDestId , " cmp " , " bypass " , flow : : kAnyChIdx , m . value - > u . b ) ;
2023-01-31 00:35:28 +00:00
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
default :
assert ( 0 ) ;
2023-01-05 12:31:49 +00:00
}
2023-12-30 16:09:46 +00:00
if ( m . value - > tid = = ui : : kDoubleTId & & app - > ioFlowH . isValid ( ) )
2023-01-31 00:35:28 +00:00
rc = io_flow : : set_variable_value ( app - > ioFlowH , flow_cross : : kAllDestId , " sd " , var_label , flow : : kAnyChIdx , ( dsp : : real_t ) m . value - > u . d ) ;
2023-01-05 12:31:49 +00:00
if ( rc ! = kOkRC )
2023-01-31 00:35:28 +00:00
rc = cwLogError ( rc , " Attempt to set a spec-dist variable '%s' " , var_label ) ;
2023-01-05 12:31:49 +00:00
return rc ;
}
2024-02-08 16:25:38 +00:00
rc_t _on_live_midi_checkbox ( app_t * app , bool useLiveMidiFl )
2023-05-27 20:01:17 +00:00
{
rc_t rc = kOkRC ;
dsp : : real_t value ;
if ( useLiveMidiFl )
{
if ( ( rc = get_value ( app - > psH , kInvalidId , preset_sel : : kMasterSyncDelayMsVarId , kInvalidId , app - > dfltSyncDelayMs ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Unable to access the sync delay value. " ) ;
goto errLabel ;
}
value = 0 ;
io : : uiSendValue ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kSyncDelayMsId ) , 0 ) ;
}
else
{
value = app - > dfltSyncDelayMs ;
io : : uiSendValue ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kSyncDelayMsId ) , app - > dfltSyncDelayMs ) ;
}
2023-12-30 16:09:46 +00:00
if ( app - > ioFlowH . isValid ( ) )
if ( ( rc = io_flow : : set_variable_value ( app - > ioFlowH , flow_cross : : kAllDestId , " sync_delay " , " delayMs " , flow : : kAnyChIdx , ( dsp : : real_t ) value ) ) ! = kOkRC )
rc = cwLogError ( rc , " Error setting sync delay 'flow' value. " ) ;
2023-05-27 20:01:17 +00:00
app - > useLiveMidiFl = useLiveMidiFl ;
errLabel :
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 ) ;
2023-06-27 21:53:04 +00:00
/*
2021-11-14 18:11:11 +00:00
// disable start and stop buttons until a score is loaded
2022-12-17 13:18:05 +00:00
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 , kLiveCheckId ) , false ) ;
2023-05-25 20:16:21 +00:00
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kEnaRecordCheckId ) , false ) ;
2023-01-05 12:31:49 +00:00
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kTrackMidiCheckId ) , false ) ;
2022-12-17 13:18:05 +00:00
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kSaveBtnId ) , false ) ;
2023-05-27 20:01:17 +00:00
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kSfResetBtnId ) , false ) ;
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kSfResetLocNumbId ) , false ) ;
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kPerfSelId ) , false ) ;
2023-06-27 21:53:04 +00:00
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kInsertLocId ) , false ) ;
*/
2021-11-06 02:28:38 +00:00
2023-05-25 20:16:21 +00:00
io : : uiSendValue ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kMidiLoadFnameId ) , app - > midiRecordDir ) ;
// load the fragment data - and begin the fragment UI creation processes
// (This is not the correct place to do this - it should be in main()
// but putting it here guarantees that the basic UI is already built
// and thus will be available to _fragment_restore_ui() when it is called
// from the io::exec callback. FIX-THIS)
if ( ( rc = _fragment_load_data ( app ) ) ! = kOkRC )
rc = cwLogError ( rc , " Preset data restore failed. " ) ;
2024-02-08 16:25:38 +00:00
_on_live_midi_checkbox ( app , app - > useLiveMidiFl ) ;
2023-05-25 20:16:21 +00:00
2021-11-01 14:28:44 +00:00
return rc ;
}
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 :
2024-03-28 23:48:46 +00:00
io : : realTimeReport ( app - > ioH ) ;
2021-11-01 14:28:44 +00:00
break ;
2022-01-22 14:55:17 +00:00
case kNetPrintBtnId :
2023-12-30 16:09:46 +00:00
if ( app - > ioFlowH . isValid ( ) )
io_flow : : print_network ( app - > ioFlowH , flow_cross : : kCurDestId ) ;
2022-01-22 14:55:17 +00:00
break ;
2021-11-01 14:28:44 +00:00
case kReportBtnId :
2023-12-03 16:20:38 +00:00
//preset_sel::report( app->psH );
2021-12-30 02:57:04 +00:00
//io_flow::apply_preset( app->ioFlowH, 2000.0, app->tmp==0 ? "a" : "b");
//app->tmp = !app->tmp;
2022-03-20 14:27:46 +00:00
//io_flow::print(app->ioFlowH);
2023-02-15 02:04:30 +00:00
//io_flow::report(app->ioFlowH);
2022-05-14 14:19:18 +00:00
//midi_record_play::save_csv(app->mrpH,"/home/kevin/temp/mrp_1.csv");
2023-01-05 12:31:49 +00:00
//printf("%i %i\n",app->beg_play_loc,app->end_play_loc);
2023-03-20 23:41:58 +00:00
//io::realTimeReport(app->ioH);
2023-05-09 12:24:46 +00:00
//midi_record_play::report(app->mrpH);
2023-05-27 20:01:17 +00:00
//score_follower::write_svg_file(app->sfH,"/home/kevin/temp/temp_sf.html");
2023-05-09 12:24:46 +00:00
//score_follower::midi_state_rt_report( app->sfH, "/home/kevin/temp/temp_midi_state_rt_report.txt" );
//score_follower::score_report(app->sfH,"/home/kevin/temp/temp_cm_score_report.txt");
2023-11-26 20:43:52 +00:00
preset_sel : : report_presets ( app - > psH ) ;
2021-11-01 14:28:44 +00:00
break ;
2024-02-10 16:34:06 +00:00
case kLatencyBtnId :
latency_measure_report ( app - > ioH ) ;
latency_measure_setup ( app - > ioH ) ;
break ;
2021-11-01 14:28:44 +00:00
case kSaveBtnId :
_on_ui_save ( app ) ;
break ;
2023-05-16 22:22:56 +00:00
case kPerfSelId :
_on_perf_select ( app , m . value - > u . u ) ;
2021-11-01 14:28:44 +00:00
break ;
2023-12-03 16:20:38 +00:00
case kAltSelId :
_on_alt_select ( app , m . value - > u . u ) ;
break ;
2024-02-18 13:41:19 +00:00
case kPriPresetProbCheckId :
app - > multiPresetFlags = cwEnaFlag ( app - > multiPresetFlags , flow : : kPriPresetProbFl , m . value - > u . b ) ;
break ;
case kSecPresetProbCheckId :
app - > multiPresetFlags = cwEnaFlag ( app - > multiPresetFlags , flow : : kSecPresetProbFl , m . value - > u . b ) ;
break ;
case kPresetInterpCheckId :
app - > multiPresetFlags = cwEnaFlag ( app - > multiPresetFlags , flow : : kInterpPresetFl , m . value - > u . b ) ;
break ;
2024-03-09 20:12:56 +00:00
case kPresetAllowAllCheckId :
app - > multiPresetFlags = cwEnaFlag ( app - > multiPresetFlags , flow : : kAllowAllPresetFl , m . value - > u . b ) ;
break ;
2021-11-01 14:28:44 +00:00
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 :
2022-01-22 14:55:17 +00:00
_do_stop_play ( app ) ;
break ;
2024-03-09 20:12:56 +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 ) ;
break ;
case kLockLoctnCheckId :
app - > lockLoctnFl = m . value - > u . b ;
break ;
2022-01-22 14:55:17 +00:00
2023-01-31 00:35:28 +00:00
case kLiveCheckId :
2024-02-08 16:25:38 +00:00
_on_live_midi_checkbox ( app , m . value - > u . b ) ;
2022-10-26 12:49:20 +00:00
break ;
2023-05-25 20:16:21 +00:00
2023-01-31 00:35:28 +00:00
case kTrackMidiCheckId :
app - > trackMidiFl = m . value - > u . b ;
break ;
2023-01-05 12:31:49 +00:00
2022-01-22 14:55:17 +00:00
case kPrintMidiCheckId :
app - > printMidiFl = m . value - > u . b ;
break ;
case kPianoMidiCheckId :
2023-03-20 23:41:58 +00:00
_on_midi_enable ( app , m . appId , midi_record_play : : kPiano_MRP_DevIdx , m . value - > u . b ) ;
2022-01-22 14:55:17 +00:00
break ;
case kSamplerMidiCheckId :
2023-03-20 23:41:58 +00:00
_on_midi_enable ( app , m . appId , midi_record_play : : kSampler_MRP_DevIdx , m . value - > u . b ) ;
2021-11-01 14:28:44 +00:00
break ;
2022-01-22 14:55:17 +00:00
case kWetInGainId :
_on_master_value ( app , " mstr_wet_in_gain " , " gain " , preset_sel : : kMasterWetInGainVarId , m . value - > u . d ) ;
break ;
case kWetOutGainId :
_on_master_value ( app , " mstr_wet_out_gain " , " gain " , preset_sel : : kMasterWetOutGainVarId , m . value - > u . d ) ;
break ;
case kDryGainId :
_on_master_value ( app , " mstr_dry_out_gain " , " gain " , preset_sel : : kMasterDryGainVarId , m . value - > u . d ) ;
break ;
case kSyncDelayMsId :
_on_master_value ( app , " sync_delay " , " delayMs " , preset_sel : : kMasterSyncDelayMsVarId , ( double ) m . value - > u . i ) ;
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 ;
2023-05-25 20:16:21 +00:00
case kEnaRecordCheckId :
_on_ui_record_check ( app , m . value - > u . b ) ;
break ;
case kMidiSaveBtnId :
_on_midi_save_btn ( app ) ;
break ;
case kMidiLoadBtnId :
_on_midi_load_btn ( app ) ;
break ;
case kMidiLoadFnameId :
_on_midi_load_fname ( app , m . value - > u . s ) ;
break ;
case kSfResetBtnId :
2023-05-27 20:01:17 +00:00
_do_sf_reset ( app , app - > sfResetLoc ) ;
2023-05-25 20:16:21 +00:00
break ;
case kSfResetLocNumbId :
app - > sfResetLoc = m . value - > u . u ;
2023-05-27 20:01:17 +00:00
_do_sf_reset ( app , app - > sfResetLoc ) ;
2023-05-25 20:16:21 +00:00
break ;
2023-01-31 00:35:28 +00:00
case kPvWndSmpCntId :
case kSdBypassId :
case kSdInGainId :
case kSdCeilingId :
case kSdExpoId :
case kSdThreshId :
case kSdUprId :
case kSdLwrId :
case kSdMixId :
case kCmpBypassId :
_on_sd_control ( app , m ) ;
break ;
2022-03-20 14:27:46 +00:00
2021-12-28 01:32:56 +00:00
case kFragInGainId :
_on_ui_frag_value ( app , m . uuId , m . value - > u . d ) ;
break ;
case kFragOutGainId :
_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 ;
2021-12-28 01:32:56 +00:00
case kFragBegPlayLocId :
_on_ui_frag_value ( app , m . uuId , m . value - > u . u ) ;
break ;
case kFragEndPlayLocId :
_on_ui_frag_value ( app , m . uuId , m . value - > u . u ) ;
break ;
case kFragPlayBtnId :
_on_ui_frag_value ( app , m . uuId , m . value - > u . b ) ;
break ;
2022-05-21 13:29:03 +00:00
case kFragPlaySeqBtnId :
_on_ui_frag_value ( app , m . uuId , m . value - > u . b ) ;
break ;
2021-12-28 01:32:56 +00:00
2022-05-21 15:22:53 +00:00
case kFragPlayAllBtnId :
_on_ui_frag_value ( app , m . uuId , m . value - > u . b ) ;
break ;
2021-12-28 01:32:56 +00:00
case kFragNoteId :
_on_ui_frag_value ( app , m . uuId , m . value - > u . s ) ;
break ;
2021-11-06 02:28:38 +00:00
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 ;
2023-12-03 16:20:38 +00:00
case kFragPresetAltId :
_on_ui_frag_value ( app , m . uuId , m . value - > u . s ) ;
break ;
2021-11-06 02:28:38 +00:00
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 ;
2022-05-21 15:22:53 +00:00
case kFragPresetSeqSelId :
_on_ui_frag_value ( app , m . uuId , m . value - > u . b ) ;
break ;
2023-03-20 23:41:58 +00:00
default :
if ( kVelTblMinId < = m . appId & & m . appId < kVelTblMaxId )
vtbl : : on_ui_value ( app - > vtH , m ) ;
2021-11-01 14:28:44 +00:00
}
return rc ;
}
2021-11-14 18:11:11 +00:00
2021-12-30 02:57:04 +00:00
rc_t _onUiCorrupt ( app_t * app , const io : : ui_msg_t & m )
{
switch ( m . appId )
{
2023-01-31 00:35:28 +00:00
case kBegPlayLocNumbId :
case kEndPlayLocNumbId :
_enable_global_play_btn ( app , false ) ;
break ;
2021-12-30 02:57:04 +00:00
2023-01-31 00:35:28 +00:00
case kInsertLocId :
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kInsertBtnId ) , false ) ;
break ;
2022-12-12 17:28:27 +00:00
2023-01-31 00:35:28 +00:00
case kFragBegPlayLocId :
case kFragEndPlayLocId :
_disable_frag_play_btn ( app , m . uuId ) ;
break ;
2021-12-30 02:57:04 +00:00
2023-01-31 00:35:28 +00:00
default :
break ;
2021-12-30 02:57:04 +00:00
}
return kOkRC ;
}
2021-11-14 18:11:11 +00:00
rc_t _onUiSelect ( app_t * app , const io : : ui_msg_t & m )
{
2021-12-30 02:57:04 +00:00
rc_t rc = kOkRC ;
bool selectFl = m . value - > u . b ; // True/False if the fragment is being selected/deselected
unsigned fragId = kInvalidId ;
if ( ( fragId = preset_sel : : gui_to_frag_id ( app - > psH , m . uuId ) ) = = kInvalidId )
{
rc = cwLogError ( kInvalidIdRC , " The fragment assoicated with the UuId %i could not be found. " , m . uuId ) ;
goto errLabel ;
}
2021-11-14 18:11:11 +00:00
// track the currently selected fragment.
2021-12-30 02:57:04 +00:00
preset_sel : : ui_select_fragment ( app - > psH , fragId , selectFl ) ;
2021-11-14 18:11:11 +00:00
// enable/disable the delete fragment button
io : : uiSetEnable ( app - > ioH , io : : uiFindElementUuId ( app - > ioH , kDeleteBtnId ) , selectFl ) ;
2021-12-30 02:57:04 +00:00
errLabel :
2021-11-14 18:11:11 +00:00
return rc ;
}
2022-10-26 12:49:20 +00:00
2021-11-01 14:28:44 +00:00
rc_t _onUiEcho ( app_t * app , const io : : ui_msg_t & m )
{
rc_t rc = kOkRC ;
2022-01-22 14:55:17 +00:00
switch ( m . appId )
{
case kPrintMidiCheckId :
break ;
case kPianoMidiCheckId :
2023-03-20 23:41:58 +00:00
_on_echo_midi_enable ( app , m . uuId , midi_record_play : : kPiano_MRP_DevIdx ) ;
2022-01-22 14:55:17 +00:00
break ;
case kSamplerMidiCheckId :
2023-03-20 23:41:58 +00:00
_on_echo_midi_enable ( app , m . uuId , midi_record_play : : kSampler_MRP_DevIdx ) ;
2022-01-22 14:55:17 +00:00
break ;
2024-02-18 13:41:19 +00:00
case kPriPresetProbCheckId :
io : : uiSendValue ( app - > ioH , m . uuId , preset_cfg_flags ( app - > ioFlowH ) & flow : : kPriPresetProbFl ) ;
break ;
case kSecPresetProbCheckId :
io : : uiSendValue ( app - > ioH , m . uuId , preset_cfg_flags ( app - > ioFlowH ) & flow : : kSecPresetProbFl ) ;
break ;
case kPresetInterpCheckId :
io : : uiSendValue ( app - > ioH , m . uuId , preset_cfg_flags ( app - > ioFlowH ) & flow : : kInterpPresetFl ) ;
break ;
2024-03-09 20:12:56 +00:00
case kPresetAllowAllCheckId :
io : : uiSendValue ( app - > ioH , m . uuId , preset_cfg_flags ( app - > ioFlowH ) & flow : : kAllowAllPresetFl ) ;
break ;
2022-01-22 14:55:17 +00:00
case kWetInGainId :
_on_echo_master_value ( app , preset_sel : : kMasterWetInGainVarId , m . uuId ) ;
break ;
case kWetOutGainId :
_on_echo_master_value ( app , preset_sel : : kMasterWetOutGainVarId , m . uuId ) ;
break ;
case kDryGainId :
_on_echo_master_value ( app , preset_sel : : kMasterDryGainVarId , m . uuId ) ;
break ;
case kSyncDelayMsId :
2023-05-27 20:01:17 +00:00
//_on_echo_master_value( app, preset_sel::kMasterSyncDelayMsVarId, m.uuId );
2022-01-22 14:55:17 +00:00
break ;
2022-03-20 14:27:46 +00:00
2022-12-14 01:58:06 +00:00
case kBegPlayLocNumbId :
io : : uiSendValue ( app - > ioH , m . uuId , app - > beg_play_loc ) ;
break ;
case kEndPlayLocNumbId :
io : : uiSendValue ( app - > ioH , m . uuId , app - > end_play_loc ) ;
break ;
2023-01-31 00:35:28 +00:00
case kLiveCheckId :
io : : uiSendValue ( app - > ioH , m . uuId , app - > useLiveMidiFl ) ;
break ;
2024-03-09 20:12:56 +00:00
2023-01-31 00:35:28 +00:00
case kTrackMidiCheckId :
io : : uiSendValue ( app - > ioH , m . uuId , app - > trackMidiFl ) ;
break ;
2023-01-05 12:31:49 +00:00
2023-05-25 20:16:21 +00:00
case kEnaRecordCheckId :
io : : uiSendValue ( app - > ioH , m . uuId , app - > enableRecordFl ) ;
break ;
case kMidiLoadBtnId :
_update_enable_midi_load_btn ( app ) ;
break ;
case kSfResetLocNumbId :
io : : uiSendValue ( app - > ioH , m . uuId , app - > sfResetLoc ) ;
break ;
2023-01-31 00:35:28 +00:00
case kPvWndSmpCntId :
io : : uiSendValue ( app - > ioH , m . uuId , app - > pvWndSmpCnt ) ;
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
case kSdBypassId :
io : : uiSendValue ( app - > ioH , m . uuId , app - > sdBypassFl ) ;
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
case kSdInGainId :
io : : uiSendValue ( app - > ioH , m . uuId , app - > sdInGain ) ;
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
case kSdCeilingId :
io : : uiSendValue ( app - > ioH , m . uuId , app - > sdCeiling ) ;
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
case kSdExpoId :
io : : uiSendValue ( app - > ioH , m . uuId , app - > sdExpo ) ;
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
case kSdThreshId :
io : : uiSendValue ( app - > ioH , m . uuId , app - > sdThresh ) ;
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
case kSdUprId :
io : : uiSendValue ( app - > ioH , m . uuId , app - > sdUpr ) ;
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
case kSdLwrId :
io : : uiSendValue ( app - > ioH , m . uuId , app - > sdLwr ) ;
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
case kSdMixId :
io : : uiSendValue ( app - > ioH , m . uuId , app - > sdMix ) ;
break ;
2023-01-05 12:31:49 +00:00
2023-01-31 00:35:28 +00:00
case kCmpBypassId :
io : : uiSendValue ( app - > ioH , m . uuId , app - > cmpBypassFl ) ;
break ;
2023-01-05 12:31:49 +00:00
2023-03-20 23:41:58 +00:00
default :
if ( kVelTblMinId < = m . appId & & m . appId < = kVelTblMaxId )
vtbl : : on_ui_echo ( app - > vtH , m ) ;
2023-01-05 12:31:49 +00:00
2022-01-22 14:55:17 +00:00
}
2021-11-01 14:28:44 +00:00
return rc ;
}
rc_t _ui_callback ( app_t * app , const io : : ui_msg_t & m )
{
rc_t rc = kOkRC ;
switch ( m . opId )
{
2023-01-31 00:35:28 +00:00
case ui : : kConnectOpId :
cwLogInfo ( " UI Connected: wsSessId:%i. " , m . wsSessId ) ;
break ;
2021-11-01 14:28:44 +00:00
2023-01-31 00:35:28 +00:00
case ui : : kDisconnectOpId :
cwLogInfo ( " UI Disconnected: wsSessId:%i. " , m . wsSessId ) ;
break ;
2021-11-01 14:28:44 +00:00
2023-01-31 00:35:28 +00:00
case ui : : kInitOpId :
_onUiInit ( app , m ) ;
break ;
2021-11-01 14:28:44 +00:00
2023-01-31 00:35:28 +00:00
case ui : : kValueOpId :
_onUiValue ( app , m ) ;
break ;
2021-11-01 14:28:44 +00:00
2023-01-31 00:35:28 +00:00
case ui : : kCorruptOpId :
_onUiCorrupt ( app , m ) ;
break ;
2021-12-30 02:57:04 +00:00
2023-01-31 00:35:28 +00:00
case ui : : kClickOpId :
_do_select_frag ( app , m . uuId ) ;
break ;
2021-11-14 18:11:11 +00:00
2023-01-31 00:35:28 +00:00
case ui : : kSelectOpId :
_onUiSelect ( app , m ) ;
break ;
2021-11-14 18:11:11 +00:00
2023-01-31 00:35:28 +00:00
case ui : : kEchoOpId :
_onUiEcho ( app , m ) ;
break ;
2021-11-01 14:28:44 +00:00
2023-01-31 00:35:28 +00:00
case ui : : kIdleOpId :
_do_seq_exec ( app ) ;
break ;
2021-11-01 14:28:44 +00:00
2023-01-31 00:35:28 +00:00
case ui : : kInvalidOpId :
// fall through
default :
assert ( 0 ) ;
break ;
2021-11-01 14:28:44 +00:00
}
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 ) ;
2023-05-25 20:16:21 +00:00
if ( app - > mrpH . isValid ( ) )
2021-11-01 14:28:44 +00:00
{
midi_record_play : : exec ( app - > mrpH , * m ) ;
2023-05-25 20:16:21 +00:00
if ( midi_record_play : : is_started ( app - > mrpH ) )
2022-10-01 22:54:06 +00:00
{
2023-05-25 20:16:21 +00:00
unsigned evt_cnt = 0 ;
if ( app - > useLiveMidiFl )
{
evt_cnt = app - > enableRecordFl ? midi_record_play : : event_index ( app - > mrpH ) : 0 ;
}
else
2022-10-01 22:54:06 +00:00
{
2023-05-25 20:16:21 +00:00
evt_cnt = midi_record_play : : event_loc ( app - > mrpH ) ;
2022-10-01 22:54:06 +00:00
}
2023-05-25 20:16:21 +00:00
if ( evt_cnt > 0 )
io : : uiSendValue ( app - > ioH , uiFindElementUuId ( app - > ioH , kCurMidiEvtCntId ) , evt_cnt ) ;
2022-10-01 22:54:06 +00:00
}
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
switch ( m - > tid )
{
2023-01-31 00:35:28 +00:00
case io : : kTimerTId :
break ;
2021-11-01 14:28:44 +00:00
2023-01-31 00:35:28 +00:00
case io : : kSerialTId :
break ;
2021-11-01 14:28:44 +00:00
2023-01-31 00:35:28 +00:00
case io : : kMidiTId :
if ( app - > useLiveMidiFl & & app - > mrpH . isValid ( ) )
2024-02-08 16:25:38 +00:00
_on_live_midi_event ( app , * m ) ;
2023-01-31 00:35:28 +00:00
break ;
2021-11-01 14:28:44 +00:00
2023-01-31 00:35:28 +00:00
case io : : kAudioTId :
break ;
2021-11-01 14:28:44 +00:00
2023-01-31 00:35:28 +00:00
case io : : kAudioMeterTId :
_on_master_audio_meter ( app , * m ) ;
break ;
2021-11-01 14:28:44 +00:00
2023-01-31 00:35:28 +00:00
case io : : kSockTId :
break ;
2021-11-01 14:28:44 +00:00
2023-01-31 00:35:28 +00:00
case io : : kWebSockTId :
break ;
2021-11-01 14:28:44 +00:00
2023-01-31 00:35:28 +00:00
case io : : kUiTId :
rc = _ui_callback ( app , m - > u . ui ) ;
break ;
2021-11-01 14:28:44 +00:00
2023-01-31 00:35:28 +00:00
case io : : kExecTId :
2023-05-25 20:16:21 +00:00
_fragment_restore_ui ( app ) ;
2023-03-20 23:41:58 +00:00
vtbl : : exec ( app - > vtH ) ;
2023-01-31 00:35:28 +00:00
break ;
2022-12-14 01:58:06 +00:00
2023-01-31 00:35:28 +00:00
default :
assert ( 0 ) ;
2021-11-01 14:28:44 +00:00
}
return rc ;
}
}
}
2022-12-17 22:54:39 +00:00
cw : : rc_t cw : : preset_sel_app : : main ( const object_t * cfg , int argc , const char * argv [ ] )
2021-11-01 14:28:44 +00:00
{
2022-03-20 14:27:46 +00:00
2021-11-01 14:28:44 +00:00
rc_t rc ;
2024-03-25 14:46:45 +00:00
app_t app = { } ;
app . trackMidiFl = true ;
app . pvWndSmpCnt = 512 ;
app . sdBypassFl = false ;
app . sdInGain = 1.0 ;
app . sdCeiling = 20.0 ;
app . sdExpo = 2.0 ;
app . sdThresh = 60.0 ;
app . sdUpr = - 1.1 ;
app . sdLwr = 2.0 ;
app . sdMix = 0.0 ;
app . cmpBypassFl = false ;
app . dflt_perf_app_id = kInvalidId ;
2021-11-03 15:09:07 +00:00
const object_t * params_cfg = nullptr ;
2023-03-20 23:41:58 +00:00
unsigned vtMapN = vtbl : : get_ui_id_map_count ( ) ;
const ui : : appIdMap_t * vtMap = vtbl : : get_ui_id_map ( kPanelDivId ) ;
unsigned bigMapN = mapN + vtMapN ;
ui : : appIdMap_t bigMap [ bigMapN ] ;
2023-05-01 01:22:49 +00:00
double sysSampleRate = 0 ;
2024-03-28 23:48:46 +00:00
time : : spec_t start_time = time : : current_time ( ) ;
2024-01-06 13:57:24 +00:00
2023-03-20 23:41:58 +00:00
for ( unsigned i = 0 ; i < mapN ; + + i )
bigMap [ i ] = mapA [ i ] ;
for ( unsigned i = 0 ; i < vtMapN ; + + i )
bigMap [ mapN + i ] = vtMap [ i ] ;
2021-11-03 15:09:07 +00:00
2021-11-01 14:28:44 +00:00
// Parse the configuration
2022-12-17 22:54:39 +00:00
if ( ( rc = _parseCfg ( & app , cfg , params_cfg , argc , argv ) ) ! = kOkRC )
2021-11-01 14:28:44 +00:00
goto errLabel ;
// create the io framework instance
2023-03-20 23:41:58 +00:00
if ( ( rc = io : : create ( app . ioH , cfg , _io_callback , & app , bigMap , bigMapN ) ) ! = kOkRC )
2021-11-01 14:28:44 +00:00
{
rc = cwLogError ( kOpFailRC , " IO Framework create failed. " ) ;
goto errLabel ;
}
2021-12-30 02:57:04 +00:00
log : : setOutputCb ( log : : globalHandle ( ) , _log_output_func , & app ) ;
2023-02-26 18:44:54 +00:00
//io::report(app.ioH);
2023-02-15 02:04:30 +00:00
2023-02-19 19:18:53 +00:00
// if an input audio file is being used
app . in_audio_dev_idx = kInvalidIdx ;
if ( app . in_audio_dev_file ! = nullptr )
{
if ( ( app . in_audio_dev_idx = audioDeviceLabelToIndex ( app . ioH , app . in_audio_dev_file ) ) = = kInvalidIdx )
{
rc = cwLogError ( kInvalidArgRC , " The input audio device file '%s' could not be found. " , cwStringNullGuard ( app . in_audio_dev_file ) ) ;
goto errLabel ;
}
if ( ( rc = audioDeviceEnable ( app . ioH , app . in_audio_dev_idx , true , false ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " The input audio device file disable failed. " ) ;
goto errLabel ;
}
}
2023-05-01 01:22:49 +00:00
// get the system sample rate
if ( ( sysSampleRate = _get_system_sample_rate ( & app , " main " ) ) = = 0 )
{
rc = cwLogError ( rc , " The system sample rate could not be determined. " ) ;
goto errLabel ;
}
cwLogInfo ( " System sample rate:%f " , sysSampleRate ) ;
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 ;
}
2023-05-27 20:01:17 +00:00
get_value ( app . psH , kInvalidId , preset_sel : : kMasterSyncDelayMsVarId , kInvalidId , app . dfltSyncDelayMs ) ;
2023-05-01 01:22:49 +00:00
// create the score follower
2023-09-13 00:32:38 +00:00
if ( ( rc = create ( app . sfH , app . score_follower_cfg , sysSampleRate ) ) ! = kOkRC )
2023-05-01 01:22:49 +00:00
{
rc = cwLogError ( kOpFailRC , " score follower create failed. " ) ;
goto errLabel ;
}
2021-11-01 14:28:44 +00:00
// create the MIDI record-play object
2023-06-27 21:53:04 +00:00
if ( ( rc = midi_record_play : : create ( app . mrpH , app . ioH , * app . midi_play_record_cfg , nullptr , _midi_play_callback , & app ) ) ! = kOkRC )
2021-11-01 14:28:44 +00:00
{
rc = cwLogError ( rc , " MIDI record-play object create failed. " ) ;
goto errLabel ;
}
2023-03-20 23:41:58 +00:00
// create the vel table tuner
if ( ( rc = create ( app . vtH , app . ioH , app . mrpH , app . velTableFname , app . velTableBackupDir ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " velocity table tuner create failed. " ) ;
goto errLabel ;
}
2023-05-16 22:22:56 +00:00
2023-05-27 20:01:17 +00:00
// create the performance selection menu
if ( ( rc = _load_perf_dir_selection_menu ( & app ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " The performance list UI create failed. " ) ;
goto errLabel ;
}
2023-12-03 16:20:38 +00:00
// create the alt. selection menu
if ( ( rc = _load_alt_menu ( & app ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " The 'alt' list UI create failed. " ) ;
goto errLabel ;
}
2023-05-27 20:01:17 +00:00
2021-12-11 20:21:03 +00:00
// create the IO Flow controller
2023-12-30 16:09:46 +00:00
if ( ! audioIsEnabled ( app . ioH ) )
2021-12-11 20:21:03 +00:00
{
2023-12-30 16:09:46 +00:00
cwLogInfo ( " Audio disabled. " ) ;
}
else
{
if ( app . flow_cfg = = nullptr | | app . flow_proc_dict = = nullptr | | ( rc = io_flow : : create ( app . ioFlowH , app . ioH , sysSampleRate , app . crossFadeCnt , * app . flow_proc_dict , * app . flow_cfg ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " The IO Flow controller create failed. " ) ;
goto errLabel ;
}
2024-02-18 13:41:19 +00:00
app . multiPresetFlags = preset_cfg_flags ( app . ioFlowH ) ;
2021-12-11 20:21:03 +00:00
}
2024-02-08 16:25:38 +00:00
printf ( " ioFlow is %s valid. \n " , app . ioFlowH . isValid ( ) ? " " : " not " ) ;
2021-11-01 14:28:44 +00:00
2022-05-06 20:11:51 +00:00
// start the IO framework instance
2021-11-01 14:28:44 +00:00
if ( ( rc = io : : start ( app . ioH ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Preset-select app start failed. " ) ;
goto errLabel ;
}
2023-05-25 20:16:21 +00:00
2023-12-30 16:09:46 +00:00
//io::uiReport(app.ioH);
2024-01-06 13:57:24 +00:00
2023-12-30 16:09:46 +00:00
2021-11-01 14:28:44 +00:00
// execute the io framework
2022-10-15 13:23:58 +00:00
while ( ! io : : isShuttingDown ( app . ioH ) )
2021-11-01 14:28:44 +00:00
{
2024-03-28 23:48:46 +00:00
const unsigned wsTimeOutMs = 50 ;
time : : spec_t t0 = time : : current_time ( ) ;
unsigned timeOutMs = app . psNextFrag ! = nullptr ? 0 : wsTimeOutMs ;
2024-01-06 13:57:24 +00:00
// This call may block on the websocket handle.
2024-03-28 23:48:46 +00:00
io : : exec ( app . ioH , timeOutMs ) ;
time : : spec_t t1 = time : : current_time ( ) ;
unsigned dMs = time : : elapsedMs ( t0 , t1 ) ;
2024-01-06 13:57:24 +00:00
2024-03-28 23:48:46 +00:00
if ( dMs < wsTimeOutMs & & app . psNextFrag = = nullptr )
{
sleepMs ( wsTimeOutMs - dMs ) ;
}
2024-01-06 13:57:24 +00:00
2024-03-28 23:48:46 +00:00
if ( app . run_dur_secs ! = 0 & & time : : elapsedMs ( start_time ) / 1000 > app . run_dur_secs )
{
printf ( " Run duration expired (%i secs). Shutting down. \n " , app . run_dur_secs ) ;
io : : stop ( app . ioH ) ;
}
2021-11-01 14:28:44 +00:00
}
2021-12-28 01:32:56 +00:00
// stop the io framework
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 ;
}