Merge branch 'master' of https://gitea.larke.org/kevin/libcw
This commit is contained in:
commit
7f5ae4396c
@ -473,6 +473,7 @@ namespace cw
|
|||||||
rc_t _write_cache_output( dev_t* d )
|
rc_t _write_cache_output( dev_t* d )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
|
//sample_t s;
|
||||||
|
|
||||||
assert( d->oCacheEnd != nullptr );
|
assert( d->oCacheEnd != nullptr );
|
||||||
|
|
||||||
@ -485,6 +486,10 @@ namespace cw
|
|||||||
memcpy(d->oCacheEnd->buf + d->oCacheEnd->frameIdx * d->oChCnt, d->oPktAudioBuf, d->framesPerCycle * d->oChCnt * sizeof(sample_t));
|
memcpy(d->oCacheEnd->buf + d->oCacheEnd->frameIdx * d->oChCnt, d->oPktAudioBuf, d->framesPerCycle * d->oChCnt * sizeof(sample_t));
|
||||||
d->oCacheEnd->frameIdx += d->framesPerCycle;
|
d->oCacheEnd->frameIdx += d->framesPerCycle;
|
||||||
|
|
||||||
|
//s = vop::sum(d->oPktAudioBuf,d->framesPerCycle * d->oChCnt);
|
||||||
|
|
||||||
|
//printf("w:%i %i %f\n",d->oCacheEnd->frameIdx,d->framesPerCycle * d->oChCnt,s);
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
2
cwFile.h
2
cwFile.h
@ -160,7 +160,7 @@ namespace cw
|
|||||||
//
|
//
|
||||||
// On the first call to this function *bufPtrPtr must be set to nullptr and
|
// On the first call to this function *bufPtrPtr must be set to nullptr and
|
||||||
// *bufByteCntPtr must be set to 0.
|
// *bufByteCntPtr must be set to 0.
|
||||||
// Following the last call to this function call cmMemPtrFree(bufPtrptr)
|
// Following the last call to this function call mem::release(bufPtrptr)
|
||||||
// to be sure the line buffer is fully released. Note this step is not
|
// to be sure the line buffer is fully released. Note this step is not
|
||||||
// neccessary if the last call does not return kOkFileRC.
|
// neccessary if the last call does not return kOkFileRC.
|
||||||
rc_t getLineAuto( handle_t h, char** bufPtrPtr, unsigned* bufByteCntPtr );
|
rc_t getLineAuto( handle_t h, char** bufPtrPtr, unsigned* bufByteCntPtr );
|
||||||
|
35
cwIo.cpp
35
cwIo.cpp
@ -58,6 +58,7 @@ namespace cw
|
|||||||
unsigned index;
|
unsigned index;
|
||||||
unsigned periodMicroSec;
|
unsigned periodMicroSec;
|
||||||
bool asyncFl;
|
bool asyncFl;
|
||||||
|
time::spec_t nextTime;
|
||||||
} timer_t;
|
} timer_t;
|
||||||
|
|
||||||
typedef struct serialPort_str
|
typedef struct serialPort_str
|
||||||
@ -282,6 +283,7 @@ namespace cw
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Timer
|
// Timer
|
||||||
@ -290,7 +292,16 @@ namespace cw
|
|||||||
{
|
{
|
||||||
timer_t* t = (timer_t*)arg;
|
timer_t* t = (timer_t*)arg;
|
||||||
|
|
||||||
sleepUs( t->periodMicroSec );
|
time::spec_t t0;
|
||||||
|
time::get(t0);
|
||||||
|
|
||||||
|
int usec = time::diffMicros(t0,t->nextTime);
|
||||||
|
|
||||||
|
if( usec > 0 )
|
||||||
|
sleepUs(usec);
|
||||||
|
|
||||||
|
time::advanceMicros(t->nextTime,t->periodMicroSec);
|
||||||
|
|
||||||
|
|
||||||
if( t->startedFl && !t->deletedFl )
|
if( t->startedFl && !t->deletedFl )
|
||||||
{
|
{
|
||||||
@ -352,6 +363,9 @@ namespace cw
|
|||||||
t->asyncFl = asyncFl;
|
t->asyncFl = asyncFl;
|
||||||
t->periodMicroSec = periodMicroSec;
|
t->periodMicroSec = periodMicroSec;
|
||||||
|
|
||||||
|
|
||||||
|
time::get(t->nextTime);
|
||||||
|
|
||||||
if((rc = thread_mach::add(p->threadMachH,_timerThreadCb,t)) != kOkRC )
|
if((rc = thread_mach::add(p->threadMachH,_timerThreadCb,t)) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"Timer thread assignment failed.");
|
rc = cwLogError(rc,"Timer thread assignment failed.");
|
||||||
@ -380,7 +394,6 @@ namespace cw
|
|||||||
rc = kInvalidIdRC;
|
rc = kInvalidIdRC;
|
||||||
else
|
else
|
||||||
p->timerA[ timerIdx ].startedFl = startFl;
|
p->timerA[ timerIdx ].startedFl = startFl;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2517,7 +2530,25 @@ cw::rc_t cw::io::timerSetPeriodMicroSec( handle_t h, unsigned timerIdx, unsig
|
|||||||
if( t == nullptr )
|
if( t == nullptr )
|
||||||
rc = kInvalidIdRC;
|
rc = kInvalidIdRC;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
p->timerA[ timerIdx ].periodMicroSec = periodMicroSec;
|
p->timerA[ timerIdx ].periodMicroSec = periodMicroSec;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::io::timerSetNextTime( handle_t h, unsigned timerIdx, const time::spec_t& time )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
io_t* p = _handleToPtr(h);
|
||||||
|
timer_t* t = _timerIndexToPtr(p, timerIdx);
|
||||||
|
|
||||||
|
if( t == nullptr )
|
||||||
|
rc = kInvalidIdRC;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p->timerA[ timerIdx ].nextTime = time;
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
6
cwIo.h
6
cwIo.h
@ -190,6 +190,12 @@ namespace cw
|
|||||||
unsigned timerId( handle_t h, unsigned timerIdx );
|
unsigned timerId( handle_t h, unsigned timerIdx );
|
||||||
unsigned timerPeriodMicroSec( handle_t h, unsigned timerIdx );
|
unsigned timerPeriodMicroSec( handle_t h, unsigned timerIdx );
|
||||||
rc_t timerSetPeriodMicroSec( handle_t h, unsigned timerIdx, unsigned periodMicroSec );
|
rc_t timerSetPeriodMicroSec( handle_t h, unsigned timerIdx, unsigned periodMicroSec );
|
||||||
|
|
||||||
|
// Set an explicit next time to trigger. The 'time' argument will over ride the next periodic callback.
|
||||||
|
// Note that the most reliable way to use this function is by calling it in the timer callback
|
||||||
|
// so that it will deterine the time of the following callback.
|
||||||
|
rc_t timerSetNextTime( handle_t h, unsigned timerIdx, const time::spec_t& time );
|
||||||
|
|
||||||
rc_t timerStart( handle_t h, unsigned timerIdx );
|
rc_t timerStart( handle_t h, unsigned timerIdx );
|
||||||
rc_t timerStop( handle_t h, unsigned timerIdx );
|
rc_t timerStop( handle_t h, unsigned timerIdx );
|
||||||
|
|
||||||
|
@ -54,12 +54,25 @@ namespace cw
|
|||||||
|
|
||||||
} am_midi_msg_t;
|
} am_midi_msg_t;
|
||||||
|
|
||||||
|
typedef struct vel_tbl_str
|
||||||
|
{
|
||||||
|
uint8_t* velTblA;
|
||||||
|
unsigned velTblN;
|
||||||
|
bool enableFl;
|
||||||
|
bool defaultFl;
|
||||||
|
char* name;
|
||||||
|
char* device;
|
||||||
|
} vel_tbl_t;
|
||||||
|
|
||||||
typedef struct midi_device_str
|
typedef struct midi_device_str
|
||||||
{
|
{
|
||||||
|
char* label;
|
||||||
|
|
||||||
char* midiOutDevLabel;
|
char* midiOutDevLabel;
|
||||||
char* midiOutPortLabel;
|
char* midiOutPortLabel;
|
||||||
unsigned midiOutDevIdx;
|
unsigned midiOutDevIdx;
|
||||||
unsigned midiOutPortIdx;
|
unsigned midiOutPortIdx;
|
||||||
|
|
||||||
bool enableFl;
|
bool enableFl;
|
||||||
unsigned velTableN;
|
unsigned velTableN;
|
||||||
uint8_t* velTableArray;
|
uint8_t* velTableArray;
|
||||||
@ -104,7 +117,6 @@ namespace cw
|
|||||||
kWaitForPedalDown,
|
kWaitForPedalDown,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef struct midi_record_play_str
|
typedef struct midi_record_play_str
|
||||||
{
|
{
|
||||||
io::handle_t ioH;
|
io::handle_t ioH;
|
||||||
@ -114,6 +126,7 @@ namespace cw
|
|||||||
unsigned msgArrayInIdx; // Next available space for loaded MIDI messages (also the current count of msgs in msgArray[])
|
unsigned msgArrayInIdx; // Next available space for loaded MIDI messages (also the current count of msgs in msgArray[])
|
||||||
unsigned msgArrayOutIdx; // Next message to transmit in msgArray[]
|
unsigned msgArrayOutIdx; // Next message to transmit in msgArray[]
|
||||||
unsigned midi_timer_period_micro_sec; // Timer period in microseconds
|
unsigned midi_timer_period_micro_sec; // Timer period in microseconds
|
||||||
|
unsigned midi_timer_index; //
|
||||||
unsigned all_off_delay_ms; // Wait this long before turning all notes off after the last note-on has played
|
unsigned all_off_delay_ms; // Wait this long before turning all notes off after the last note-on has played
|
||||||
|
|
||||||
am_midi_msg_t* iMsgArray; // msgArray[ msgArrayN ]
|
am_midi_msg_t* iMsgArray; // msgArray[ msgArrayN ]
|
||||||
@ -151,7 +164,6 @@ namespace cw
|
|||||||
time::spec_t start_time;
|
time::spec_t start_time;
|
||||||
time::spec_t end_play_event_timestamp;
|
time::spec_t end_play_event_timestamp;
|
||||||
time::spec_t all_off_timestamp;
|
time::spec_t all_off_timestamp;
|
||||||
time::spec_t store_time;
|
|
||||||
|
|
||||||
event_callback_t cb;
|
event_callback_t cb;
|
||||||
void* cb_arg;
|
void* cb_arg;
|
||||||
@ -169,13 +181,13 @@ namespace cw
|
|||||||
rc_t _destroy( midi_record_play_t* p )
|
rc_t _destroy( midi_record_play_t* p )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
unsigned timerIdx;
|
|
||||||
|
|
||||||
if((timerIdx = io::timerLabelToIndex( p->ioH, TIMER_LABEL )) != kInvalidIdx )
|
if(p->midi_timer_index != kInvalidIdx )
|
||||||
io::timerDestroy( p->ioH, timerIdx);
|
io::timerDestroy( p->ioH, p->midi_timer_index);
|
||||||
|
|
||||||
for(unsigned i=0; i<p->midiDevN; ++i)
|
for(unsigned i=0; i<p->midiDevN; ++i)
|
||||||
{
|
{
|
||||||
|
mem::release(p->midiDevA[i].label);
|
||||||
mem::release(p->midiDevA[i].midiOutDevLabel);
|
mem::release(p->midiDevA[i].midiOutDevLabel);
|
||||||
mem::release(p->midiDevA[i].midiOutPortLabel);
|
mem::release(p->midiDevA[i].midiOutPortLabel);
|
||||||
mem::release(p->midiDevA[i].velTableArray);
|
mem::release(p->midiDevA[i].velTableArray);
|
||||||
@ -184,11 +196,21 @@ namespace cw
|
|||||||
mem::release(p->midiDevA);
|
mem::release(p->midiDevA);
|
||||||
mem::release(p->msgArray);
|
mem::release(p->msgArray);
|
||||||
mem::release(p->iMsgArray);
|
mem::release(p->iMsgArray);
|
||||||
|
printf("P:%p\n",p);
|
||||||
mem::release(p);
|
mem::release(p);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned _label_to_device_index( midi_record_play_t* p, const char* label )
|
||||||
|
{
|
||||||
|
for(unsigned i=0; i<p->midiDevN; ++i)
|
||||||
|
if( textCompare(p->midiDevA[i].label,label) == 0 )
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return kInvalidIdx;
|
||||||
|
}
|
||||||
|
|
||||||
void _xmit_midi( midi_record_play_t* p, unsigned devIdx, uint8_t ch, uint8_t status, uint8_t d0, uint8_t d1 )
|
void _xmit_midi( midi_record_play_t* p, unsigned devIdx, uint8_t ch, uint8_t status, uint8_t d0, uint8_t d1 )
|
||||||
{
|
{
|
||||||
if( !p->supressMidiXmitFl )
|
if( !p->supressMidiXmitFl )
|
||||||
@ -352,7 +374,6 @@ namespace cw
|
|||||||
}
|
}
|
||||||
|
|
||||||
_set_chord_note_count(m0,m,chordNoteCnt);
|
_set_chord_note_count(m0,m,chordNoteCnt);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_t _parseCfg(midi_record_play_t* p, const object_t& cfg )
|
rc_t _parseCfg(midi_record_play_t* p, const object_t& cfg )
|
||||||
@ -386,13 +407,14 @@ namespace cw
|
|||||||
for(unsigned i=0; i<p->midiDevN; ++i)
|
for(unsigned i=0; i<p->midiDevN; ++i)
|
||||||
{
|
{
|
||||||
const object_t* ele = midiDevL->child_ele(i);
|
const object_t* ele = midiDevL->child_ele(i);
|
||||||
|
const char* label = nullptr;
|
||||||
const char* midiOutDevLabel = nullptr;
|
const char* midiOutDevLabel = nullptr;
|
||||||
const char* midiOutPortLabel = nullptr;
|
const char* midiOutPortLabel = nullptr;
|
||||||
const object_t* velTable = nullptr;
|
|
||||||
const object_t* pedalRecd = nullptr;
|
const object_t* pedalRecd = nullptr;
|
||||||
bool enableFl = false;
|
bool enableFl = false;
|
||||||
|
|
||||||
if((rc = ele->getv( "midi_out_device", midiOutDevLabel,
|
if((rc = ele->getv( "label", label,
|
||||||
|
"midi_out_device", midiOutDevLabel,
|
||||||
"midi_out_port", midiOutPortLabel,
|
"midi_out_port", midiOutPortLabel,
|
||||||
"enableFl", enableFl)) != kOkRC )
|
"enableFl", enableFl)) != kOkRC )
|
||||||
{
|
{
|
||||||
@ -402,7 +424,6 @@ namespace cw
|
|||||||
|
|
||||||
|
|
||||||
if((rc = ele->getv_opt(
|
if((rc = ele->getv_opt(
|
||||||
"vel_table", velTable,
|
|
||||||
"pedal", pedalRecd,
|
"pedal", pedalRecd,
|
||||||
"force_damper_down_fl",p->midiDevA[i].force_damper_down_fl,
|
"force_damper_down_fl",p->midiDevA[i].force_damper_down_fl,
|
||||||
"force_damper_down_threshold",p->midiDevA[i].force_damper_down_threshold,
|
"force_damper_down_threshold",p->midiDevA[i].force_damper_down_threshold,
|
||||||
@ -425,28 +446,11 @@ namespace cw
|
|||||||
p->midiDevA[i].damper_dead_band_min_value,
|
p->midiDevA[i].damper_dead_band_min_value,
|
||||||
p->midiDevA[i].damper_dead_band_max_value );
|
p->midiDevA[i].damper_dead_band_max_value );
|
||||||
|
|
||||||
|
p->midiDevA[i].label = mem::duplStr( label );
|
||||||
p->midiDevA[i].midiOutDevLabel = mem::duplStr( midiOutDevLabel);
|
p->midiDevA[i].midiOutDevLabel = mem::duplStr( midiOutDevLabel);
|
||||||
p->midiDevA[i].midiOutPortLabel = mem::duplStr( midiOutPortLabel);
|
p->midiDevA[i].midiOutPortLabel = mem::duplStr( midiOutPortLabel);
|
||||||
p->midiDevA[i].enableFl = enableFl;
|
p->midiDevA[i].enableFl = enableFl;
|
||||||
|
|
||||||
/*
|
|
||||||
if( velTable != nullptr )
|
|
||||||
{
|
|
||||||
p->midiDevA[i].velTableN = velTable->child_count();
|
|
||||||
p->midiDevA[i].velTableArray = mem::allocZ<uint8_t>(p->midiDevA[i].velTableN);
|
|
||||||
|
|
||||||
|
|
||||||
for(unsigned j=0; j<p->midiDevA[i].velTableN; ++j)
|
|
||||||
{
|
|
||||||
if((rc = velTable->child_ele(j)->value( p->midiDevA[i].velTableArray[j] )) != kOkRC )
|
|
||||||
{
|
|
||||||
rc = cwLogError(kSyntaxErrorRC,"An error occured while parsing the velocity table for MIDI device:'%s' port:'%s'.",midiOutDevLabel,midiOutPortLabel);
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if( pedalRecd != nullptr )
|
if( pedalRecd != nullptr )
|
||||||
{
|
{
|
||||||
if((rc = pedalRecd->getv( "down_id", p->midiDevA[i].pedalDownVelId,
|
if((rc = pedalRecd->getv( "down_id", p->midiDevA[i].pedalDownVelId,
|
||||||
@ -564,7 +568,7 @@ namespace cw
|
|||||||
{
|
{
|
||||||
// verify that the vel. is legal given the table
|
// verify that the vel. is legal given the table
|
||||||
if( d1 >= p->midiDevA[i].velTableN )
|
if( d1 >= p->midiDevA[i].velTableN )
|
||||||
cwLogError(kInvalidIdRC,"A MIDI note-on velocity (%i) outside the velocity table range was encountered.",d1);
|
cwLogError(kInvalidIdRC,"A MIDI note-on velocity (%i) outside the velocity table (%i>%i) range was encountered on device:%s.",d1,(p->midiDevA[i].velTableN)-1,cwStringNullGuard(p->midiDevA[i].label));
|
||||||
else
|
else
|
||||||
out_d1 = p->midiDevA[i].velTableArray[ d1 ];
|
out_d1 = p->midiDevA[i].velTableArray[ d1 ];
|
||||||
|
|
||||||
@ -1256,6 +1260,8 @@ namespace cw
|
|||||||
{
|
{
|
||||||
io::timerStop( p->ioH, io::timerIdToIndex(p->ioH, kMidiRecordPlayTimerId) );
|
io::timerStop( p->ioH, io::timerIdToIndex(p->ioH, kMidiRecordPlayTimerId) );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// BUG BUG BUG: should work for all channels
|
// BUG BUG BUG: should work for all channels
|
||||||
|
|
||||||
@ -1348,7 +1354,6 @@ namespace cw
|
|||||||
while( p->msgArray[ p->msgArrayOutIdx ].microsec <= cur_time_us )
|
while( p->msgArray[ p->msgArrayOutIdx ].microsec <= cur_time_us )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
am_midi_msg_t* mm = p->msgArray + p->msgArrayOutIdx;
|
am_midi_msg_t* mm = p->msgArray + p->msgArrayOutIdx;
|
||||||
|
|
||||||
//_print_midi_msg(mm);
|
//_print_midi_msg(mm);
|
||||||
@ -1364,105 +1369,23 @@ namespace cw
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( p->msgArrayOutIdx < p->msgArrayInIdx )
|
||||||
|
{
|
||||||
|
// the next callback should happen at now() + (next_msg_us - cur_us)
|
||||||
|
time::advanceMicros(t, p->msgArray[ p->msgArrayOutIdx ].microsec - cur_time_us );
|
||||||
|
io::timerSetNextTime( p->ioH, p->midi_timer_index,t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_t _loadVelTable( midi_record_play_t* p, const object_t* cfg, midi_device_t* dev, unsigned devIdx )
|
|
||||||
{
|
|
||||||
rc_t rc = kOkRC;
|
|
||||||
const char* refDevLabel = nullptr;
|
|
||||||
const object_t* tables = nullptr;
|
|
||||||
unsigned i = 0;
|
|
||||||
|
|
||||||
// get the textual name the device
|
|
||||||
switch( devIdx )
|
|
||||||
{
|
|
||||||
case kSampler_MRP_DevIdx: refDevLabel="sampler"; break;
|
|
||||||
case kPiano_MRP_DevIdx: refDevLabel="piano"; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// verify that the device has a label
|
|
||||||
if( refDevLabel == nullptr )
|
|
||||||
{
|
|
||||||
rc = cwLogError(kInvalidStateRC,"The MIDI record-play unit device '%i' does not have a device label.",devIdx);
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the 'tables' node
|
|
||||||
if((rc = cfg->getv("tables",tables)) != kOkRC )
|
|
||||||
{
|
|
||||||
rc = cwLogError(rc,"The 'tables' field could not be read from the vel. table cfg. object.");
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// for each table
|
|
||||||
for(i=0; i<tables->child_count(); ++i)
|
|
||||||
{
|
|
||||||
const object_t* tbl = tables->child_ele(i);
|
|
||||||
const object_t* array = nullptr;
|
|
||||||
bool enableFl = false;
|
|
||||||
bool defaultFl = false;
|
|
||||||
const char* deviceLabel = nullptr;
|
|
||||||
|
|
||||||
// read the table record
|
|
||||||
if((rc = tbl->getv("table",array,
|
|
||||||
"enableFl",enableFl,
|
|
||||||
"defaultFl",defaultFl,
|
|
||||||
"device",deviceLabel)) != kOkRC )
|
|
||||||
{
|
|
||||||
rc = cwLogError(rc,"Parsing failed on the velocity table at index '%i'.",i);
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if this table is enabled and the 'default' for this device
|
|
||||||
if( enableFl && defaultFl && textCompare(refDevLabel,deviceLabel) == 0 )
|
|
||||||
{
|
|
||||||
// allocate the actual velocity table
|
|
||||||
dev->velTableN = array->child_count();
|
|
||||||
dev->velTableArray = mem::allocZ<uint8_t>(dev->velTableN);
|
|
||||||
|
|
||||||
// for each velocity entry
|
|
||||||
for(unsigned j=0; j<dev->velTableN; ++j)
|
|
||||||
{
|
|
||||||
// read the velocity value
|
|
||||||
unsigned v;
|
|
||||||
if((rc = array->child_ele(j)->value(v)) != kOkRC )
|
|
||||||
{
|
|
||||||
rc = cwLogError(rc,"Parsing failed on the velocity at index '%i'.",j);
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate the velocity range
|
|
||||||
if( 0 <= v && v <= 127 )
|
|
||||||
dev->velTableArray[j] = (uint8_t)v;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rc = cwLogError(kInvalidArgRC,"A velocity table entry outside the range 0-127 was encountered at index %i.",j);
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if no enabled and default table was found for this device
|
|
||||||
if( i >= tables->child_count() )
|
|
||||||
{
|
|
||||||
cwLogError(kInvalidStateRC,"A velocity table was not found for MIDI device index '%i'.",devIdx );
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
errLabel:
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::midi_record_play::create( handle_t& hRef,
|
cw::rc_t cw::midi_record_play::create( handle_t& hRef,
|
||||||
io::handle_t ioH,
|
io::handle_t ioH,
|
||||||
const object_t& cfg,
|
const object_t& cfg,
|
||||||
@ -1480,20 +1403,16 @@ cw::rc_t cw::midi_record_play::create( handle_t& hRef,
|
|||||||
|
|
||||||
p = mem::allocZ<midi_record_play_t>();
|
p = mem::allocZ<midi_record_play_t>();
|
||||||
|
|
||||||
|
printf("P0:%p\n",p);
|
||||||
|
|
||||||
p->ioH = ioH; // p->ioH is used in _destory() so initialize it here
|
p->ioH = ioH; // p->ioH is used in _destory() so initialize it here
|
||||||
|
|
||||||
// parse the cfg
|
// parse the cfg
|
||||||
if((rc = _parseCfg(p,cfg)) != kOkRC )
|
if((rc = _parseCfg(p,cfg)) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
// parse the vel table cfg
|
|
||||||
if(velTableFname != nullptr )
|
|
||||||
if((rc = objectFromFile(velTableFname,velTblCfg)) != kOkRC )
|
|
||||||
{
|
|
||||||
rc = cwLogError(rc,"Parsing the velocity table cfg. failed on '%s'.",cwStringNullGuard(velTableFname));
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
p->midi_timer_index = kInvalidIdx;
|
||||||
p->cb = cb;
|
p->cb = cb;
|
||||||
p->cb_arg = cb_arg;
|
p->cb_arg = cb_arg;
|
||||||
p->halfPedalState = kHalfPedalDone;
|
p->halfPedalState = kHalfPedalDone;
|
||||||
@ -1526,13 +1445,6 @@ cw::rc_t cw::midi_record_play::create( handle_t& hRef,
|
|||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( velTblCfg != nullptr )
|
|
||||||
if((rc = _loadVelTable( p, velTblCfg, dev, i )) != kOkRC )
|
|
||||||
{
|
|
||||||
rc = cwLogError(rc,"MIDI record-play velocity table setup failed.");
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s %s : %i %i\n",dev->midiOutDevLabel, dev->midiOutPortLabel, dev->midiOutDevIdx, dev->midiOutPortIdx );
|
printf("%s %s : %i %i\n",dev->midiOutDevLabel, dev->midiOutPortLabel, dev->midiOutDevIdx, dev->midiOutPortIdx );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1543,6 +1455,12 @@ cw::rc_t cw::midi_record_play::create( handle_t& hRef,
|
|||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if((p->midi_timer_index = io::timerLabelToIndex( p->ioH, TIMER_LABEL )) == kInvalidIdx )
|
||||||
|
{
|
||||||
|
cwLogError(rc,"Audio-MIDI timer index access failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
_midi_state_clear(p);
|
_midi_state_clear(p);
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
@ -1610,9 +1528,13 @@ cw::rc_t cw::midi_record_play::start( handle_t h, bool rewindFl, const time::spe
|
|||||||
_set_midi_msg_next_play_index(p,0);
|
_set_midi_msg_next_play_index(p,0);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
|
io::timerSetNextTime( p->ioH, p->midi_timer_index,p->play_time);
|
||||||
|
|
||||||
// Set the begin play time back by the time offset of the current output event.
|
// Set the begin play time back by the time offset of the current output event.
|
||||||
// This will cause that event to be played back immediately.
|
// This will cause that event to be played back immediately.
|
||||||
time::subtractMicros(p->play_time, p->msgArray[ p->msgArrayOutIdx ].microsec );
|
time::subtractMicros(p->play_time, p->msgArray[ p->msgArrayOutIdx ].microsec );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( p->halfPedalFl )
|
if( p->halfPedalFl )
|
||||||
@ -1726,8 +1648,6 @@ cw::rc_t cw::midi_record_play::save_synced_csv( handle_t h, const char* fn, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
p->iMsgArray[i].loc = syncA[j].loc;
|
p->iMsgArray[i].loc = syncA[j].loc;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1836,6 +1756,18 @@ cw::rc_t cw::midi_record_play::load( handle_t h, const midi_msg_t* msg, unsigned
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned cw::midi_record_play::label_to_device_index( handle_t h, const char* devLabel )
|
||||||
|
{
|
||||||
|
midi_record_play_t* p = _handleToPtr(h);
|
||||||
|
return _label_to_device_index( p, devLabel );
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* cw::midi_record_play::device_index_to_label( handle_t h, unsigned devIdx )
|
||||||
|
{
|
||||||
|
midi_record_play_t* p = _handleToPtr(h);
|
||||||
|
return 0 <= devIdx && devIdx < p->midiDevN ? p->midiDevA[devIdx].label : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
cw::rc_t cw::midi_record_play::seek( handle_t h, time::spec_t seek_timestamp )
|
cw::rc_t cw::midi_record_play::seek( handle_t h, time::spec_t seek_timestamp )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
@ -1845,14 +1777,14 @@ cw::rc_t cw::midi_record_play::seek( handle_t h, time::spec_t seek_timestamp )
|
|||||||
_midi_state_clear(p);
|
_midi_state_clear(p);
|
||||||
|
|
||||||
// supress MIDI transmission during the seek
|
// supress MIDI transmission during the seek
|
||||||
p->supressMidiXmitFl = true;
|
p->supressMidiXmitFl = true;
|
||||||
|
|
||||||
// iterate throught the MIDI msg array
|
// iterate throught the MIDI msg array
|
||||||
for(unsigned i=0; i<p->msgArrayInIdx; ++i)
|
for(unsigned i=0; i<p->msgArrayInIdx; ++i)
|
||||||
{
|
{
|
||||||
am_midi_msg_t* mm = p->msgArray + i;
|
am_midi_msg_t* mm = p->msgArray + i;
|
||||||
|
|
||||||
// if this msg is prior to or equal to the seek target
|
// if this msg is at or after the seek target
|
||||||
if( time::isLTE(seek_timestamp,mm->timestamp) )
|
if( time::isLTE(seek_timestamp,mm->timestamp) )
|
||||||
{
|
{
|
||||||
p->msgArrayOutIdx = i;
|
p->msgArrayOutIdx = i;
|
||||||
@ -2097,6 +2029,31 @@ unsigned cw::midi_record_play::dev_count( handle_t h )
|
|||||||
return p->midiDevN;
|
return p->midiDevN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::midi_record_play::vel_table_disable( handle_t h, unsigned devIdx )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
midi_record_play_t* p = _handleToPtr(h);
|
||||||
|
|
||||||
|
if( devIdx != kInvalidIdx )
|
||||||
|
{
|
||||||
|
if( devIdx > p->midiDevN )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidArgRC,"The device index '%i'is invalid.",devIdx);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->midiDevA[devIdx].velTableArray = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(unsigned i=0; i<p->midiDevN; ++i)
|
||||||
|
p->midiDevA[i].velTableArray = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned cw::midi_record_play::vel_table_count( handle_t h, unsigned devIdx )
|
unsigned cw::midi_record_play::vel_table_count( handle_t h, unsigned devIdx )
|
||||||
{
|
{
|
||||||
midi_record_play_t* p = _handleToPtr(h);
|
midi_record_play_t* p = _handleToPtr(h);
|
||||||
@ -2126,3 +2083,4 @@ cw::rc_t cw::midi_record_play::vel_table_set( handle_t h, unsigned devIdx, const
|
|||||||
|
|
||||||
return kOkRC;
|
return kOkRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +83,11 @@ namespace cw
|
|||||||
|
|
||||||
rc_t exec( handle_t h, const io::msg_t& msg );
|
rc_t exec( handle_t h, const io::msg_t& msg );
|
||||||
|
|
||||||
|
unsigned label_to_device_index( handle_t h, const char* devLabel );
|
||||||
|
const char* device_index_to_label( handle_t h, unsigned devIdx );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned device_count( handle_t h );
|
unsigned device_count( handle_t h );
|
||||||
bool is_device_enabled( handle_t h, unsigned devIdx );
|
bool is_device_enabled( handle_t h, unsigned devIdx );
|
||||||
void enable_device( handle_t h, unsigned devIdx, bool enableFl );
|
void enable_device( handle_t h, unsigned devIdx, bool enableFl );
|
||||||
@ -97,6 +102,9 @@ namespace cw
|
|||||||
|
|
||||||
unsigned dev_count( handle_t h );
|
unsigned dev_count( handle_t h );
|
||||||
|
|
||||||
|
// Set devIdx to kInvalididx to disable vel tables on all devices
|
||||||
|
rc_t vel_table_disable( handle_t h, unsigned devIdx=kInvalidIdx );
|
||||||
|
|
||||||
unsigned vel_table_count( handle_t h, unsigned devIdx );
|
unsigned vel_table_count( handle_t h, unsigned devIdx );
|
||||||
const uint8_t* vel_table( handle_t h, unsigned devIdx );
|
const uint8_t* vel_table( handle_t h, unsigned devIdx );
|
||||||
rc_t vel_table_set( handle_t h, unsigned devIdx, const uint8_t* tbl, unsigned tblN );
|
rc_t vel_table_set( handle_t h, unsigned devIdx, const uint8_t* tbl, unsigned tblN );
|
||||||
|
@ -238,27 +238,36 @@ namespace cw
|
|||||||
unsigned presetId;
|
unsigned presetId;
|
||||||
} ui_blob_t;
|
} ui_blob_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct vel_tbl_str
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
const char* device;
|
||||||
|
} vel_tbl_t;
|
||||||
|
|
||||||
typedef struct perf_recording_str
|
typedef struct perf_recording_str
|
||||||
{
|
{
|
||||||
char* fname; // perf recording
|
char* fname; // perf recording
|
||||||
char* label; // menu label
|
char* label; // menu label
|
||||||
unsigned id; // menu appId
|
unsigned id; // menu appId
|
||||||
unsigned uuId; // menu uuid
|
unsigned uuId; // menu uuid
|
||||||
|
vel_tbl_t* vel_tblA; // vel_tblA[ velTblN ]
|
||||||
|
unsigned vel_tblN; //
|
||||||
struct perf_recording_str* link;
|
struct perf_recording_str* link;
|
||||||
} perf_recording_t;
|
} perf_recording_t;
|
||||||
|
|
||||||
typedef struct app_str
|
typedef struct app_str
|
||||||
{
|
{
|
||||||
io::handle_t ioH;
|
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;
|
||||||
|
|
||||||
const char* record_dir;
|
|
||||||
const char* record_fn;
|
|
||||||
const char* record_fn_ext;
|
|
||||||
const char* record_backup_dir;
|
|
||||||
const char* scoreFn;
|
const char* scoreFn;
|
||||||
const object_t* perfL;
|
|
||||||
const object_t* perfDirL;
|
const object_t* perfDirL;
|
||||||
unsigned perfMenuCnt;
|
|
||||||
const char* velTableFname;
|
const char* velTableFname;
|
||||||
const char* velTableBackupDir;
|
const char* velTableBackupDir;
|
||||||
const object_t* midi_play_record_cfg;
|
const object_t* midi_play_record_cfg;
|
||||||
@ -271,47 +280,43 @@ namespace cw
|
|||||||
unsigned in_audio_begin_loc;
|
unsigned in_audio_begin_loc;
|
||||||
double in_audio_offset_sec;
|
double in_audio_offset_sec;
|
||||||
|
|
||||||
cm::handle_t cmCtxH;
|
cm::handle_t cmCtxH;
|
||||||
score_follower::handle_t sfH;
|
score_follower::handle_t sfH;
|
||||||
midi_record_play::handle_t mrpH;
|
midi_record_play::handle_t mrpH;
|
||||||
unsigned scoreFollowMaxLocId;
|
|
||||||
|
|
||||||
score::handle_t scoreH;
|
score::handle_t scoreH;
|
||||||
loc_map_t* locMap;
|
loc_map_t* locMap;
|
||||||
unsigned locMapN;
|
unsigned locMapN;
|
||||||
|
|
||||||
unsigned insertLoc; // last valid insert location id received from the GUI
|
unsigned insertLoc; // last valid insert location id received from the GUI
|
||||||
|
|
||||||
unsigned minLoc;
|
unsigned minLoc; // min/max locations of the currently loaded performance
|
||||||
unsigned maxLoc;
|
unsigned maxLoc;
|
||||||
|
|
||||||
time::spec_t beg_play_timestamp;
|
unsigned beg_play_loc; // beg/end play loc's from the UI
|
||||||
time::spec_t end_play_timestamp;
|
unsigned end_play_loc;
|
||||||
|
|
||||||
unsigned beg_play_loc;
|
preset_sel::handle_t psH;
|
||||||
unsigned end_play_loc;
|
const preset_sel::frag_t* psNextFrag;
|
||||||
|
time::spec_t psLoadT0;
|
||||||
|
|
||||||
preset_sel::handle_t psH;
|
vtbl::handle_t vtH;
|
||||||
const preset_sel::frag_t* psNextFrag;
|
io_flow::handle_t ioFlowH;
|
||||||
time::spec_t psLoadT0;
|
|
||||||
|
|
||||||
vtbl::handle_t vtH;
|
|
||||||
io_flow::handle_t ioFlowH;
|
|
||||||
|
|
||||||
double crossFadeSrate;
|
double crossFadeSrate;
|
||||||
unsigned crossFadeCnt;
|
unsigned crossFadeCnt;
|
||||||
|
|
||||||
bool printMidiFl;
|
bool printMidiFl;
|
||||||
|
|
||||||
bool seqActiveFl; // true if the sequence is currently active (set by 'Play Seq' btn)
|
bool seqActiveFl; // true if the sequence is currently active (set by 'Play Seq' btn)
|
||||||
unsigned seqStartedFl; // set by the first seq idle callback
|
unsigned seqStartedFl; // set by the first seq idle callback
|
||||||
unsigned seqFragId; //
|
unsigned seqFragId; //
|
||||||
unsigned seqPresetIdx; //
|
unsigned seqPresetIdx; //
|
||||||
|
|
||||||
bool useLiveMidiFl; // use incoming MIDI to drive program (otherwise use score file)
|
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)
|
bool trackMidiFl; // apply presets based on MIDI location (otherwise respond only to direct manipulation of fragment control)
|
||||||
|
|
||||||
bool enableRecordFl; // enable recording of incoming MIDI
|
bool enableRecordFl; // enable recording of incoming MIDI
|
||||||
char* midiRecordDir;
|
char* midiRecordDir;
|
||||||
const char* midiRecordFolder;
|
const char* midiRecordFolder;
|
||||||
char* midiLoadFname;
|
char* midiLoadFname;
|
||||||
@ -385,19 +390,18 @@ namespace cw
|
|||||||
const char* flow_proc_dict_fn = nullptr;
|
const char* flow_proc_dict_fn = nullptr;
|
||||||
const char* midi_record_dir;
|
const char* midi_record_dir;
|
||||||
|
|
||||||
if((rc = cfg->getv( "params", params_cfgRef,
|
if((rc = cfg->getv( "params", params_cfgRef,
|
||||||
"flow", app->flow_cfg)) != kOkRC )
|
"flow", app->flow_cfg)) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(kSyntaxErrorRC,"Preset Select App 'params' cfg record not found.");
|
rc = cwLogError(kSyntaxErrorRC,"Preset Select App 'params' cfg record not found.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((rc = params_cfgRef->getv( "record_dir", app->record_dir,
|
if((rc = params_cfgRef->getv( "record_dir", app->record_dir,
|
||||||
"record_fn", app->record_fn,
|
"record_fn", app->record_fn,
|
||||||
"record_fn_ext", app->record_fn_ext,
|
"record_fn_ext", app->record_fn_ext,
|
||||||
"score_fn", app->scoreFn,
|
"score_fn", app->scoreFn,
|
||||||
"perfDirL", app->perfDirL,
|
"perfDirL", app->perfDirL,
|
||||||
"perfL", app->perfL,
|
|
||||||
"flow_proc_dict_fn", flow_proc_dict_fn,
|
"flow_proc_dict_fn", flow_proc_dict_fn,
|
||||||
"midi_play_record", app->midi_play_record_cfg,
|
"midi_play_record", app->midi_play_record_cfg,
|
||||||
"vel_table_fname", app->velTableFname,
|
"vel_table_fname", app->velTableFname,
|
||||||
@ -485,59 +489,12 @@ namespace cw
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_t _load_perf_selection_menu( app_t* app )
|
|
||||||
{
|
|
||||||
rc_t rc = kOkRC;
|
|
||||||
unsigned selectUuId = kInvalidId;
|
|
||||||
|
|
||||||
// verify that a performance list was given
|
|
||||||
if( app->perfL == nullptr || app->perfL->child_count()==0)
|
|
||||||
{
|
|
||||||
rc = cwLogError(rc,"The performance list is missing or empty.");
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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(unsigned i=0; i<app->perfL->child_count(); ++i)
|
|
||||||
{
|
|
||||||
const object_t* pair = nullptr;
|
|
||||||
unsigned uuId = kInvalidId;
|
|
||||||
|
|
||||||
// get and validate the option label
|
|
||||||
if((pair = app->perfL->child_ele(i)) == nullptr || !pair->is_pair() || pair->pair_label()==nullptr)
|
|
||||||
{
|
|
||||||
rc = cwLogError(kSyntaxErrorRC,"The performance list contains a syntax error near element index %i.",i);
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create an option entry in the selection ui
|
|
||||||
if((rc = uiCreateOption( app->ioH, uuId, selectUuId, nullptr, kPerfOptionBaseId+i, kInvalidId, "optClass", pair->pair_label() )) != kOkRC )
|
|
||||||
{
|
|
||||||
rc = cwLogError(kSyntaxErrorRC,"The performance list contains a syntax error near element index %i.",i);
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
errLabel:
|
|
||||||
|
|
||||||
app->perfMenuCnt = app->perfL->child_count();
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc_t _load_perf_recording_menu( app_t* app )
|
rc_t _load_perf_recording_menu( app_t* app )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
perf_recording_t* prp = nullptr;
|
perf_recording_t* prp = nullptr;
|
||||||
unsigned id = 0;
|
unsigned id = 0;
|
||||||
unsigned selectUuId = kInvalidId;
|
unsigned selectUuId = kInvalidId;
|
||||||
|
|
||||||
// get the peformance menu UI uuid
|
// get the peformance menu UI uuid
|
||||||
if((selectUuId = io::uiFindElementUuId( app->ioH, kPerfSelId )) == kInvalidId )
|
if((selectUuId = io::uiFindElementUuId( app->ioH, kPerfSelId )) == kInvalidId )
|
||||||
@ -547,7 +504,7 @@ namespace cw
|
|||||||
}
|
}
|
||||||
|
|
||||||
// for each performance recording
|
// for each performance recording
|
||||||
for(prp=app->perfRecordingBeg; prp!=nullptr; prp=prp->link)
|
for(prp = app->perfRecordingBeg; prp!=nullptr; prp=prp->link)
|
||||||
{
|
{
|
||||||
// create an option entry in the selection ui
|
// create an option entry in the selection ui
|
||||||
if((rc = uiCreateOption( app->ioH, prp->uuId, selectUuId, nullptr, kPerfOptionBaseId+id, kInvalidId, "optClass", prp->label )) != kOkRC )
|
if((rc = uiCreateOption( app->ioH, prp->uuId, selectUuId, nullptr, kPerfOptionBaseId+id, kInvalidId, "optClass", prp->label )) != kOkRC )
|
||||||
@ -558,8 +515,6 @@ namespace cw
|
|||||||
|
|
||||||
prp->id = id;
|
prp->id = id;
|
||||||
id += 1;
|
id += 1;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
@ -567,12 +522,43 @@ namespace cw
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_t _parse_perf_recording_dir( app_t* app, const char* dir, const char* fname )
|
rc_t _parse_perf_recording_vel_tbl( app_t* app, const object_t* velTblCfg, vel_tbl_t*& velTblA_Ref, unsigned& velTblN_Ref )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _parse_perf_recording_dir( app_t* app, const char* dir, const char* fname, const object_t* velTblCfg )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
filesys::dirEntry_t* deA = nullptr;
|
filesys::dirEntry_t* deA = nullptr;
|
||||||
unsigned deN = 0;
|
unsigned deN = 0;
|
||||||
char* path = nullptr;
|
char* path = nullptr;
|
||||||
|
|
||||||
// get the directory entries based on 'dir'
|
// get the directory entries based on 'dir'
|
||||||
if((deA = filesys::dirEntries( dir, filesys::kDirFsFl, &deN )) == nullptr )
|
if((deA = filesys::dirEntries( dir, filesys::kDirFsFl, &deN )) == nullptr )
|
||||||
@ -585,7 +571,7 @@ namespace cw
|
|||||||
cwLogWarning("The performance recording directory '%s' was found to be empty.",cwStringNullGuard(dir));
|
cwLogWarning("The performance recording directory '%s' was found to be empty.",cwStringNullGuard(dir));
|
||||||
|
|
||||||
// for each directory entry
|
// for each directory entry
|
||||||
for(unsigned i=0; i<deN; ++i)
|
for(unsigned i = 0; i<deN && rc == kOkRC; ++i)
|
||||||
{
|
{
|
||||||
perf_recording_t* prp = nullptr;
|
perf_recording_t* prp = nullptr;
|
||||||
|
|
||||||
@ -607,6 +593,12 @@ namespace cw
|
|||||||
prp->fname = mem::duplStr(path);
|
prp->fname = mem::duplStr(path);
|
||||||
prp->label = mem::duplStr(deA[i].name);
|
prp->label = mem::duplStr(deA[i].name);
|
||||||
|
|
||||||
|
if((rc = _parse_perf_recording_vel_tbl(app, velTblCfg, prp->vel_tblA, prp->vel_tblN )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Parse failed on vel table at directory entry index '%i'.",i);
|
||||||
|
// don't goto errLabel because the perf_recording record would be leaked
|
||||||
|
}
|
||||||
|
|
||||||
if( app->perfRecordingEnd == nullptr )
|
if( app->perfRecordingEnd == nullptr )
|
||||||
{
|
{
|
||||||
app->perfRecordingBeg = prp;
|
app->perfRecordingBeg = prp;
|
||||||
@ -640,9 +632,10 @@ namespace cw
|
|||||||
// for each performance directory
|
// for each performance directory
|
||||||
for(unsigned i=0; i<app->perfDirL->child_count(); ++i)
|
for(unsigned i=0; i<app->perfDirL->child_count(); ++i)
|
||||||
{
|
{
|
||||||
const object_t* d;
|
const object_t* d = nullptr;;
|
||||||
const char* dir=nullptr;
|
const char* dir = nullptr;
|
||||||
const char* fname=nullptr;
|
const char* fname = nullptr;
|
||||||
|
const object_t* velTblCfg = nullptr;
|
||||||
|
|
||||||
// get the directory dict. from the cfg file
|
// get the directory dict. from the cfg file
|
||||||
if((d = app->perfDirL->child_ele(i)) == nullptr || !d->is_dict() )
|
if((d = app->perfDirL->child_ele(i)) == nullptr || !d->is_dict() )
|
||||||
@ -652,14 +645,16 @@ namespace cw
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get the directory
|
// get the directory
|
||||||
if((rc = d->getv("dir",dir,"fname",fname)) != kOkRC )
|
if((rc = d->getv("dir",dir,
|
||||||
|
"fname",fname,
|
||||||
|
"vel_table", velTblCfg)) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc ,"Error parsing the performance directory entry at index '%i'.",i);
|
rc = cwLogError(rc ,"Error parsing the performance directory entry at index '%i'.",i);
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the performance records from this directory
|
// create the performance records from this directory
|
||||||
if((rc = _parse_perf_recording_dir(app,dir,fname)) != kOkRC )
|
if((rc = _parse_perf_recording_dir(app,dir,fname,velTblCfg)) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc ,"Error creating the performance directory entry at index '%i'.",i);
|
rc = cwLogError(rc ,"Error creating the performance directory entry at index '%i'.",i);
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
@ -727,6 +722,7 @@ namespace cw
|
|||||||
perf_recording_t* tmp = prp->link;
|
perf_recording_t* tmp = prp->link;
|
||||||
mem::release(prp->fname);
|
mem::release(prp->fname);
|
||||||
mem::release(prp->label);
|
mem::release(prp->label);
|
||||||
|
mem::release(prp->vel_tblA);
|
||||||
mem::release(prp);
|
mem::release(prp);
|
||||||
prp = tmp;
|
prp = tmp;
|
||||||
}
|
}
|
||||||
@ -904,17 +900,11 @@ namespace cw
|
|||||||
maxLocId = matchLocA[i];
|
maxLocId = matchLocA[i];
|
||||||
printf("%i ",matchLocA[i]);
|
printf("%i ",matchLocA[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// notice if the end of the score was reached
|
|
||||||
if( maxLocId > app->scoreFollowMaxLocId )
|
|
||||||
{
|
|
||||||
loc = maxLocId;
|
|
||||||
app->scoreFollowMaxLocId = maxLocId;
|
|
||||||
printf(" set");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
|
||||||
|
loc = maxLocId;
|
||||||
|
|
||||||
clear_match_id_array(app->sfH);
|
clear_match_id_array(app->sfH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -960,7 +950,8 @@ namespace cw
|
|||||||
double sec = time::specToSeconds(timestamp);
|
double sec = time::specToSeconds(timestamp);
|
||||||
|
|
||||||
// call the score follower
|
// call the score follower
|
||||||
loc = _get_loc_from_score_follower( app, sec, id, status, d0, d1 );
|
if( score_follower::is_enabled(app->sfH) )
|
||||||
|
loc = _get_loc_from_score_follower( app, sec, id, status, d0, d1 );
|
||||||
|
|
||||||
// TODO: ZERO SHOULD BE A VALID LOC VALUE - MAKE -1 THE INVALID LOC VALUE
|
// TODO: ZERO SHOULD BE A VALID LOC VALUE - MAKE -1 THE INVALID LOC VALUE
|
||||||
|
|
||||||
@ -1098,8 +1089,6 @@ namespace cw
|
|||||||
|
|
||||||
score_follower::reset(app->sfH,app->sfResetLoc);
|
score_follower::reset(app->sfH,app->sfResetLoc);
|
||||||
|
|
||||||
app->scoreFollowMaxLocId = 0;
|
|
||||||
|
|
||||||
cwLogInfo("SF reset loc: %i",app->sfResetLoc);
|
cwLogInfo("SF reset loc: %i",app->sfResetLoc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -1160,13 +1149,10 @@ namespace cw
|
|||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
app->beg_play_timestamp = begMap->timestamp;
|
if( !time::isZero(begMap->timestamp) )
|
||||||
app->end_play_timestamp = endMap->timestamp;
|
|
||||||
|
|
||||||
if( !time::isZero(app->beg_play_timestamp) )
|
|
||||||
{
|
{
|
||||||
// seek the player to the requested loc
|
// seek the player to the requested loc
|
||||||
if((rc = midi_record_play::seek( app->mrpH, app->beg_play_timestamp )) != kOkRC )
|
if((rc = midi_record_play::seek( app->mrpH, begMap->timestamp )) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"MIDI seek failed.");
|
rc = cwLogError(rc,"MIDI seek failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
@ -1186,10 +1172,7 @@ namespace cw
|
|||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kMidiSaveBtnId ), false );
|
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kMidiSaveBtnId ), false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// reset the score follower
|
// reset the score follower
|
||||||
//if((rc = score_follower::reset(app->sfH,score_loc)) != kOkRC )
|
|
||||||
if((rc = _do_sf_reset(app,score_loc)) != kOkRC )
|
if((rc = _do_sf_reset(app,score_loc)) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"Score follower reset failed.");
|
rc = cwLogError(rc,"Score follower reset failed.");
|
||||||
@ -1208,7 +1191,7 @@ namespace cw
|
|||||||
{
|
{
|
||||||
unsigned evt_cnt = 0;
|
unsigned evt_cnt = 0;
|
||||||
|
|
||||||
if((rc = midi_record_play::start(app->mrpH,rewindFl,&app->end_play_timestamp)) != kOkRC )
|
if((rc = midi_record_play::start(app->mrpH,rewindFl,&endMap->timestamp)) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"MIDI start failed.");
|
rc = cwLogError(rc,"MIDI start failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
@ -1335,7 +1318,7 @@ namespace cw
|
|||||||
//io::uiSendValue( app->ioH, uiFindElementUuId(app->ioH,kCurMidiEvtCntId), midi_record_play::event_index(app->mrpH) );
|
//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) );
|
//io::uiSendValue( app->ioH, uiFindElementUuId(app->ioH,kTotalMidiEvtCntId), midi_record_play::event_count(app->mrpH) );
|
||||||
|
|
||||||
io::uiSendValue( app->ioH, uiFindElementUuId(app->ioH,kTotalMidiEvtCntId), app->maxLoc );
|
io::uiSendValue( app->ioH, uiFindElementUuId(app->ioH,kTotalMidiEvtCntId), app->maxLoc-app->minLoc );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the UI with the value from the the fragment data record.
|
// Update the UI with the value from the the fragment data record.
|
||||||
@ -1638,8 +1621,6 @@ namespace cw
|
|||||||
unsigned fragListUuId = io::uiFindElementUuId( app->ioH, kFragListId );
|
unsigned fragListUuId = io::uiFindElementUuId( app->ioH, kFragListId );
|
||||||
unsigned fragChanId = fragId; //endLoc; // use the frag. endLoc as the channel id
|
unsigned fragChanId = fragId; //endLoc; // use the frag. endLoc as the channel id
|
||||||
unsigned fragPanelUuId = kInvalidId;
|
unsigned fragPanelUuId = kInvalidId;
|
||||||
//unsigned fragBegLocUuId = kInvalidId;
|
|
||||||
//unsigned fragEndLocUuId = kInvalidId;
|
|
||||||
unsigned fragPresetRowUuId = kInvalidId;
|
unsigned fragPresetRowUuId = kInvalidId;
|
||||||
unsigned presetN = preset_sel::preset_count( app->psH );
|
unsigned presetN = preset_sel::preset_count( app->psH );
|
||||||
unsigned fragBegLoc = 0;
|
unsigned fragBegLoc = 0;
|
||||||
@ -1653,13 +1634,9 @@ namespace cw
|
|||||||
|
|
||||||
// get the uuid's of the new fragment panel and the endloc number display
|
// get the uuid's of the new fragment panel and the endloc number display
|
||||||
fragPanelUuId = io::uiFindElementUuId( app->ioH, fragListUuId, kFragPanelId, fragChanId );
|
fragPanelUuId = io::uiFindElementUuId( app->ioH, fragListUuId, kFragPanelId, fragChanId );
|
||||||
//fragBegLocUuId = io::uiFindElementUuId( app->ioH, fragPanelUuId, kFragBegLocId, fragChanId );
|
|
||||||
//fragEndLocUuId = io::uiFindElementUuId( app->ioH, fragPanelUuId, kFragEndLocId, fragChanId );
|
|
||||||
fragPresetRowUuId = io::uiFindElementUuId( app->ioH, fragPanelUuId, kFragPresetRowId, fragChanId );
|
fragPresetRowUuId = io::uiFindElementUuId( app->ioH, fragPanelUuId, kFragPresetRowId, fragChanId );
|
||||||
|
|
||||||
assert( fragPanelUuId != kInvalidId );
|
assert( fragPanelUuId != kInvalidId );
|
||||||
//assert( fragBegLocUuId != kInvalidId );
|
|
||||||
//assert( fragEndLocUuId != kInvalidId );
|
|
||||||
assert( fragPresetRowUuId != kInvalidId );
|
assert( fragPresetRowUuId != kInvalidId );
|
||||||
|
|
||||||
// Make the fragment panel clickable
|
// Make the fragment panel clickable
|
||||||
@ -1726,7 +1703,6 @@ namespace cw
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Settting psNextFrag to a non-null value causes the
|
// Settting psNextFrag to a non-null value causes the
|
||||||
// _fragment_restore_ui() to be called from the io::exec() callback
|
|
||||||
app->psNextFrag = preset_sel::get_fragment_base(app->psH);
|
app->psNextFrag = preset_sel::get_fragment_base(app->psH);
|
||||||
|
|
||||||
_set_status(app,"Loaded fragment file.");
|
_set_status(app,"Loaded fragment file.");
|
||||||
@ -1766,18 +1742,11 @@ namespace cw
|
|||||||
// if all the fragment UI's have been created
|
// if all the fragment UI's have been created
|
||||||
if( app->psNextFrag == nullptr )
|
if( app->psNextFrag == nullptr )
|
||||||
{
|
{
|
||||||
// enable the start/stop buttons
|
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStartBtnId ), true );
|
// the fragments are loaded enable the 'load' menu
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStopBtnId ), true );
|
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kLiveCheckId ), true );
|
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kEnaRecordCheckId ), true );
|
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kTrackMidiCheckId ), true );
|
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kSaveBtnId ), true );
|
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kSfResetBtnId ), true );
|
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kSfResetLocNumbId ), true );
|
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kPerfSelId ), true );
|
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kPerfSelId ), true );
|
||||||
|
|
||||||
_set_status(app,"Fragment restore complete: elapsed secs:%f\n",time::elapsedSecs(app->psLoadT0));
|
cwLogInfo("Fragment restore complete: elapsed secs:%f",time::elapsedSecs(app->psLoadT0));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1954,8 +1923,6 @@ namespace cw
|
|||||||
|
|
||||||
midiEventCntRef = midiEventN;
|
midiEventCntRef = midiEventN;
|
||||||
|
|
||||||
//uiSetNumbRange( app->ioH, io::uiFindElementUuId(app->ioH, kSfResetLocNumbId), app->minLoc, app->maxLoc, 1, 0, app->minLoc );
|
|
||||||
|
|
||||||
cwLogInfo("%i MIDI events loaded from score. Loc Min:%i Max:%i", midiEventN , app->minLoc, app->maxLoc);
|
cwLogInfo("%i MIDI events loaded from score. Loc Min:%i Max:%i", midiEventN , app->minLoc, app->maxLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1965,7 +1932,56 @@ namespace cw
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_t _do_load( app_t* app, const char* perf_fn )
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
assignN += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( assignN == 0 )
|
||||||
|
cwLogWarning("All velocity tables disabled.");
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
|
||||||
|
if( rc != kOkRC )
|
||||||
|
rc = cwLogError(rc,"Velocity table assignment failed.");
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _do_load( app_t* app, const char* perf_fn, const vel_tbl_t* vtA=nullptr, unsigned vtN=0 )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
unsigned midiEventN = 0;
|
unsigned midiEventN = 0;
|
||||||
@ -1973,73 +1989,56 @@ namespace cw
|
|||||||
cwLogInfo("Loading");
|
cwLogInfo("Loading");
|
||||||
_set_status(app,"Loading...");
|
_set_status(app,"Loading...");
|
||||||
|
|
||||||
// create the score
|
// load the performance or score
|
||||||
if( perf_fn != nullptr )
|
if((rc= score::create( app->scoreH, perf_fn )) != kOkRC )
|
||||||
if((rc= score::create( app->scoreH, perf_fn )) != kOkRC )
|
|
||||||
{
|
|
||||||
cwLogError(rc,"Score create failed on '%s'.",app->scoreFn);
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((rc = _load_midi_player(app, midiEventN )) != kOkRC )
|
|
||||||
{
|
{
|
||||||
cwLogError(rc,"MIDI player load failed.");
|
cwLogError(rc,"Score create failed on '%s'.",app->scoreFn);
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset the timestamp tracker
|
// load the midi player, create locMap[], set app->min/maxLoc
|
||||||
track_loc_reset( app->psH );
|
if((rc = _load_midi_player(app, midiEventN )) != kOkRC )
|
||||||
|
|
||||||
// set the range of the global play location controls
|
|
||||||
//if( firstLoadFl )
|
|
||||||
if( true )
|
|
||||||
{
|
{
|
||||||
unsigned begPlayLocUuId = io::uiFindElementUuId(app->ioH, kBegPlayLocNumbId);
|
rc = cwLogError(rc,"MIDI player load failed.");
|
||||||
unsigned endPlayLocUuId = io::uiFindElementUuId(app->ioH, kEndPlayLocNumbId);
|
goto errLabel;
|
||||||
|
|
||||||
//if( app->end_play_loc == 0 )
|
|
||||||
app->end_play_loc = app->maxLoc;
|
|
||||||
|
|
||||||
//if( !(app->minLoc <= app->beg_play_loc && app->beg_play_loc <= app->maxLoc) )
|
|
||||||
app->beg_play_loc = app->minLoc;
|
|
||||||
|
|
||||||
io::uiSetNumbRange( app->ioH, begPlayLocUuId, app->minLoc, app->maxLoc, 1, 0, app->beg_play_loc );
|
|
||||||
io::uiSetNumbRange( app->ioH, endPlayLocUuId, app->minLoc, app->maxLoc, 1, 0, app->end_play_loc );
|
|
||||||
|
|
||||||
io::uiSendValue( app->ioH, begPlayLocUuId, app->beg_play_loc);
|
|
||||||
io::uiSendValue( app->ioH, endPlayLocUuId, app->end_play_loc);
|
|
||||||
|
|
||||||
// enable the insert 'End Loc' number box since the score is loaded
|
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kInsertLocId ), true );
|
|
||||||
|
|
||||||
uiSetNumbRange( app->ioH, io::uiFindElementUuId(app->ioH, kSfResetLocNumbId), app->minLoc, app->maxLoc, 1, 0, app->beg_play_loc );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// assign the vel. table
|
||||||
|
if((rc = _set_vel_table(app, vtA, vtN )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Velocity table assignment failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
// update the current event and event count
|
// A performance is loaded so enable the UI
|
||||||
_update_event_ui(app);
|
|
||||||
|
|
||||||
// enable the start/stop buttons
|
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStartBtnId ), true );
|
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStartBtnId ), true );
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStopBtnId ), true );
|
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStopBtnId ), true );
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kLiveCheckId ), true );
|
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kLiveCheckId ), true );
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kEnaRecordCheckId ), true );
|
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kEnaRecordCheckId ), true );
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kTrackMidiCheckId ), true );
|
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kTrackMidiCheckId ), true );
|
||||||
|
|
||||||
// restore the fragment records
|
|
||||||
if( firstLoadFl )
|
|
||||||
if((rc = _restore_fragment_data( app )) != kOkRC )
|
|
||||||
{
|
|
||||||
rc = cwLogError(rc,"Restore failed.");
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
//io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kLoadBtnId ), true );
|
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kSaveBtnId ), true );
|
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kSaveBtnId ), true );
|
||||||
|
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kInsertLocId ), true );
|
||||||
|
|
||||||
|
// set the UI begin/end play to the locations of the newly loaded performance
|
||||||
|
app->end_play_loc = app->maxLoc;
|
||||||
|
app->beg_play_loc = app->minLoc;
|
||||||
|
|
||||||
|
// Update the master range of the play beg/end number widgets
|
||||||
|
io::uiSetNumbRange( app->ioH, io::uiFindElementUuId(app->ioH, kBegPlayLocNumbId), app->minLoc, app->maxLoc, 1, 0, app->beg_play_loc );
|
||||||
|
io::uiSetNumbRange( app->ioH, io::uiFindElementUuId(app->ioH, kEndPlayLocNumbId), app->minLoc, app->maxLoc, 1, 0, app->end_play_loc );
|
||||||
|
|
||||||
|
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 );
|
||||||
|
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kSfResetLocNumbId ), true );
|
||||||
|
io::uiSetNumbRange( app->ioH, io::uiFindElementUuId(app->ioH, kSfResetLocNumbId), app->minLoc, app->maxLoc, 1, 0, app->beg_play_loc );
|
||||||
|
io::uiSendValue( app->ioH, io::uiFindElementUuId(app->ioH, kSfResetLocNumbId), app->minLoc);
|
||||||
|
|
||||||
*/
|
|
||||||
cwLogInfo("'%s' loaded.",perf_fn);
|
cwLogInfo("'%s' loaded.",perf_fn);
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
@ -2084,14 +2083,12 @@ namespace cw
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load the requested performance
|
// load the requested performance
|
||||||
if((rc = _do_load(app,prp->fname)) != kOkRC )
|
if((rc = _do_load(app,prp->fname,prp->vel_tblA, prp->vel_tblN)) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(kSyntaxErrorRC,"The performance load failed.");
|
rc = cwLogError(kSyntaxErrorRC,"The performance load failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
//_do_sf_reset(app,app->beg_play_loc);
|
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -2709,6 +2706,7 @@ namespace cw
|
|||||||
|
|
||||||
_update_event_ui(app);
|
_update_event_ui(app);
|
||||||
|
|
||||||
|
/*
|
||||||
// disable start and stop buttons until a score is loaded
|
// disable start and stop buttons until a score is loaded
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStartBtnId ), false );
|
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStartBtnId ), false );
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStopBtnId ), false );
|
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStopBtnId ), false );
|
||||||
@ -2719,6 +2717,8 @@ namespace cw
|
|||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kSfResetBtnId ), false );
|
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, kSfResetLocNumbId ), false );
|
||||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kPerfSelId ), false );
|
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kPerfSelId ), false );
|
||||||
|
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kInsertLocId ), false );
|
||||||
|
*/
|
||||||
|
|
||||||
io::uiSendValue( app->ioH, io::uiFindElementUuId( app->ioH, kMidiLoadFnameId), app->midiRecordDir);
|
io::uiSendValue( app->ioH, io::uiFindElementUuId( app->ioH, kMidiLoadFnameId), app->midiRecordDir);
|
||||||
|
|
||||||
@ -2730,13 +2730,6 @@ namespace cw
|
|||||||
if((rc = _fragment_load_data(app)) != kOkRC )
|
if((rc = _fragment_load_data(app)) != kOkRC )
|
||||||
rc = cwLogError(rc,"Preset data restore failed.");
|
rc = cwLogError(rc,"Preset data restore failed.");
|
||||||
|
|
||||||
if( app->sfH.isValid() )
|
|
||||||
{
|
|
||||||
cw_loc_range(app->sfH,app->minLoc,app->maxLoc);
|
|
||||||
printf("SF Loc range:%i %i\n",app->minLoc,app->maxLoc);
|
|
||||||
uiSetNumbRange( app->ioH, io::uiFindElementUuId(app->ioH, kSfResetLocNumbId), app->minLoc, app->maxLoc, 1, 0, app->minLoc );
|
|
||||||
}
|
|
||||||
|
|
||||||
_on_live_midi_fl(app,app->useLiveMidiFl);
|
_on_live_midi_fl(app,app->useLiveMidiFl);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@ -2779,10 +2772,6 @@ namespace cw
|
|||||||
_on_ui_save(app);
|
_on_ui_save(app);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kLoadBtnId:
|
|
||||||
_do_load(app,app->scoreFn);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case kPerfSelId:
|
case kPerfSelId:
|
||||||
_on_perf_select(app,m.value->u.u);
|
_on_perf_select(app,m.value->u.u);
|
||||||
break;
|
break;
|
||||||
@ -3344,7 +3333,7 @@ cw::rc_t cw::preset_sel_app::main( const object_t* cfg, int argc, const char* ar
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create the MIDI record-play object
|
// create the MIDI record-play object
|
||||||
if((rc = midi_record_play::create(app.mrpH,app.ioH,*app.midi_play_record_cfg,app.velTableFname,_midi_play_callback,&app)) != kOkRC )
|
if((rc = midi_record_play::create(app.mrpH,app.ioH,*app.midi_play_record_cfg,nullptr,_midi_play_callback,&app)) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"MIDI record-play object create failed.");
|
rc = cwLogError(rc,"MIDI record-play object create failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
@ -3357,14 +3346,6 @@ cw::rc_t cw::preset_sel_app::main( const object_t* cfg, int argc, const char* ar
|
|||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the performance selection menu
|
|
||||||
/*
|
|
||||||
if((rc= _load_perf_selection_menu(&app)) != kOkRC )
|
|
||||||
{
|
|
||||||
rc = cwLogError(rc,"The performance list UI create failed.");
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// create the performance selection menu
|
// create the performance selection menu
|
||||||
if((rc= _load_perf_dir_selection_menu(&app)) != kOkRC )
|
if((rc= _load_perf_dir_selection_menu(&app)) != kOkRC )
|
||||||
{
|
{
|
||||||
|
@ -39,6 +39,7 @@ namespace cw
|
|||||||
{
|
{
|
||||||
typedef struct score_follower_str
|
typedef struct score_follower_str
|
||||||
{
|
{
|
||||||
|
bool enableFl;
|
||||||
double srate;
|
double srate;
|
||||||
unsigned search_area_locN;
|
unsigned search_area_locN;
|
||||||
unsigned key_wnd_locN;
|
unsigned key_wnd_locN;
|
||||||
@ -74,7 +75,8 @@ namespace cw
|
|||||||
|
|
||||||
const char* cm_score_csv_fname;
|
const char* cm_score_csv_fname;
|
||||||
|
|
||||||
if((rc = cfg->getv("cm_score_csv_fname", cm_score_csv_fname,
|
if((rc = cfg->getv("enable_flag", p->enableFl,
|
||||||
|
"cm_score_csv_fname", cm_score_csv_fname,
|
||||||
"search_area_locN", p->search_area_locN,
|
"search_area_locN", p->search_area_locN,
|
||||||
"key_wnd_locN", p->key_wnd_locN )) != kOkRC )
|
"key_wnd_locN", p->key_wnd_locN )) != kOkRC )
|
||||||
{
|
{
|
||||||
@ -324,6 +326,12 @@ cw::rc_t cw::score_follower::destroy( handle_t& hRef )
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cw::score_follower::is_enabled( handle_t h )
|
||||||
|
{
|
||||||
|
score_follower_t* p = _handleToPtr(h);
|
||||||
|
return p->enableFl;
|
||||||
|
}
|
||||||
|
|
||||||
cw::rc_t cw::score_follower::reset( handle_t h, unsigned cwLocId )
|
cw::rc_t cw::score_follower::reset( handle_t h, unsigned cwLocId )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
@ -363,6 +371,10 @@ cw::rc_t cw::score_follower::exec( handle_t h, double sec, unsigned smpIdx, uns
|
|||||||
unsigned scLocIdx = cmInvalidIdx;
|
unsigned scLocIdx = cmInvalidIdx;
|
||||||
unsigned pre_match_id_curN = p->match_id_curN;
|
unsigned pre_match_id_curN = p->match_id_curN;
|
||||||
|
|
||||||
|
if( !p->enableFl )
|
||||||
|
return cwLogError(kInvalidStateRC,"The score follower is not enabled.");
|
||||||
|
|
||||||
|
|
||||||
newMatchFlRef = false;
|
newMatchFlRef = false;
|
||||||
|
|
||||||
// Note: pass p->perf_idx as 'muid' to the score follower
|
// Note: pass p->perf_idx as 'muid' to the score follower
|
||||||
|
@ -11,6 +11,8 @@ namespace cw
|
|||||||
|
|
||||||
rc_t destroy( handle_t& hRef );
|
rc_t destroy( handle_t& hRef );
|
||||||
|
|
||||||
|
bool is_enabled( handle_t h );
|
||||||
|
|
||||||
// Set the starting search location and calls clear_match_id_array().
|
// Set the starting search location and calls clear_match_id_array().
|
||||||
rc_t reset( handle_t h, unsigned loc );
|
rc_t reset( handle_t h, unsigned loc );
|
||||||
|
|
||||||
|
25
cwTime.cpp
25
cwTime.cpp
@ -226,12 +226,12 @@ void cw::time::advanceMicros( spec_t& ts, unsigned us )
|
|||||||
ts.tv_sec += sec;
|
ts.tv_sec += sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
ts.tv_nsec += us * 1000000000; // convert microseconds to nanoseconds
|
ts.tv_nsec += us * 1000; // convert microseconds to nanoseconds
|
||||||
|
|
||||||
// stip off whole seconds from tv_nsec
|
// stip off whole seconds from tv_nsec
|
||||||
while( ts.tv_nsec > 1e9 )
|
while( ts.tv_nsec > 1000000000 )
|
||||||
{
|
{
|
||||||
ts.tv_nsec -= 1e9;
|
ts.tv_nsec -= 1000000000;
|
||||||
ts.tv_sec +=1;
|
ts.tv_sec +=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,9 +253,9 @@ void cw::time::advanceMs( spec_t& ts, unsigned ms )
|
|||||||
ts.tv_nsec += ms * 1000000; // convert millisconds to nanoseconds
|
ts.tv_nsec += ms * 1000000; // convert millisconds to nanoseconds
|
||||||
|
|
||||||
// stip off whole seconds from tv_nsec
|
// stip off whole seconds from tv_nsec
|
||||||
while( ts.tv_nsec > 1e9 )
|
while( ts.tv_nsec > 1000000000 )
|
||||||
{
|
{
|
||||||
ts.tv_nsec -= 1e9;
|
ts.tv_nsec -= 1000000000;
|
||||||
ts.tv_sec +=1;
|
ts.tv_sec +=1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -279,10 +279,10 @@ double cw::time::specToSeconds( const spec_t& t )
|
|||||||
{
|
{
|
||||||
spec_t ts = t;
|
spec_t ts = t;
|
||||||
double sec = ts.tv_sec;
|
double sec = ts.tv_sec;
|
||||||
while( ts.tv_nsec >= 1e9 )
|
while( ts.tv_nsec >= 1000000000 )
|
||||||
{
|
{
|
||||||
sec += 1.0;
|
sec += 1.0;
|
||||||
ts.tv_nsec -= 1e9;
|
ts.tv_nsec -= 1000000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sec + ((double)ts.tv_nsec)/1e9;
|
return sec + ((double)ts.tv_nsec)/1e9;
|
||||||
@ -365,6 +365,17 @@ cw::rc_t cw::time::test()
|
|||||||
printf("%li %li\n",t0.tv_sec,t0.tv_nsec);
|
printf("%li %li\n",t0.tv_sec,t0.tv_nsec);
|
||||||
|
|
||||||
|
|
||||||
|
time::get(t0);
|
||||||
|
//time::get(t1);
|
||||||
|
t1 = t0;
|
||||||
|
|
||||||
|
advanceMicros(t1,5000);
|
||||||
|
|
||||||
|
int usec = time::elapsedMicros(t0,t1);
|
||||||
|
|
||||||
|
printf("usec:%i\n",usec);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return kOkRC;
|
return kOkRC;
|
||||||
|
|
||||||
|
@ -1110,3 +1110,23 @@ cw::rc_t cw::vtbl::exec( handle_t h )
|
|||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint8_t* cw::vtbl::get_vel_table( handle_t h, const char* label, unsigned& velTblN_Ref )
|
||||||
|
{
|
||||||
|
vtbl_t* p = _handleToPtr(h);
|
||||||
|
|
||||||
|
const tbl_t* t= nullptr;
|
||||||
|
|
||||||
|
velTblN_Ref = 0;
|
||||||
|
|
||||||
|
if((t = _table_from_name( p, label )) == nullptr )
|
||||||
|
{
|
||||||
|
cwLogError(kInvalidArgRC,"The velocity table named:'%s' could not be found.",cwStringNullGuard(label));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
velTblN_Ref = t->tableN;
|
||||||
|
|
||||||
|
return t->tableA;
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -80,5 +80,8 @@ namespace cw
|
|||||||
// Update the state of the player
|
// Update the state of the player
|
||||||
rc_t exec( handle_t h );
|
rc_t exec( handle_t h );
|
||||||
|
|
||||||
|
|
||||||
|
const uint8_t* get_vel_table( handle_t h, const char* label, unsigned& velTblN_Ref );
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
button:{ name: ioReportBtnId, title:"IO Report" },
|
button:{ name: ioReportBtnId, title:"IO Report" },
|
||||||
button:{ name: netPrintBtnId, title:"Print Network" }
|
button:{ name: netPrintBtnId, title:"Print Network" }
|
||||||
button:{ name: reportBtnId, title:"App Report" },
|
button:{ name: reportBtnId, title:"App Report" },
|
||||||
//button:{ name: loadBtnId, title:"Load" },
|
|
||||||
button:{ name: saveBtnId, title:"Save" },
|
button:{ name: saveBtnId, title:"Save" },
|
||||||
|
|
||||||
select:{ name: perfSelId, title:"Load",children: {} },
|
select:{ name: perfSelId, title:"Load",children: {} },
|
||||||
@ -33,16 +32,16 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
row: {
|
row: {
|
||||||
button:{ name: startBtnId, title:"Start" },
|
button:{ name: startBtnId, title:"Start", enable: false },
|
||||||
button:{ name: stopBtnId, title:"Stop" },
|
button:{ name: stopBtnId, title:"Stop", enable: false },
|
||||||
number:{ name: begLocNumbId, title:"Loc:", min:0, max:100000, step:1, decpl:0 },
|
number:{ name: begLocNumbId, title:"Loc:", min:0, max:100000, step:1, decpl:0, enable: false },
|
||||||
number:{ name: endLocNumbId, title:"End:", min:0, max:100000, step:1, decpl:0 },
|
number:{ name: endLocNumbId, title:"End:", min:0, max:100000, step:1, decpl:0, enable: false },
|
||||||
check: { name: liveCheckId, title:"Live" },
|
check: { name: liveCheckId, title:"Live", enable: false },
|
||||||
check: { name: trackMidiCheckId, title:"Track MIDI" },
|
check: { name: trackMidiCheckId, title:"Track MIDI", enable: false },
|
||||||
},
|
},
|
||||||
|
|
||||||
row: {
|
row: {
|
||||||
check:{ name: midiThruCheckId, title:"MIDI Thru" },
|
check:{ name: midiThruCheckId, title:"MIDI Thru", enable: false },
|
||||||
numb_disp: { name: curMidiEvtCntId, title:"Current Loc:" },
|
numb_disp: { name: curMidiEvtCntId, title:"Current Loc:" },
|
||||||
numb_disp: { name: totalMidiEvtCntId, title:"Max Loc:" },
|
numb_disp: { name: totalMidiEvtCntId, title:"Max Loc:" },
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user