cwMidiDevice.h/cpp,cwMidiDecls.h : Added getBuffer(),clearBuffer(),maxBufferMsgCount() to cwMidiDevice.
Changed the MIDI device callback function to move the user arg outside of the 'packet_t'. Added midi::ch_msg_t
This commit is contained in:
parent
7d3be5ebc6
commit
a6f518ed54
@ -17,7 +17,7 @@ namespace cw
|
|||||||
|
|
||||||
typedef struct packet_str
|
typedef struct packet_str
|
||||||
{
|
{
|
||||||
void* cbArg; // Application supplied reference value
|
//void* cbArg; // Application supplied reference value
|
||||||
unsigned devIdx; // The device the msg originated from
|
unsigned devIdx; // The device the msg originated from
|
||||||
unsigned portIdx; // The port index on the source device
|
unsigned portIdx; // The port index on the source device
|
||||||
msg_t* msgArray; // Pointer to an array of 'msgCnt' mdMsg records or NULL if sysExMsg is non-NULL
|
msg_t* msgArray; // Pointer to an array of 'msgCnt' mdMsg records or NULL if sysExMsg is non-NULL
|
||||||
@ -25,8 +25,19 @@ namespace cw
|
|||||||
unsigned msgCnt; // Count of mdMsg records or sys-ex bytes
|
unsigned msgCnt; // Count of mdMsg records or sys-ex bytes
|
||||||
} packet_t;
|
} packet_t;
|
||||||
|
|
||||||
typedef void (*cbFunc_t)( const packet_t* pktArray, unsigned pktCnt );
|
typedef void (*cbFunc_t)( void* cbArg, const packet_t* pktArray, unsigned pktCnt );
|
||||||
|
|
||||||
|
typedef struct ch_msg_str
|
||||||
|
{
|
||||||
|
time::spec_t timeStamp;
|
||||||
|
unsigned devIdx; // The device the msg originated from
|
||||||
|
unsigned portIdx; // The port index on the source device
|
||||||
|
unsigned uid; // application specified id
|
||||||
|
uint8_t ch; // midi channel
|
||||||
|
uint8_t status; // midi status byte (channel has been removed)
|
||||||
|
uint8_t d0; // midi data byte 0
|
||||||
|
uint8_t d1; // midi data byte 1
|
||||||
|
} ch_msg_t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
125
cwMidiDevice.cpp
125
cwMidiDevice.cpp
@ -55,6 +55,11 @@ namespace cw
|
|||||||
unsigned long long last_posn_micros;
|
unsigned long long last_posn_micros;
|
||||||
time::spec_t start_time;
|
time::spec_t start_time;
|
||||||
|
|
||||||
|
ch_msg_t* buf;
|
||||||
|
unsigned bufN;
|
||||||
|
std::atomic<unsigned> buf_ii;
|
||||||
|
std::atomic<unsigned> buf_oi;
|
||||||
|
|
||||||
} device_t;
|
} device_t;
|
||||||
|
|
||||||
device_t* _handleToPtr( handle_t h )
|
device_t* _handleToPtr( handle_t h )
|
||||||
@ -102,8 +107,11 @@ namespace cw
|
|||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
destroy(p->alsaDevH);
|
destroy(p->alsaDevH);
|
||||||
destroy(p->fileDevH);
|
destroy(p->fileDevH);
|
||||||
|
|
||||||
|
mem::release(p->buf);
|
||||||
mem::release(p);
|
mem::release(p);
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
@ -173,6 +181,45 @@ namespace cw
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _callback( void* cbArg, const packet_t* pktArray, unsigned pktCnt )
|
||||||
|
{
|
||||||
|
device_t* p = (device_t*)cbArg;
|
||||||
|
|
||||||
|
for(unsigned i=0; i<pktCnt; ++i)
|
||||||
|
{
|
||||||
|
const packet_t* pkt = pktArray + i;
|
||||||
|
if( pkt->msgArray != nullptr )
|
||||||
|
{
|
||||||
|
unsigned ii = p->buf_ii.load();
|
||||||
|
unsigned oi = p->buf_oi.load();
|
||||||
|
for(unsigned j=0; j<pkt->msgCnt; ++j)
|
||||||
|
{
|
||||||
|
ch_msg_t* m = p->buf + ii;
|
||||||
|
m->devIdx = pkt->devIdx;
|
||||||
|
m->portIdx = pkt->portIdx;
|
||||||
|
m->timeStamp = pkt->msgArray[j].timeStamp;
|
||||||
|
m->uid = pkt->msgArray[j].uid;
|
||||||
|
m->ch = pkt->msgArray[j].ch;
|
||||||
|
m->status = pkt->msgArray[j].status;
|
||||||
|
m->d0 = pkt->msgArray[j].d0;
|
||||||
|
m->d1 = pkt->msgArray[j].d1;
|
||||||
|
|
||||||
|
ii = (ii+1 == p->bufN ? 0 : ii+1);
|
||||||
|
if( ii == oi )
|
||||||
|
{
|
||||||
|
cwLogError(kBufTooSmallRC,"The MIDI device buffer is full %i.",p->bufN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p->buf_ii.store(ii);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( p->cbFunc != nullptr )
|
||||||
|
p->cbFunc(p->cbArg,pktArray,pktCnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // device
|
} // device
|
||||||
} // midi
|
} // midi
|
||||||
@ -188,7 +235,9 @@ cw::rc_t cw::midi::device::create( handle_t& hRef,
|
|||||||
const char* appNameStr,
|
const char* appNameStr,
|
||||||
const char* fileDevName,
|
const char* fileDevName,
|
||||||
unsigned fileDevReadAheadMicros,
|
unsigned fileDevReadAheadMicros,
|
||||||
unsigned parserBufByteCnt )
|
unsigned parserBufByteCnt,
|
||||||
|
bool enableBufFl,
|
||||||
|
unsigned bufferMsgCnt )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
rc_t rc1 = kOkRC;
|
rc_t rc1 = kOkRC;
|
||||||
@ -198,7 +247,11 @@ cw::rc_t cw::midi::device::create( handle_t& hRef,
|
|||||||
|
|
||||||
device_t* p = mem::allocZ<device_t>();
|
device_t* p = mem::allocZ<device_t>();
|
||||||
|
|
||||||
if((rc = create( p->alsaDevH, cbFunc, cbArg, parserBufByteCnt, appNameStr )) != kOkRC )
|
if((rc = create( p->alsaDevH,
|
||||||
|
enableBufFl ? _callback : cbFunc,
|
||||||
|
enableBufFl ? p : cbArg,
|
||||||
|
parserBufByteCnt,
|
||||||
|
appNameStr )) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"ALSA MIDI device create failed.");
|
rc = cwLogError(rc,"ALSA MIDI device create failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
@ -206,16 +259,29 @@ cw::rc_t cw::midi::device::create( handle_t& hRef,
|
|||||||
|
|
||||||
p->alsa_dev_cnt = count(p->alsaDevH);
|
p->alsa_dev_cnt = count(p->alsaDevH);
|
||||||
|
|
||||||
if((rc = create( p->fileDevH, cbFunc, cbArg, p->alsa_dev_cnt, filePortLabelA, max_file_cnt, fileDevName, fileDevReadAheadMicros )) != kOkRC )
|
if((rc = create( p->fileDevH,
|
||||||
|
enableBufFl ? _callback : cbFunc,
|
||||||
|
enableBufFl ? p : cbArg,
|
||||||
|
p->alsa_dev_cnt,
|
||||||
|
filePortLabelA,
|
||||||
|
max_file_cnt,
|
||||||
|
fileDevName,
|
||||||
|
fileDevReadAheadMicros )) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"MIDI file device create failed.");
|
rc = cwLogError(rc,"MIDI file device create failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p->cbFunc = cbFunc;
|
||||||
|
p->cbArg = cbArg;
|
||||||
p->file_dev_cnt = count(p->fileDevH);
|
p->file_dev_cnt = count(p->fileDevH);
|
||||||
p->total_dev_cnt = p->alsa_dev_cnt + p->file_dev_cnt;
|
p->total_dev_cnt = p->alsa_dev_cnt + p->file_dev_cnt;
|
||||||
p->alsaPollfdA = pollFdArray(p->alsaDevH,p->alsaPollfdN);
|
p->alsaPollfdA = pollFdArray(p->alsaDevH,p->alsaPollfdN);
|
||||||
p->fileDevStateId = kStoppedStateId;
|
p->fileDevStateId = kStoppedStateId;
|
||||||
|
p->buf = mem::allocZ<ch_msg_t>( bufferMsgCnt );
|
||||||
|
p->bufN = bufferMsgCnt;
|
||||||
|
p->buf_ii.store(0);
|
||||||
|
p->buf_oi.store(0);
|
||||||
|
|
||||||
if((rc = thread::create(p->threadH,
|
if((rc = thread::create(p->threadH,
|
||||||
_thread_func,
|
_thread_func,
|
||||||
@ -257,6 +323,8 @@ cw::rc_t cw::midi::device::create( handle_t& h,
|
|||||||
const char* fileDevName = "file_dev";
|
const char* fileDevName = "file_dev";
|
||||||
unsigned fileDevReadAheadMicros = 3000;
|
unsigned fileDevReadAheadMicros = 3000;
|
||||||
unsigned parseBufByteCnt = 1024;
|
unsigned parseBufByteCnt = 1024;
|
||||||
|
bool enableBufFl = false;
|
||||||
|
unsigned bufMsgCnt = 0;
|
||||||
const object_t* file_ports = nullptr;
|
const object_t* file_ports = nullptr;
|
||||||
const object_t* port = nullptr;
|
const object_t* port = nullptr;
|
||||||
|
|
||||||
@ -264,6 +332,8 @@ cw::rc_t cw::midi::device::create( handle_t& h,
|
|||||||
"fileDevName",fileDevName,
|
"fileDevName",fileDevName,
|
||||||
"fileDevReadAheadMicros",fileDevReadAheadMicros,
|
"fileDevReadAheadMicros",fileDevReadAheadMicros,
|
||||||
"parseBufByteCnt",parseBufByteCnt,
|
"parseBufByteCnt",parseBufByteCnt,
|
||||||
|
"enableBufFl",enableBufFl,
|
||||||
|
"bufferMsgCnt",bufMsgCnt,
|
||||||
"file_ports",file_ports)) != kOkRC )
|
"file_ports",file_ports)) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"MIDI port parse args. failed.");
|
rc = cwLogError(rc,"MIDI port parse args. failed.");
|
||||||
@ -290,7 +360,7 @@ cw::rc_t cw::midi::device::create( handle_t& h,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = create(h,cbFunc,cbArg,labelArray,fpi,appNameStr,fileDevName,fileDevReadAheadMicros,parseBufByteCnt);
|
rc = create(h,cbFunc,cbArg,labelArray,fpi,appNameStr,fileDevName,fileDevReadAheadMicros,parseBufByteCnt,enableBufFl,bufMsgCnt);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,15 +507,15 @@ const char* cw::midi::device::portName( handle_t h, unsigned devIdx, unsigned
|
|||||||
const char* name = nullptr;
|
const char* name = nullptr;
|
||||||
|
|
||||||
if((alsaDevIdx = _devIdxToAlsaDevIdx(p,devIdx)) != kInvalidIdx )
|
if((alsaDevIdx = _devIdxToAlsaDevIdx(p,devIdx)) != kInvalidIdx )
|
||||||
name = portName(p->alsaDevH,alsaDevIdx,flags,portIdx);
|
name = portName(p->alsaDevH,alsaDevIdx,flags,portIdx);
|
||||||
else
|
else
|
||||||
if((fileDevIdx = _devIdxToFileDevIdx(p,devIdx)) != kInvalidIdx )
|
if((fileDevIdx = _devIdxToFileDevIdx(p,devIdx)) != kInvalidIdx )
|
||||||
name = portName(p->fileDevH,fileDevIdx,flags,portIdx);
|
name = portName(p->fileDevH,fileDevIdx,flags,portIdx);
|
||||||
else
|
else
|
||||||
cwLogError(kInvalidArgRC,"The device index %i is not valid.");
|
cwLogError(kInvalidArgRC,"The device index %i is not valid.");
|
||||||
|
|
||||||
if( name == nullptr )
|
if( name == nullptr )
|
||||||
cwLogError(kOpFailRC,"The access to port name on device index %i port index %i failed.",devIdx,portIdx);
|
cwLogError(kOpFailRC,"The access to %s port name on device index %i port index %i failed.",flags & kInMpFl ? "input" : "output", devIdx,portIdx);
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@ -573,7 +643,7 @@ errLabel:
|
|||||||
cw::rc_t cw::midi::device::setEndMsg( handle_t h, unsigned devIdx, unsigned portIdx, unsigned msgIdx )
|
cw::rc_t cw::midi::device::setEndMsg( handle_t h, unsigned devIdx, unsigned portIdx, unsigned msgIdx )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
device_t* p = _handleToPtr(h);
|
device_t* p = _handleToPtr(h);
|
||||||
|
|
||||||
if(_devIdxToFileDevIdx(p,devIdx) == kInvalidIdx )
|
if(_devIdxToFileDevIdx(p,devIdx) == kInvalidIdx )
|
||||||
{
|
{
|
||||||
@ -591,6 +661,43 @@ errLabel:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned cw::midi::device::maxBufferMsgCount( handle_t h )
|
||||||
|
{
|
||||||
|
device_t* p = _handleToPtr(h);
|
||||||
|
return p->bufN;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cw::midi::ch_msg_t* cw::midi::device::getBuffer( handle_t h, unsigned& msgCntRef )
|
||||||
|
{
|
||||||
|
device_t* p = _handleToPtr(h);
|
||||||
|
unsigned ii = p->buf_ii.load();
|
||||||
|
unsigned oi = p->buf_oi.load();
|
||||||
|
ch_msg_t* m = nullptr;
|
||||||
|
|
||||||
|
msgCntRef = ii >= oi ? ii-oi : p->bufN - oi;
|
||||||
|
|
||||||
|
if( msgCntRef > 0 )
|
||||||
|
m = p->buf + oi;
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::midi::device::clearBuffer( handle_t h, unsigned msgCnt )
|
||||||
|
{
|
||||||
|
if( msgCnt > 0 )
|
||||||
|
{
|
||||||
|
device_t* p = _handleToPtr(h);
|
||||||
|
unsigned oi = p->buf_oi.load();
|
||||||
|
|
||||||
|
oi = (oi + msgCnt) % p->bufN;
|
||||||
|
|
||||||
|
p->buf_oi.store(oi);
|
||||||
|
}
|
||||||
|
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::midi::device::start( handle_t h )
|
cw::rc_t cw::midi::device::start( handle_t h )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
@ -669,6 +776,8 @@ cw::rc_t cw::midi::device::report( handle_t h )
|
|||||||
|
|
||||||
report(h,tbH);
|
report(h,tbH);
|
||||||
|
|
||||||
|
printf("%s\n",text(tbH));
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
destroy(tbH);
|
destroy(tbH);
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -30,7 +30,9 @@ namespace cw
|
|||||||
const char* appNameStr,
|
const char* appNameStr,
|
||||||
const char* fileDevName = "file_dev",
|
const char* fileDevName = "file_dev",
|
||||||
unsigned fileDevReadAheadMicros = 3000,
|
unsigned fileDevReadAheadMicros = 3000,
|
||||||
unsigned parserBufByteCnt = 1024 );
|
unsigned parserBufByteCnt = 1024,
|
||||||
|
bool enableBufFl = false, // Enable buffer to hold all incoming msg's until RT thread can pick them up.
|
||||||
|
unsigned bufferMsgCnt = 4096); // Count of messages in input buffer.
|
||||||
|
|
||||||
rc_t create( handle_t& h,
|
rc_t create( handle_t& h,
|
||||||
cbFunc_t cbFunc,
|
cbFunc_t cbFunc,
|
||||||
@ -57,6 +59,10 @@ namespace cw
|
|||||||
rc_t seekToMsg( handle_t h, unsigned devIdx, unsigned portIdx, unsigned msgIdx );
|
rc_t seekToMsg( handle_t h, unsigned devIdx, unsigned portIdx, unsigned msgIdx );
|
||||||
rc_t setEndMsg( handle_t h, unsigned devIdx, unsigned portidx, unsigned msgIdx );
|
rc_t setEndMsg( handle_t h, unsigned devIdx, unsigned portidx, unsigned msgIdx );
|
||||||
|
|
||||||
|
unsigned maxBufferMsgCount( handle_t h ); // max number of msg's which will ever be returned in a buffer
|
||||||
|
const ch_msg_t* getBuffer( handle_t h, unsigned& msgCntRef );
|
||||||
|
rc_t clearBuffer( handle_t h, unsigned msgCnt );
|
||||||
|
|
||||||
rc_t start( handle_t h );
|
rc_t start( handle_t h );
|
||||||
rc_t stop( handle_t h );
|
rc_t stop( handle_t h );
|
||||||
rc_t pause( handle_t h, bool pause_fl );
|
rc_t pause( handle_t h, bool pause_fl );
|
||||||
|
Loading…
Reference in New Issue
Block a user