diff --git a/cmUiAudioSysMstr.c b/cmUiAudioSysMstr.c new file mode 100644 index 0000000..af46d23 --- /dev/null +++ b/cmUiAudioSysMstr.c @@ -0,0 +1,450 @@ +#include "cmGlobal.h" +#include "cmFloatTypes.h" +#include "cmRpt.h" +#include "cmErr.h" +#include "cmCtx.h" +#include "cmMem.h" +#include "cmMallocDebug.h" +#include "cmJson.h" +#include "cmThread.h" +#include "cmUdpPort.h" +#include "cmUdpNet.h" +#include "cmAudioSysMsg.h" +#include "cmAudioSys.h" +#include "cmUiDrvr.h" +#include "cmUi.h" +#include "cmUiAudioSysMstr.h" + +enum +{ + kLabelAmId, + kInSliderAmId, + kInMeterAmId, + kInToneAmId, + kInPassAmId, + kInMuteAmId, + kOutSliderAmId, + kOutMeterAmId, + kOutToneAmId, + kOutPassAmId, + kOutMuteAmId, + kAmCnt +}; + + +enum +{ + kMinDb = 24, + kMaxDb = -24, + kMtrMin = 0, + kMtrMax = 100 +}; + +typedef struct cmAmPanel_str +{ + unsigned asSubIdx; + + unsigned panelId; + + unsigned updateId; + unsigned wakeupId; + unsigned msgCbId; + unsigned audioCbId; + + unsigned updateCnt; + unsigned wakeupCnt; + unsigned msgCbCnt; + unsigned audioCbCnt; + + unsigned baseOutId; + unsigned iDevIdx; + unsigned oDevIdx; + unsigned iChCnt; + unsigned oChCnt; + + unsigned a[ kAmCnt ]; + + + struct cmAmPanel_str* link; +} cmAmPanel_t; + +typedef struct +{ + cmErr_t err; + unsigned appId; + cmUiH_t uiH; + cmAudioSysH_t asH; + unsigned nextId; + cmAmPanel_t* list; +} cmAm_t; + +cmUiASMstrH_t cmUiASMstrNullHandle = cmSTATIC_NULL_HANDLE; + +cmAm_t* _cmUiAmHandleToPtr( cmUiASMstrH_t h ) +{ + cmAm_t* p = (cmAm_t*)h.h; + assert( p!=NULL); + return p; +} + +cmAmRC_t _cmUiAmFreePanels( cmAm_t* p, bool callDriverFl ) +{ + cmAmRC_t rc = kOkAmRC; + cmAmPanel_t* pp = p->list; + + while( pp != NULL ) + { + cmAmPanel_t* np = pp->link; + + unsigned panelId = pp->panelId; + + if( callDriverFl ) + if( cmUiClearPanel( p->uiH, panelId ) != kOkUiRC ) + { + rc = cmErrMsg(&p->err,kUiFailAmRC,"The panel %i clear failed.",panelId); + goto errLabel; + } + + cmMemFree(pp); + + pp = np; + } + + p->nextId = 0; + p->list = NULL; + + errLabel: + return rc; +} + + +cmAmRC_t _cmUiAmFree( cmAm_t* p ) +{ + _cmUiAmFreePanels(p,false); + cmMemFree(p); + return kOkAmRC; +} + +cmAmRC_t cmUiAudioSysMstrAlloc( cmCtx_t* ctx, cmUiASMstrH_t* hp, cmUiH_t uiH, cmAudioSysH_t asH, unsigned appId ) +{ + cmAmRC_t rc = kOkAmRC; + + if((rc = cmUiAudioSysMstrFree(hp)) != kOkAmRC ) + return rc; + + cmAm_t* p = cmMemAllocZ(cmAm_t,1); + cmErrSetup(&p->err,&ctx->rpt,"Audio System Master UI"); + p->appId = appId; + p->uiH = uiH; + p->asH = asH; + p->nextId = 0; + hp->h = p; + return rc; +} + +cmAmRC_t cmUiAudioSysMstrFree( cmUiASMstrH_t* hp ) +{ + cmAmRC_t rc = kOkAmRC; + + if(hp==NULL || cmUiAudioSysMstrIsValid(*hp)==false ) + return kOkAmRC; + + cmAm_t* p = _cmUiAmHandleToPtr(*hp); + + if((rc = _cmUiAmFree(p)) != kOkAmRC ) + return rc; + + hp->h = NULL; + + return rc; +} + +bool cmUiAudioSysMstrIsValid( cmUiASMstrH_t h ) +{ return h.h != NULL; } + + +cmAmRC_t cmUiAudioSysMstrInitialize( cmUiASMstrH_t amH, const cmAudioSysSsInitMsg_t* m, const cmChar_t* inDevLabel, const cmChar_t* outDevLabel ) +{ + cmAmRC_t rc = kOkAmRC; + cmAm_t* p = _cmUiAmHandleToPtr(amH); + cmUiH_t uiH = p->uiH; + + cmUiSetAppId( p->uiH, p->appId ); + + if( m->asSubIdx == 0 ) + { + if((rc = _cmUiAmFreePanels(p,true)) != kOkAmRC ) + return rc; + assert(p->list == NULL ); + } + + // create the panel recd and link it to the beginning of the list + cmAmPanel_t* pp = cmMemAllocZ(cmAmPanel_t,1); + + pp->link = p->list; + p->list = pp; + pp->asSubIdx = m->asSubIdx; + pp->iDevIdx = m->inDevIdx; + pp->oDevIdx = m->outDevIdx; + pp->iChCnt = m->inChCnt; + pp->oChCnt = m->outChCnt; + + + pp->panelId = p->nextId++; + pp->updateId = p->nextId++; + pp->wakeupId = p->nextId++; + pp->msgCbId = p->nextId++; + pp->audioCbId = p->nextId++; + + pp->a[kLabelAmId] = p->nextId; + pp->a[kInSliderAmId] = p->nextId += m->inChCnt; + pp->a[kInMeterAmId] = p->nextId += m->inChCnt; + pp->a[kInToneAmId] = p->nextId += m->inChCnt; + pp->a[kInPassAmId] = p->nextId += m->inChCnt; + pp->a[kInMuteAmId] = p->nextId += m->inChCnt; + + pp->baseOutId = p->nextId += m->inChCnt; + + pp->a[kOutSliderAmId] = pp->baseOutId; + pp->a[kOutMeterAmId] = p->nextId += m->outChCnt; + pp->a[kOutToneAmId] = p->nextId += m->outChCnt; + pp->a[kOutPassAmId] = p->nextId += m->outChCnt; + pp->a[kOutMuteAmId] = p->nextId += m->outChCnt; + p->nextId += m->outChCnt; + + unsigned panelId = pp->panelId; + unsigned colW = 50; + unsigned ctlW = 45; + unsigned n = 31; + cmChar_t chNumStr[ n+1 ]; + int w; + + if( cmUiCreatePanel(uiH, panelId, "Master" ) != kOkUiRC ) + { + rc = cmErrMsg(&p->err,kUiFailAmRC,"Panel %i create failed.",panelId); + goto errLabel; + } + + cmUiSetFillRows( uiH, panelId, true ); + cmUiCreateProgress(uiH, panelId, pp->updateId, "Update", 0, 0, 1, 0 ); + cmUiCreateProgress(uiH, panelId, pp->wakeupId, "Wakeup", 0, 0, 1, 0 ); + cmUiCreateProgress(uiH, panelId, pp->msgCbId, "Message", 0, 0, 1, 0 ); + cmUiCreateProgress(uiH, panelId, pp->audioCbId,"Audio", 0, 0, 1, 0 ); + cmUiSetFillRows( uiH, panelId, false ); + + cmUiNewLine( uiH, panelId ); + cmUiCreateLabel( uiH, panelId, cmInvalidId, inDevLabel, kInsideUiFl | kLeftUiFl ); + cmUiNewLine( uiH, panelId ); + + unsigned i; + for(i=0; iinChCnt; ++i) + { + snprintf(chNumStr,n,"%i",i); + + cmUiSetNextW( uiH, panelId, ctlW ); + cmUiCreateLabel( uiH, panelId, cmInvalidId, chNumStr, 0 ); + cmUiCreateVSlider(uiH, panelId, pp->a[kInSliderAmId] + i, NULL, 0, kMinDb, kMaxDb, 0.1, 0 ); + cmUiPlaceRight( uiH, panelId ); + cmUiCreateVMeter( uiH, panelId, pp->a[kInMeterAmId] + i, NULL, 0, kMtrMin, kMtrMax, 0 ); + w = cmUiSetW( uiH, panelId, ctlW ); + cmUiCreateCheck( uiH, panelId, pp->a[kInToneAmId] + i, "T", 0, false ); + cmUiCreateCheck( uiH, panelId, pp->a[kInPassAmId] + i, "P", 0, false ); + cmUiCreateCheck( uiH, panelId, pp->a[kInMuteAmId] + i, "M", 0, false ); + cmUiSetW( uiH, panelId, w ); + cmUiSetBaseCol( uiH, panelId, 5 + (i+1)*colW); + } + + cmUiSetBaseCol( uiH, panelId, 0); + cmUiNewLine( uiH, panelId ); + cmUiCreateLabel( uiH,panelId, cmInvalidId, outDevLabel, kInsideUiFl | kLeftUiFl ); + cmUiNewLine( uiH, panelId ); + + for(i=0; ioutChCnt; ++i) + { + snprintf(chNumStr,n,"%i",i); + + cmUiSetNextW( uiH, panelId, ctlW ); + cmUiCreateLabel( uiH, panelId, cmInvalidId, chNumStr, 0 ); + cmUiCreateVSlider(uiH, panelId, pp->a[kOutSliderAmId] + i, NULL, 0, kMinDb, kMaxDb, 0.1, 0 ); + cmUiPlaceRight( uiH, panelId ); + cmUiCreateVMeter( uiH, panelId, pp->a[kOutMeterAmId] + i, NULL, 0, kMtrMin, kMtrMax, 0 ); + w = cmUiSetW( uiH, panelId, ctlW ); + cmUiCreateCheck( uiH, panelId, pp->a[kOutToneAmId] + i, "T", 0, false ); + cmUiCreateCheck( uiH, panelId, pp->a[kOutPassAmId] + i, "P", 0, false ); + cmUiCreateCheck( uiH, panelId, pp->a[kOutMuteAmId] + i, "M", 0, false ); + cmUiSetW( uiH, panelId, w ); + cmUiSetBaseCol( uiH, panelId, 5 + (i+1)*colW); + } + + errLabel: + return rc; +} + + +cmAmPanel_t* _cmUiAmFindPanel( cmAm_t* p, unsigned panelId ) +{ + cmAmPanel_t* pp = p->list; + for(; pp!=NULL; pp=pp->link) + if( pp->panelId == panelId ) + return pp; + + cmErrMsg(&p->err,kPanelNotFoundAmRC,"The panel %i was not found.",panelId); + + return NULL; +} + +unsigned _cmUiAmCtlTypeId( cmAm_t* p, cmAmPanel_t* pp, cmUiCId_t cId, unsigned usrId, + unsigned sliderId, unsigned toneId, unsigned passId, unsigned muteId ) +{ + switch( cId ) + { + case kSliderUiCId: + assert( pp->a[sliderId] <= usrId && usrId < pp->a[sliderId]+pp->oChCnt); + return sliderId; + break; + + case kCheckUiCId: + if( pp->a[toneId] <= usrId && usrId < pp->a[toneId]+pp->oChCnt ) + return toneId; + + if( pp->a[passId] <= usrId && usrId < pp->a[passId]+pp->oChCnt ) + return passId; + + if( pp->a[muteId] <= usrId && usrId < pp->a[muteId]+pp->oChCnt ) + return muteId; + break; + + default: + assert(0); + break; + + } + + return cmInvalidId; +} + + +cmUiRC_t cmUiAudioSysMstrOnUiEvent( cmUiASMstrH_t h, const cmUiDriverArg_t* a ) +{ + cmUiRC_t rc = kOkUiRC; + cmAm_t* p = _cmUiAmHandleToPtr(h); + cmAmPanel_t* pp; + cmAudioSysMstr_t r; + unsigned typeId; + + if((pp = _cmUiAmFindPanel( p, a->panelId )) == NULL) + return cmErrLastRC(&p->err); + + if( a->usrId == pp->panelId ) + { + cmAudioSysStatusNotifyEnable(p->asH, pp->asSubIdx, a->ival ); + return rc; + } + + if( a->usrId >= pp->baseOutId ) + typeId = _cmUiAmCtlTypeId(p,pp,a->cId,a->usrId,kOutSliderAmId,kOutToneAmId,kOutPassAmId,kOutMuteAmId); + else + typeId = _cmUiAmCtlTypeId(p,pp,a->cId,a->usrId,kInSliderAmId,kInToneAmId,kInPassAmId,kInMuteAmId); + + + assert( typeId != cmInvalidId ); + if( typeId == cmInvalidId ) + return cmErrMsg(&p->err,kCtlNotFoundUiRC,"The type of a UI control could not be determined."); + + + unsigned asInFl = 0; + unsigned asCtlId = cmInvalidId; + unsigned asCh = a->usrId - pp->a[typeId]; + double asValue = 0; + + switch( typeId ) + { + case kInSliderAmId: + asInFl = 1; + asCtlId = kSliderUiAsId; + asValue = a->fval; + break; + + case kInToneAmId: + asInFl = 1; + asCtlId = kToneUiAsId; + asValue = a->ival; + break; + + case kInPassAmId: + asInFl = 1; + asCtlId = kPassUiAsId; + asValue = a->ival; + break; + + case kInMuteAmId: + asInFl = 1;; + asCtlId = kMuteUiAsId; + asValue = a->ival; + break; + + case kOutSliderAmId: + asCtlId = kSliderUiAsId; + asValue = a->fval; + break; + + case kOutToneAmId: + asCtlId = kToneUiAsId; + asValue = a->ival; + break; + + case kOutPassAmId: + asCtlId = kPassUiAsId; + asValue = a->ival; + break; + + case kOutMuteAmId: + asCtlId = kMuteUiAsId; + asValue = a->ival; + break; + + } + + unsigned asDevIdx = asInFl ? pp->iDevIdx : pp->oDevIdx; + + r.asSubIdx = pp->asSubIdx; + r.uiId = kUiMstrSelAsId; + r.selId = cmInvalidId; + r.instId = cmAudioSysFormUiInstId(asDevIdx,asCh,asInFl,asCtlId); + r.instVarId = cmInvalidId; + r.value = asValue; + + if( cmAudioSysDeliverMsg(p->asH, &r, sizeof(r), cmInvalidId ) != kOkAsRC ) + rc = cmErrMsg(&p->err,kSubSysFailUiRC,"Audio System master control UI message delivery to the audio system failed."); + + + return rc; +} + +cmUiRC_t cmUiAudioSysMstrOnStatusEvent( cmUiASMstrH_t h, const cmAudioSysStatus_t* m, const double* iMeterArray, const double* oMeterArray ) +{ + cmAm_t* p = _cmUiAmHandleToPtr(h); + cmAmPanel_t* pp = p->list; + for(; pp!=NULL; pp=pp->link) + if(pp->asSubIdx == m->asSubIdx ) + break; + + if( pp == NULL ) + return cmErrMsg(&p->err,kPanelNotFoundUiRC,"The panel associated with Audio system index %i could not be found.",m->asSubIdx); + + cmUiSetAppId(p->uiH,p->appId); + + cmUiSetInt(p->uiH, pp->updateId, m->updateCnt != pp->updateCnt ); + cmUiSetInt(p->uiH, pp->wakeupId, m->wakeupCnt != pp->wakeupCnt ); + cmUiSetInt(p->uiH, pp->msgCbId, m->msgCbCnt != pp->msgCbCnt ); + cmUiSetInt(p->uiH, pp->audioCbId, m->audioCbCnt != pp->audioCbCnt ); + + pp->updateCnt = m->updateCnt; + pp->wakeupCnt = m->wakeupCnt; + pp->msgCbCnt = m->msgCbCnt; + pp->audioCbCnt= m->audioCbCnt; + + cmUiSetAppId(p->uiH,cmInvalidId); + + return kOkUiRC; +} diff --git a/cmUiAudioSysMstr.h b/cmUiAudioSysMstr.h new file mode 100644 index 0000000..708bea8 --- /dev/null +++ b/cmUiAudioSysMstr.h @@ -0,0 +1,37 @@ +#ifndef cmUiAudioSysMstr_h +#define cmUiAudioSysMstr_h + +#ifdef __cplusplus +extern "C" { +#endif + + enum + { + kOkAmRC = cmOkRC, + kUiFailAmRC, + kPanelNotFoundAmRC + }; + + typedef cmHandle_t cmUiASMstrH_t; + typedef cmRC_t cmAmRC_t; + + extern cmUiASMstrH_t cmUiASMstrNullHandle; + + cmAmRC_t cmUiAudioSysMstrAlloc( cmCtx_t* ctx, cmUiASMstrH_t* hp, cmUiH_t uiH, cmAudioSysH_t asH, unsigned appId ); + cmAmRC_t cmUiAudioSysMstrFree( cmUiASMstrH_t* hp ); + + bool cmUiAudioSysMstrIsValid( cmUiASMstrH_t h ); + + cmAmRC_t cmUiAudioSysMstrInitialize( cmUiASMstrH_t h, const cmAudioSysSsInitMsg_t* m, const cmChar_t* inDevLabel, const cmChar_t* outDevLabel ); + + // Receive UI events. + cmUiRC_t cmUiAudioSysMstrOnUiEvent( cmUiASMstrH_t h, const cmUiDriverArg_t* a ); + + // Receive UI status events + cmUiRC_t cmUiAudioSysMstrOnStatusEvent( cmUiASMstrH_t h, const cmAudioSysStatus_t* m, const double* iMeterArray, const double* oMeterArray ); + +#ifdef __cplusplus +} +#endif + +#endif