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
|
||||
{
|
||||
void* cbArg; // Application supplied reference value
|
||||
//void* cbArg; // Application supplied reference value
|
||||
unsigned devIdx; // The device the msg originated from
|
||||
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
|
||||
@ -25,8 +25,19 @@ namespace cw
|
||||
unsigned msgCnt; // Count of mdMsg records or sys-ex bytes
|
||||
} 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
|
||||
|
125
cwMidiDevice.cpp
125
cwMidiDevice.cpp
@ -55,6 +55,11 @@ namespace cw
|
||||
unsigned long long last_posn_micros;
|
||||
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* _handleToPtr( handle_t h )
|
||||
@ -102,8 +107,11 @@ namespace cw
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
|
||||
destroy(p->alsaDevH);
|
||||
destroy(p->fileDevH);
|
||||
|
||||
mem::release(p->buf);
|
||||
mem::release(p);
|
||||
|
||||
errLabel:
|
||||
@ -173,6 +181,45 @@ namespace cw
|
||||
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
|
||||
} // midi
|
||||
@ -188,7 +235,9 @@ cw::rc_t cw::midi::device::create( handle_t& hRef,
|
||||
const char* appNameStr,
|
||||
const char* fileDevName,
|
||||
unsigned fileDevReadAheadMicros,
|
||||
unsigned parserBufByteCnt )
|
||||
unsigned parserBufByteCnt,
|
||||
bool enableBufFl,
|
||||
unsigned bufferMsgCnt )
|
||||
{
|
||||
rc_t rc = 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>();
|
||||
|
||||
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.");
|
||||
goto errLabel;
|
||||
@ -206,16 +259,29 @@ cw::rc_t cw::midi::device::create( handle_t& hRef,
|
||||
|
||||
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.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
p->cbFunc = cbFunc;
|
||||
p->cbArg = cbArg;
|
||||
p->file_dev_cnt = count(p->fileDevH);
|
||||
p->total_dev_cnt = p->alsa_dev_cnt + p->file_dev_cnt;
|
||||
p->alsaPollfdA = pollFdArray(p->alsaDevH,p->alsaPollfdN);
|
||||
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,
|
||||
_thread_func,
|
||||
@ -257,6 +323,8 @@ cw::rc_t cw::midi::device::create( handle_t& h,
|
||||
const char* fileDevName = "file_dev";
|
||||
unsigned fileDevReadAheadMicros = 3000;
|
||||
unsigned parseBufByteCnt = 1024;
|
||||
bool enableBufFl = false;
|
||||
unsigned bufMsgCnt = 0;
|
||||
const object_t* file_ports = nullptr;
|
||||
const object_t* port = nullptr;
|
||||
|
||||
@ -264,6 +332,8 @@ cw::rc_t cw::midi::device::create( handle_t& h,
|
||||
"fileDevName",fileDevName,
|
||||
"fileDevReadAheadMicros",fileDevReadAheadMicros,
|
||||
"parseBufByteCnt",parseBufByteCnt,
|
||||
"enableBufFl",enableBufFl,
|
||||
"bufferMsgCnt",bufMsgCnt,
|
||||
"file_ports",file_ports)) != kOkRC )
|
||||
{
|
||||
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;
|
||||
|
||||
if((alsaDevIdx = _devIdxToAlsaDevIdx(p,devIdx)) != kInvalidIdx )
|
||||
name = portName(p->alsaDevH,alsaDevIdx,flags,portIdx);
|
||||
name = portName(p->alsaDevH,alsaDevIdx,flags,portIdx);
|
||||
else
|
||||
if((fileDevIdx = _devIdxToFileDevIdx(p,devIdx)) != kInvalidIdx )
|
||||
name = portName(p->fileDevH,fileDevIdx,flags,portIdx);
|
||||
name = portName(p->fileDevH,fileDevIdx,flags,portIdx);
|
||||
else
|
||||
cwLogError(kInvalidArgRC,"The device index %i is not valid.");
|
||||
|
||||
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;
|
||||
}
|
||||
@ -573,7 +643,7 @@ errLabel:
|
||||
cw::rc_t cw::midi::device::setEndMsg( handle_t h, unsigned devIdx, unsigned portIdx, unsigned msgIdx )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
device_t* p = _handleToPtr(h);
|
||||
device_t* p = _handleToPtr(h);
|
||||
|
||||
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 )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
@ -669,6 +776,8 @@ cw::rc_t cw::midi::device::report( handle_t h )
|
||||
|
||||
report(h,tbH);
|
||||
|
||||
printf("%s\n",text(tbH));
|
||||
|
||||
errLabel:
|
||||
destroy(tbH);
|
||||
return rc;
|
||||
|
@ -30,7 +30,9 @@ namespace cw
|
||||
const char* appNameStr,
|
||||
const char* fileDevName = "file_dev",
|
||||
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,
|
||||
cbFunc_t cbFunc,
|
||||
@ -57,6 +59,10 @@ namespace cw
|
||||
rc_t seekToMsg( 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 stop( handle_t h );
|
||||
rc_t pause( handle_t h, bool pause_fl );
|
||||
|
Loading…
Reference in New Issue
Block a user