cwIo.h/cpp : Added optional synchronous callbacks for all sub-systems.

The UI is now automatically cleared in io::stop().
This commit is contained in:
kevin 2022-12-13 13:27:32 -05:00
parent 277323d1f8
commit f0e6a56a60
2 changed files with 49 additions and 19 deletions

View File

@ -167,14 +167,14 @@ namespace cw
// All callbacks to the application occur through this function // All callbacks to the application occur through this function
rc_t _ioCallback( io_t* p, bool asyncFl, const msg_t* m ) rc_t _ioCallback( io_t* p, bool asyncFl, const msg_t* m, rc_t* app_rc_ref=nullptr )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
rc_t rc_app = kOkRC;
bool unlockFl = false; bool unlockFl = false;
bool isSynchronousFl = !asyncFl;
// if this is not an async callback then lock the mutex // if this is a synchronous callback then lock the mutex
if( !asyncFl ) if( isSynchronousFl )
{ {
switch(rc = mutex::lock(p->cbMutexH,p->cbMutexTimeOutMs)) switch(rc = mutex::lock(p->cbMutexH,p->cbMutexTimeOutMs))
{ {
@ -194,8 +194,11 @@ namespace cw
// make the callback to the client // make the callback to the client
if( rc == kOkRC ) if( rc == kOkRC )
rc_app = p->cbFunc( p->cbArg, m ); {
rc_t app_rc = p->cbFunc( p->cbArg, m );
if( app_rc_ref != nullptr )
*app_rc_ref = app_rc;
}
// if the mutex is locked // if the mutex is locked
if( unlockFl ) if( unlockFl )
@ -206,7 +209,7 @@ namespace cw
} }
} }
return rc_app; return rc;
} }
rc_t _ioParse( io_t* p, const object_t* cfg ) rc_t _ioParse( io_t* p, const object_t* cfg )
@ -235,6 +238,7 @@ namespace cw
// //
bool _threadFunc( void* arg ) bool _threadFunc( void* arg )
{ {
rc_t rc = kOkRC;
thread_t* t = (thread_t*)arg; thread_t* t = (thread_t*)arg;
thread_msg_t tm = { .id=t->id, .arg=t->arg }; thread_msg_t tm = { .id=t->id, .arg=t->arg };
msg_t m; msg_t m;
@ -242,7 +246,8 @@ namespace cw
m.tid = kThreadTId; m.tid = kThreadTId;
m.u.thread = &tm; m.u.thread = &tm;
_ioCallback( t->p, t->asyncFl, &m ); if((rc = _ioCallback( t->p, t->asyncFl, &m )) != kOkRC )
cwLogError(rc,"Thread app callback failed.");
return true; return true;
} }
@ -270,13 +275,16 @@ namespace cw
if( t->startedFl && !t->deletedFl ) if( t->startedFl && !t->deletedFl )
{ {
rc_t rc = kOkRC;
msg_t m; msg_t m;
timer_msg_t tm; timer_msg_t tm;
tm.id = t->id; tm.id = t->id;
m.tid = kTimerTId; m.tid = kTimerTId;
m.u.timer = &tm; m.u.timer = &tm;
_ioCallback( t->io, t->asyncFl, &m );
if((rc = _ioCallback( t->io, t->asyncFl, &m )) != kOkRC )
cwLogError(rc,"Timer app callback failed.");
} }
return !t->deletedFl; return !t->deletedFl;
@ -366,6 +374,7 @@ namespace cw
cwLogError(kAssertFailRC,"The serial cfg index %i is out of range %i in serial port callback.", serialCfgIdx, p->serialN ); cwLogError(kAssertFailRC,"The serial cfg index %i is out of range %i in serial port callback.", serialCfgIdx, p->serialN );
else else
{ {
rc_t rc = kOkRC;
const serialPort_t* sp = p->serialA + serialCfgIdx; const serialPort_t* sp = p->serialA + serialCfgIdx;
msg_t m; msg_t m;
serial_msg_t sm; serial_msg_t sm;
@ -377,7 +386,8 @@ namespace cw
m.tid = kSerialTId; m.tid = kSerialTId;
m.u.serial = &sm; m.u.serial = &sm;
_ioCallback( p, sp->asyncFl, &m ); if((rc = _ioCallback( p, sp->asyncFl, &m )) != kOkRC )
cwLogError(rc,"Serial port app callback failed.");
} }
} }
@ -558,13 +568,15 @@ namespace cw
midi_msg_t mm; midi_msg_t mm;
const midi::packet_t* pkt = pktArray + i; const midi::packet_t* pkt = pktArray + i;
io_t* p = reinterpret_cast<io_t*>(pkt->cbDataPtr); io_t* p = reinterpret_cast<io_t*>(pkt->cbDataPtr);
rc_t rc = kOkRC;
mm.pkt = pkt; mm.pkt = pkt;
m.tid = kMidiTId; m.tid = kMidiTId;
m.u.midi = &mm; m.u.midi = &mm;
_ioCallback( p, p->midiAsyncFl, &m ); if((rc = _ioCallback( p, p->midiAsyncFl, &m )) !=kOkRC )
cwLogError(rc,"MIDI app callback failed.");
/* /*
for(unsigned j=0; j<pkt->msgCnt; ++j) for(unsigned j=0; j<pkt->msgCnt; ++j)
@ -652,7 +664,10 @@ namespace cw
m.tid = kSockTId; m.tid = kSockTId;
m.u.sock = &sm; m.u.sock = &sm;
_ioCallback( p, p->sockA[ sockArray_index ].asyncFl, &m ); rc_t rc;
if((rc = _ioCallback( p, p->sockA[ sockArray_index ].asyncFl, &m )) != kOkRC )
cwLogError(rc,"Socket app callback failed.");
} }
} }
@ -937,6 +952,7 @@ namespace cw
rc_t rc = kOkRC; rc_t rc = kOkRC;
if( agd != nullptr && ag != nullptr && cwIsFlag(agd->flags,kMeterFl)) if( agd != nullptr && ag != nullptr && cwIsFlag(agd->flags,kMeterFl))
{ {
rc_t app_rc = kOkRC;
msg_t m; msg_t m;
m.tid = kAudioMeterTId; m.tid = kAudioMeterTId;
m.u.audioGroupDev = agd; m.u.audioGroupDev = agd;
@ -945,8 +961,10 @@ namespace cw
audio::buf::meter(p->audioBufH, agd->devIdx, audioBufFlags, agd->meterA, agd->chCnt ); audio::buf::meter(p->audioBufH, agd->devIdx, audioBufFlags, agd->meterA, agd->chCnt );
// callback the application with the current meter values // callback the application with the current meter values
rc = _ioCallback( p, ag->asyncFl, &m); if((rc = _ioCallback( p, ag->asyncFl, &m, &app_rc )) != kOkRC )
cwLogError(rc,"Audio meter app callback failed.");
rc = app_rc;
} }
return rc; return rc;
@ -1055,7 +1073,8 @@ namespace cw
_audioGroupProcSampleBufs( ag->p, ag, kAudioGroupGetBuf, true ); _audioGroupProcSampleBufs( ag->p, ag, kAudioGroupGetBuf, true );
_audioGroupProcSampleBufs( ag->p, ag, kAudioGroupGetBuf, false ); _audioGroupProcSampleBufs( ag->p, ag, kAudioGroupGetBuf, false );
_ioCallback( ag->p, ag->asyncFl, &msg); if((rc = _ioCallback( ag->p, ag->asyncFl, &msg)) != kOkRC )
cwLogError(rc,"Audio app callback failed %i.",ag->asyncFl);
_audioGroupProcSampleBufs( ag->p, ag, kAudioGroupAdvBuf, true ); _audioGroupProcSampleBufs( ag->p, ag, kAudioGroupAdvBuf, true );
_audioGroupProcSampleBufs( ag->p, ag, kAudioGroupAdvBuf, false ); _audioGroupProcSampleBufs( ag->p, ag, kAudioGroupAdvBuf, false );
@ -1344,6 +1363,7 @@ namespace cw
{ {
if(( rc = node->getv( if(( rc = node->getv(
"enableFl", p->audioGroupA[i].enableFl, "enableFl", p->audioGroupA[i].enableFl,
"asyncFl", p->audioGroupA[i].asyncFl,
"label", p->audioGroupA[i].msg.label, "label", p->audioGroupA[i].msg.label,
"id", p->audioGroupA[i].msg.userId, "id", p->audioGroupA[i].msg.userId,
"srate", p->audioGroupA[i].msg.srate, "srate", p->audioGroupA[i].msg.srate,
@ -1687,11 +1707,16 @@ namespace cw
{ {
io_t* p = (io_t*)cbArg; io_t* p = (io_t*)cbArg;
msg_t r; msg_t r;
rc_t rc = kOkRC;
rc_t app_rc = kOkRC;
r.tid = kUiTId; r.tid = kUiTId;
r.u.ui = { .opId=opId, .wsSessId=wsSessId, .parentAppId=parentAppId, .uuId=uuId, .appId=appId, .chanId=chanId, .value=v }; r.u.ui = { .opId=opId, .wsSessId=wsSessId, .parentAppId=parentAppId, .uuId=uuId, .appId=appId, .chanId=chanId, .value=v };
return _ioCallback( p, p->uiAsyncFl, &r ); if((rc = _ioCallback( p, p->uiAsyncFl, &r, &app_rc )) != kOkRC )
cwLogError(rc,"UI app callback failed.");
return app_rc;
} }
rc_t _uiConfig( io_t* p, const object_t* c, const ui::appIdMap_t* mapA, unsigned mapN ) rc_t _uiConfig( io_t* p, const object_t* c, const ui::appIdMap_t* mapA, unsigned mapN )
@ -1957,8 +1982,13 @@ cw::rc_t cw::io::stop( handle_t h )
io_t* p = _handleToPtr(h); io_t* p = _handleToPtr(h);
p->quitFl.store(true); p->quitFl.store(true);
// stop the audio devices
_audioDeviceStartStop(p,false); _audioDeviceStartStop(p,false);
// clear the UI
if( p->wsUiH.isValid() )
uiDestroyElement(h,ui::kRootUuId);
return kOkRC; return kOkRC;
} }

2
cwIo.h
View File

@ -36,7 +36,7 @@ namespace cw
kSockTId, kSockTId,
kWebSockTId, kWebSockTId,
kUiTId, kUiTId,
kExecTId kExecTId // callback from io::exec() which is inside the application main loop thread
}; };
typedef struct thread_msg_str typedef struct thread_msg_str