2013-03-25 22:59:49 +00:00
# include "cmGlobal.h"
2013-03-26 19:38:08 +00:00
# include "cmFloatTypes.h"
2013-03-25 22:59:49 +00:00
# include "cmRpt.h"
# include "cmErr.h"
# include "cmCtx.h"
# include "cmMem.h"
# include "cmMallocDebug.h"
2013-03-27 16:56:51 +00:00
# include "cmLinkedHeap.h"
2013-03-29 06:15:09 +00:00
# include "cmFileSys.h"
2013-03-25 22:59:49 +00:00
# include "cmJson.h"
2013-03-27 16:56:51 +00:00
# include "cmText.h"
2013-03-26 19:38:08 +00:00
# include "cmThread.h"
2013-03-25 22:59:49 +00:00
# include "cmMidi.h"
# include "cmMidiPort.h"
2013-03-26 19:38:08 +00:00
# include "cmAudioPort.h"
# include "cmUdpPort.h"
# include "cmUdpNet.h"
# include "cmAudioSysMsg.h"
# include "cmAudioSys.h"
2013-03-25 22:59:49 +00:00
# include "cmDevCfg.h"
cmDevCfgH_t cmDevCfgNullHandle = cmSTATIC_NULL_HANDLE ;
2013-03-27 16:56:51 +00:00
typedef struct cmDcmCfg_str
2013-03-25 22:59:49 +00:00
{
2013-03-29 06:15:09 +00:00
cmChar_t * dcLabelStr ; // the cfg label
2013-03-27 16:56:51 +00:00
unsigned cfgId ; // unique among all cfg's assigned to a loc
2013-03-29 06:15:09 +00:00
cmTypeDcmId_t typeId ; // the cfg type id (e.g. midi, audio, net, ...)
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().
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
union
{
cmDcmMidi_t m ;
cmDcmAudio_t a ;
cmDcmNet_t n ;
} u ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
struct cmDcmCfg_str * next ;
struct cmDcmCfg_str * prev ;
} cmDcmCfg_t ;
2013-03-25 22:59:49 +00:00
typedef struct
{
cmTypeDcmId_t tid ; // Type Id for this map or tInvalidDcmTId if the record is not active.
2013-03-27 16:56:51 +00:00
unsigned cfgId ; // cfgId of the cfg recd assoc'd with this map
cmDcmCfg_t * cfg ; // pointer to the cfg recd assoc'd with this map (cfg->cfgId == cmDcmMap_t.cfgId)
2013-03-25 22:59:49 +00:00
} cmDcmMap_t ;
typedef struct
{
bool activeFl ;
cmDcmMap_t * map ;
unsigned mapCnt ;
} cmDcmApp_t ;
2013-03-27 16:56:51 +00:00
typedef struct cmDcmLoc_str
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
cmChar_t * labelStr ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
cmDcmApp_t * app ;
unsigned appCnt ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
cmDcmCfg_t * cfg ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
struct cmDcmLoc_str * next ;
struct cmDcmLoc_str * prev ;
2013-03-26 19:38:08 +00:00
} cmDcmLoc_t ;
typedef struct
{
2013-03-27 16:56:51 +00:00
cmErr_t err ;
2013-03-29 06:15:09 +00:00
cmCtx_t * ctx ;
2013-03-27 16:56:51 +00:00
cmDcmLoc_t * loc ;
cmDcmLoc_t * clp ;
2013-03-29 06:15:09 +00:00
cmChar_t * fn ;
2013-03-25 22:59:49 +00:00
} cmDcm_t ;
2013-03-27 16:56:51 +00:00
2013-03-25 22:59:49 +00:00
cmDcm_t * _cmDcmHandleToPtr ( cmDevCfgH_t h )
{
cmDcm_t * p = ( cmDcm_t * ) h . h ;
assert ( p ! = NULL ) ;
return p ;
}
2013-03-27 16:56:51 +00:00
const cmChar_t * _cmDcmTrimLabel ( cmDcm_t * p , const cmChar_t * s , const cmChar_t * title )
2013-03-26 19:38:08 +00:00
{
2013-03-27 16:56:51 +00:00
if ( s = = NULL )
2013-03-26 19:38:08 +00:00
{
2013-03-27 16:56:51 +00:00
cmErrMsg ( & p - > err , kBlankLabelDcRC , " A blank '%s' label was encountered. " , title ) ;
return NULL ;
2013-03-26 19:38:08 +00:00
}
2013-03-27 16:56:51 +00:00
while ( * s & & isspace ( * s ) )
+ + s ;
if ( strlen ( s ) = = 0 )
2013-03-26 19:38:08 +00:00
{
2013-03-27 16:56:51 +00:00
cmErrMsg ( & p - > err , kBlankLabelDcRC , " An empty '%s' label was encountered. " , title ) ;
return NULL ;
2013-03-26 19:38:08 +00:00
}
2013-03-27 16:56:51 +00:00
return s ;
2013-03-26 19:38:08 +00:00
}
2013-03-27 16:56:51 +00:00
void _cmDcmFreeMidi ( cmDcmMidi_t * r )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
cmMemFree ( r - > devLabelStr ) ;
cmMemFree ( r - > portLabelStr ) ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
void _cmDcmDuplMidi ( cmDcmMidi_t * d , const cmDcmMidi_t * s )
2013-03-26 19:38:08 +00:00
{
d - > devLabelStr = cmMemAllocStr ( s - > devLabelStr ) ;
d - > portLabelStr = cmMemAllocStr ( s - > portLabelStr ) ;
d - > inputFl = s - > inputFl ;
d - > devIdx = s - > devIdx ;
d - > portIdx = s - > portIdx ;
}
2013-03-27 16:56:51 +00:00
void _cmDcmFreeAudio ( cmDcmAudio_t * r )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
cmMemFree ( r - > inDevLabelStr ) ;
cmMemFree ( r - > outDevLabelStr ) ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
void _cmDcmDuplAudio ( cmDcmAudio_t * d , const cmDcmAudio_t * s )
2013-03-26 19:38:08 +00:00
{
2013-03-27 16:56:51 +00:00
d - > inDevLabelStr = cmMemAllocStr ( s - > inDevLabelStr ) ;
2013-03-26 19:38:08 +00:00
d - > outDevLabelStr = cmMemAllocStr ( s - > outDevLabelStr ) ;
2013-03-27 16:56:51 +00:00
d - > audioSysArgs = s - > audioSysArgs ;
2013-03-26 19:38:08 +00:00
}
2013-03-27 16:56:51 +00:00
void _cmDcmFreeNet ( cmDcmNet_t * r )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
cmMemFree ( r - > sockAddr ) ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
void _cmDcmDuplNet ( cmDcmNet_t * d , const cmDcmNet_t * s )
2013-03-26 19:38:08 +00:00
{
d - > sockAddr = cmMemAllocStr ( s - > sockAddr ) ;
d - > portNumber = s - > portNumber ;
2013-03-25 22:59:49 +00:00
}
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
void _cmDcmFreeCfg ( cmDcm_t * p , cmDcmLoc_t * lp , cmDcmCfg_t * cp )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
// unlink the cfg recd
if ( cp - > prev = = NULL )
lp - > cfg = cp - > next ;
else
cp - > prev - > next = cp - > next ;
if ( cp - > next ! = NULL )
cp - > next - > prev = cp - > prev ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
cmMemFree ( cp - > dcLabelStr ) ;
cmMemFree ( cp - > descStr ) ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
switch ( cp - > typeId )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
case kMidiDcmTId : _cmDcmFreeMidi ( & cp - > u . m ) ; break ;
case kAudioDcmTId : _cmDcmFreeAudio ( & cp - > u . a ) ; break ;
case kNetDcmTId : _cmDcmFreeNet ( & cp - > u . n ) ; break ;
default :
assert ( 0 ) ;
break ;
2013-03-25 22:59:49 +00:00
}
2013-03-29 06:15:09 +00:00
cmMemFree ( cp ) ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
void _cmDcmFreeLoc ( cmDcm_t * p , cmDcmLoc_t * lp )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
unsigned i ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
// unlink the loc recd
if ( lp - > prev = = NULL )
p - > loc = lp - > next ;
2013-03-25 22:59:49 +00:00
else
2013-03-27 16:56:51 +00:00
lp - > prev - > next = lp - > next ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
if ( lp - > next ! = NULL )
lp - > next - > prev = lp - > prev ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
// free each app
for ( i = 0 ; i < lp - > appCnt ; + + i )
cmMemFree ( lp - > app [ i ] . map ) ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
cmMemFree ( lp - > app ) ;
cmMemFree ( lp - > labelStr ) ;
while ( lp - > cfg ! = NULL )
_cmDcmFreeCfg ( p , lp , lp - > cfg ) ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
cmMemFree ( lp ) ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
void _cmDcmFreeAllLocs ( cmDcm_t * p )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
while ( p - > loc ! = NULL )
_cmDcmFreeLoc ( p , p - > loc ) ;
p - > clp = NULL ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
cmDcRC_t _cmDcmFree ( cmDcm_t * p )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
cmDcRC_t rc = kOkDcRC ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
_cmDcmFreeAllLocs ( p ) ;
2013-03-29 06:15:09 +00:00
cmMemFree ( p - > fn ) ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
cmMemFree ( p ) ;
return rc ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
cmDcmLoc_t * _cmDcmFindLoc ( cmDcm_t * p , const cmChar_t * labelStr )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
cmDcmLoc_t * lp = p - > loc ;
for ( ; lp ! = NULL ; lp = lp - > next )
if ( strcmp ( lp - > labelStr , labelStr ) = = 0 )
return lp ;
return NULL ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
cmDcRC_t _cmDcmNewLoc ( cmDcm_t * p , const cmChar_t * labelStr , cmDcmLoc_t * * locRef )
2013-03-26 19:38:08 +00:00
{
2013-03-27 16:56:51 +00:00
cmDcmLoc_t * lp ;
assert ( locRef ! = NULL ) ;
* locRef = NULL ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
// verify and condition the label
if ( ( labelStr = _cmDcmTrimLabel ( p , labelStr , " location " ) ) = = NULL )
return cmErrLastRC ( & p - > err ) ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
// verify that the label is not already in use
if ( ( lp = _cmDcmFindLoc ( p , labelStr ) ) ! = NULL )
return cmErrMsg ( & p - > err , kDuplLabelDcRC , " The location label '%s' is already in use. " , labelStr ) ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
// create a new loc recd
lp = cmMemAllocZ ( cmDcmLoc_t , 1 ) ;
lp - > labelStr = cmMemAllocStr ( labelStr ) ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
// if the cur loc is not current set - then prepend loc
if ( p - > clp = = NULL )
{
lp - > prev = NULL ;
lp - > next = p - > loc ;
if ( p - > loc = = NULL )
p - > loc = lp ;
else
p - > loc - > prev = lp ;
2013-03-26 19:38:08 +00:00
}
2013-03-27 16:56:51 +00:00
else // otherwise insert loc after the cur loc
2013-03-26 19:38:08 +00:00
{
2013-03-27 16:56:51 +00:00
lp - > prev = p - > clp ;
lp - > next = p - > clp - > next ;
if ( p - > clp - > next ! = NULL )
p - > clp - > next - > prev = lp ;
p - > clp - > next = lp ;
2013-03-26 19:38:08 +00:00
}
2013-03-27 16:56:51 +00:00
// make the new loc the current loc
p - > clp = lp ;
* locRef = lp ;
2013-03-26 19:38:08 +00:00
return kOkDcRC ;
2013-03-27 16:56:51 +00:00
2013-03-26 19:38:08 +00:00
}
2013-03-29 06:15:09 +00:00
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 )
2013-03-25 22:59:49 +00:00
{
cmDcRC_t rc ;
2013-03-27 16:56:51 +00:00
cmDcmLoc_t * lp ;
2013-03-29 06:15:09 +00:00
if ( ( rc = cmDevCfgFree ( hp ) ) ! = kOkDcRC )
2013-03-25 22:59:49 +00:00
return rc ;
cmDcm_t * p = cmMemAllocZ ( cmDcm_t , 1 ) ;
2013-03-27 16:56:51 +00:00
cmErrSetup ( & p - > err , & c - > rpt , " cmDevCfg " ) ;
2013-03-29 06:15:09 +00:00
p - > ctx = c ;
2013-03-27 16:56:51 +00:00
2013-03-29 06:15:09 +00:00
if ( fn ! = NULL )
{
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 ;
}
2013-03-25 22:59:49 +00:00
hp - > h = p ;
2013-03-27 16:56:51 +00:00
errLabel :
2013-03-25 22:59:49 +00:00
if ( rc ! = kOkDcRC )
_cmDcmFree ( p ) ;
return rc ;
}
2013-03-29 06:15:09 +00:00
cmDcRC_t cmDevCfgFree ( cmDevCfgH_t * hp )
2013-03-25 22:59:49 +00:00
{
cmDcRC_t rc = kOkDcRC ;
2013-03-27 16:56:51 +00:00
if ( hp = = NULL | | cmDevCfgIsValid ( * hp ) = = false )
2013-03-25 22:59:49 +00:00
return rc ;
cmDcm_t * p = _cmDcmHandleToPtr ( * hp ) ;
if ( ( rc = _cmDcmFree ( p ) ) ! = kOkDcRC )
return rc ;
hp - > h = NULL ;
return rc ;
}
2013-03-27 16:56:51 +00:00
bool cmDevCfgIsValid ( cmDevCfgH_t h )
2013-03-25 22:59:49 +00:00
{ return h . h ! = NULL ; }
2013-03-26 19:38:08 +00:00
unsigned cmDevCfgCount ( cmDevCfgH_t h , cmTypeDcmId_t typeId )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
unsigned n = 0 ;
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
assert ( p - > clp ! = NULL ) ;
const cmDcmCfg_t * cp = p - > clp - > cfg ;
for ( ; cp ! = NULL ; cp = cp - > next )
if ( cp - > typeId = = typeId )
+ + n ;
2013-03-25 22:59:49 +00:00
2013-03-26 19:38:08 +00:00
return n ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
cmDcmCfg_t * _cmDevCfgIndexToPtr ( cmDcm_t * p , cmTypeDcmId_t typeId , unsigned index , bool errFl )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
unsigned n = 0 ;
assert ( p - > clp ! = NULL ) ;
cmDcmCfg_t * cp = p - > clp - > cfg ;
for ( ; cp ! = NULL ; cp = cp - > next )
if ( cp - > typeId = = typeId )
{
if ( n = = index )
return cp ;
+ + n ;
}
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
if ( errFl )
cmErrMsg ( & p - > err , kInvalidCfgIdxDcRC , " The cfg index %i is not valid in location '%s'. " , cmStringNullGuard ( p - > clp - > labelStr ) ) ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
return NULL ;
}
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
const cmChar_t * cmDevCfgLabel ( cmDevCfgH_t h , cmTypeDcmId_t typeId , unsigned index )
{
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
cmDcmCfg_t * cp ;
if ( ( cp = _cmDevCfgIndexToPtr ( p , typeId , index , false ) ) = = NULL )
return NULL ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
return cp - > dcLabelStr ;
}
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
const cmChar_t * cmDevCfgDesc ( cmDevCfgH_t h , cmTypeDcmId_t typeId , unsigned index )
{
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
cmDcmCfg_t * cp ;
if ( ( cp = _cmDevCfgIndexToPtr ( p , typeId , index , false ) ) = = NULL )
2013-03-26 19:38:08 +00:00
return NULL ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
return cp - > descStr ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
cmDcmCfg_t * _cmDcmCfgLabelToPtr ( cmDcm_t * p , cmTypeDcmId_t typeId , const cmChar_t * label , bool errFl )
2013-03-26 19:38:08 +00:00
{
2013-03-27 16:56:51 +00:00
assert ( p - > clp ! = NULL ) ;
cmDcmCfg_t * cp = p - > clp - > cfg ;
for ( ; cp ! = NULL ; cp = cp - > next )
if ( cp - > typeId = = typeId )
{
if ( strcmp ( cp - > dcLabelStr , label ) = = 0 )
return cp ;
}
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
if ( errFl )
cmErrMsg ( & p - > err , kLabelNotFoundDcRC , " The cfg label '%s' was not found. " , cmStringNullGuard ( label ) ) ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
return NULL ;
2013-03-26 19:38:08 +00:00
}
2013-03-27 16:56:51 +00:00
unsigned cmDevCfgLabelToIndex ( cmDevCfgH_t h , cmTypeDcmId_t typeId , const cmChar_t * label )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
unsigned n = 0 ;
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
assert ( p - > clp ! = NULL ) ;
const cmDcmCfg_t * cp = p - > clp - > cfg ;
for ( ; cp ! = NULL ; cp = cp - > next )
if ( cp - > typeId = = typeId )
{
if ( strcmp ( cp - > dcLabelStr , label ) = = 0 )
break ;
+ + n ;
}
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
return n ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
cmDcmCfg_t * _cmDcmFindOrCreateCfg ( cmDcm_t * p , cmTypeDcmId_t typeId , const cmChar_t * dcLabelStr )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
assert ( p - > clp ! = NULL ) ;
cmDcmCfg_t * cp ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
// validate the label
if ( ( dcLabelStr = _cmDcmTrimLabel ( p , dcLabelStr , " cfg " ) ) = = NULL )
return NULL ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
// if the cfg recd already exists then return it
if ( ( cp = _cmDcmCfgLabelToPtr ( p , typeId , dcLabelStr , false ) ) ! = NULL )
return cp ;
unsigned newCfgId = 0 ;
// use ep to track the end of the list
cmDcmCfg_t * ep = NULL ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
// find the max cfgId used by this loc
cp = p - > clp - > cfg ;
for ( ; cp ! = NULL ; cp = cp - > next )
{
if ( cp - > cfgId > newCfgId )
newCfgId = cp - > cfgId ;
ep = cp ;
}
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
// add one to the max cfgId to create a unique cfgId
newCfgId + = 1 ;
// allocate a new cfg recd
cp = cmMemAllocZ ( cmDcmCfg_t , 1 ) ;
cp - > dcLabelStr = cmMemAllocStr ( dcLabelStr ) ;
cp - > cfgId = newCfgId ;
cp - > typeId = typeId ;
2013-03-29 06:15:09 +00:00
2013-03-27 16:56:51 +00:00
// link to the end of the loc's cfg list
if ( ep = = NULL )
p - > clp - > cfg = cp ;
else
{
ep - > next = cp ;
cp - > prev = ep ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
return cp ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
void _cmDcmDisconnectMap ( cmDcmMap_t * mp )
{
mp - > tid = kInvalidDcmTId ;
mp - > cfgId = cmInvalidId ;
mp - > cfg = NULL ;
}
cmDcRC_t cmDevCfgDeleteCfg ( cmDevCfgH_t h , cmTypeDcmId_t typeId , const cmChar_t * dcLabelStr )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
cmDcmCfg_t * cp ;
2013-03-25 22:59:49 +00:00
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
2013-03-27 16:56:51 +00:00
unsigned i , j ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
// locate the cfg to delete
if ( ( cp = _cmDcmCfgLabelToPtr ( p , typeId , dcLabelStr , true ) ) = = NULL )
return cmErrLastRC ( & p - > err ) ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
// for every app in the current location ...
for ( i = 0 ; i < p - > clp - > appCnt ; + + i )
{
cmDcmApp_t * ap = p - > clp - > app + i ;
// ... disconnect any maps to this cfg
if ( ap - > activeFl & & ap - > map ! = NULL )
for ( j = 0 ; j < ap - > mapCnt ; + + j )
if ( ap - > map [ j ] . cfgId = = cp - > cfgId )
_cmDcmDisconnectMap ( ap - > map + j ) ;
}
// unlink and release the cfg recd
_cmDcmFreeCfg ( p , p - > clp , cp ) ;
return kOkDcRC ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
cmDcRC_t cmDevCfgCreateMap ( cmDevCfgH_t h , cmTypeDcmId_t typeId , const cmChar_t * dcLabelStr , unsigned usrAppId , unsigned usrMapId )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
cmDcRC_t rc = kOkDcRC ;
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
cmDcmCfg_t * cp ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
// locate the cfg to map to
if ( ( cp = _cmDcmCfgLabelToPtr ( p , typeId , dcLabelStr , true ) ) = = NULL )
return cmErrLastRC ( & p - > err ) ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
// if usrAppId references a new app
if ( usrAppId > = p - > clp - > appCnt )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
p - > clp - > appCnt = usrAppId + 1 ;
p - > clp - > app = cmMemResizePZ ( cmDcmApp_t , p - > clp - > app , p - > clp - > appCnt ) ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
cmDcmApp_t * ap = p - > clp - > app + usrAppId ;
// if usrMapId ref's a new map
if ( usrMapId > = ap - > mapCnt )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
ap - > mapCnt = usrMapId + 1 ;
ap - > map = cmMemResizePZ ( cmDcmMap_t , ap - > map , ap - > mapCnt ) ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
cmDcmMap_t * mp = ap - > map + usrMapId ;
mp - > tid = typeId ;
mp - > cfgId = cp - > cfgId ;
mp - > cfg = cp ;
return rc ;
}
cmDcmMap_t * _cmDcmFindMap ( cmDcm_t * p , cmTypeDcmId_t typeId , unsigned usrAppId , unsigned usrMapId , bool activeFl )
{
if ( usrAppId > = p - > clp - > appCnt )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
cmErrMsg ( & p - > err , kInvalidUserAppIdRC , " The user app. id %i is out of range %i in location '%s'. " , usrAppId , p - > clp - > appCnt , cmStringNullGuard ( p - > clp - > labelStr ) ) ;
2013-03-25 22:59:49 +00:00
goto errLabel ;
}
2013-03-27 16:56:51 +00:00
cmDcmApp_t * ap = p - > clp - > app + usrAppId ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
if ( usrMapId > = ap - > mapCnt )
{
cmErrMsg ( & p - > err , kInvalidUserMapIdRC , " The user map id %i is out of range %i in location '%s'. " , usrMapId , ap - > mapCnt , cmStringNullGuard ( p - > clp - > labelStr ) ) ;
goto errLabel ;
}
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
if ( activeFl & & ( ap - > map [ usrMapId ] . tid = = kInvalidDcmTId | | ap - > map [ usrMapId ] . cfg = = NULL ) )
{
cmErrMsg ( & p - > err , kInvalidUserMapIdRC , " The user map id %i inactive in location '%s'. " , usrMapId , cmStringNullGuard ( p - > clp - > labelStr ) ) ;
goto errLabel ;
}
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
return ap - > map + usrMapId ;
errLabel :
return NULL ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
cmDcRC_t cmDevCfgDeleteMap ( cmDevCfgH_t h , cmTypeDcmId_t typeId , unsigned usrAppId , unsigned usrMapId )
{
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
cmDcmMap_t * mp ;
if ( ( mp = _cmDcmFindMap ( p , typeId , usrAppId , usrMapId , false ) ) = = NULL )
return cmErrLastRC ( & p - > err ) ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
_cmDcmDisconnectMap ( mp ) ;
return kOkDcRC ;
}
cmDcRC_t cmDevCfgNameMidiPort (
cmDevCfgH_t h ,
const cmChar_t * dcLabelStr ,
const cmChar_t * devLabelStr ,
const cmChar_t * portLabelStr ,
bool inputFl )
2013-03-25 22:59:49 +00:00
{
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
2013-03-27 16:56:51 +00:00
cmDcmCfg_t * cp ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
unsigned midiDevIdx ;
unsigned midiPortIdx ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
// validate the label
if ( ( dcLabelStr = _cmDcmTrimLabel ( p , dcLabelStr , " MIDI cfg " ) ) = = NULL )
return cmErrLastRC ( & p - > err ) ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
// verify that the device label is valid
if ( ( midiDevIdx = cmMpDeviceNameToIndex ( devLabelStr ) ) = = cmInvalidIdx )
return cmErrMsg ( & p - > err , kInvalidArgDcRC , " The MIDI device name '%s' is not valid. " , devLabelStr ) ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
// verify that the port label is valid
if ( ( midiPortIdx = cmMpDevicePortNameToIndex ( midiDevIdx , inputFl ? kInMpFl : kOutMpFl , portLabelStr ) ) = = cmInvalidIdx )
return cmErrMsg ( & p - > err , kInvalidArgDcRC , " The MIDI port name '%s' is not valid on the device '%s'. " , portLabelStr , devLabelStr ) ;
// if dcLabelStr is already in use for this location and type then update
// the assoc'd recd otherwise create a new one.
if ( ( cp = _cmDcmFindOrCreateCfg ( p , kMidiDcmTId , dcLabelStr ) ) = = NULL )
return cmErrLastRC ( & p - > err ) ;
cp - > u . m . devLabelStr = cmMemResizeStr ( cp - > u . m . devLabelStr , devLabelStr ) ;
cp - > u . m . portLabelStr = cmMemResizeStr ( cp - > u . m . portLabelStr , portLabelStr ) ;
cp - > u . m . inputFl = inputFl ;
cp - > u . m . devIdx = midiDevIdx ;
cp - > u . m . portIdx = midiPortIdx ;
cp - > descStr = cmTsPrintfP ( cp - > descStr , " %s %s %s " , inputFl ? " Input " : " Output " , devLabelStr , portLabelStr ) ;
return kOkDcRC ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
const cmDcmMidi_t * cmDevCfgMidiCfg ( cmDevCfgH_t h , unsigned cfgIdx )
{
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
cmDcmCfg_t * cp ;
if ( ( cp = _cmDevCfgIndexToPtr ( p , kMidiDcmTId , cfgIdx , true ) ) = = NULL )
return NULL ;
return & cp - > u . m ;
}
const cmDcmMidi_t * cmDevCfgMidiDevMap ( cmDevCfgH_t h , unsigned usrAppId , unsigned usrMapId )
{
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
cmDcmMap_t * mp ;
if ( ( mp = _cmDcmFindMap ( p , kMidiDcmTId , usrAppId , usrMapId , true ) ) = = NULL )
return NULL ;
return & mp - > cfg - > u . m ;
}
2013-03-25 22:59:49 +00:00
cmDcRC_t cmDevCfgNameAudioPort (
cmDevCfgH_t h ,
const cmChar_t * dcLabelStr ,
const cmChar_t * inDevNameStr ,
const cmChar_t * outDevNameStr ,
bool syncInputFl ,
unsigned msgQueueByteCnt ,
unsigned devFramesPerCycle ,
unsigned dspFramesPerCycle ,
unsigned audioBufCnt ,
double srate )
{
2013-03-27 16:56:51 +00:00
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
cmDcmCfg_t * cp ;
unsigned inDevIdx ;
unsigned outDevIdx ;
// validate the label
2013-03-29 06:15:09 +00:00
if ( ( dcLabelStr = _cmDcmTrimLabel ( p , dcLabelStr , " Audio cfg " ) ) = = NULL )
2013-03-27 16:56:51 +00:00
return cmErrLastRC ( & p - > err ) ;
// validate the input device
if ( ( inDevIdx = cmApDeviceLabelToIndex ( inDevNameStr ) ) = = cmInvalidIdx )
return cmErrMsg ( & p - > err , kInvalidArgDcRC , " The input audio device name '%s' is not valid. " , cmStringNullGuard ( inDevNameStr ) ) ;
// validate the output device
if ( ( outDevIdx = cmApDeviceLabelToIndex ( outDevNameStr ) ) = = cmInvalidIdx )
return cmErrMsg ( & p - > err , kInvalidArgDcRC , " The output audio device name '%s' is not valid. " , cmStringNullGuard ( outDevNameStr ) ) ;
2013-03-29 06:15:09 +00:00
// 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. " ) ;
2013-03-27 16:56:51 +00:00
// if dcLabelStr is already in use for this location and type then update
// the assoc'd recd otherwise create a new one.
if ( ( cp = _cmDcmFindOrCreateCfg ( p , kAudioDcmTId , dcLabelStr ) ) = = NULL )
return cmErrLastRC ( & p - > err ) ;
2013-03-29 06:15:09 +00:00
unsigned inChCnt = cmApDeviceChannelCount ( inDevIdx , true ) ;
unsigned outChCnt = cmApDeviceChannelCount ( outDevIdx , false ) ;
2013-03-27 16:56:51 +00:00
cp - > u . a . inDevLabelStr = cmMemAllocStr ( inDevNameStr ) ;
cp - > u . a . outDevLabelStr = cmMemAllocStr ( outDevNameStr ) ;
cp - > u . a . audioSysArgs . rpt = p - > err . rpt ;
cp - > u . a . audioSysArgs . inDevIdx = inDevIdx ;
cp - > u . a . audioSysArgs . outDevIdx = outDevIdx ;
cp - > u . a . audioSysArgs . syncInputFl = syncInputFl ;
cp - > u . a . audioSysArgs . msgQueueByteCnt = msgQueueByteCnt ;
cp - > u . a . audioSysArgs . devFramesPerCycle = devFramesPerCycle ;
cp - > u . a . audioSysArgs . dspFramesPerCycle = dspFramesPerCycle ;
cp - > u . a . audioSysArgs . audioBufCnt = audioBufCnt ;
cp - > u . a . audioSysArgs . srate = srate ;
2013-03-29 06:15:09 +00:00
cp - > descStr = cmTsPrintfP ( cp - > descStr , " In: Chs:%i %s \n Out: Chs:%i %s " , inChCnt , inDevNameStr , outChCnt , outDevNameStr ) ;
2013-03-27 16:56:51 +00:00
return kOkDcRC ;
}
2013-03-26 19:38:08 +00:00
2013-03-29 06:15:09 +00:00
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 ;
}
2013-03-27 16:56:51 +00:00
const cmDcmAudio_t * cmDevCfgAudioCfg ( cmDevCfgH_t h , unsigned cfgIdx )
{
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
cmDcmCfg_t * cp ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
if ( ( cp = _cmDevCfgIndexToPtr ( p , kAudioDcmTId , cfgIdx , true ) ) = = NULL )
return NULL ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
return & cp - > u . a ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
const cmDcmAudio_t * cmDevCfgAudioDevMap ( cmDevCfgH_t h , unsigned usrAppId , unsigned usrMapId )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
cmDcmMap_t * mp ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
if ( ( mp = _cmDcmFindMap ( p , kAudioDcmTId , usrAppId , usrMapId , true ) ) = = NULL )
2013-03-26 19:38:08 +00:00
return NULL ;
2013-03-27 16:56:51 +00:00
return & mp - > cfg - > u . a ;
2013-03-25 22:59:49 +00:00
}
2013-03-29 06:15:09 +00:00
cmDcRC_t cmDevCfgNameNetPort (
2013-03-25 22:59:49 +00:00
cmDevCfgH_t h ,
const cmChar_t * dcLabelStr ,
const cmChar_t * sockAddr ,
unsigned portNumber )
{
2013-03-27 16:56:51 +00:00
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
cmDcmCfg_t * cp ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
if ( portNumber > 0xffff )
return cmErrMsg ( & p - > err , kInvalidArgDcRC , " The network port number %i is invalid. The valid IP port number range is:0-0xffff. " ) ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
// validate the label
if ( ( dcLabelStr = _cmDcmTrimLabel ( p , dcLabelStr , " MIDI cfg " ) ) = = NULL )
return cmErrLastRC ( & p - > err ) ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
// if dcLabelStr is already in use for this location and type then update
// the assoc'd recd otherwise create a new one.
2013-03-29 06:15:09 +00:00
if ( ( cp = _cmDcmFindOrCreateCfg ( p , kNetDcmTId , dcLabelStr ) ) = = NULL )
2013-03-27 16:56:51 +00:00
return cmErrLastRC ( & p - > err ) ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
cp - > u . n . sockAddr = cmMemAllocStr ( sockAddr ) ;
cp - > u . n . portNumber = portNumber ;
cp - > descStr = cmTsPrintfP ( cp - > descStr , " %s:%i " , sockAddr , portNumber ) ;
return kOkDcRC ;
2013-03-26 19:38:08 +00:00
}
2013-03-27 16:56:51 +00:00
const cmDcmNet_t * cmDevCfgNetCfg ( cmDevCfgH_t h , unsigned cfgIdx )
2013-03-26 19:38:08 +00:00
{
2013-03-27 16:56:51 +00:00
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
cmDcmCfg_t * cp ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
if ( ( cp = _cmDevCfgIndexToPtr ( p , kNetDcmTId , cfgIdx , true ) ) = = NULL )
return NULL ;
return & cp - > u . n ;
}
const cmDcmNet_t * cmDevCfgNetDevMap ( cmDevCfgH_t h , unsigned usrAppId , unsigned usrMapId )
{
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
cmDcmMap_t * mp ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
if ( ( mp = _cmDcmFindMap ( p , kNetDcmTId , usrAppId , usrMapId , true ) ) = = NULL )
2013-03-26 19:38:08 +00:00
return NULL ;
2013-03-27 16:56:51 +00:00
return & mp - > cfg - > u . n ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
unsigned cmDevCfgLocCount ( cmDevCfgH_t h )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
unsigned n = 0 ;
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
const cmDcmLoc_t * lp = p - > loc ;
for ( ; lp ! = NULL ; lp = lp - > next )
+ + n ;
return n ;
}
const cmChar_t * cmDevCfgLocLabel ( cmDevCfgH_t h , unsigned locIdx )
{
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
const cmDcmLoc_t * lp = p - > loc ;
2013-03-29 06:15:09 +00:00
unsigned i ;
for ( i = 0 ; lp ! = NULL ; lp = lp - > next , + + i )
if ( i = = locIdx )
2013-03-27 16:56:51 +00:00
return lp - > labelStr ;
assert ( 0 ) ;
2013-03-25 22:59:49 +00:00
return NULL ;
}
2013-03-27 16:56:51 +00:00
2013-03-29 06:15:09 +00:00
cmDcmLoc_t * _cmDcmLocLabelToPtr ( cmDcm_t * p , const cmChar_t * locLabelStr , bool errFl )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
if ( ( locLabelStr = _cmDcmTrimLabel ( p , locLabelStr , " location " ) ) = = NULL )
return NULL ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
cmDcmLoc_t * lp = p - > loc ;
for ( ; lp ! = NULL ; lp = lp - > next )
if ( strcmp ( lp - > labelStr , locLabelStr ) = = 0 )
return lp ;
2013-03-26 19:38:08 +00:00
2013-03-29 06:15:09 +00:00
if ( errFl )
cmErrMsg ( & p - > err , kLabelNotFoundDcRC , " The location label '%s' was not found. " , locLabelStr ) ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
return NULL ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
cmDcRC_t cmDevCfgLocStore ( cmDevCfgH_t h , const cmChar_t * locLabelStr )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
cmDcRC_t rc = kOkDcRC ;
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
unsigned i , j ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
// if this location label is already in use then it has already been stored.
2013-03-29 06:15:09 +00:00
if ( _cmDcmLocLabelToPtr ( p , locLabelStr , false ) ! = NULL )
2013-03-27 16:56:51 +00:00
return kOkDcRC ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
// store the current loc ptr
cmDcmLoc_t * olp = p - > clp ;
cmDcmLoc_t * nlp ;
// create a new location recd and make it current
if ( ( rc = _cmDcmNewLoc ( p , locLabelStr , & nlp ) ) ! = kOkDcRC )
return kOkDcRC ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
// duplicate the cfg's
cmDcmCfg_t * ocp = olp - > cfg ;
for ( ; ocp ! = NULL ; ocp = ocp - > next )
{
cmDcmCfg_t * ncp ;
2013-03-26 19:38:08 +00:00
2013-03-29 06:15:09 +00:00
// this will always create (never find) a new cfg recd
2013-03-27 16:56:51 +00:00
if ( ( ncp = _cmDcmFindOrCreateCfg ( p , ocp - > typeId , ocp - > dcLabelStr ) ) = = NULL )
{
rc = cmErrLastRC ( & p - > err ) ;
goto errLabel ;
}
2013-03-29 06:15:09 +00:00
// duplicate the desc. string
ncp - > descStr = cmMemAllocStr ( ocp - > descStr ) ;
2013-03-27 16:56:51 +00:00
switch ( ncp - > typeId )
{
case kMidiDcmTId : _cmDcmDuplMidi ( & ncp - > u . m , & ocp - > u . m ) ; break ;
case kAudioDcmTId : _cmDcmDuplAudio ( & ncp - > u . a , & ocp - > u . a ) ; break ;
case kNetDcmTId : _cmDcmDuplNet ( & ncp - > u . n , & ocp - > u . n ) ; break ;
default :
assert ( 0 ) ;
break ;
}
}
// duplicate the app array
nlp - > appCnt = olp - > appCnt ;
nlp - > app = cmMemAllocZ ( cmDcmApp_t , nlp - > appCnt ) ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
for ( i = 0 ; i < nlp - > appCnt ; + + i )
{
cmDcmApp_t * nap = nlp - > app + i ;
cmDcmApp_t * oap = olp - > app + i ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
//nap->usrAppId = oap->usrAppId;
nap - > activeFl = oap - > activeFl ;
nap - > mapCnt = oap - > mapCnt ;
nap - > map = cmMemAllocZ ( cmDcmMap_t , nap - > mapCnt ) ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
for ( j = 0 ; j < nap - > mapCnt ; + + j )
{
cmDcmMap_t * nmp = nap - > map + j ;
cmDcmMap_t * omp = oap - > map + j ;
2013-03-25 22:59:49 +00:00
2013-03-27 16:56:51 +00:00
nmp - > tid = omp - > tid ;
nmp - > cfgId = omp - > cfgId ;
if ( omp - > tid ! = kInvalidDcmTId & & omp - > cfg - > dcLabelStr ! = NULL )
nmp - > cfg = _cmDcmCfgLabelToPtr ( p , nmp - > tid , omp - > cfg - > dcLabelStr , true ) ;
}
}
errLabel :
if ( rc ! = kOkDcRC )
_cmDcmFreeLoc ( p , nlp ) ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
return rc ;
}
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
cmDcRC_t cmDevCfgLocRecall ( cmDevCfgH_t h , const cmChar_t * locLabelStr )
{
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
cmDcmLoc_t * lp ;
2013-03-26 19:38:08 +00:00
2013-03-29 06:15:09 +00:00
if ( ( lp = _cmDcmLocLabelToPtr ( p , locLabelStr , true ) ) = = NULL )
2013-03-27 16:56:51 +00:00
return cmErrLastRC ( & p - > err ) ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
p - > clp = lp ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
return kOkDcRC ;
}
cmDcRC_t cmDevCfgLocDelete ( cmDevCfgH_t h , const cmChar_t * locLabelStr )
{
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
cmDcmLoc_t * lp ;
2013-03-26 19:38:08 +00:00
2013-03-29 06:15:09 +00:00
if ( ( lp = _cmDcmLocLabelToPtr ( p , locLabelStr , true ) ) = = NULL )
2013-03-27 16:56:51 +00:00
return cmErrLastRC ( & p - > err ) ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
_cmDcmFreeLoc ( p , lp ) ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
return kOkDcRC ;
2013-03-26 19:38:08 +00:00
}
2013-03-27 16:56:51 +00:00
unsigned cmDevCfgLocCurIndex ( cmDevCfgH_t h )
2013-03-26 19:38:08 +00:00
{
2013-03-27 16:56:51 +00:00
unsigned i ;
cmDcm_t * p = _cmDcmHandleToPtr ( h ) ;
cmDcmLoc_t * lp = p - > loc ;
for ( i = 0 ; lp ! = NULL ; lp = lp - > next , + + i )
if ( lp = = p - > clp )
return i ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
assert ( 0 ) ;
return cmInvalidIdx ;
}
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
cmDcRC_t _cmDcmJsonNotFound ( cmDcm_t * p , const cmChar_t * tagStr )
{ return cmErrMsg ( & p - > err , kJsonFailDcRC , " JSON element '%s' not found. " , tagStr ) ; }
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
cmDcRC_t _cmDcmJsonSyntaxErr ( cmDcm_t * p , const cmChar_t * tagStr )
{ return cmErrMsg ( & p - > err , kJsonFailDcRC , " JSON syntax error '%s' not found. " , tagStr ) ; }
2013-03-26 19:38:08 +00:00
2013-03-29 06:15:09 +00:00
cmDcRC_t _cmDevCfgRead ( cmDcm_t * p , cmJsonH_t jsH , const cmJsonNode_t * rootObjPtr )
2013-03-26 19:38:08 +00:00
{
2013-03-27 16:56:51 +00:00
cmDcRC_t rc = kOkDcRC ;
const cmChar_t * errLabelPtr = NULL ;
cmJsonNode_t * cfgNp , * locArrNp ;
unsigned i , j ;
2013-03-29 06:15:09 +00:00
cmDevCfgH_t h ;
h . h = p ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
// clear the all locations
_cmDcmFreeAllLocs ( p ) ;
if ( ( cfgNp = cmJsonFindValue ( jsH , " cfg " , rootObjPtr , kObjectTId ) ) = = NULL )
return _cmDcmJsonNotFound ( p , " cfg " ) ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
// get loc array
if ( ( locArrNp = cmJsonFindValue ( jsH , " loc " , cfgNp , kArrayTId ) ) = = NULL )
return _cmDcmJsonNotFound ( p , " loc " ) ;
// for each loc object
for ( i = 0 ; i < cmJsonChildCount ( locArrNp ) ; + + i )
2013-03-26 19:38:08 +00:00
{
2013-03-27 16:56:51 +00:00
cmJsonNode_t * locObjNp , * cfgArrNp ;
2013-03-29 06:15:09 +00:00
const cmChar_t * locLabelStr = NULL ;
2013-03-27 16:56:51 +00:00
// get the loc object
if ( ( locObjNp = cmJsonArrayElement ( locArrNp , i ) ) = = NULL | | cmJsonIsObject ( locObjNp ) = = false )
return _cmDcmJsonSyntaxErr ( p , " loc object " ) ;
// read the loc object fields
if ( cmJsonMemberValues ( locObjNp , & errLabelPtr ,
2013-03-29 06:15:09 +00:00
" label " , kStringTId , & locLabelStr ,
2013-03-27 16:56:51 +00:00
" cfg " , kArrayTId , & cfgArrNp ,
2013-03-29 06:15:09 +00:00
NULL ) ! = kOkJsRC )
2013-03-27 16:56:51 +00:00
{ return _cmDcmJsonNotFound ( p , errLabelPtr ) ; }
// create a new location recd
cmDcmLoc_t * locPtr = NULL ;
2013-03-29 06:15:09 +00:00
if ( ( rc = _cmDcmNewLoc ( p , locLabelStr , & locPtr ) ) ! = kOkDcRC )
return cmErrMsg ( & p - > err , kJsonFailDcRC , " Location '%s' create failed. " , cmStringNullGuard ( locLabelStr ) ) ;
2013-03-27 16:56:51 +00:00
/*
// read each app object
for ( j = 0 ; j < cmJsonChildCount ( appArrNp ) ; + + j )
{
cmJsonNode_t * appObjNp ;
// get the app object
if ( ( appObjNp = cmJsonArrayElement ( appArrNp , j ) ) = = NULL | | cmJsonIsObject ( appObjNp ) = = false )
return _cmDcmJsonSyntaxErr ( p , " loc object " ) ;
// locate the map array
cmJsonNode_t * mapArrNp ;
if ( ( mapArrNp = cmJsonFindValue ( jsH , " map " , appObjNp , kArrayTId ) ) = = NULL )
return _cmDcmJsonNotFound ( p , " map " ) ;
// for each map array
for ( k = 0 ; k < cmJsonChildCount ( mapArrNp ) ; + + k )
2013-03-26 19:38:08 +00:00
{
2013-03-27 16:56:51 +00:00
unsigned tid , cfgId ;
cmJsonNode_t * mapObjNp ;
if ( ( mapObjNp = cmJsonArrayElement ( mapArrNp , j ) ) = = NULL | | cmJsonIsObject ( mapObjNp ) = = false )
return _cmDcmJsonSyntaxErr ( p , " cfg object " ) ;
if ( cmJsonMemberValues ( mapObjNp , & errLabelPtr ,
" tid " , kIntTId , & tid ,
" cfgId " , kIntTId , & cfgId ,
NULL ) ! = kOkDcRC )
{ return _cmDcmJsonSyntaxErr ( p , errLabelPtr ) ; }
}
}
*/
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
// read each cfg object
for ( j = 0 ; j < cmJsonChildCount ( cfgArrNp ) ; + + j )
2013-03-26 19:38:08 +00:00
{
2013-03-27 16:56:51 +00:00
cmJsonNode_t * cfgObjNp ;
const cmChar_t * dcLabelStr ;
const cmChar_t * descStr ;
unsigned cfgId , typeId ;
if ( ( cfgObjNp = cmJsonArrayElement ( cfgArrNp , j ) ) = = NULL | | cmJsonIsObject ( cfgObjNp ) = = false )
return _cmDcmJsonSyntaxErr ( p , " cfg object " ) ;
if ( cmJsonMemberValues ( cfgObjNp , & errLabelPtr ,
" label " , kStringTId , & dcLabelStr ,
" cfgId " , kIntTId , & cfgId ,
" typeId " , kIntTId , & typeId ,
" desc " , kStringTId , & descStr ,
2013-03-29 06:15:09 +00:00
NULL ) ! = kOkJsRC )
2013-03-27 16:56:51 +00:00
{ _cmDcmJsonSyntaxErr ( p , errLabelPtr ) ; }
cmDcmMidi_t m ;
cmDcmAudio_t a ;
cmDcmNet_t n ;
2013-03-29 06:15:09 +00:00
2013-03-27 16:56:51 +00:00
switch ( typeId )
{
case kMidiDcmTId :
if ( cmJsonMemberValues ( cfgObjNp , & errLabelPtr ,
" devLabelStr " , kStringTId , & m . devLabelStr ,
" portLabelStr " , kStringTId , & m . portLabelStr ,
2013-03-29 06:15:09 +00:00
" inputFl " , kBoolTId , & m . inputFl ,
2013-03-27 16:56:51 +00:00
NULL ) ! = kOkJsRC )
2013-03-29 06:15:09 +00:00
{
rc = _cmDcmJsonSyntaxErr ( p , errLabelPtr ) ;
goto errLabel ;
}
2013-03-27 16:56:51 +00:00
2013-03-29 06:15:09 +00:00
if ( ( rc = cmDevCfgNameMidiPort ( h , dcLabelStr , m . devLabelStr , m . portLabelStr , m . inputFl ) ) ! = kOkDcRC )
goto errLabel ;
2013-03-27 16:56:51 +00:00
break ;
case kAudioDcmTId :
if ( cmJsonMemberValues ( cfgObjNp , & errLabelPtr ,
" inDevLabelStr " , kStringTId , & a . inDevLabelStr ,
" outDevLabelStr " , kStringTId , & a . outDevLabelStr ,
" syncInputFl " , kBoolTId , & a . audioSysArgs . syncInputFl ,
" msgQueueByteCnt " , kIntTId , & a . audioSysArgs . msgQueueByteCnt ,
" devFramesPerCycle " , kIntTId , & a . audioSysArgs . devFramesPerCycle ,
" dspFramesPerCycle " , kIntTId , & a . audioSysArgs . dspFramesPerCycle ,
" audioBufCnt " , kIntTId , & a . audioSysArgs . audioBufCnt ,
2013-03-29 06:15:09 +00:00
" srate " , kRealTId , & a . audioSysArgs . srate ,
NULL ) ! = kOkJsRC )
{
rc = _cmDcmJsonSyntaxErr ( p , errLabelPtr ) ;
goto errLabel ;
}
if ( ( rc = cmDevCfgNameAudioPort ( h , dcLabelStr , a . inDevLabelStr , a . outDevLabelStr ,
a . audioSysArgs . syncInputFl ,
a . audioSysArgs . msgQueueByteCnt ,
a . audioSysArgs . devFramesPerCycle ,
a . audioSysArgs . dspFramesPerCycle ,
a . audioSysArgs . audioBufCnt ,
a . audioSysArgs . srate ) ) ! = kOkDcRC )
{
goto errLabel ;
}
2013-03-27 16:56:51 +00:00
break ;
case kNetDcmTId :
if ( cmJsonMemberValues ( cfgObjNp , & errLabelPtr ,
" sockAddr " , kStringTId , & n . sockAddr ,
" portNumber " , kIntTId , & n . portNumber ,
NULL ) ! = kOkJsRC )
2013-03-29 06:15:09 +00:00
{
rc = _cmDcmJsonSyntaxErr ( p , errLabelPtr ) ;
goto errLabel ;
}
2013-03-27 16:56:51 +00:00
2013-03-29 06:15:09 +00:00
if ( ( rc = cmDevCfgNameNetPort ( h , dcLabelStr , n . sockAddr , n . portNumber ) ) ! = kOkDcRC )
goto errLabel ;
2013-03-27 16:56:51 +00:00
break ;
default :
assert ( 0 ) ;
break ;
}
}
2013-03-26 19:38:08 +00:00
}
2013-03-29 06:15:09 +00:00
errLabel :
2013-03-27 16:56:51 +00:00
return kOkDcRC ;
2013-03-25 22:59:49 +00:00
}
2013-03-27 16:56:51 +00:00
cmDcRC_t _cmDevCfgWrite ( cmDcm_t * p , cmJsonH_t jsH , cmJsonNode_t * rootObjPtr )
2013-03-26 19:38:08 +00:00
{
2013-03-27 16:56:51 +00:00
cmDcRC_t rc = kOkDcRC ;
2013-03-29 06:15:09 +00:00
const cmDcmLoc_t * lp = p - > loc ;
2013-03-27 16:56:51 +00:00
cmJsonNode_t * cfgNp = cmJsonInsertPairObject ( jsH , rootObjPtr , " cfg " ) ;
// create the loc array
cmJsonNode_t * locArrNp = cmJsonInsertPairArray ( jsH , cfgNp , " loc " ) ;
for ( ; lp ! = NULL ; lp = lp - > next )
2013-03-26 19:38:08 +00:00
{
2013-03-27 16:56:51 +00:00
// create the 'loc' object
cmJsonNode_t * locObjNp = cmJsonCreateObject ( jsH , locArrNp ) ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
// set the loc label
2013-03-29 06:15:09 +00:00
cmJsonInsertPairString ( jsH , locObjNp , " label " , lp - > labelStr ) ;
2013-03-26 19:38:08 +00:00
2013-03-27 16:56:51 +00:00
/*
// create the 'loc.app[]' array
cmJsonNode_t * appArrNp = cmJsonInsertPairArray ( jsH , locObjNp , " app " ) ;
// for each app recd
for ( i = 0 ; i < lp - > appCnt ; + + i )
if ( lp - > app [ i ] . activeFl )
{
// create the app recd
cmJsonNode_t * appNp = cmJsonCreateObject ( jsH , appArrNp ) ;
// create the map array
cmJsonNode_t * mapArrNp = cmJsonInsertPairArray ( jsH , appNp , " map " ) ;
// for each map recd
for ( j = 0 ; j < lp - > app [ i ] . mapCnt ; + + j )
{
cmJsonNode_t * mapNp = cmJsonCreateObject ( jsH , mapArrNp ) ;
cmJsonInsertPairs ( jsH , mapNp ,
" tid " , kIntTId , lp - > app [ i ] . map [ j ] . tid ,
" cfgId " , kIntTId , lp - > app [ i ] . map [ j ] . cfgId ,
NULL ) ;
}
}
*/
// create the 'loc.cfg[]' array
cmJsonNode_t * cfgArrNp = cmJsonInsertPairArray ( jsH , locObjNp , " cfg " ) ;
// for each cfg recd
cmDcmCfg_t * cp = lp - > cfg ;
for ( ; cp ! = NULL ; cp = cp - > next )
{
// create the cfg recd
cmJsonNode_t * cfgObjNp = cmJsonCreateObject ( jsH , cfgArrNp ) ;
// fill the cfg recd
cmJsonInsertPairs ( jsH , cfgObjNp ,
" label " , kStringTId , cp - > dcLabelStr ,
" cfgId " , kIntTId , cp - > cfgId ,
" typeId " , kIntTId , cp - > typeId ,
" desc " , kStringTId , cp - > descStr ,
NULL ) ;
switch ( cp - > typeId )
{
case kMidiDcmTId :
cmJsonInsertPairs ( jsH , cfgObjNp ,
" devLabelStr " , kStringTId , cp - > u . m . devLabelStr ,
" portLabelStr " , kStringTId , cp - > u . m . portLabelStr ,
" inputFl " , kBoolTId , cp - > u . m . inputFl ,
NULL ) ;
break ;
case kAudioDcmTId :
cmJsonInsertPairs ( jsH , cfgObjNp ,
" inDevLabelStr " , kStringTId , cp - > u . a . inDevLabelStr ,
" outDevLabelStr " , kStringTId , cp - > u . a . outDevLabelStr ,
" syncInputFl " , kBoolTId , cp - > u . a . audioSysArgs . syncInputFl ,
" msgQueueByteCnt " , kIntTId , cp - > u . a . audioSysArgs . msgQueueByteCnt ,
" devFramesPerCycle " , kIntTId , cp - > u . a . audioSysArgs . devFramesPerCycle ,
" dspFramesPerCycle " , kIntTId , cp - > u . a . audioSysArgs . dspFramesPerCycle ,
" audioBufCnt " , kIntTId , cp - > u . a . audioSysArgs . audioBufCnt ,
2013-03-29 06:15:09 +00:00
" srate " , kRealTId , cp - > u . a . audioSysArgs . srate ,
2013-03-27 16:56:51 +00:00
NULL ) ;
break ;
case kNetDcmTId :
cmJsonInsertPairs ( jsH , cfgObjNp ,
" sockAddr " , kStringTId , cp - > u . n . sockAddr ,
" portNumber " , kIntTId , cp - > u . n . portNumber ,
NULL ) ;
break ;
default :
assert ( 0 ) ;
break ;
}
}
}
return rc ;
2013-03-26 19:38:08 +00:00
}
2013-03-25 22:59:49 +00:00
2013-03-29 06:15:09 +00:00
cmDcRC_t cmDevCfgWrite ( cmDevCfgH_t h , const cmChar_t * fn )
2013-03-25 22:59:49 +00:00
{
2013-03-27 16:56:51 +00:00
cmDcRC_t rc = kOkDcRC ;
2013-03-29 06:15:09 +00:00
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. " ) ;
2013-03-27 16:56:51 +00:00
return rc ;
2013-03-25 22:59:49 +00:00
}