libcm is a C development framework with an emphasis on audio signal processing applications.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

cmDevCfg.c 30KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170
  1. #include "cmGlobal.h"
  2. #include "cmFloatTypes.h"
  3. #include "cmRpt.h"
  4. #include "cmErr.h"
  5. #include "cmCtx.h"
  6. #include "cmMem.h"
  7. #include "cmMallocDebug.h"
  8. #include "cmLinkedHeap.h"
  9. #include "cmJson.h"
  10. #include "cmText.h"
  11. #include "cmThread.h"
  12. #include "cmMidi.h"
  13. #include "cmMidiPort.h"
  14. #include "cmAudioPort.h"
  15. #include "cmUdpPort.h"
  16. #include "cmUdpNet.h"
  17. #include "cmAudioSysMsg.h"
  18. #include "cmAudioSys.h"
  19. #include "cmDevCfg.h"
  20. cmDevCfgH_t cmDevCfgNullHandle = cmSTATIC_NULL_HANDLE;
  21. typedef struct cmDcmCfg_str
  22. {
  23. cmChar_t* dcLabelStr;
  24. unsigned cfgId; // unique among all cfg's assigned to a loc
  25. cmTypeDcmId_t typeId;
  26. cmChar_t* descStr;
  27. union
  28. {
  29. cmDcmMidi_t m;
  30. cmDcmAudio_t a;
  31. cmDcmNet_t n;
  32. } u;
  33. struct cmDcmCfg_str* next;
  34. struct cmDcmCfg_str* prev;
  35. } cmDcmCfg_t;
  36. typedef struct
  37. {
  38. cmTypeDcmId_t tid; // Type Id for this map or tInvalidDcmTId if the record is not active.
  39. unsigned cfgId; // cfgId of the cfg recd assoc'd with this map
  40. cmDcmCfg_t* cfg; // pointer to the cfg recd assoc'd with this map (cfg->cfgId == cmDcmMap_t.cfgId)
  41. } cmDcmMap_t;
  42. typedef struct
  43. {
  44. bool activeFl;
  45. cmDcmMap_t* map;
  46. unsigned mapCnt;
  47. } cmDcmApp_t;
  48. typedef struct cmDcmLoc_str
  49. {
  50. cmChar_t* labelStr;
  51. cmDcmApp_t* app;
  52. unsigned appCnt;
  53. cmDcmCfg_t* cfg;
  54. struct cmDcmLoc_str* next;
  55. struct cmDcmLoc_str* prev;
  56. } cmDcmLoc_t;
  57. typedef struct
  58. {
  59. cmErr_t err;
  60. cmDcmLoc_t* loc;
  61. cmDcmLoc_t* clp;
  62. } cmDcm_t;
  63. cmDcm_t* _cmDcmHandleToPtr( cmDevCfgH_t h )
  64. {
  65. cmDcm_t* p = (cmDcm_t*)h.h;
  66. assert( p!=NULL );
  67. return p;
  68. }
  69. const cmChar_t* _cmDcmTrimLabel( cmDcm_t*p, const cmChar_t* s, const cmChar_t* title )
  70. {
  71. if( s == NULL )
  72. {
  73. cmErrMsg(&p->err,kBlankLabelDcRC,"A blank '%s' label was encountered.",title);
  74. return NULL;
  75. }
  76. while( *s && isspace(*s) )
  77. ++s;
  78. if( strlen(s) == 0 )
  79. {
  80. cmErrMsg(&p->err,kBlankLabelDcRC,"An empty '%s' label was encountered.",title);
  81. return NULL;
  82. }
  83. return s;
  84. }
  85. void _cmDcmFreeMidi( cmDcmMidi_t* r )
  86. {
  87. cmMemFree(r->devLabelStr);
  88. cmMemFree(r->portLabelStr);
  89. }
  90. void _cmDcmDuplMidi( cmDcmMidi_t* d, const cmDcmMidi_t* s )
  91. {
  92. d->devLabelStr = cmMemAllocStr(s->devLabelStr);
  93. d->portLabelStr = cmMemAllocStr(s->portLabelStr);
  94. d->inputFl = s->inputFl;
  95. d->devIdx = s->devIdx;
  96. d->portIdx = s->portIdx;
  97. }
  98. void _cmDcmFreeAudio( cmDcmAudio_t* r )
  99. {
  100. cmMemFree(r->inDevLabelStr);
  101. cmMemFree(r->outDevLabelStr);
  102. }
  103. void _cmDcmDuplAudio( cmDcmAudio_t* d, const cmDcmAudio_t* s )
  104. {
  105. d->inDevLabelStr = cmMemAllocStr(s->inDevLabelStr);
  106. d->outDevLabelStr = cmMemAllocStr(s->outDevLabelStr);
  107. d->audioSysArgs = s->audioSysArgs;
  108. }
  109. void _cmDcmFreeNet( cmDcmNet_t* r )
  110. {
  111. cmMemFree(r->sockAddr);
  112. }
  113. void _cmDcmDuplNet( cmDcmNet_t* d, const cmDcmNet_t* s )
  114. {
  115. d->sockAddr = cmMemAllocStr(s->sockAddr);
  116. d->portNumber = s->portNumber;
  117. }
  118. void _cmDcmFreeCfg( cmDcm_t* p, cmDcmLoc_t* lp, cmDcmCfg_t* cp )
  119. {
  120. // unlink the cfg recd
  121. if( cp->prev == NULL )
  122. lp->cfg = cp->next;
  123. else
  124. cp->prev->next = cp->next;
  125. if( cp->next != NULL )
  126. cp->next->prev = cp->prev;
  127. cmMemFree(cp->dcLabelStr);
  128. cmMemFree(cp->descStr);
  129. switch( cp->typeId )
  130. {
  131. case kMidiDcmTId: _cmDcmFreeMidi(&cp->u.m); break;
  132. case kAudioDcmTId: _cmDcmFreeAudio(&cp->u.a); break;
  133. case kNetDcmTId: _cmDcmFreeNet(&cp->u.n); break;
  134. default:
  135. assert(0);
  136. break;
  137. }
  138. }
  139. void _cmDcmFreeLoc( cmDcm_t* p, cmDcmLoc_t* lp )
  140. {
  141. unsigned i;
  142. // unlink the loc recd
  143. if( lp->prev == NULL )
  144. p->loc = lp->next;
  145. else
  146. lp->prev->next = lp->next;
  147. if( lp->next != NULL )
  148. lp->next->prev = lp->prev;
  149. // free each app
  150. for(i=0; i<lp->appCnt; ++i)
  151. cmMemFree(lp->app[i].map);
  152. cmMemFree(lp->app);
  153. cmMemFree(lp->labelStr);
  154. while( lp->cfg != NULL )
  155. _cmDcmFreeCfg(p,lp,lp->cfg);
  156. cmMemFree(lp);
  157. }
  158. void _cmDcmFreeAllLocs( cmDcm_t* p )
  159. {
  160. while( p->loc != NULL )
  161. _cmDcmFreeLoc(p,p->loc);
  162. p->clp = NULL;
  163. }
  164. cmDcRC_t _cmDcmFree( cmDcm_t* p )
  165. {
  166. cmDcRC_t rc = kOkDcRC;
  167. _cmDcmFreeAllLocs(p);
  168. cmMemFree(p);
  169. return rc;
  170. }
  171. cmDcmLoc_t* _cmDcmFindLoc( cmDcm_t* p, const cmChar_t* labelStr )
  172. {
  173. cmDcmLoc_t* lp = p->loc;
  174. for(; lp!=NULL; lp=lp->next)
  175. if(strcmp(lp->labelStr,labelStr)==0)
  176. return lp;
  177. return NULL;
  178. }
  179. cmDcRC_t _cmDcmNewLoc( cmDcm_t* p, const cmChar_t* labelStr, cmDcmLoc_t** locRef)
  180. {
  181. cmDcmLoc_t* lp;
  182. assert(locRef != NULL);
  183. *locRef = NULL;
  184. // verify and condition the label
  185. if((labelStr = _cmDcmTrimLabel(p,labelStr,"location")) == NULL )
  186. return cmErrLastRC(&p->err);
  187. // verify that the label is not already in use
  188. if((lp = _cmDcmFindLoc(p,labelStr)) != NULL )
  189. return cmErrMsg(&p->err,kDuplLabelDcRC,"The location label '%s' is already in use.",labelStr);
  190. // create a new loc recd
  191. lp = cmMemAllocZ(cmDcmLoc_t,1);
  192. lp->labelStr = cmMemAllocStr(labelStr);
  193. // if the cur loc is not current set - then prepend loc
  194. if( p->clp == NULL )
  195. {
  196. lp->prev = NULL;
  197. lp->next = p->loc;
  198. if( p->loc == NULL )
  199. p->loc = lp;
  200. else
  201. p->loc->prev = lp;
  202. }
  203. else // otherwise insert loc after the cur loc
  204. {
  205. lp->prev = p->clp;
  206. lp->next = p->clp->next;
  207. if( p->clp->next != NULL )
  208. p->clp->next->prev = lp;
  209. p->clp->next = lp;
  210. }
  211. // make the new loc the current loc
  212. p->clp = lp;
  213. *locRef = lp;
  214. return kOkDcRC;
  215. }
  216. cmDcRC_t cmDevCfgMgrAlloc( cmCtx_t* c, cmDevCfgH_t* hp )
  217. {
  218. cmDcRC_t rc;
  219. cmDcmLoc_t* lp;
  220. if((rc = cmDevCfgMgrFree(hp)) != kOkDcRC )
  221. return rc;
  222. cmDcm_t* p = cmMemAllocZ(cmDcm_t,1);
  223. cmErrSetup(&p->err,&c->rpt,"cmDevCfg");
  224. if((rc = _cmDcmNewLoc(p,"Default", &lp)) != kOkDcRC )
  225. goto errLabel;
  226. hp->h = p;
  227. errLabel:
  228. if( rc != kOkDcRC )
  229. _cmDcmFree(p);
  230. return rc;
  231. }
  232. cmDcRC_t cmDevCfgMgrFree( cmDevCfgH_t* hp )
  233. {
  234. cmDcRC_t rc = kOkDcRC;
  235. if( hp == NULL || cmDevCfgIsValid(*hp)==false )
  236. return rc;
  237. cmDcm_t* p = _cmDcmHandleToPtr(*hp);
  238. if((rc = _cmDcmFree(p)) != kOkDcRC )
  239. return rc;
  240. hp->h = NULL;
  241. return rc;
  242. }
  243. bool cmDevCfgIsValid( cmDevCfgH_t h )
  244. { return h.h != NULL; }
  245. unsigned cmDevCfgCount( cmDevCfgH_t h, cmTypeDcmId_t typeId )
  246. {
  247. unsigned n=0;
  248. cmDcm_t* p = _cmDcmHandleToPtr(h);
  249. assert( p->clp != NULL);
  250. const cmDcmCfg_t* cp = p->clp->cfg;
  251. for(; cp!= NULL; cp=cp->next)
  252. if( cp->typeId == typeId )
  253. ++n;
  254. return n;
  255. }
  256. cmDcmCfg_t* _cmDevCfgIndexToPtr( cmDcm_t* p, cmTypeDcmId_t typeId, unsigned index, bool errFl )
  257. {
  258. unsigned n=0;
  259. assert( p->clp != NULL);
  260. cmDcmCfg_t* cp = p->clp->cfg;
  261. for(; cp!= NULL; cp=cp->next)
  262. if( cp->typeId == typeId )
  263. {
  264. if( n == index )
  265. return cp;
  266. ++n;
  267. }
  268. if( errFl )
  269. cmErrMsg(&p->err,kInvalidCfgIdxDcRC,"The cfg index %i is not valid in location '%s'.",cmStringNullGuard(p->clp->labelStr));
  270. return NULL;
  271. }
  272. const cmChar_t* cmDevCfgLabel( cmDevCfgH_t h, cmTypeDcmId_t typeId, unsigned index )
  273. {
  274. cmDcm_t* p = _cmDcmHandleToPtr(h);
  275. cmDcmCfg_t* cp;
  276. if((cp = _cmDevCfgIndexToPtr(p,typeId,index,false)) == NULL )
  277. return NULL;
  278. return cp->dcLabelStr;
  279. }
  280. const cmChar_t* cmDevCfgDesc( cmDevCfgH_t h, cmTypeDcmId_t typeId, unsigned index )
  281. {
  282. cmDcm_t* p = _cmDcmHandleToPtr(h);
  283. cmDcmCfg_t* cp;
  284. if((cp = _cmDevCfgIndexToPtr(p,typeId,index,false)) == NULL )
  285. return NULL;
  286. return cp->descStr;
  287. }
  288. cmDcmCfg_t* _cmDcmCfgLabelToPtr( cmDcm_t* p, cmTypeDcmId_t typeId, const cmChar_t* label, bool errFl )
  289. {
  290. assert( p->clp != NULL);
  291. cmDcmCfg_t* cp = p->clp->cfg;
  292. for(; cp!= NULL; cp=cp->next)
  293. if( cp->typeId == typeId )
  294. {
  295. if( strcmp(cp->dcLabelStr,label)==0 )
  296. return cp;
  297. }
  298. if( errFl )
  299. cmErrMsg(&p->err,kLabelNotFoundDcRC, "The cfg label '%s' was not found.",cmStringNullGuard(label));
  300. return NULL;
  301. }
  302. unsigned cmDevCfgLabelToIndex( cmDevCfgH_t h, cmTypeDcmId_t typeId, const cmChar_t* label )
  303. {
  304. unsigned n = 0;
  305. cmDcm_t* p = _cmDcmHandleToPtr(h);
  306. assert( p->clp != NULL);
  307. const cmDcmCfg_t* cp = p->clp->cfg;
  308. for(; cp!= NULL; cp=cp->next)
  309. if( cp->typeId == typeId )
  310. {
  311. if( strcmp(cp->dcLabelStr,label)==0 )
  312. break;
  313. ++n;
  314. }
  315. return n;
  316. }
  317. cmDcmCfg_t* _cmDcmFindOrCreateCfg( cmDcm_t* p, cmTypeDcmId_t typeId, const cmChar_t* dcLabelStr )
  318. {
  319. assert( p->clp != NULL );
  320. cmDcmCfg_t* cp;
  321. // validate the label
  322. if( (dcLabelStr=_cmDcmTrimLabel(p,dcLabelStr,"cfg")) == NULL )
  323. return NULL;
  324. // if the cfg recd already exists then return it
  325. if((cp = _cmDcmCfgLabelToPtr(p, typeId, dcLabelStr, false )) != NULL )
  326. return cp;
  327. unsigned newCfgId = 0;
  328. // use ep to track the end of the list
  329. cmDcmCfg_t* ep = NULL;
  330. // find the max cfgId used by this loc
  331. cp = p->clp->cfg;
  332. for(; cp!=NULL; cp=cp->next)
  333. {
  334. if( cp->cfgId > newCfgId )
  335. newCfgId = cp->cfgId;
  336. ep = cp;
  337. }
  338. // add one to the max cfgId to create a unique cfgId
  339. newCfgId += 1;
  340. // allocate a new cfg recd
  341. cp = cmMemAllocZ(cmDcmCfg_t,1);
  342. cp->dcLabelStr = cmMemAllocStr(dcLabelStr);
  343. cp->cfgId = newCfgId;
  344. cp->typeId = typeId;
  345. // link to the end of the loc's cfg list
  346. if( ep == NULL )
  347. p->clp->cfg = cp;
  348. else
  349. {
  350. ep->next = cp;
  351. cp->prev = ep;
  352. }
  353. return cp;
  354. }
  355. void _cmDcmDisconnectMap( cmDcmMap_t* mp )
  356. {
  357. mp->tid = kInvalidDcmTId;
  358. mp->cfgId = cmInvalidId;
  359. mp->cfg = NULL;
  360. }
  361. cmDcRC_t cmDevCfgDeleteCfg( cmDevCfgH_t h, cmTypeDcmId_t typeId, const cmChar_t* dcLabelStr )
  362. {
  363. cmDcmCfg_t* cp;
  364. cmDcm_t* p = _cmDcmHandleToPtr(h);
  365. unsigned i,j;
  366. // locate the cfg to delete
  367. if((cp = _cmDcmCfgLabelToPtr(p,typeId,dcLabelStr,true)) == NULL )
  368. return cmErrLastRC(&p->err);
  369. // for every app in the current location ...
  370. for(i=0; i<p->clp->appCnt; ++i)
  371. {
  372. cmDcmApp_t* ap = p->clp->app + i;
  373. // ... disconnect any maps to this cfg
  374. if( ap->activeFl && ap->map != NULL )
  375. for(j=0; j<ap->mapCnt; ++j)
  376. if( ap->map[j].cfgId == cp->cfgId )
  377. _cmDcmDisconnectMap(ap->map + j );
  378. }
  379. // unlink and release the cfg recd
  380. _cmDcmFreeCfg(p,p->clp,cp);
  381. return kOkDcRC;
  382. }
  383. cmDcRC_t cmDevCfgCreateMap( cmDevCfgH_t h, cmTypeDcmId_t typeId, const cmChar_t* dcLabelStr, unsigned usrAppId, unsigned usrMapId )
  384. {
  385. cmDcRC_t rc = kOkDcRC;
  386. cmDcm_t* p = _cmDcmHandleToPtr(h);
  387. cmDcmCfg_t* cp;
  388. // locate the cfg to map to
  389. if((cp = _cmDcmCfgLabelToPtr(p,typeId,dcLabelStr,true)) == NULL )
  390. return cmErrLastRC(&p->err);
  391. // if usrAppId references a new app
  392. if( usrAppId >= p->clp->appCnt )
  393. {
  394. p->clp->appCnt = usrAppId + 1;
  395. p->clp->app = cmMemResizePZ(cmDcmApp_t,p->clp->app,p->clp->appCnt);
  396. }
  397. cmDcmApp_t* ap = p->clp->app + usrAppId;
  398. // if usrMapId ref's a new map
  399. if( usrMapId >= ap->mapCnt )
  400. {
  401. ap->mapCnt = usrMapId+1;
  402. ap->map = cmMemResizePZ(cmDcmMap_t,ap->map,ap->mapCnt);
  403. }
  404. cmDcmMap_t* mp = ap->map + usrMapId;
  405. mp->tid = typeId;
  406. mp->cfgId = cp->cfgId;
  407. mp->cfg = cp;
  408. return rc;
  409. }
  410. cmDcmMap_t* _cmDcmFindMap( cmDcm_t* p, cmTypeDcmId_t typeId, unsigned usrAppId, unsigned usrMapId, bool activeFl )
  411. {
  412. if( usrAppId >= p->clp->appCnt )
  413. {
  414. 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));
  415. goto errLabel;
  416. }
  417. cmDcmApp_t* ap = p->clp->app + usrAppId;
  418. if( usrMapId >= ap->mapCnt )
  419. {
  420. cmErrMsg(&p->err,kInvalidUserMapIdRC,"The user map id %i is out of range %i in location '%s'.",usrMapId,ap->mapCnt,cmStringNullGuard(p->clp->labelStr));
  421. goto errLabel;
  422. }
  423. if( activeFl && (ap->map[usrMapId].tid == kInvalidDcmTId || ap->map[usrMapId].cfg == NULL))
  424. {
  425. cmErrMsg(&p->err,kInvalidUserMapIdRC,"The user map id %i inactive in location '%s'.",usrMapId,cmStringNullGuard(p->clp->labelStr));
  426. goto errLabel;
  427. }
  428. return ap->map + usrMapId;
  429. errLabel:
  430. return NULL;
  431. }
  432. cmDcRC_t cmDevCfgDeleteMap( cmDevCfgH_t h, cmTypeDcmId_t typeId, unsigned usrAppId, unsigned usrMapId )
  433. {
  434. cmDcm_t* p = _cmDcmHandleToPtr(h);
  435. cmDcmMap_t* mp;
  436. if((mp = _cmDcmFindMap(p,typeId,usrAppId,usrMapId,false)) == NULL )
  437. return cmErrLastRC(&p->err);
  438. _cmDcmDisconnectMap( mp );
  439. return kOkDcRC;
  440. }
  441. cmDcRC_t cmDevCfgNameMidiPort(
  442. cmDevCfgH_t h,
  443. const cmChar_t* dcLabelStr,
  444. const cmChar_t* devLabelStr,
  445. const cmChar_t* portLabelStr,
  446. bool inputFl )
  447. {
  448. cmDcm_t* p = _cmDcmHandleToPtr(h);
  449. cmDcmCfg_t* cp;
  450. unsigned midiDevIdx;
  451. unsigned midiPortIdx;
  452. // validate the label
  453. if((dcLabelStr = _cmDcmTrimLabel(p,dcLabelStr,"MIDI cfg")) == NULL)
  454. return cmErrLastRC(&p->err);
  455. // verify that the device label is valid
  456. if((midiDevIdx = cmMpDeviceNameToIndex( devLabelStr )) == cmInvalidIdx )
  457. return cmErrMsg(&p->err, kInvalidArgDcRC,"The MIDI device name '%s' is not valid.",devLabelStr);
  458. // verify that the port label is valid
  459. if((midiPortIdx = cmMpDevicePortNameToIndex( midiDevIdx, inputFl ? kInMpFl : kOutMpFl, portLabelStr )) == cmInvalidIdx )
  460. return cmErrMsg(&p->err, kInvalidArgDcRC,"The MIDI port name '%s' is not valid on the device '%s'.",portLabelStr,devLabelStr);
  461. // if dcLabelStr is already in use for this location and type then update
  462. // the assoc'd recd otherwise create a new one.
  463. if((cp = _cmDcmFindOrCreateCfg(p,kMidiDcmTId, dcLabelStr)) == NULL )
  464. return cmErrLastRC(&p->err);
  465. cp->u.m.devLabelStr = cmMemResizeStr(cp->u.m.devLabelStr,devLabelStr);
  466. cp->u.m.portLabelStr = cmMemResizeStr(cp->u.m.portLabelStr,portLabelStr);
  467. cp->u.m.inputFl = inputFl;
  468. cp->u.m.devIdx = midiDevIdx;
  469. cp->u.m.portIdx = midiPortIdx;
  470. cp->descStr = cmTsPrintfP(cp->descStr,"%s %s %s",inputFl?"Input":"Output",devLabelStr,portLabelStr);
  471. return kOkDcRC;
  472. }
  473. const cmDcmMidi_t* cmDevCfgMidiCfg( cmDevCfgH_t h, unsigned cfgIdx )
  474. {
  475. cmDcm_t* p = _cmDcmHandleToPtr(h);
  476. cmDcmCfg_t* cp;
  477. if((cp = _cmDevCfgIndexToPtr(p, kMidiDcmTId, cfgIdx, true )) == NULL )
  478. return NULL;
  479. return &cp->u.m;
  480. }
  481. const cmDcmMidi_t* cmDevCfgMidiDevMap( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId )
  482. {
  483. cmDcm_t* p = _cmDcmHandleToPtr(h);
  484. cmDcmMap_t* mp;
  485. if((mp =_cmDcmFindMap(p,kMidiDcmTId, usrAppId, usrMapId, true )) == NULL )
  486. return NULL;
  487. return &mp->cfg->u.m;
  488. }
  489. cmDcRC_t cmDevCfgNameAudioPort(
  490. cmDevCfgH_t h,
  491. const cmChar_t* dcLabelStr,
  492. const cmChar_t* inDevNameStr,
  493. const cmChar_t* outDevNameStr,
  494. bool syncInputFl,
  495. unsigned msgQueueByteCnt,
  496. unsigned devFramesPerCycle,
  497. unsigned dspFramesPerCycle,
  498. unsigned audioBufCnt,
  499. double srate )
  500. {
  501. cmDcm_t* p = _cmDcmHandleToPtr(h);
  502. cmDcmCfg_t* cp;
  503. unsigned inDevIdx;
  504. unsigned outDevIdx;
  505. // validate the label
  506. if((dcLabelStr = _cmDcmTrimLabel(p,dcLabelStr,"MIDI cfg")) == NULL)
  507. return cmErrLastRC(&p->err);
  508. // validate the input device
  509. if(( inDevIdx = cmApDeviceLabelToIndex(inDevNameStr)) == cmInvalidIdx )
  510. return cmErrMsg(&p->err, kInvalidArgDcRC,"The input audio device name '%s' is not valid.",cmStringNullGuard(inDevNameStr));
  511. // validate the output device
  512. if(( outDevIdx = cmApDeviceLabelToIndex(outDevNameStr)) == cmInvalidIdx )
  513. return cmErrMsg(&p->err, kInvalidArgDcRC,"The output audio device name '%s' is not valid.",cmStringNullGuard(outDevNameStr));
  514. // if dcLabelStr is already in use for this location and type then update
  515. // the assoc'd recd otherwise create a new one.
  516. if((cp = _cmDcmFindOrCreateCfg(p,kAudioDcmTId, dcLabelStr)) == NULL )
  517. return cmErrLastRC(&p->err);
  518. cp->u.a.inDevLabelStr = cmMemAllocStr(inDevNameStr);
  519. cp->u.a.outDevLabelStr = cmMemAllocStr(outDevNameStr);
  520. cp->u.a.audioSysArgs.rpt = p->err.rpt;
  521. cp->u.a.audioSysArgs.inDevIdx = inDevIdx;
  522. cp->u.a.audioSysArgs.outDevIdx = outDevIdx;
  523. cp->u.a.audioSysArgs.syncInputFl = syncInputFl;
  524. cp->u.a.audioSysArgs.msgQueueByteCnt = msgQueueByteCnt;
  525. cp->u.a.audioSysArgs.devFramesPerCycle = devFramesPerCycle;
  526. cp->u.a.audioSysArgs.dspFramesPerCycle = dspFramesPerCycle;
  527. cp->u.a.audioSysArgs.audioBufCnt = audioBufCnt;
  528. cp->u.a.audioSysArgs.srate = srate;
  529. cp->descStr = cmTsPrintfP(cp->descStr,"In:%s Out:%s",inDevNameStr,outDevNameStr);
  530. return kOkDcRC;
  531. }
  532. const cmDcmAudio_t* cmDevCfgAudioCfg( cmDevCfgH_t h, unsigned cfgIdx )
  533. {
  534. cmDcm_t* p = _cmDcmHandleToPtr(h);
  535. cmDcmCfg_t* cp;
  536. if((cp = _cmDevCfgIndexToPtr(p, kAudioDcmTId, cfgIdx, true )) == NULL )
  537. return NULL;
  538. return &cp->u.a;
  539. }
  540. const cmDcmAudio_t* cmDevCfgAudioDevMap( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId )
  541. {
  542. cmDcm_t* p = _cmDcmHandleToPtr(h);
  543. cmDcmMap_t* mp;
  544. if((mp =_cmDcmFindMap(p,kAudioDcmTId, usrAppId, usrMapId, true )) == NULL )
  545. return NULL;
  546. return &mp->cfg->u.a;
  547. }
  548. cmDcRC_t cmDevCfgNetPort(
  549. cmDevCfgH_t h,
  550. const cmChar_t* dcLabelStr,
  551. const cmChar_t* sockAddr,
  552. unsigned portNumber )
  553. {
  554. cmDcm_t* p = _cmDcmHandleToPtr(h);
  555. cmDcmCfg_t* cp;
  556. if( portNumber > 0xffff )
  557. return cmErrMsg(&p->err,kInvalidArgDcRC,"The network port number %i is invalid. The valid IP port number range is:0-0xffff.");
  558. // validate the label
  559. if((dcLabelStr = _cmDcmTrimLabel(p,dcLabelStr,"MIDI cfg")) == NULL)
  560. return cmErrLastRC(&p->err);
  561. // if dcLabelStr is already in use for this location and type then update
  562. // the assoc'd recd otherwise create a new one.
  563. if((cp = _cmDcmFindOrCreateCfg(p,kAudioDcmTId, dcLabelStr)) == NULL )
  564. return cmErrLastRC(&p->err);
  565. cp->u.n.sockAddr = cmMemAllocStr(sockAddr);
  566. cp->u.n.portNumber = portNumber;
  567. cp->descStr = cmTsPrintfP(cp->descStr,"%s:%i",sockAddr,portNumber);
  568. return kOkDcRC;
  569. }
  570. const cmDcmNet_t* cmDevCfgNetCfg( cmDevCfgH_t h, unsigned cfgIdx )
  571. {
  572. cmDcm_t* p = _cmDcmHandleToPtr(h);
  573. cmDcmCfg_t* cp;
  574. if((cp = _cmDevCfgIndexToPtr(p, kNetDcmTId, cfgIdx, true )) == NULL )
  575. return NULL;
  576. return &cp->u.n;
  577. }
  578. const cmDcmNet_t* cmDevCfgNetDevMap( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId )
  579. {
  580. cmDcm_t* p = _cmDcmHandleToPtr(h);
  581. cmDcmMap_t* mp;
  582. if((mp =_cmDcmFindMap(p,kNetDcmTId, usrAppId, usrMapId, true )) == NULL )
  583. return NULL;
  584. return &mp->cfg->u.n;
  585. }
  586. unsigned cmDevCfgLocCount( cmDevCfgH_t h )
  587. {
  588. unsigned n = 0;
  589. cmDcm_t* p = _cmDcmHandleToPtr(h);
  590. const cmDcmLoc_t* lp = p->loc;
  591. for(; lp!=NULL; lp=lp->next)
  592. ++n;
  593. return n;
  594. }
  595. const cmChar_t* cmDevCfgLocLabel( cmDevCfgH_t h, unsigned locIdx )
  596. {
  597. unsigned n = 0;
  598. cmDcm_t* p = _cmDcmHandleToPtr(h);
  599. const cmDcmLoc_t* lp = p->loc;
  600. for(; lp!=NULL; lp=lp->next)
  601. if( n == locIdx )
  602. return lp->labelStr;
  603. assert(0);
  604. return NULL;
  605. }
  606. cmDcmLoc_t* _cmDcmLocLabelToPtr( cmDcm_t* p, const cmChar_t* locLabelStr)
  607. {
  608. if((locLabelStr = _cmDcmTrimLabel(p,locLabelStr,"location")) == NULL )
  609. return NULL;
  610. cmDcmLoc_t* lp = p->loc;
  611. for(; lp!=NULL; lp=lp->next)
  612. if( strcmp(lp->labelStr,locLabelStr) == 0 )
  613. return lp;
  614. cmErrMsg(&p->err,kLabelNotFoundDcRC,"The location label '%s' was not found.",locLabelStr);
  615. return NULL;
  616. }
  617. cmDcRC_t cmDevCfgLocStore( cmDevCfgH_t h, const cmChar_t* locLabelStr )
  618. {
  619. cmDcRC_t rc = kOkDcRC;
  620. cmDcm_t* p = _cmDcmHandleToPtr(h);
  621. unsigned i,j;
  622. // if this location label is already in use then it has already been stored.
  623. if( _cmDcmLocLabelToPtr(p,locLabelStr) != NULL )
  624. return kOkDcRC;
  625. // store the current loc ptr
  626. cmDcmLoc_t* olp = p->clp;
  627. cmDcmLoc_t* nlp;
  628. // create a new location recd and make it current
  629. if((rc = _cmDcmNewLoc(p,locLabelStr,&nlp)) != kOkDcRC )
  630. return kOkDcRC;
  631. // duplicate the cfg's
  632. cmDcmCfg_t* ocp = olp->cfg;
  633. for(; ocp!=NULL; ocp=ocp->next)
  634. {
  635. cmDcmCfg_t* ncp;
  636. if((ncp = _cmDcmFindOrCreateCfg(p,ocp->typeId, ocp->dcLabelStr)) == NULL )
  637. {
  638. rc = cmErrLastRC(&p->err);
  639. goto errLabel;
  640. }
  641. switch( ncp->typeId )
  642. {
  643. case kMidiDcmTId: _cmDcmDuplMidi(&ncp->u.m,&ocp->u.m); break;
  644. case kAudioDcmTId: _cmDcmDuplAudio(&ncp->u.a,&ocp->u.a); break;
  645. case kNetDcmTId: _cmDcmDuplNet( &ncp->u.n,&ocp->u.n); break;
  646. default:
  647. assert(0);
  648. break;
  649. }
  650. }
  651. // duplicate the app array
  652. nlp->appCnt = olp->appCnt;
  653. nlp->app = cmMemAllocZ(cmDcmApp_t,nlp->appCnt);
  654. for(i=0; i<nlp->appCnt; ++i)
  655. {
  656. cmDcmApp_t* nap = nlp->app + i;
  657. cmDcmApp_t* oap = olp->app + i;
  658. //nap->usrAppId = oap->usrAppId;
  659. nap->activeFl = oap->activeFl;
  660. nap->mapCnt = oap->mapCnt;
  661. nap->map = cmMemAllocZ(cmDcmMap_t,nap->mapCnt);
  662. for(j=0; j<nap->mapCnt; ++j)
  663. {
  664. cmDcmMap_t* nmp = nap->map + j;
  665. cmDcmMap_t* omp = oap->map + j;
  666. nmp->tid = omp->tid;
  667. nmp->cfgId = omp->cfgId;
  668. if( omp->tid != kInvalidDcmTId && omp->cfg->dcLabelStr != NULL )
  669. nmp->cfg = _cmDcmCfgLabelToPtr(p,nmp->tid,omp->cfg->dcLabelStr,true);
  670. }
  671. }
  672. errLabel:
  673. if( rc != kOkDcRC )
  674. _cmDcmFreeLoc(p,nlp);
  675. return rc;
  676. }
  677. cmDcRC_t cmDevCfgLocRecall( cmDevCfgH_t h, const cmChar_t* locLabelStr )
  678. {
  679. cmDcm_t* p = _cmDcmHandleToPtr(h);
  680. cmDcmLoc_t* lp;
  681. if((lp = _cmDcmLocLabelToPtr(p,locLabelStr)) == NULL)
  682. return cmErrLastRC(&p->err);
  683. p->clp = lp;
  684. return kOkDcRC;
  685. }
  686. cmDcRC_t cmDevCfgLocDelete( cmDevCfgH_t h, const cmChar_t* locLabelStr )
  687. {
  688. cmDcm_t* p = _cmDcmHandleToPtr(h);
  689. cmDcmLoc_t* lp;
  690. if((lp = _cmDcmLocLabelToPtr(p,locLabelStr)) == NULL )
  691. return cmErrLastRC(&p->err);
  692. _cmDcmFreeLoc(p,lp);
  693. return kOkDcRC;
  694. }
  695. unsigned cmDevCfgLocCurIndex( cmDevCfgH_t h )
  696. {
  697. unsigned i;
  698. cmDcm_t* p = _cmDcmHandleToPtr(h);
  699. cmDcmLoc_t* lp = p->loc;
  700. for(i=0; lp!=NULL; lp=lp->next,++i)
  701. if( lp == p->clp )
  702. return i;
  703. assert(0);
  704. return cmInvalidIdx;
  705. }
  706. cmDcRC_t _cmDcmJsonNotFound( cmDcm_t* p, const cmChar_t* tagStr )
  707. { return cmErrMsg(&p->err,kJsonFailDcRC,"JSON element '%s' not found.",tagStr); }
  708. cmDcRC_t _cmDcmJsonSyntaxErr( cmDcm_t* p, const cmChar_t* tagStr )
  709. { return cmErrMsg(&p->err,kJsonFailDcRC,"JSON syntax error '%s' not found.",tagStr); }
  710. cmDcRC_t _cmDevCfgRead( cmDevCfgH_t h, cmJsonH_t jsH, const cmJsonNode_t* rootObjPtr )
  711. {
  712. cmDcRC_t rc = kOkDcRC;
  713. const cmChar_t* errLabelPtr = NULL;
  714. cmJsonNode_t* cfgNp, *locArrNp;
  715. unsigned i,j;
  716. cmDcm_t* p = _cmDcmHandleToPtr(h);
  717. // clear the all locations
  718. _cmDcmFreeAllLocs(p);
  719. if((cfgNp = cmJsonFindValue(jsH, "cfg", rootObjPtr, kObjectTId )) == NULL )
  720. return _cmDcmJsonNotFound(p,"cfg");
  721. // get loc array
  722. if((locArrNp = cmJsonFindValue(jsH,"loc",cfgNp, kArrayTId )) == NULL )
  723. return _cmDcmJsonNotFound(p,"loc");
  724. // for each loc object
  725. for(i=0; i<cmJsonChildCount(locArrNp); ++i)
  726. {
  727. cmJsonNode_t* locObjNp, *cfgArrNp;
  728. const cmChar_t* label = NULL;
  729. // get the loc object
  730. if((locObjNp = cmJsonArrayElement(locArrNp,i)) == NULL || cmJsonIsObject(locObjNp)==false )
  731. return _cmDcmJsonSyntaxErr(p,"loc object");
  732. // read the loc object fields
  733. if( cmJsonMemberValues(locObjNp, &errLabelPtr,
  734. "label", kStringTId, &label,
  735. "cfg", kArrayTId, &cfgArrNp,
  736. NULL ) == kOkJsRC )
  737. { return _cmDcmJsonNotFound(p,errLabelPtr); }
  738. // create a new location recd
  739. cmDcmLoc_t* locPtr = NULL;
  740. if((rc = _cmDcmNewLoc(p,label,&locPtr)) == kOkDcRC )
  741. return cmErrMsg(&p->err,kJsonFailDcRC,"Location '%s' create failed.",cmStringNullGuard(label));
  742. /*
  743. // read each app object
  744. for(j=0; j<cmJsonChildCount(appArrNp); ++j)
  745. {
  746. cmJsonNode_t* appObjNp;
  747. // get the app object
  748. if((appObjNp = cmJsonArrayElement(appArrNp,j)) == NULL || cmJsonIsObject(appObjNp)==false )
  749. return _cmDcmJsonSyntaxErr(p,"loc object");
  750. // locate the map array
  751. cmJsonNode_t* mapArrNp;
  752. if((mapArrNp = cmJsonFindValue(jsH,"map",appObjNp,kArrayTId)) == NULL )
  753. return _cmDcmJsonNotFound(p,"map");
  754. // for each map array
  755. for(k=0; k<cmJsonChildCount(mapArrNp); ++k)
  756. {
  757. unsigned tid,cfgId;
  758. cmJsonNode_t* mapObjNp;
  759. if((mapObjNp = cmJsonArrayElement(mapArrNp,j))==NULL || cmJsonIsObject(mapObjNp)==false)
  760. return _cmDcmJsonSyntaxErr(p,"cfg object");
  761. if( cmJsonMemberValues( mapObjNp, &errLabelPtr,
  762. "tid", kIntTId, &tid,
  763. "cfgId", kIntTId, &cfgId,
  764. NULL ) != kOkDcRC )
  765. { return _cmDcmJsonSyntaxErr(p,errLabelPtr); }
  766. }
  767. }
  768. */
  769. // read each cfg object
  770. for(j=0; j<cmJsonChildCount(cfgArrNp); ++j)
  771. {
  772. cmJsonNode_t* cfgObjNp;
  773. const cmChar_t* dcLabelStr;
  774. const cmChar_t* descStr;
  775. unsigned cfgId, typeId;
  776. if((cfgObjNp = cmJsonArrayElement(cfgArrNp,j))==NULL || cmJsonIsObject(cfgObjNp)==false)
  777. return _cmDcmJsonSyntaxErr(p,"cfg object");
  778. if( cmJsonMemberValues( cfgObjNp, &errLabelPtr,
  779. "label", kStringTId, &dcLabelStr,
  780. "cfgId", kIntTId, &cfgId,
  781. "typeId", kIntTId, &typeId,
  782. "desc", kStringTId, &descStr,
  783. NULL ) == kOkJsRC )
  784. { _cmDcmJsonSyntaxErr(p,errLabelPtr); }
  785. cmDcmMidi_t m;
  786. cmDcmAudio_t a;
  787. cmDcmNet_t n;
  788. switch( typeId )
  789. {
  790. case kMidiDcmTId:
  791. if( cmJsonMemberValues( cfgObjNp, &errLabelPtr,
  792. "devLabelStr", kStringTId, &m.devLabelStr,
  793. "portLabelStr",kStringTId, &m.portLabelStr,
  794. NULL) != kOkJsRC )
  795. {}
  796. cmDevCfgNameMidiPort(h,label,m.devLabelStr,m.portLabelStr,m.inputFl);
  797. break;
  798. case kAudioDcmTId:
  799. if( cmJsonMemberValues( cfgObjNp, &errLabelPtr,
  800. "inDevLabelStr", kStringTId, &a.inDevLabelStr,
  801. "outDevLabelStr", kStringTId, &a.outDevLabelStr,
  802. "syncInputFl", kBoolTId, &a.audioSysArgs.syncInputFl,
  803. "msgQueueByteCnt", kIntTId, &a.audioSysArgs.msgQueueByteCnt,
  804. "devFramesPerCycle", kIntTId, &a.audioSysArgs.devFramesPerCycle,
  805. "dspFramesPerCycle", kIntTId, &a.audioSysArgs.dspFramesPerCycle,
  806. "audioBufCnt", kIntTId, &a.audioSysArgs.audioBufCnt,
  807. "srate", kIntTId, &a.audioSysArgs.srate ) == kOkJsRC )
  808. {}
  809. cmDevCfgNameAudioPort(h,label,a.inDevLabelStr,a.outDevLabelStr,
  810. a.audioSysArgs.syncInputFl,
  811. a.audioSysArgs.msgQueueByteCnt,
  812. a.audioSysArgs.devFramesPerCycle,
  813. a.audioSysArgs.dspFramesPerCycle,
  814. a.audioSysArgs.audioBufCnt,
  815. a.audioSysArgs.srate );
  816. break;
  817. case kNetDcmTId:
  818. if( cmJsonMemberValues( cfgObjNp, &errLabelPtr,
  819. "sockAddr", kStringTId, &n.sockAddr,
  820. "portNumber", kIntTId, &n.portNumber,
  821. NULL ) != kOkJsRC )
  822. {}
  823. cmDevCfgNetPort(h,label,n.sockAddr,n.portNumber);
  824. break;
  825. default:
  826. assert(0);
  827. break;
  828. }
  829. }
  830. }
  831. return kOkDcRC;
  832. }
  833. cmDcRC_t _cmDevCfgWrite( cmDcm_t* p, cmJsonH_t jsH, cmJsonNode_t* rootObjPtr )
  834. {
  835. cmDcRC_t rc = kOkDcRC;
  836. const cmDcmLoc_t* lp;
  837. cmJsonNode_t* cfgNp = cmJsonInsertPairObject(jsH, rootObjPtr, "cfg" );
  838. // create the loc array
  839. cmJsonNode_t* locArrNp = cmJsonInsertPairArray( jsH, cfgNp, "loc" );
  840. for(; lp!=NULL; lp=lp->next)
  841. {
  842. // create the 'loc' object
  843. cmJsonNode_t* locObjNp = cmJsonCreateObject(jsH,locArrNp);
  844. // set the loc label
  845. cmJsonInsertPairString(jsH, locObjNp, lp->labelStr, "label" );
  846. /*
  847. // create the 'loc.app[]' array
  848. cmJsonNode_t* appArrNp = cmJsonInsertPairArray(jsH,locObjNp,"app");
  849. // for each app recd
  850. for(i=0; i<lp->appCnt; ++i)
  851. if( lp->app[i].activeFl )
  852. {
  853. // create the app recd
  854. cmJsonNode_t* appNp = cmJsonCreateObject(jsH,appArrNp );
  855. // create the map array
  856. cmJsonNode_t* mapArrNp = cmJsonInsertPairArray(jsH, appNp, "map" );
  857. // for each map recd
  858. for(j=0; j<lp->app[i].mapCnt; ++j)
  859. {
  860. cmJsonNode_t* mapNp = cmJsonCreateObject(jsH,mapArrNp);
  861. cmJsonInsertPairs(jsH, mapNp,
  862. "tid", kIntTId, lp->app[i].map[j].tid,
  863. "cfgId", kIntTId, lp->app[i].map[j].cfgId,
  864. NULL );
  865. }
  866. }
  867. */
  868. // create the 'loc.cfg[]' array
  869. cmJsonNode_t* cfgArrNp = cmJsonInsertPairArray(jsH,locObjNp,"cfg");
  870. // for each cfg recd
  871. cmDcmCfg_t* cp = lp->cfg;
  872. for(; cp!=NULL; cp=cp->next)
  873. {
  874. // create the cfg recd
  875. cmJsonNode_t* cfgObjNp = cmJsonCreateObject(jsH,cfgArrNp);
  876. // fill the cfg recd
  877. cmJsonInsertPairs(jsH, cfgObjNp,
  878. "label", kStringTId, cp->dcLabelStr,
  879. "cfgId", kIntTId, cp->cfgId,
  880. "typeId", kIntTId, cp->typeId,
  881. "desc", kStringTId, cp->descStr,
  882. NULL );
  883. switch( cp->typeId )
  884. {
  885. case kMidiDcmTId:
  886. cmJsonInsertPairs(jsH, cfgObjNp,
  887. "devLabelStr", kStringTId, cp->u.m.devLabelStr,
  888. "portLabelStr",kStringTId, cp->u.m.portLabelStr,
  889. "inputFl", kBoolTId, cp->u.m.inputFl,
  890. NULL );
  891. break;
  892. case kAudioDcmTId:
  893. cmJsonInsertPairs(jsH, cfgObjNp,
  894. "inDevLabelStr", kStringTId, cp->u.a.inDevLabelStr,
  895. "outDevLabelStr", kStringTId, cp->u.a.outDevLabelStr,
  896. "syncInputFl", kBoolTId, cp->u.a.audioSysArgs.syncInputFl,
  897. "msgQueueByteCnt", kIntTId, cp->u.a.audioSysArgs.msgQueueByteCnt,
  898. "devFramesPerCycle", kIntTId, cp->u.a.audioSysArgs.devFramesPerCycle,
  899. "dspFramesPerCycle", kIntTId, cp->u.a.audioSysArgs.dspFramesPerCycle,
  900. "audioBufCnt", kIntTId, cp->u.a.audioSysArgs.audioBufCnt,
  901. "srate", kIntTId, cp->u.a.audioSysArgs.srate,
  902. NULL );
  903. break;
  904. case kNetDcmTId:
  905. cmJsonInsertPairs(jsH, cfgObjNp,
  906. "sockAddr", kStringTId, cp->u.n.sockAddr,
  907. "portNumber",kIntTId, cp->u.n.portNumber,
  908. NULL );
  909. break;
  910. default:
  911. assert(0);
  912. break;
  913. }
  914. }
  915. }
  916. return rc;
  917. }
  918. cmDcRC_t cmDevCfgWrite( cmDevCfgH_t h )
  919. {
  920. cmDcRC_t rc = kOkDcRC;
  921. return rc;
  922. }