cwIoMidiRecordPlay.h/cpp : Add multiple MIDI devices.
This commit is contained in:
parent
e4dcb5f83c
commit
586b71b93c
@ -34,20 +34,27 @@ namespace cw
|
|||||||
|
|
||||||
} am_midi_msg_t;
|
} am_midi_msg_t;
|
||||||
|
|
||||||
typedef struct midi_record_play_str
|
typedef struct midi_device_str
|
||||||
{
|
{
|
||||||
io::handle_t ioH;
|
|
||||||
|
|
||||||
am_midi_msg_t* msgArray;
|
|
||||||
unsigned msgArrayN;
|
|
||||||
unsigned msgArrayInIdx;
|
|
||||||
unsigned msgArrayOutIdx;
|
|
||||||
unsigned midi_timer_period_micro_sec;
|
|
||||||
|
|
||||||
char* midiOutDevLabel;
|
char* midiOutDevLabel;
|
||||||
char* midiOutPortLabel;
|
char* midiOutPortLabel;
|
||||||
unsigned midiOutDevIdx;
|
unsigned midiOutDevIdx;
|
||||||
unsigned midiOutPortIdx;
|
unsigned midiOutPortIdx;
|
||||||
|
bool enableFl;
|
||||||
|
} midi_device_t;
|
||||||
|
|
||||||
|
typedef struct midi_record_play_str
|
||||||
|
{
|
||||||
|
io::handle_t ioH;
|
||||||
|
|
||||||
|
am_midi_msg_t* msgArray; // msgArray[ msgArrayN ]
|
||||||
|
unsigned msgArrayN; // Count of messages allocated in msgArray.
|
||||||
|
unsigned msgArrayInIdx; // Next available space for incoming MIDI messages (also the current count of msgs in msgArray[])
|
||||||
|
unsigned msgArrayOutIdx; // Next message to transmit in msgArray[]
|
||||||
|
unsigned midi_timer_period_micro_sec; // Timer period in microseconds
|
||||||
|
|
||||||
|
midi_device_t* midiDevA;
|
||||||
|
unsigned midiDevN;
|
||||||
|
|
||||||
bool startedFl;
|
bool startedFl;
|
||||||
bool recordFl;
|
bool recordFl;
|
||||||
@ -80,9 +87,14 @@ namespace cw
|
|||||||
if((timerIdx = io::timerLabelToIndex( p->ioH, TIMER_LABEL )) != kInvalidIdx )
|
if((timerIdx = io::timerLabelToIndex( p->ioH, TIMER_LABEL )) != kInvalidIdx )
|
||||||
io::timerDestroy( p->ioH, timerIdx);
|
io::timerDestroy( p->ioH, timerIdx);
|
||||||
|
|
||||||
|
for(unsigned i=0; i<p->midiDevN; ++i)
|
||||||
|
{
|
||||||
|
mem::release(p->midiDevA[i].midiOutDevLabel);
|
||||||
|
mem::release(p->midiDevA[i].midiOutPortLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
mem::release(p->midiDevA);
|
||||||
mem::release(p->msgArray);
|
mem::release(p->msgArray);
|
||||||
mem::release(p->midiOutDevLabel);
|
|
||||||
mem::release(p->midiOutPortLabel);
|
|
||||||
mem::release(p);
|
mem::release(p);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@ -91,21 +103,47 @@ namespace cw
|
|||||||
rc_t _parseCfg(midi_record_play_t* p, const object_t& cfg )
|
rc_t _parseCfg(midi_record_play_t* p, const object_t& cfg )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
|
const object_t* midiDevL = nullptr;
|
||||||
if((rc = cfg.getv(
|
if((rc = cfg.getv(
|
||||||
"max_midi_msg_count", p->msgArrayN,
|
"max_midi_msg_count", p->msgArrayN,
|
||||||
"midi_timer_period_micro_sec", p->midi_timer_period_micro_sec,
|
"midi_timer_period_micro_sec", p->midi_timer_period_micro_sec,
|
||||||
"midi_out_device", p->midiOutDevLabel,
|
"midi_device_list", midiDevL)) != kOkRC )
|
||||||
"midi_out_port", p->midiOutPortLabel)) != kOkRC )
|
|
||||||
{
|
{
|
||||||
rc = cwLogError(kSyntaxErrorRC,"MIDI record play configuration parse failed.");
|
rc = cwLogError(kSyntaxErrorRC,"MIDI record play configuration parse failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( midiDevL->child_count() > 0 )
|
||||||
|
{
|
||||||
|
p->midiDevN = midiDevL->child_count();
|
||||||
|
p->midiDevA = mem::allocZ<midi_device_t>(p->midiDevN);
|
||||||
|
|
||||||
|
printf("Midi record play devices:%i\n",p->midiDevN);
|
||||||
|
|
||||||
|
for(unsigned i=0; i<p->midiDevN; ++i)
|
||||||
|
{
|
||||||
|
const object_t* ele = midiDevL->child_ele(i);
|
||||||
|
const char* midiOutDevLabel = nullptr;
|
||||||
|
const char* midiOutPortLabel = nullptr;
|
||||||
|
bool enableFl = false;
|
||||||
|
|
||||||
|
if((rc = ele->getv( "midi_out_device", midiOutDevLabel,
|
||||||
|
"midi_out_port", midiOutPortLabel,
|
||||||
|
"enableFl", enableFl)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kSyntaxErrorRC,"MIDI record play device list configuration parse failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->midiDevA[i].midiOutDevLabel = mem::duplStr( midiOutDevLabel);
|
||||||
|
p->midiDevA[i].midiOutPortLabel = mem::duplStr( midiOutPortLabel);
|
||||||
|
p->midiDevA[i].enableFl = enableFl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// allocate the MIDI msg buffer
|
// allocate the MIDI msg buffer
|
||||||
p->msgArray = mem::allocZ<am_midi_msg_t>( p->msgArrayN );
|
p->msgArray = mem::allocZ<am_midi_msg_t>( p->msgArrayN );
|
||||||
p->midiOutDevLabel = mem::duplStr( p->midiOutDevLabel);
|
|
||||||
p->midiOutPortLabel = mem::duplStr( p->midiOutPortLabel);
|
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
return rc;
|
return rc;
|
||||||
@ -117,13 +155,15 @@ namespace cw
|
|||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
if( !time::isZero(p->end_play_event_timestamp) && time::isGTE(timestamp,p->end_play_event_timestamp))
|
if( !time::isZero(p->end_play_event_timestamp) && time::isGT(timestamp,p->end_play_event_timestamp))
|
||||||
{
|
{
|
||||||
rc = _stop(p);
|
rc = _stop(p);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
io::midiDeviceSend( p->ioH, p->midiOutDevIdx, p->midiOutPortIdx, status + ch, d0, d1 );
|
for(unsigned i=0; i<p->midiDevN; ++i)
|
||||||
|
if(p->midiDevA[i].enableFl )
|
||||||
|
io::midiDeviceSend( p->ioH, p->midiDevA[i].midiOutDevIdx, p->midiDevA[i].midiOutPortIdx, status + ch, d0, d1 );
|
||||||
|
|
||||||
if( p->cb )
|
if( p->cb )
|
||||||
p->cb( p->cb_arg, id, timestamp, ch, status, d0, d1 );
|
p->cb( p->cb_arg, id, timestamp, ch, status, d0, d1 );
|
||||||
@ -407,15 +447,19 @@ namespace cw
|
|||||||
_transmit_ctl( p, 0, 123, 0 ); // all notes off
|
_transmit_ctl( p, 0, 123, 0 ); // all notes off
|
||||||
_transmit_ctl( p, 0, 0, 0 ); // switch to bank 0
|
_transmit_ctl( p, 0, 0, 0 ); // switch to bank 0
|
||||||
|
|
||||||
|
//_transmit_pedal( p, 0, midi::kSustainCtlMdId, false );
|
||||||
|
//_transmit_pedal( p, 0, midi::kSostenutoCtlMdId, false );
|
||||||
|
//_transmit_pedal( p, 0, midi::kSoftPedalCtlMdId, false );
|
||||||
|
|
||||||
// send pgm change 0
|
// send pgm change 0
|
||||||
time::spec_t ts = {0};
|
//time::spec_t ts = {0};
|
||||||
_event_callback( p, kInvalidId, ts, 0, midi::kPgmMdId, 0, 0 );
|
//_event_callback( p, kInvalidId, ts, 0, midi::kPgmMdId, 0, 0 );
|
||||||
|
|
||||||
p->pedalFl = false;
|
p->pedalFl = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cwLogInfo("Runtime: %5.2f seconds.", time::elapsedMs(p->start_time,t1)/1000.0 );
|
//cwLogInfo("Runtime: %5.2f seconds.", time::elapsedMs(p->start_time,t1)/1000.0 );
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -471,10 +515,7 @@ namespace cw
|
|||||||
p->msgArrayInIdx += 1;
|
p->msgArrayInIdx += 1;
|
||||||
|
|
||||||
if( p->thruFl )
|
if( p->thruFl )
|
||||||
{
|
|
||||||
_transmit_msg( p, am );
|
_transmit_msg( p, am );
|
||||||
//io::midiDeviceSend( p->ioH, p->midiOutDevIdx, p->midiOutPortIdx, am->status + am->ch, am->d0, am->d1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// send msg count
|
// send msg count
|
||||||
//io::uiSendValue( p->ioH, kInvalidId, uiFindElementUuId(p->ioH,kMsgCntId), p->msgArrayInIdx );
|
//io::uiSendValue( p->ioH, kInvalidId, uiFindElementUuId(p->ioH,kMsgCntId), p->msgArrayInIdx );
|
||||||
@ -575,18 +616,26 @@ cw::rc_t cw::midi_record_play::create( handle_t& hRef, io::handle_t ioH, const o
|
|||||||
p->cb = cb;
|
p->cb = cb;
|
||||||
p->cb_arg = cb_arg;
|
p->cb_arg = cb_arg;
|
||||||
|
|
||||||
if((p->midiOutDevIdx = io::midiDeviceIndex(p->ioH,p->midiOutDevLabel)) == kInvalidIdx )
|
for( unsigned i=0; i<
|
||||||
|
p->midiDevN; ++i)
|
||||||
{
|
{
|
||||||
rc = cwLogError(kInvalidArgRC,"The MIDI output device: '%s' was not found.", cwStringNullGuard(p->midiOutDevLabel) );
|
midi_device_t* dev = p->midiDevA + i;
|
||||||
|
|
||||||
|
if((dev->midiOutDevIdx = io::midiDeviceIndex(p->ioH,dev->midiOutDevLabel)) == kInvalidIdx )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidArgRC,"The MIDI output device: '%s' was not found.", cwStringNullGuard(dev->midiOutDevLabel) );
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((p->midiOutPortIdx = io::midiDevicePortIndex(p->ioH,p->midiOutDevIdx,false,p->midiOutPortLabel)) == kInvalidIdx )
|
if((dev->midiOutPortIdx = io::midiDevicePortIndex(p->ioH,dev->midiOutDevIdx,false,dev->midiOutPortLabel)) == kInvalidIdx )
|
||||||
{
|
{
|
||||||
rc = cwLogError(kInvalidArgRC,"The MIDI output port: '%s' was not found.", cwStringNullGuard(p->midiOutPortLabel) );
|
rc = cwLogError(kInvalidArgRC,"The MIDI output port: '%s' was not found.", cwStringNullGuard(dev->midiOutPortLabel) );
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("%s %s : %i %i\n",dev->midiOutDevLabel, dev->midiOutPortLabel, dev->midiOutDevIdx, dev->midiOutPortIdx );
|
||||||
|
}
|
||||||
|
|
||||||
// create the MIDI playback timer
|
// create the MIDI playback timer
|
||||||
if((rc = timerCreate( p->ioH, TIMER_LABEL, kMidiRecordPlayTimerId, p->midi_timer_period_micro_sec)) != kOkRC )
|
if((rc = timerCreate( p->ioH, TIMER_LABEL, kMidiRecordPlayTimerId, p->midi_timer_period_micro_sec)) != kOkRC )
|
||||||
{
|
{
|
||||||
@ -738,8 +787,8 @@ cw::rc_t cw::midi_record_play::load( handle_t h, const midi_msg_t* msg, unsigned
|
|||||||
p->msgArray[i].status = msg[i].status;
|
p->msgArray[i].status = msg[i].status;
|
||||||
p->msgArray[i].d0 = msg[i].d0;
|
p->msgArray[i].d0 = msg[i].d0;
|
||||||
p->msgArray[i].d1 = msg[i].d1;
|
p->msgArray[i].d1 = msg[i].d1;
|
||||||
p->msgArray[i].devIdx = p->midiOutDevIdx;
|
p->msgArray[i].devIdx = kInvalidIdx;
|
||||||
p->msgArray[i].portIdx = p->midiOutPortIdx;
|
p->msgArray[i].portIdx = kInvalidIdx;
|
||||||
p->msgArray[i].microsec = time::elapsedMicros(p->msgArray[0].timestamp,p->msgArray[i].timestamp);
|
p->msgArray[i].microsec = time::elapsedMicros(p->msgArray[0].timestamp,p->msgArray[i].timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -842,7 +891,37 @@ cw::rc_t cw::midi_record_play::exec( handle_t h, const io::msg_t& m )
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned cw::midi_record_play::device_count( handle_t h )
|
||||||
|
{
|
||||||
|
midi_record_play_t* p = _handleToPtr(h);
|
||||||
|
return p->midiDevN;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cw::midi_record_play::is_device_enabled( handle_t h, unsigned devIdx )
|
||||||
|
{
|
||||||
|
midi_record_play_t* p = _handleToPtr(h);
|
||||||
|
bool fl = false;
|
||||||
|
|
||||||
|
if( devIdx >= p->midiDevN )
|
||||||
|
cwLogError(kInvalidArgRC,"The MIDI record-play device index '%i' is invalid.",devIdx );
|
||||||
|
else
|
||||||
|
fl = p->midiDevA[devIdx].enableFl;
|
||||||
|
|
||||||
|
return fl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cw::midi_record_play::enable_device( handle_t h, unsigned devIdx, bool enableFl )
|
||||||
|
{
|
||||||
|
midi_record_play_t* p = _handleToPtr(h);
|
||||||
|
|
||||||
|
if( devIdx >= p->midiDevN )
|
||||||
|
cwLogError(kInvalidArgRC,"The MIDI record-play device index '%i' is invalid.",devIdx );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p->midiDevA[devIdx].enableFl = enableFl;
|
||||||
|
printf("Enable: %i = %i\n",devIdx,enableFl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cw::rc_t cw::midi_record_play::am_to_midi_file( const char* am_filename, const char* midi_filename )
|
cw::rc_t cw::midi_record_play::am_to_midi_file( const char* am_filename, const char* midi_filename )
|
||||||
{
|
{
|
||||||
|
@ -40,6 +40,8 @@ namespace cw
|
|||||||
|
|
||||||
rc_t save( handle_t h, const char* fn );
|
rc_t save( handle_t h, const char* fn );
|
||||||
rc_t open( handle_t h, const char* fn );
|
rc_t open( handle_t h, const char* fn );
|
||||||
|
|
||||||
|
// Load the playback buffer with messages to output.
|
||||||
rc_t load( handle_t h, const midi_msg_t* msg, unsigned msg_count );
|
rc_t load( handle_t h, const midi_msg_t* msg, unsigned msg_count );
|
||||||
|
|
||||||
rc_t seek( handle_t h, time::spec_t timestamp );
|
rc_t seek( handle_t h, time::spec_t timestamp );
|
||||||
@ -48,6 +50,10 @@ namespace cw
|
|||||||
unsigned event_index( handle_t h );
|
unsigned event_index( handle_t h );
|
||||||
rc_t exec( handle_t h, const io::msg_t& msg );
|
rc_t exec( handle_t h, const io::msg_t& msg );
|
||||||
|
|
||||||
|
unsigned device_count( handle_t h );
|
||||||
|
bool is_device_enabled( handle_t h, unsigned devIdx );
|
||||||
|
void enable_device( handle_t h, unsigned devIdx, bool enableFl );
|
||||||
|
|
||||||
// Convert an audio-midi file to a MIDI file
|
// Convert an audio-midi file to a MIDI file
|
||||||
rc_t am_to_midi_file( const char* am_filename, const char* midi_filename );
|
rc_t am_to_midi_file( const char* am_filename, const char* midi_filename );
|
||||||
rc_t am_to_midi_dir( const char* inDir );
|
rc_t am_to_midi_dir( const char* inDir );
|
||||||
|
Loading…
Reference in New Issue
Block a user