cmDevCfg.h/c: Many changes and additions to complete implementation.

This commit is contained in:
kevin 2013-03-28 23:15:09 -07:00
parent 5b8e7dfae7
commit 646f65222e
2 changed files with 256 additions and 54 deletions

View File

@ -6,6 +6,7 @@
#include "cmMem.h" #include "cmMem.h"
#include "cmMallocDebug.h" #include "cmMallocDebug.h"
#include "cmLinkedHeap.h" #include "cmLinkedHeap.h"
#include "cmFileSys.h"
#include "cmJson.h" #include "cmJson.h"
#include "cmText.h" #include "cmText.h"
#include "cmThread.h" #include "cmThread.h"
@ -24,10 +25,13 @@ cmDevCfgH_t cmDevCfgNullHandle = cmSTATIC_NULL_HANDLE;
typedef struct cmDcmCfg_str typedef struct cmDcmCfg_str
{ {
cmChar_t* dcLabelStr; cmChar_t* dcLabelStr; // the cfg label
unsigned cfgId; // unique among all cfg's assigned to a loc unsigned cfgId; // unique among all cfg's assigned to a loc
cmTypeDcmId_t typeId; cmTypeDcmId_t typeId; // the cfg type id (e.g. midi, audio, net, ...)
cmChar_t* descStr; cmChar_t* descStr; // summary description string
// NOTE: any fields added to this structure, type generic (above)
// or type specific (below), must be explicitely duplicated in cmDevCfgLocStore().
union union
{ {
@ -71,8 +75,10 @@ typedef struct cmDcmLoc_str
typedef struct typedef struct
{ {
cmErr_t err; cmErr_t err;
cmCtx_t* ctx;
cmDcmLoc_t* loc; cmDcmLoc_t* loc;
cmDcmLoc_t* clp; cmDcmLoc_t* clp;
cmChar_t* fn;
} cmDcm_t; } cmDcm_t;
@ -166,6 +172,8 @@ void _cmDcmFreeCfg( cmDcm_t* p, cmDcmLoc_t* lp, cmDcmCfg_t* cp )
assert(0); assert(0);
break; break;
} }
cmMemFree(cp);
} }
void _cmDcmFreeLoc( cmDcm_t* p, cmDcmLoc_t* lp ) void _cmDcmFreeLoc( cmDcm_t* p, cmDcmLoc_t* lp )
@ -208,6 +216,7 @@ cmDcRC_t _cmDcmFree( cmDcm_t* p )
cmDcRC_t rc = kOkDcRC; cmDcRC_t rc = kOkDcRC;
_cmDcmFreeAllLocs(p); _cmDcmFreeAllLocs(p);
cmMemFree(p->fn);
cmMemFree(p); cmMemFree(p);
return rc; return rc;
@ -270,21 +279,64 @@ cmDcRC_t _cmDcmNewLoc( cmDcm_t* p, const cmChar_t* labelStr, cmDcmLoc_t** locRe
} }
cmDcRC_t cmDevCfgMgrAlloc( cmCtx_t* c, cmDevCfgH_t* hp ) cmDcRC_t _cmDevCfgRead( cmDcm_t* p, cmJsonH_t jsH, const cmJsonNode_t* rootObjPtr );
cmDcRC_t _cmDevCfgReadFile( cmDcm_t* p, const cmChar_t* fn )
{
cmDcRC_t rc = kOkDcRC;
cmJsonH_t jsH = cmJsonNullHandle;
// initialize the JSON tree from the preferences file
if( cmJsonInitializeFromFile( &jsH, fn, p->ctx ) != kOkJsRC )
{
rc = cmErrMsg(&p->err,kJsonFailDcRC,"JSON initialization from '%s' failed.",cmStringNullGuard(fn));
goto errLabel;
}
if((rc = _cmDevCfgRead(p, jsH, cmJsonRoot(jsH))) != kOkJsRC )
goto errLabel;
errLabel:
if( cmJsonFinalize(&jsH) != kOkJsRC )
cmErrMsg(&p->err,kJsonFailDcRC,"JSON finalization failed following dev cfg read.");
return rc;
}
cmDcRC_t cmDevCfgAlloc( cmCtx_t* c, cmDevCfgH_t* hp, const cmChar_t* fn )
{ {
cmDcRC_t rc; cmDcRC_t rc;
cmDcmLoc_t* lp; cmDcmLoc_t* lp;
if((rc = cmDevCfgMgrFree(hp)) != kOkDcRC ) if((rc = cmDevCfgFree(hp)) != kOkDcRC )
return rc; return rc;
cmDcm_t* p = cmMemAllocZ(cmDcm_t,1); cmDcm_t* p = cmMemAllocZ(cmDcm_t,1);
cmErrSetup(&p->err,&c->rpt,"cmDevCfg"); cmErrSetup(&p->err,&c->rpt,"cmDevCfg");
p->ctx = c;
if((rc = _cmDcmNewLoc(p,"Default", &lp)) != kOkDcRC ) if( fn != NULL )
goto errLabel; {
p->fn = cmMemAllocStr(fn);
if( cmFsIsFile(fn) )
{
// if the file read fails then reset and go with the default empty setup.
if(_cmDevCfgReadFile(p,fn) != kOkDcRC )
_cmDcmFreeAllLocs(p);
}
}
// if the location array is empty then create a default location
if( p->loc == NULL )
{
if((rc = _cmDcmNewLoc(p,"Default", &lp)) != kOkDcRC )
goto errLabel;
}
hp->h = p; hp->h = p;
@ -295,7 +347,7 @@ cmDcRC_t cmDevCfgMgrAlloc( cmCtx_t* c, cmDevCfgH_t* hp )
return rc; return rc;
} }
cmDcRC_t cmDevCfgMgrFree( cmDevCfgH_t* hp ) cmDcRC_t cmDevCfgFree( cmDevCfgH_t* hp )
{ {
cmDcRC_t rc = kOkDcRC; cmDcRC_t rc = kOkDcRC;
if( hp == NULL || cmDevCfgIsValid(*hp)==false ) if( hp == NULL || cmDevCfgIsValid(*hp)==false )
@ -436,7 +488,7 @@ cmDcmCfg_t* _cmDcmFindOrCreateCfg( cmDcm_t* p, cmTypeDcmId_t typeId, const cmCh
cp->dcLabelStr = cmMemAllocStr(dcLabelStr); cp->dcLabelStr = cmMemAllocStr(dcLabelStr);
cp->cfgId = newCfgId; cp->cfgId = newCfgId;
cp->typeId = typeId; cp->typeId = typeId;
// link to the end of the loc's cfg list // link to the end of the loc's cfg list
if( ep == NULL ) if( ep == NULL )
p->clp->cfg = cp; p->clp->cfg = cp;
@ -643,7 +695,7 @@ cmDcRC_t cmDevCfgNameAudioPort(
unsigned outDevIdx; unsigned outDevIdx;
// validate the label // validate the label
if((dcLabelStr = _cmDcmTrimLabel(p,dcLabelStr,"MIDI cfg")) == NULL) if((dcLabelStr = _cmDcmTrimLabel(p,dcLabelStr,"Audio cfg")) == NULL)
return cmErrLastRC(&p->err); return cmErrLastRC(&p->err);
// validate the input device // validate the input device
@ -654,11 +706,30 @@ cmDcRC_t cmDevCfgNameAudioPort(
if(( outDevIdx = cmApDeviceLabelToIndex(outDevNameStr)) == cmInvalidIdx ) if(( outDevIdx = cmApDeviceLabelToIndex(outDevNameStr)) == cmInvalidIdx )
return cmErrMsg(&p->err, kInvalidArgDcRC,"The output audio device name '%s' is not valid.",cmStringNullGuard(outDevNameStr)); return cmErrMsg(&p->err, kInvalidArgDcRC,"The output audio device name '%s' is not valid.",cmStringNullGuard(outDevNameStr));
// validate the msg byte cnt
if( msgQueueByteCnt == 0 )
return cmErrMsg(&p->err, kInvalidArgDcRC,"The 'message queue size' must be greater than zero.");
// validate the dev. frames per cycle
if( devFramesPerCycle == 0 )
return cmErrMsg(&p->err, kInvalidArgDcRC,"The 'device frames per cycle' must be greater than zero.");
// validate the dsp frames per cycle
if( dspFramesPerCycle == 0 || ((devFramesPerCycle/dspFramesPerCycle) * dspFramesPerCycle != devFramesPerCycle) )
return cmErrMsg(&p->err, kInvalidArgDcRC,"The 'DSP frames per cycle' must be greater than zero and an integer factor of 'Device frames per cycle.'.");
// validate the sample rate
if( srate == 0 )
return cmErrMsg(&p->err, kInvalidArgDcRC,"The audio sample rate must be greater than zero.");
// if dcLabelStr is already in use for this location and type then update // if dcLabelStr is already in use for this location and type then update
// the assoc'd recd otherwise create a new one. // the assoc'd recd otherwise create a new one.
if((cp = _cmDcmFindOrCreateCfg(p,kAudioDcmTId, dcLabelStr)) == NULL ) if((cp = _cmDcmFindOrCreateCfg(p,kAudioDcmTId, dcLabelStr)) == NULL )
return cmErrLastRC(&p->err); return cmErrLastRC(&p->err);
unsigned inChCnt = cmApDeviceChannelCount( inDevIdx, true );
unsigned outChCnt = cmApDeviceChannelCount( outDevIdx, false );
cp->u.a.inDevLabelStr = cmMemAllocStr(inDevNameStr); cp->u.a.inDevLabelStr = cmMemAllocStr(inDevNameStr);
cp->u.a.outDevLabelStr = cmMemAllocStr(outDevNameStr); cp->u.a.outDevLabelStr = cmMemAllocStr(outDevNameStr);
cp->u.a.audioSysArgs.rpt = p->err.rpt; cp->u.a.audioSysArgs.rpt = p->err.rpt;
@ -670,10 +741,60 @@ cmDcRC_t cmDevCfgNameAudioPort(
cp->u.a.audioSysArgs.dspFramesPerCycle = dspFramesPerCycle; cp->u.a.audioSysArgs.dspFramesPerCycle = dspFramesPerCycle;
cp->u.a.audioSysArgs.audioBufCnt = audioBufCnt; cp->u.a.audioSysArgs.audioBufCnt = audioBufCnt;
cp->u.a.audioSysArgs.srate = srate; cp->u.a.audioSysArgs.srate = srate;
cp->descStr = cmTsPrintfP(cp->descStr,"In:%s Out:%s",inDevNameStr,outDevNameStr); cp->descStr = cmTsPrintfP(cp->descStr,"In: Chs:%i %s\nOut: Chs:%i %s",inChCnt,inDevNameStr,outChCnt,outDevNameStr);
return kOkDcRC; return kOkDcRC;
} }
cmDcRC_t cmDevCfgAudioSetDefaultCfgIndex( cmDevCfgH_t h, unsigned cfgIdx )
{
cmDcm_t* p = _cmDcmHandleToPtr(h);
assert( p->clp != NULL );
cmDcmCfg_t* cp = p->clp->cfg;
unsigned i;
for(i=0; cp!=NULL; cp=cp->next)
if( cp->typeId == kAudioDcmTId )
{
if( i == cfgIdx )
cp->u.a.dfltFl = true;
else
{
if( cp->u.a.dfltFl )
cp->u.a.dfltFl = false;
}
++i;
}
return kOkDcRC;
}
unsigned cmDevCfgAudioGetDefaultCfgIndex( cmDevCfgH_t h )
{
cmDcm_t* p = _cmDcmHandleToPtr(h);
assert( p->clp != NULL );
cmDcmCfg_t* cp = p->clp->cfg;
unsigned i;
for(i=0; cp!=NULL; cp=cp->next)
if( cp->typeId == kAudioDcmTId )
{
if( cp->u.a.dfltFl )
return i;
++i;
}
return cmInvalidIdx;
}
const cmDcmAudio_t* cmDevCfgAudioCfg( cmDevCfgH_t h, unsigned cfgIdx ) const cmDcmAudio_t* cmDevCfgAudioCfg( cmDevCfgH_t h, unsigned cfgIdx )
{ {
cmDcm_t* p = _cmDcmHandleToPtr(h); cmDcm_t* p = _cmDcmHandleToPtr(h);
@ -697,7 +818,7 @@ const cmDcmAudio_t* cmDevCfgAudioDevMap( cmDevCfgH_t h, unsigned usrAppId, un
} }
cmDcRC_t cmDevCfgNetPort( cmDcRC_t cmDevCfgNameNetPort(
cmDevCfgH_t h, cmDevCfgH_t h,
const cmChar_t* dcLabelStr, const cmChar_t* dcLabelStr,
const cmChar_t* sockAddr, const cmChar_t* sockAddr,
@ -716,7 +837,7 @@ cmDcRC_t cmDevCfgNetPort(
// if dcLabelStr is already in use for this location and type then update // if dcLabelStr is already in use for this location and type then update
// the assoc'd recd otherwise create a new one. // the assoc'd recd otherwise create a new one.
if((cp = _cmDcmFindOrCreateCfg(p,kAudioDcmTId, dcLabelStr)) == NULL ) if((cp = _cmDcmFindOrCreateCfg(p,kNetDcmTId, dcLabelStr)) == NULL )
return cmErrLastRC(&p->err); return cmErrLastRC(&p->err);
cp->u.n.sockAddr = cmMemAllocStr(sockAddr); cp->u.n.sockAddr = cmMemAllocStr(sockAddr);
@ -760,11 +881,11 @@ unsigned cmDevCfgLocCount( cmDevCfgH_t h )
} }
const cmChar_t* cmDevCfgLocLabel( cmDevCfgH_t h, unsigned locIdx ) const cmChar_t* cmDevCfgLocLabel( cmDevCfgH_t h, unsigned locIdx )
{ {
unsigned n = 0;
cmDcm_t* p = _cmDcmHandleToPtr(h); cmDcm_t* p = _cmDcmHandleToPtr(h);
const cmDcmLoc_t* lp = p->loc; const cmDcmLoc_t* lp = p->loc;
for(; lp!=NULL; lp=lp->next) unsigned i;
if( n == locIdx ) for(i=0; lp!=NULL; lp=lp->next,++i)
if( i == locIdx )
return lp->labelStr; return lp->labelStr;
assert(0); assert(0);
@ -772,7 +893,7 @@ const cmChar_t* cmDevCfgLocLabel( cmDevCfgH_t h, unsigned locIdx )
} }
cmDcmLoc_t* _cmDcmLocLabelToPtr( cmDcm_t* p, const cmChar_t* locLabelStr) cmDcmLoc_t* _cmDcmLocLabelToPtr( cmDcm_t* p, const cmChar_t* locLabelStr, bool errFl)
{ {
if((locLabelStr = _cmDcmTrimLabel(p,locLabelStr,"location")) == NULL ) if((locLabelStr = _cmDcmTrimLabel(p,locLabelStr,"location")) == NULL )
return NULL; return NULL;
@ -782,7 +903,8 @@ cmDcmLoc_t* _cmDcmLocLabelToPtr( cmDcm_t* p, const cmChar_t* locLabelStr)
if( strcmp(lp->labelStr,locLabelStr) == 0 ) if( strcmp(lp->labelStr,locLabelStr) == 0 )
return lp; return lp;
cmErrMsg(&p->err,kLabelNotFoundDcRC,"The location label '%s' was not found.",locLabelStr); if( errFl )
cmErrMsg(&p->err,kLabelNotFoundDcRC,"The location label '%s' was not found.",locLabelStr);
return NULL; return NULL;
} }
@ -795,7 +917,7 @@ cmDcRC_t cmDevCfgLocStore( cmDevCfgH_t h, const cmChar_t* locLabelStr )
unsigned i,j; unsigned i,j;
// if this location label is already in use then it has already been stored. // if this location label is already in use then it has already been stored.
if( _cmDcmLocLabelToPtr(p,locLabelStr) != NULL ) if( _cmDcmLocLabelToPtr(p,locLabelStr,false) != NULL )
return kOkDcRC; return kOkDcRC;
// store the current loc ptr // store the current loc ptr
@ -812,11 +934,15 @@ cmDcRC_t cmDevCfgLocStore( cmDevCfgH_t h, const cmChar_t* locLabelStr )
{ {
cmDcmCfg_t* ncp; cmDcmCfg_t* ncp;
// this will always create (never find) a new cfg recd
if((ncp = _cmDcmFindOrCreateCfg(p,ocp->typeId, ocp->dcLabelStr)) == NULL ) if((ncp = _cmDcmFindOrCreateCfg(p,ocp->typeId, ocp->dcLabelStr)) == NULL )
{ {
rc = cmErrLastRC(&p->err); rc = cmErrLastRC(&p->err);
goto errLabel; goto errLabel;
} }
// duplicate the desc. string
ncp->descStr = cmMemAllocStr(ocp->descStr);
switch( ncp->typeId ) switch( ncp->typeId )
{ {
@ -869,7 +995,7 @@ cmDcRC_t cmDevCfgLocRecall( cmDevCfgH_t h, const cmChar_t* locLabelStr )
cmDcm_t* p = _cmDcmHandleToPtr(h); cmDcm_t* p = _cmDcmHandleToPtr(h);
cmDcmLoc_t* lp; cmDcmLoc_t* lp;
if((lp = _cmDcmLocLabelToPtr(p,locLabelStr)) == NULL) if((lp = _cmDcmLocLabelToPtr(p,locLabelStr,true)) == NULL)
return cmErrLastRC(&p->err); return cmErrLastRC(&p->err);
p->clp = lp; p->clp = lp;
@ -881,7 +1007,7 @@ cmDcRC_t cmDevCfgLocDelete( cmDevCfgH_t h, const cmChar_t* locLabelStr )
cmDcm_t* p = _cmDcmHandleToPtr(h); cmDcm_t* p = _cmDcmHandleToPtr(h);
cmDcmLoc_t* lp; cmDcmLoc_t* lp;
if((lp = _cmDcmLocLabelToPtr(p,locLabelStr)) == NULL ) if((lp = _cmDcmLocLabelToPtr(p,locLabelStr,true)) == NULL )
return cmErrLastRC(&p->err); return cmErrLastRC(&p->err);
_cmDcmFreeLoc(p,lp); _cmDcmFreeLoc(p,lp);
@ -908,14 +1034,14 @@ cmDcRC_t _cmDcmJsonNotFound( cmDcm_t* p, const cmChar_t* tagStr )
cmDcRC_t _cmDcmJsonSyntaxErr( cmDcm_t* p, const cmChar_t* tagStr ) cmDcRC_t _cmDcmJsonSyntaxErr( cmDcm_t* p, const cmChar_t* tagStr )
{ return cmErrMsg(&p->err,kJsonFailDcRC,"JSON syntax error '%s' not found.",tagStr); } { return cmErrMsg(&p->err,kJsonFailDcRC,"JSON syntax error '%s' not found.",tagStr); }
cmDcRC_t _cmDevCfgRead( cmDevCfgH_t h, cmJsonH_t jsH, const cmJsonNode_t* rootObjPtr ) cmDcRC_t _cmDevCfgRead( cmDcm_t* p, cmJsonH_t jsH, const cmJsonNode_t* rootObjPtr )
{ {
cmDcRC_t rc = kOkDcRC; cmDcRC_t rc = kOkDcRC;
const cmChar_t* errLabelPtr = NULL; const cmChar_t* errLabelPtr = NULL;
cmJsonNode_t* cfgNp, *locArrNp; cmJsonNode_t* cfgNp, *locArrNp;
unsigned i,j; unsigned i,j;
cmDevCfgH_t h;
cmDcm_t* p = _cmDcmHandleToPtr(h); h.h = p;
// clear the all locations // clear the all locations
_cmDcmFreeAllLocs(p); _cmDcmFreeAllLocs(p);
@ -931,7 +1057,7 @@ cmDcRC_t _cmDevCfgRead( cmDevCfgH_t h, cmJsonH_t jsH, const cmJsonNode_t* rootOb
for(i=0; i<cmJsonChildCount(locArrNp); ++i) for(i=0; i<cmJsonChildCount(locArrNp); ++i)
{ {
cmJsonNode_t* locObjNp, *cfgArrNp; cmJsonNode_t* locObjNp, *cfgArrNp;
const cmChar_t* label = NULL; const cmChar_t* locLabelStr = NULL;
// get the loc object // get the loc object
if((locObjNp = cmJsonArrayElement(locArrNp,i)) == NULL || cmJsonIsObject(locObjNp)==false ) if((locObjNp = cmJsonArrayElement(locArrNp,i)) == NULL || cmJsonIsObject(locObjNp)==false )
@ -939,15 +1065,15 @@ cmDcRC_t _cmDevCfgRead( cmDevCfgH_t h, cmJsonH_t jsH, const cmJsonNode_t* rootOb
// read the loc object fields // read the loc object fields
if( cmJsonMemberValues(locObjNp, &errLabelPtr, if( cmJsonMemberValues(locObjNp, &errLabelPtr,
"label", kStringTId, &label, "label", kStringTId, &locLabelStr,
"cfg", kArrayTId, &cfgArrNp, "cfg", kArrayTId, &cfgArrNp,
NULL ) == kOkJsRC ) NULL ) != kOkJsRC )
{ return _cmDcmJsonNotFound(p,errLabelPtr); } { return _cmDcmJsonNotFound(p,errLabelPtr); }
// create a new location recd // create a new location recd
cmDcmLoc_t* locPtr = NULL; cmDcmLoc_t* locPtr = NULL;
if((rc = _cmDcmNewLoc(p,label,&locPtr)) == kOkDcRC ) if((rc = _cmDcmNewLoc(p,locLabelStr,&locPtr)) != kOkDcRC )
return cmErrMsg(&p->err,kJsonFailDcRC,"Location '%s' create failed.",cmStringNullGuard(label)); return cmErrMsg(&p->err,kJsonFailDcRC,"Location '%s' create failed.",cmStringNullGuard(locLabelStr));
/* /*
// read each app object // read each app object
@ -998,23 +1124,28 @@ cmDcRC_t _cmDevCfgRead( cmDevCfgH_t h, cmJsonH_t jsH, const cmJsonNode_t* rootOb
"cfgId", kIntTId, &cfgId, "cfgId", kIntTId, &cfgId,
"typeId", kIntTId, &typeId, "typeId", kIntTId, &typeId,
"desc", kStringTId, &descStr, "desc", kStringTId, &descStr,
NULL ) == kOkJsRC ) NULL ) != kOkJsRC )
{ _cmDcmJsonSyntaxErr(p,errLabelPtr); } { _cmDcmJsonSyntaxErr(p,errLabelPtr); }
cmDcmMidi_t m; cmDcmMidi_t m;
cmDcmAudio_t a; cmDcmAudio_t a;
cmDcmNet_t n; cmDcmNet_t n;
switch( typeId ) switch( typeId )
{ {
case kMidiDcmTId: case kMidiDcmTId:
if( cmJsonMemberValues( cfgObjNp, &errLabelPtr, if( cmJsonMemberValues( cfgObjNp, &errLabelPtr,
"devLabelStr", kStringTId, &m.devLabelStr, "devLabelStr", kStringTId, &m.devLabelStr,
"portLabelStr",kStringTId, &m.portLabelStr, "portLabelStr",kStringTId, &m.portLabelStr,
"inputFl", kBoolTId, &m.inputFl,
NULL) != kOkJsRC ) NULL) != kOkJsRC )
{} {
rc = _cmDcmJsonSyntaxErr(p,errLabelPtr);
goto errLabel;
}
cmDevCfgNameMidiPort(h,label,m.devLabelStr,m.portLabelStr,m.inputFl); if((rc = cmDevCfgNameMidiPort(h,dcLabelStr,m.devLabelStr,m.portLabelStr,m.inputFl)) != kOkDcRC )
goto errLabel;
break; break;
@ -1027,16 +1158,23 @@ cmDcRC_t _cmDevCfgRead( cmDevCfgH_t h, cmJsonH_t jsH, const cmJsonNode_t* rootOb
"devFramesPerCycle", kIntTId, &a.audioSysArgs.devFramesPerCycle, "devFramesPerCycle", kIntTId, &a.audioSysArgs.devFramesPerCycle,
"dspFramesPerCycle", kIntTId, &a.audioSysArgs.dspFramesPerCycle, "dspFramesPerCycle", kIntTId, &a.audioSysArgs.dspFramesPerCycle,
"audioBufCnt", kIntTId, &a.audioSysArgs.audioBufCnt, "audioBufCnt", kIntTId, &a.audioSysArgs.audioBufCnt,
"srate", kIntTId, &a.audioSysArgs.srate ) == kOkJsRC ) "srate", kRealTId, &a.audioSysArgs.srate,
{} NULL ) != kOkJsRC )
{
rc = _cmDcmJsonSyntaxErr(p,errLabelPtr);
goto errLabel;
}
cmDevCfgNameAudioPort(h,label,a.inDevLabelStr,a.outDevLabelStr, if((rc = cmDevCfgNameAudioPort(h,dcLabelStr,a.inDevLabelStr,a.outDevLabelStr,
a.audioSysArgs.syncInputFl, a.audioSysArgs.syncInputFl,
a.audioSysArgs.msgQueueByteCnt, a.audioSysArgs.msgQueueByteCnt,
a.audioSysArgs.devFramesPerCycle, a.audioSysArgs.devFramesPerCycle,
a.audioSysArgs.dspFramesPerCycle, a.audioSysArgs.dspFramesPerCycle,
a.audioSysArgs.audioBufCnt, a.audioSysArgs.audioBufCnt,
a.audioSysArgs.srate ); a.audioSysArgs.srate )) != kOkDcRC )
{
goto errLabel;
}
break; break;
@ -1045,9 +1183,13 @@ cmDcRC_t _cmDevCfgRead( cmDevCfgH_t h, cmJsonH_t jsH, const cmJsonNode_t* rootOb
"sockAddr", kStringTId, &n.sockAddr, "sockAddr", kStringTId, &n.sockAddr,
"portNumber", kIntTId, &n.portNumber, "portNumber", kIntTId, &n.portNumber,
NULL ) != kOkJsRC ) NULL ) != kOkJsRC )
{} {
rc = _cmDcmJsonSyntaxErr(p,errLabelPtr);
goto errLabel;
}
cmDevCfgNetPort(h,label,n.sockAddr,n.portNumber); if((rc = cmDevCfgNameNetPort(h,dcLabelStr,n.sockAddr,n.portNumber)) != kOkDcRC )
goto errLabel;
break; break;
@ -1058,13 +1200,14 @@ cmDcRC_t _cmDevCfgRead( cmDevCfgH_t h, cmJsonH_t jsH, const cmJsonNode_t* rootOb
} }
} }
errLabel:
return kOkDcRC; return kOkDcRC;
} }
cmDcRC_t _cmDevCfgWrite( cmDcm_t* p, cmJsonH_t jsH, cmJsonNode_t* rootObjPtr ) cmDcRC_t _cmDevCfgWrite( cmDcm_t* p, cmJsonH_t jsH, cmJsonNode_t* rootObjPtr )
{ {
cmDcRC_t rc = kOkDcRC; cmDcRC_t rc = kOkDcRC;
const cmDcmLoc_t* lp; const cmDcmLoc_t* lp = p->loc;
cmJsonNode_t* cfgNp = cmJsonInsertPairObject(jsH, rootObjPtr, "cfg" ); cmJsonNode_t* cfgNp = cmJsonInsertPairObject(jsH, rootObjPtr, "cfg" );
@ -1077,7 +1220,7 @@ cmDcRC_t _cmDevCfgWrite( cmDcm_t* p, cmJsonH_t jsH, cmJsonNode_t* rootObjPtr )
cmJsonNode_t* locObjNp = cmJsonCreateObject(jsH,locArrNp); cmJsonNode_t* locObjNp = cmJsonCreateObject(jsH,locArrNp);
// set the loc label // set the loc label
cmJsonInsertPairString(jsH, locObjNp, lp->labelStr, "label" ); cmJsonInsertPairString(jsH, locObjNp, "label", lp->labelStr );
/* /*
// create the 'loc.app[]' array // create the 'loc.app[]' array
@ -1143,7 +1286,7 @@ cmDcRC_t _cmDevCfgWrite( cmDcm_t* p, cmJsonH_t jsH, cmJsonNode_t* rootObjPtr )
"devFramesPerCycle", kIntTId, cp->u.a.audioSysArgs.devFramesPerCycle, "devFramesPerCycle", kIntTId, cp->u.a.audioSysArgs.devFramesPerCycle,
"dspFramesPerCycle", kIntTId, cp->u.a.audioSysArgs.dspFramesPerCycle, "dspFramesPerCycle", kIntTId, cp->u.a.audioSysArgs.dspFramesPerCycle,
"audioBufCnt", kIntTId, cp->u.a.audioSysArgs.audioBufCnt, "audioBufCnt", kIntTId, cp->u.a.audioSysArgs.audioBufCnt,
"srate", kIntTId, cp->u.a.audioSysArgs.srate, "srate", kRealTId, cp->u.a.audioSysArgs.srate,
NULL ); NULL );
break; break;
@ -1163,8 +1306,49 @@ cmDcRC_t _cmDevCfgWrite( cmDcm_t* p, cmJsonH_t jsH, cmJsonNode_t* rootObjPtr )
return rc; return rc;
} }
cmDcRC_t cmDevCfgWrite( cmDevCfgH_t h ) cmDcRC_t cmDevCfgWrite( cmDevCfgH_t h, const cmChar_t* fn )
{ {
cmDcRC_t rc = kOkDcRC; cmDcRC_t rc = kOkDcRC;
cmDcm_t* p = _cmDcmHandleToPtr(h);
cmJsonH_t jsH = cmJsonNullHandle;
if( fn == NULL )
fn = p->fn;
// validate the filename
if( fn == NULL || strlen(fn)==0 )
return cmErrMsg(&p->err,kInvalidFnDcRC,"No output file name was provided.");
// create a json object
if( cmJsonInitialize( &jsH, p->ctx ) != kOkJsRC )
{
rc = cmErrMsg(&p->err,kJsonFailDcRC,"An empty JSON tree could not be created.");
goto errLabel;
}
// insert a wrapper object as the root
if( cmJsonCreateObject( jsH, NULL ) == NULL )
{
rc = cmErrMsg(&p->err,kJsonFailDcRC,"The JSON root object could not be created.");
goto errLabel;
}
// fill the JSON tree
if((rc = _cmDevCfgWrite(p,jsH,cmJsonRoot(jsH))) != kOkDcRC )
goto errLabel;
// write the output file
if( cmJsonWrite(jsH, cmJsonRoot(jsH), fn ) != kOkJsRC )
{
rc = cmErrMsg(&p->err,kJsonFailDcRC,"The JSON file write failed on '%s'.",cmStringNullGuard(fn));
goto errLabel;
}
errLabel:
if( cmJsonFinalize(&jsH) != kOkJsRC )
cmErrMsg(&p->err,kJsonFailDcRC,"JSON tree finalization failed.");
return rc; return rc;
} }

View File

@ -50,7 +50,8 @@ extern "C" {
kInvalidUserMapIdRC, kInvalidUserMapIdRC,
kInvalidArgDcRC, kInvalidArgDcRC,
kInvalidCfgIdxDcRC, kInvalidCfgIdxDcRC,
kJsonFailDcRC kJsonFailDcRC,
kInvalidFnDcRC
}; };
typedef enum typedef enum
@ -78,6 +79,7 @@ extern "C" {
cmChar_t* inDevLabelStr; // Input audio device label. cmChar_t* inDevLabelStr; // Input audio device label.
cmChar_t* outDevLabelStr; // Output audio device label. cmChar_t* outDevLabelStr; // Output audio device label.
cmAudioSysArgs_t audioSysArgs; // Audio system cfg recd cmAudioSysArgs_t audioSysArgs; // Audio system cfg recd
bool dfltFl; // true if this is the default audio cfg.
} cmDcmAudio_t; } cmDcmAudio_t;
typedef struct typedef struct
@ -88,8 +90,8 @@ extern "C" {
extern cmDevCfgH_t cmDevCfgNullHandle; extern cmDevCfgH_t cmDevCfgNullHandle;
cmDcRC_t cmDevCfgMgrAlloc( cmCtx_t* c, cmDevCfgH_t* hp ); cmDcRC_t cmDevCfgAlloc( cmCtx_t* c, cmDevCfgH_t* hp, const cmChar_t* fn );
cmDcRC_t cmDevCfgMgrFree( cmDevCfgH_t* hp ); cmDcRC_t cmDevCfgFree( cmDevCfgH_t* hp );
bool cmDevCfgIsValid( cmDevCfgH_t h ); bool cmDevCfgIsValid( cmDevCfgH_t h );
// Return the count of cfg records for the given type in the current location. // Return the count of cfg records for the given type in the current location.
@ -139,12 +141,16 @@ extern "C" {
unsigned audioBufCnt, unsigned audioBufCnt,
double srate ); double srate );
cmDcRC_t cmDevCfgAudioSetDefaultCfgIndex( cmDevCfgH_t h, unsigned cfgIdx );
unsigned cmDevCfgAudioGetDefaultCfgIndex( cmDevCfgH_t h );
const cmDcmAudio_t* cmDevCfgAudioCfg( cmDevCfgH_t h, unsigned cfgIdx ); const cmDcmAudio_t* cmDevCfgAudioCfg( cmDevCfgH_t h, unsigned cfgIdx );
const cmDcmAudio_t* cmDevCfgAudioMap( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId ); const cmDcmAudio_t* cmDevCfgAudioMap( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId );
const struct cmAudioSysArgs_str* cmDevCfgAudioSysArgs( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId ); const struct cmAudioSysArgs_str* cmDevCfgAudioSysArgs( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId );
cmDcRC_t cmDevCfgNetPort( cmDcRC_t cmDevCfgNameNetPort(
cmDevCfgH_t h, cmDevCfgH_t h,
const cmChar_t* dcLabelStr, const cmChar_t* dcLabelStr,
const cmChar_t* sockAddr, const cmChar_t* sockAddr,
@ -153,19 +159,31 @@ extern "C" {
const cmDcmNet_t* cmDevCfgNetCfg( cmDevCfgH_t h, unsigned cfgIdx ); const cmDcmNet_t* cmDevCfgNetCfg( cmDevCfgH_t h, unsigned cfgIdx );
const cmDcmNet_t* cmDevCfgNetMap( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId ); const cmDcmNet_t* cmDevCfgNetMap( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId );
//---------------------------------------------------------------------------------------
// Location Management Functions: // Location Management Functions:
// Store and recall groups cfg records. // Store and recall groups of cfg records.
// Return a count of the current number of locations.
unsigned cmDevCfgLocCount( cmDevCfgH_t h ); unsigned cmDevCfgLocCount( cmDevCfgH_t h );
// Given a location index (0 to cmDevCfgLocCount()-1) return the locations label.
const cmChar_t* cmDevCfgLocLabel( cmDevCfgH_t h, unsigned locIdx ); const cmChar_t* cmDevCfgLocLabel( cmDevCfgH_t h, unsigned locIdx );
// If 'locLabelStr' has already been used then this function does nothing and returns.
// otherwise the current location is duplicated and the duplicate is named 'locLabelStr'.
cmDcRC_t cmDevCfgLocStore( cmDevCfgH_t h, const cmChar_t* locLabelStr ); cmDcRC_t cmDevCfgLocStore( cmDevCfgH_t h, const cmChar_t* locLabelStr );
// Make the location named 'locLabelStr' the current location.
cmDcRC_t cmDevCfgLocRecall( cmDevCfgH_t h, const cmChar_t* locLabelStr ); cmDcRC_t cmDevCfgLocRecall( cmDevCfgH_t h, const cmChar_t* locLabelStr );
// Delete the location named by 'locLabelStr'.
cmDcRC_t cmDevCfgLocDelete( cmDevCfgH_t h, const cmChar_t* locLabelStr ); cmDcRC_t cmDevCfgLocDelete( cmDevCfgH_t h, const cmChar_t* locLabelStr );
// Return the current location index // Return the current location index
unsigned cmDevCfgLocCurIndex( cmDevCfgH_t h ); unsigned cmDevCfgLocCurIndex( cmDevCfgH_t h );
cmDcRC_t cmDevCfgWrite( cmDevCfgH_t h ); // Set 'fn' to NULL to use filename from cmDevCfgAlloc()
cmDcRC_t cmDevCfgWrite( cmDevCfgH_t h, const cmChar_t* fn );
#ifdef __cplusplus #ifdef __cplusplus