libcm is a C development framework with an emphasis on audio signal processing applications.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

cmDevCfg.c 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023
  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 "cmJson.h"
  9. #include "cmThread.h"
  10. #include "cmMidi.h"
  11. #include "cmMidiPort.h"
  12. #include "cmAudioPort.h"
  13. #include "cmUdpPort.h"
  14. #include "cmUdpNet.h"
  15. #include "cmAudioSysMsg.h"
  16. #include "cmAudioSys.h"
  17. #include "cmDevCfg.h"
  18. cmDevCfgH_t cmDevCfgNullHandle = cmSTATIC_NULL_HANDLE;
  19. typedef struct
  20. {
  21. cmChar_t* dcLabelStr; // Name of this cfg recd or NULL if the recd is inactive.
  22. cmChar_t* devLabelStr; // Midi device label.
  23. cmChar_t* portLabelStr; // Midi device port label.
  24. bool inputFl; // 'True' if this is an input port.
  25. unsigned devIdx; // Midi device index.
  26. unsigned portIdx; // Midi port index.
  27. } cmDcmMidi_t;
  28. typedef struct
  29. {
  30. cmChar_t* dcLabelStr; // Name of this cfg record or NULL if the recd is inactive.
  31. cmChar_t* inDevLabelStr; // Input audio device label.
  32. cmChar_t* outDevLabelStr; // Output audio device label.
  33. cmAudioSysArgs_t ss;
  34. } cmDcmAudio_t;
  35. typedef struct
  36. {
  37. cmChar_t* dcLabelStr; // Name of this cfg recd or NULL if the recd is inactive
  38. cmChar_t* sockAddr; // Remote socket address.
  39. unsigned portNumber; // Remote socket port number
  40. unsigned netNodeId; // Network node id associated with sockAddr and portNumber.
  41. } cmDcmNet_t;
  42. typedef struct
  43. {
  44. cmTypeDcmId_t tid; // Type Id for this map or tInvalidDcmTId if the record is not active.
  45. unsigned usrDevId; // Same as index into p->map[] for this recd.
  46. unsigned cfgIndex; // Index into p->midi[],p->audio[], or p->net[].
  47. } cmDcmMap_t;
  48. typedef struct
  49. {
  50. unsigned usrAppId;
  51. bool activeFl;
  52. cmDcmMap_t* map;
  53. unsigned mapCnt;
  54. } cmDcmApp_t;
  55. typedef struct
  56. {
  57. cmChar_t* labelStr;
  58. cmDcmApp_t* app;
  59. unsigned appCnt;
  60. cmDcmMidi_t* midi;
  61. unsigned midiCnt;
  62. cmDcmAudio_t* audio;
  63. unsigned audioCnt;
  64. cmDcmNet_t* net;
  65. unsigned netCnt;
  66. } cmDcmLoc_t;
  67. typedef struct
  68. {
  69. cmErr_t err;
  70. cmDcmLoc_t* loc;
  71. unsigned locCnt;
  72. cmDcmLoc_t* l;
  73. } cmDcm_t;
  74. cmDcm_t* _cmDcmHandleToPtr( cmDevCfgH_t h )
  75. {
  76. cmDcm_t* p = (cmDcm_t*)h.h;
  77. assert( p!=NULL );
  78. return p;
  79. }
  80. void _cmDcmAppDupl( cmDcmApp_t* d, const cmDcmApp_t* s )
  81. {
  82. *d = *s;
  83. if( d->activeFl )
  84. {
  85. unsigned i;
  86. d->map = cmMemAllocZ(cmDcmMap_t,s->mapCnt);
  87. for(i=0; i<s->mapCnt; ++i)
  88. d->map[i] = s->map[i];
  89. }
  90. else
  91. {
  92. d->mapCnt = 0;
  93. d->map = NULL;
  94. }
  95. }
  96. void _cmDcmMidiFree( cmDcmMidi_t* r )
  97. {
  98. cmMemPtrFree(&r->dcLabelStr);
  99. cmMemPtrFree(&r->devLabelStr);
  100. cmMemPtrFree(&r->portLabelStr);
  101. }
  102. void _cmDcmMidiDupl( cmDcmMidi_t* d, const cmDcmMidi_t* s )
  103. {
  104. d->dcLabelStr = cmMemAllocStr(s->dcLabelStr);
  105. d->devLabelStr = cmMemAllocStr(s->devLabelStr);
  106. d->portLabelStr = cmMemAllocStr(s->portLabelStr);
  107. d->inputFl = s->inputFl;
  108. d->devIdx = s->devIdx;
  109. d->portIdx = s->portIdx;
  110. }
  111. void _cmDcmAudioFree( cmDcmAudio_t* r )
  112. {
  113. cmMemPtrFree(&r->dcLabelStr);
  114. cmMemPtrFree(&r->inDevLabelStr);
  115. cmMemPtrFree(&r->outDevLabelStr);
  116. }
  117. void _cmDcmAudioDupl( cmDcmAudio_t* d, const cmDcmAudio_t* s )
  118. {
  119. d->dcLabelStr = cmMemAllocStr(s->dcLabelStr);
  120. d->inDevLabelStr = cmMemAllocStr(s->inDevLabelStr);
  121. d->outDevLabelStr = cmMemAllocStr(s->outDevLabelStr);
  122. d->ss = s->ss;
  123. }
  124. void _cmDcmNetFree( cmDcmNet_t* r )
  125. {
  126. cmMemPtrFree(&r->dcLabelStr);
  127. cmMemPtrFree(&r->sockAddr);
  128. }
  129. void _cmDcmNetDupl( cmDcmNet_t* d, const cmDcmNet_t* s )
  130. {
  131. d->dcLabelStr = cmMemAllocStr(s->dcLabelStr);
  132. d->sockAddr = cmMemAllocStr(s->sockAddr);
  133. d->portNumber = s->portNumber;
  134. d->netNodeId = s->netNodeId;
  135. }
  136. void _cmDcmAppFree( cmDcmApp_t* r )
  137. {
  138. cmMemPtrFree(&r->map);
  139. }
  140. cmDcRC_t _cmDcmFreeLoc( cmDcm_t* p, cmDcmLoc_t* loc )
  141. {
  142. unsigned i;
  143. for(i=0; loc->midi!=NULL && i<loc->midiCnt; ++i)
  144. _cmDcmMidiFree(loc->midi + i );
  145. cmMemPtrFree(&loc->midi);
  146. loc->midiCnt = 0;
  147. for(i=0; loc->audio!=NULL && i<loc->audioCnt; ++i)
  148. _cmDcmAudioFree(loc->audio + i );
  149. cmMemPtrFree(&loc->audio);
  150. loc->audioCnt = 0;
  151. for(i=0; loc->net!=NULL && i<loc->netCnt; ++i)
  152. _cmDcmNetFree(loc->net + i );
  153. cmMemPtrFree(&loc->net);
  154. loc->netCnt = 0;
  155. for(i=0; loc->app!=NULL && i<loc->appCnt; ++i)
  156. _cmDcmAppFree(loc->app + i );
  157. cmMemPtrFree(&loc->app);
  158. loc->appCnt = 0;
  159. cmMemPtrFree(&loc->labelStr);
  160. return kOkDcRC;
  161. }
  162. cmDcRC_t _cmDcmFree( cmDcm_t* p )
  163. {
  164. cmDcRC_t rc = kOkDcRC;
  165. unsigned i;
  166. for(i=0; i<p->locCnt; ++i)
  167. if((rc = _cmDcmFreeLoc(p,p->loc + i )) != kOkDcRC )
  168. return rc;
  169. cmMemPtrFree(&p->loc);
  170. return rc;
  171. }
  172. cmDcmMidi_t* _cmDcmMidiFind( cmDcm_t* p, const cmChar_t* dcLabelStr, bool errFl )
  173. {
  174. assert( dcLabelStr != NULL );
  175. unsigned i;
  176. for(i=0; i<p->l->midiCnt; ++i)
  177. if(p->l->midi[i].dcLabelStr!=NULL && strcmp(p->l->midi[i].dcLabelStr,dcLabelStr)==0)
  178. return p->l->midi + i;
  179. if( errFl )
  180. cmErrMsg(&p->err,cmLabelNotFoundDcRC,"The MIDI cfg. record '%s' not found.",dcLabelStr);
  181. return NULL;
  182. }
  183. cmDcmAudio_t* _cmDcmAudioFind( cmDcm_t* p, const cmChar_t* dcLabelStr, bool errFl )
  184. {
  185. assert( dcLabelStr != NULL );
  186. unsigned i;
  187. for(i=0; i<p->l->audioCnt; ++i)
  188. if(p->l->audio[i].dcLabelStr!=NULL && strcmp(p->l->audio[i].dcLabelStr,dcLabelStr)==0)
  189. return p->l->audio + i;
  190. if( errFl )
  191. cmErrMsg(&p->err,cmLabelNotFoundDcRC,"The audio cfg. record '%s' not found.",dcLabelStr);
  192. return NULL;
  193. }
  194. cmDcmNet_t* _cmDcmNetFind( cmDcm_t* p, const cmChar_t* dcLabelStr, bool errFl )
  195. {
  196. assert( dcLabelStr != NULL );
  197. unsigned i;
  198. for(i=0; i<p->l->netCnt; ++i)
  199. if(p->l->net[i].dcLabelStr!=NULL && strcmp(p->l->net[i].dcLabelStr,dcLabelStr)==0)
  200. return p->l->net + i;
  201. if( errFl )
  202. cmErrMsg(&p->err,cmLabelNotFoundDcRC,"The net cfg. record '%s' not found.",dcLabelStr);
  203. return NULL;
  204. }
  205. cmDcmApp_t* _cmDcmFindOrCreateApp(cmDcm_t* p, unsigned usrAppId )
  206. {
  207. cmDcmApp_t* a;
  208. if( usrAppId < p->l->appCnt )
  209. a = p->l->app + usrAppId;
  210. else
  211. {
  212. p->l->appCnt = usrAppId + 1;
  213. p->l->app = cmMemResizePZ(cmDcmApp_t,p->l->app,p->l->appCnt);
  214. a = p->l->app + usrAppId;
  215. a->usrAppId = usrAppId;
  216. a->activeFl = true;
  217. }
  218. return a;
  219. }
  220. cmDcmMap_t* _cmDcmFindOrCreateMap(cmDcm_t* p, cmDcmApp_t* a, unsigned usrDevId )
  221. {
  222. cmDcmMap_t* m;
  223. if( usrDevId < a->mapCnt )
  224. m = a->map + usrDevId;
  225. else
  226. {
  227. a->mapCnt = usrDevId + 1;
  228. a->map = cmMemResizePZ(cmDcmMap_t,a->map,a->mapCnt);
  229. m = a->map + usrDevId;
  230. m->usrDevId = usrDevId;
  231. }
  232. return m;
  233. }
  234. cmDcRC_t _cmDcmLookupApp(cmDcm_t* p, unsigned usrAppId, cmDcmApp_t** appRef)
  235. {
  236. // validate the usrAppId
  237. if( usrAppId >= p->l->appCnt )
  238. return cmErrMsg(&p->err,kInvalidDevArgDcRC,"Invalid user app. id:%i\n",usrAppId);
  239. // check that the app recd is active
  240. if( p->l->app[usrAppId].activeFl == false )
  241. return cmErrMsg(&p->err,kInvalidDevArgDcRC,"The user app. with id:%i is not active.",usrAppId);
  242. *appRef = p->l->app + usrAppId;
  243. return kOkDcRC;
  244. }
  245. cmDcRC_t _cmDcmLookupMap(cmDcm_t* p, cmDcmApp_t* a, unsigned usrDevId, cmDcmMap_t** mapRef )
  246. {
  247. // validate the usrDevId
  248. if( usrDevId >= a->mapCnt )
  249. return cmErrMsg(&p->err,kInvalidDevArgDcRC,"Invalid user device id:%i on app:%i\n",usrDevId,a->usrAppId);
  250. // check that the map recd is active
  251. if( a->map[ usrDevId ].tid == kInvalidDcmTId )
  252. return cmErrMsg(&p->err,kInvalidDevArgDcRC,"The user device id:%i on app:%i is not active.",usrDevId,a->usrAppId);
  253. *mapRef = a->map + usrDevId;
  254. return kOkDcRC;
  255. }
  256. cmDcRC_t _cmDcmLookupAppMap(cmDcm_t* p, unsigned usrAppId, unsigned usrDevId, cmDcmMap_t** mapRef )
  257. {
  258. cmDcRC_t rc;
  259. cmDcmApp_t* a;
  260. if((rc = _cmDcmLookupApp(p,usrAppId,&a)) == kOkDcRC )
  261. return rc;
  262. return _cmDcmLookupMap(p,a,usrDevId,mapRef );
  263. }
  264. // Delete all maps in all apps which reference a particular cfg recd.
  265. void _cmDevCfgDeleteCfgMaps( cmDcm_t* p, cmTypeDcmId_t tid, unsigned cfgIndex )
  266. {
  267. unsigned i,j;
  268. for(i=0; i<p->l->appCnt; ++i)
  269. if( p->l->app[i].activeFl )
  270. for(j=0; j<p->l->app[i].mapCnt; ++j)
  271. if( p->l->app[i].map[j].tid == tid && p->l->app[i].map[j].cfgIndex == cfgIndex )
  272. {
  273. p->l->app[i].map[j].tid = kInvalidDcmTId;
  274. break;
  275. }
  276. }
  277. cmDcRC_t _cmDcmFindCfgIndex( cmDcm_t* p, cmTypeDcmId_t tid, const cmChar_t* dcLabelStr, unsigned* cfgIndexRef )
  278. {
  279. cmDcRC_t rc = kOkDcRC;
  280. *cfgIndexRef = cmInvalidIdx;
  281. switch( tid )
  282. {
  283. case kMidiDcmTId:
  284. {
  285. const cmDcmMidi_t* r;
  286. if((r = _cmDcmMidiFind(p,dcLabelStr,true)) == NULL )
  287. rc = cmErrLastRC(&p->err);
  288. else
  289. *cfgIndexRef = r - p->l->midi;
  290. }
  291. break;
  292. case kAudioDcmTId:
  293. {
  294. const cmDcmAudio_t* r;
  295. if((r = _cmDcmAudioFind(p,dcLabelStr,true)) == NULL )
  296. rc = cmErrLastRC(&p->err);
  297. else
  298. *cfgIndexRef = r - p->l->audio;
  299. }
  300. break;
  301. case kNetDcmTId:
  302. {
  303. const cmDcmNet_t* r;
  304. if((r = _cmDcmNetFind(p,dcLabelStr,true)) == NULL )
  305. rc = cmErrLastRC(&p->err);
  306. else
  307. *cfgIndexRef = r - p->l->net;
  308. }
  309. break;
  310. default:
  311. assert(0);
  312. break;
  313. }
  314. return rc;
  315. }
  316. cmDcRC_t _cmDevCfgDeleteCfg( cmDcm_t* p, cmTypeDcmId_t tid, unsigned cfgIndex )
  317. {
  318. // release any resources held by this cfg record and mark
  319. // the record as inactive by setting the dcLabelStr field to NULL.
  320. switch( tid )
  321. {
  322. case kMidiDcmTId:
  323. _cmDcmMidiFree( p->l->midi + cfgIndex );
  324. break;
  325. case kAudioDcmTId:
  326. _cmDcmAudioFree( p->l->audio + cfgIndex );
  327. break;
  328. case kNetDcmTId:
  329. _cmDcmNetFree( p->l->net + cfgIndex );
  330. break;
  331. default:
  332. assert(0);
  333. break;
  334. }
  335. // delete all maps which reference this cfg recd
  336. if( cfgIndex != cmInvalidIdx )
  337. _cmDevCfgDeleteCfgMaps(p, tid, cfgIndex );
  338. return kOkDcRC;
  339. }
  340. cmDcRC_t cmDevCfgMgrAlloc( cmCtx_t* ctx, cmDevCfgH_t* hp )
  341. {
  342. cmDcRC_t rc;
  343. if((rc = cmDevCfgMgrFree(hp)) != kOkDcRC )
  344. return rc;
  345. cmDcm_t* p = cmMemAllocZ(cmDcm_t,1);
  346. cmErrSetup(&p->err,&ctx->rpt,"DevCfgMgr");
  347. p->loc = cmMemAllocZ(cmDcmLoc_t,1);
  348. p->locCnt = 1;
  349. p->l = p->loc;
  350. p->l->labelStr = cmMemAllocStr("Default");
  351. hp->h = p;
  352. if( rc != kOkDcRC )
  353. _cmDcmFree(p);
  354. return rc;
  355. }
  356. cmDcRC_t cmDevCfgMgrFree( cmDevCfgH_t* hp )
  357. {
  358. cmDcRC_t rc = kOkDcRC;
  359. if(hp==NULL || cmDevCfgIsValid(*hp)==false)
  360. return rc;
  361. cmDcm_t* p = _cmDcmHandleToPtr(*hp);
  362. if((rc = _cmDcmFree(p)) != kOkDcRC )
  363. return rc;
  364. cmMemFree(p);
  365. hp->h = NULL;
  366. return rc;
  367. }
  368. cmDcRC_t cmDevCfgIsValid( cmDevCfgH_t h )
  369. { return h.h != NULL; }
  370. unsigned cmDevCfgCount( cmDevCfgH_t h, cmTypeDcmId_t typeId )
  371. {
  372. cmDcm_t* p = _cmDcmHandleToPtr(h);
  373. unsigned n = 0;
  374. unsigned i;
  375. switch( typeId )
  376. {
  377. case kMidiDcmTId:
  378. for(i=0; i<p->l->midiCnt; ++i)
  379. if( p->l->midi[i].dcLabelStr != NULL )
  380. ++n;
  381. break;
  382. case kAudioDcmTId:
  383. for(i=0; i<p->l->audioCnt; ++i)
  384. if( p->l->audio[i].dcLabelStr != NULL )
  385. ++n;
  386. break;
  387. case kNetDcmTId:
  388. for(i=0; i<p->l->netCnt; ++i)
  389. if( p->l->net[i].dcLabelStr != NULL )
  390. ++n;
  391. break;
  392. default:
  393. assert(0);
  394. break;
  395. }
  396. return n;
  397. }
  398. const cmChar_t* cmDevCfgLabel( cmDevCfgH_t h, cmTypeDcmId_t typeId, unsigned index )
  399. {
  400. cmDcm_t* p = _cmDcmHandleToPtr(h);
  401. int j = -1;
  402. unsigned i;
  403. unsigned n = 0;
  404. const cmChar_t* s;
  405. switch( typeId )
  406. {
  407. case kMidiDcmTId:
  408. n = p->l->midiCnt;
  409. for(i=0; i<n; ++i)
  410. if( (s = p->l->midi[i].dcLabelStr) != NULL )
  411. if(++j == index )
  412. break;
  413. break;
  414. case kAudioDcmTId:
  415. n = p->l->audioCnt;
  416. for(i=0; i<n; ++i)
  417. if( (s = p->l->audio[i].dcLabelStr) != NULL )
  418. if(++j == index )
  419. break;
  420. break;
  421. case kNetDcmTId:
  422. n = p->l->netCnt;
  423. for(i=0; i<n; ++i)
  424. if( (s = p->l->net[i].dcLabelStr) != NULL )
  425. if(++j == index )
  426. break;
  427. break;
  428. default:
  429. assert(0);
  430. break;
  431. }
  432. if( i == n )
  433. return NULL;
  434. return s;
  435. }
  436. unsigned cmDevCfgLabelToIndex( cmDevCfgH_t h, cmTypeDcmId_t tid, const cmChar_t* dcLabelStr )
  437. {
  438. cmDcm_t* p = _cmDcmHandleToPtr(h);
  439. unsigned cfgIdx = cmInvalidIdx;
  440. if( _cmDcmFindCfgIndex( p, tid, dcLabelStr, &cfgIdx ) != kOkDcRC )
  441. return cmInvalidIdx;
  442. return cfgIdx;
  443. }
  444. cmDcRC_t cmDevCfgDeleteCfg( cmDevCfgH_t h, cmTypeDcmId_t tid, const cmChar_t* dcLabelStr )
  445. {
  446. cmDcRC_t rc;
  447. cmDcm_t* p = _cmDcmHandleToPtr(h);
  448. unsigned cfgIndex = cmInvalidIdx;
  449. // locate the cfg record index
  450. if((rc = _cmDcmFindCfgIndex(p,tid,dcLabelStr,&cfgIndex)) == kOkDcRC )
  451. return rc;
  452. return _cmDevCfgDeleteCfg( p, tid, cfgIndex );
  453. }
  454. cmDcRC_t cmDevCfgCreateMap( cmDevCfgH_t h, cmTypeDcmId_t tid, const cmChar_t* dcLabelStr, unsigned usrAppId, unsigned usrDevId )
  455. {
  456. cmDcRC_t rc = kOkDcRC;
  457. cmDcm_t* p = _cmDcmHandleToPtr(h);
  458. unsigned cfgIndex = cmInvalidIdx;
  459. if((rc = _cmDcmFindCfgIndex(p,tid,dcLabelStr,&cfgIndex)) == kOkDcRC )
  460. return rc;
  461. if( cfgIndex != cmInvalidIdx )
  462. {
  463. cmDcmApp_t* a;
  464. cmDcmMap_t* m;
  465. // locate or create the requested app recrod
  466. if((a = _cmDcmFindOrCreateApp(p,usrAppId)) == NULL )
  467. {
  468. rc = cmErrLastRC(&p->err);
  469. goto errLabel;
  470. }
  471. // locate or create the requested map record
  472. if((m = _cmDcmFindOrCreateMap(p,a,usrDevId)) == NULL )
  473. {
  474. rc = cmErrLastRC(&p->err);
  475. goto errLabel;
  476. }
  477. m->usrDevId = usrDevId;
  478. m->tid = tid;
  479. m->cfgIndex = cfgIndex;
  480. }
  481. errLabel:
  482. return rc;
  483. }
  484. cmDcRC_t cmDevCfgDeleteMap( cmDevCfgH_t h, cmTypeDcmId_t typeId, unsigned usrAppId, unsigned usrDevId )
  485. {
  486. cmDcRC_t rc = kOkDcRC;
  487. cmDcm_t* p = _cmDcmHandleToPtr(h);
  488. cmDcmMap_t* m;
  489. if((rc = _cmDcmLookupAppMap(p,usrAppId,usrDevId,&m)) != kOkDcRC )
  490. return rc;
  491. m->usrDevId = cmInvalidId;
  492. m->tid = kInvalidDcmTId;
  493. m->cfgIndex = cmInvalidIdx;
  494. return rc;
  495. }
  496. cmDcRC_t cmDevCfgNameMidiPort(
  497. cmDevCfgH_t h,
  498. const cmChar_t* dcLabelStr,
  499. const cmChar_t* devNameStr,
  500. const cmChar_t* portNameStr,
  501. bool inputFl )
  502. {
  503. cmDcRC_t rc = kOkDcRC;
  504. cmDcm_t* p = _cmDcmHandleToPtr(h);
  505. cmDcmMidi_t* r = _cmDcmMidiFind(p,dcLabelStr,false);
  506. unsigned i;
  507. // if 'dcLabelStr' was not already used then look for an empty MIDI record.
  508. if( r == NULL )
  509. for(i=0; i<p->l->midiCnt; ++i)
  510. if( p->l->midi[i].dcLabelStr == NULL )
  511. {
  512. r = p->l->midi + i;
  513. break;
  514. }
  515. // if no available cfg record exists then create one
  516. if( r == NULL )
  517. {
  518. p->l->midi = cmMemResizePZ(cmDcmMidi_t,p->l->midi,p->l->midiCnt+1);
  519. r = p->l->midi + p->l->midiCnt;
  520. p->l->midiCnt += 1;
  521. }
  522. assert( r != NULL );
  523. // verify that the device label is valid
  524. if((r->devIdx = cmMpDeviceNameToIndex( devNameStr )) == cmInvalidIdx )
  525. {
  526. rc = cmErrMsg(&p->err, kInvalidDevArgDcRC,"The MIDI device name '%s' is not valid.",devNameStr);
  527. goto errLabel;
  528. }
  529. // verify that the port label is valid
  530. if((r->portIdx = cmMpDevicePortNameToIndex( r->devIdx, r->inputFl ? kInMpFl : kOutMpFl, portNameStr )) == cmInvalidIdx )
  531. {
  532. rc = cmErrMsg(&p->err, kInvalidDevArgDcRC,"The MIDI port name '%s' is not valid on the device '%s'.",portNameStr,devNameStr);
  533. goto errLabel;
  534. }
  535. // if this cfg recd was not previously active then assign a cfg label
  536. if( r->dcLabelStr == NULL )
  537. r->dcLabelStr = cmMemAllocStr(dcLabelStr);
  538. // fill in the cfg recd
  539. r->devLabelStr = cmMemResizeStr(r->devLabelStr,devNameStr);
  540. r->portLabelStr = cmMemResizeStr(r->portLabelStr,portNameStr);
  541. r->inputFl = inputFl;
  542. errLabel:
  543. // on error delete the cfg record and any maps depending on it
  544. if( rc != kOkDcRC && r != NULL )
  545. _cmDevCfgDeleteCfg( p, kMidiDcmTId, r - p->l->midi );
  546. return rc;
  547. }
  548. cmDcRC_t cmDevCfgMidiDevIdx( cmDevCfgH_t h, unsigned usrAppId, unsigned usrDevId, unsigned* midiDevIdxRef, unsigned* midiPortIdxRef )
  549. {
  550. cmDcRC_t rc = kOkDcRC;
  551. cmDcm_t* p = _cmDcmHandleToPtr(h);
  552. cmDcmMap_t* m;
  553. if((rc = _cmDcmLookupAppMap(p,usrAppId,usrDevId,&m)) != kOkDcRC )
  554. return rc;
  555. cmDcmMidi_t* r = p->l->midi + m->cfgIndex;
  556. assert(r->dcLabelStr != NULL );
  557. *midiDevIdxRef = r->devIdx;
  558. *midiPortIdxRef = r->portIdx;
  559. return rc;
  560. }
  561. cmDcRC_t cmDevCfgNameAudioPort(
  562. cmDevCfgH_t h,
  563. const cmChar_t* dcLabelStr,
  564. const cmChar_t* inDevNameStr,
  565. const cmChar_t* outDevNameStr,
  566. bool syncInputFl,
  567. unsigned msgQueueByteCnt,
  568. unsigned devFramesPerCycle,
  569. unsigned dspFramesPerCycle,
  570. unsigned audioBufCnt,
  571. double srate )
  572. {
  573. cmDcRC_t rc = kOkDcRC;
  574. cmDcm_t* p = _cmDcmHandleToPtr(h);
  575. cmDcmAudio_t* r = _cmDcmAudioFind(p,dcLabelStr,false);
  576. unsigned i;
  577. // if 'dcLabelStr' was not already used then look for an empty audio record.
  578. if( r == NULL )
  579. for(i=0; i<p->l->audioCnt; ++i)
  580. if( p->l->audio[i].dcLabelStr == NULL )
  581. {
  582. r = p->l->audio + i;
  583. break;
  584. }
  585. // if no available cfg record exists then create one
  586. if( r == NULL )
  587. {
  588. p->l->audio = cmMemResizePZ(cmDcmAudio_t,p->l->audio,p->l->audioCnt+1);
  589. r = p->l->audio + p->l->audioCnt;
  590. p->l->audioCnt += 1;
  591. }
  592. assert( r != NULL );
  593. // verify that the device label is valid
  594. if((r->ss.inDevIdx = cmApDeviceLabelToIndex( inDevNameStr )) == cmInvalidIdx )
  595. {
  596. rc = cmErrMsg(&p->err, kInvalidDevArgDcRC,"The input audio device name '%s' is not valid.",inDevNameStr);
  597. goto errLabel;
  598. }
  599. // verify that the device label is valid
  600. if((r->ss.outDevIdx = cmApDeviceLabelToIndex( outDevNameStr )) == cmInvalidIdx )
  601. {
  602. rc = cmErrMsg(&p->err, kInvalidDevArgDcRC,"The output audio device name '%s' is not valid.",outDevNameStr);
  603. goto errLabel;
  604. }
  605. // if this cfg recd was not previously active then assign a cfg label
  606. if( r->dcLabelStr == NULL )
  607. r->dcLabelStr = cmMemAllocStr(dcLabelStr);
  608. // fill in the cfg recd
  609. r->inDevLabelStr = cmMemResizeStr(r->inDevLabelStr,inDevNameStr);
  610. r->outDevLabelStr = cmMemResizeStr(r->outDevLabelStr,outDevNameStr);
  611. r->ss.rpt = p->err.rpt;
  612. r->ss.syncInputFl = syncInputFl;
  613. r->ss.msgQueueByteCnt = msgQueueByteCnt;
  614. r->ss.devFramesPerCycle = devFramesPerCycle;
  615. r->ss.dspFramesPerCycle = dspFramesPerCycle;
  616. r->ss.audioBufCnt = audioBufCnt;
  617. r->ss.srate = srate;
  618. errLabel:
  619. // on error delete the cfg record and any maps depending on it
  620. if( rc != kOkDcRC && r != NULL )
  621. _cmDevCfgDeleteCfg( p, kAudioDcmTId, r - p->l->audio );
  622. return rc;
  623. }
  624. const struct cmAudioSysArgs_str* cmDevCfgAudioSysArgs( cmDevCfgH_t h, unsigned usrAppId, unsigned usrDevId )
  625. {
  626. cmDcRC_t rc = kOkDcRC;
  627. cmDcm_t* p = _cmDcmHandleToPtr(h);
  628. cmDcmMap_t* m;
  629. if((rc = _cmDcmLookupAppMap(p,usrAppId,usrDevId,&m)) != kOkDcRC )
  630. return NULL;
  631. cmDcmAudio_t* r = p->l->audio + m->cfgIndex;
  632. assert(r->dcLabelStr != NULL );
  633. return &r->ss;
  634. }
  635. cmDcRC_t cmDevCfgNetPort(
  636. cmDevCfgH_t h,
  637. const cmChar_t* dcLabelStr,
  638. const cmChar_t* sockAddr,
  639. unsigned portNumber )
  640. {
  641. return kOkDcRC;
  642. }
  643. unsigned cmDevCfgNetNodeId( cmDevCfgH_t h, unsigned usrAppId, unsigned usrDevId )
  644. {
  645. return cmInvalidId;
  646. }
  647. // Loc Management Functions:
  648. unsigned cmDevCfgLocCount( cmDevCfgH_t h )
  649. {
  650. cmDcm_t* p = _cmDcmHandleToPtr(h);
  651. unsigned i;
  652. unsigned n = 0;
  653. for(i=0; i<p->locCnt; ++i)
  654. if( p->loc[i].labelStr != NULL )
  655. ++n;
  656. return n;
  657. }
  658. const cmChar_t* cmDevCfgLocLabel( cmDevCfgH_t h, unsigned locIdx )
  659. {
  660. cmDcm_t* p = _cmDcmHandleToPtr(h);
  661. unsigned i;
  662. int j = -1;
  663. for(i=0; j<locIdx && i<p->locCnt; ++i)
  664. if( p->loc[i].labelStr != NULL )
  665. ++j;
  666. if( i == p->locCnt )
  667. return NULL;
  668. return p->loc[i].labelStr;
  669. }
  670. cmDcmLoc_t* _cmDcmFindLoc( cmDcm_t* p, const cmChar_t* label )
  671. {
  672. unsigned i=0;
  673. for(; i<p->locCnt; ++i)
  674. if( strcmp(p->loc[i].labelStr,label)==0 )
  675. return p->loc + i;
  676. return NULL;
  677. }
  678. cmDcmLoc_t* _cmDcmNewLoc( cmDcm_t* p )
  679. {
  680. unsigned i;
  681. // find a deleted location record
  682. for(i=0; i<p->locCnt; ++i)
  683. if( p->loc[i].labelStr == NULL )
  684. return p->loc + i;
  685. // no deleted location records exist so append one to p->loc[].
  686. unsigned cli = p->l - p->loc; // store the cur loc recd idx
  687. p->locCnt += 1;
  688. p->loc = cmMemResizeZ(cmDcmLoc_t,p->loc,p->locCnt);
  689. p->l = p->loc + cli; // restore the cur loc recd ptr
  690. return p->loc + p->locCnt - 1;
  691. }
  692. // Duplicate *sl and return a ptr to the new loc recd.
  693. cmDcmLoc_t* _cmDcmDuplLoc( cmDcm_t* p, const cmDcmLoc_t* sl, const cmChar_t* label )
  694. {
  695. unsigned i;
  696. cmDcmLoc_t* l = _cmDcmNewLoc(p);
  697. l->labelStr = cmMemAllocStr(label);
  698. l->appCnt = sl->appCnt;
  699. l->app = cmMemAllocZ(cmDcmApp_t,l->appCnt);
  700. for(i=0; i<l->appCnt; ++i)
  701. _cmDcmAppDupl(l->app + i, sl->app + i );
  702. l->midiCnt = sl->midiCnt;
  703. l->midi = cmMemAllocZ(cmDcmMidi_t,l->midiCnt);
  704. for(i=0; i<l->midiCnt; ++i)
  705. _cmDcmMidiDupl(l->midi + i, sl->midi + i );
  706. l->audioCnt = sl->audioCnt;
  707. l->audio = cmMemAllocZ(cmDcmAudio_t,l->audioCnt);
  708. for(i=0; i<l->audioCnt; ++i)
  709. _cmDcmAudioDupl(l->audio + i, sl->audio + i );
  710. l->netCnt = sl->netCnt;
  711. l->net = cmMemAllocZ(cmDcmNet_t,l->netCnt);
  712. for(i=0; i<l->netCnt; ++i)
  713. _cmDcmNetDupl(l->net + i, sl->net + i );
  714. return l;
  715. }
  716. cmDcRC_t cmDevCfgLocStore( cmDevCfgH_t h, const cmChar_t* locLabelStr )
  717. {
  718. cmDcRC_t rc= kOkDcRC;
  719. cmDcm_t* p = _cmDcmHandleToPtr(h);
  720. if( locLabelStr==NULL || strlen(locLabelStr)==0)
  721. return cmErrMsg(&p->err,kEmptyLabelDcRC,"The location label was empty or NULL.");
  722. assert(p->l != NULL );
  723. // if the location name is the same as the current location name ...
  724. if( strcmp(locLabelStr,p->l->labelStr)==0 )
  725. return rc; // ... there is noting to do
  726. // get a ptr (if it exists) to the location already named 'locLabelStr'.
  727. cmDcmLoc_t* sl = _cmDcmFindLoc(p,locLabelStr);
  728. // duplicate the current location
  729. cmDcmLoc_t* dl = _cmDcmDuplLoc(p, p->l, locLabelStr );
  730. // make the new location the current location
  731. p->l = dl;
  732. // if loc with the same name already existed then delete it
  733. if(sl != NULL )
  734. _cmDcmFreeLoc(p,sl);
  735. return rc;
  736. }
  737. cmDcRC_t cmDevCfgLocRecall( cmDevCfgH_t h, const cmChar_t* locLabelStr )
  738. {
  739. cmDcRC_t rc = kOkDcRC;
  740. cmDcm_t* p = _cmDcmHandleToPtr(h);
  741. cmDcmLoc_t* loc;
  742. if((loc = _cmDcmFindLoc(p,locLabelStr)) == NULL )
  743. return cmErrMsg(&p->err,kLocNotFoundDcRC,"The location '%s' could not be found.",cmStringNullGuard(locLabelStr));
  744. p->l = loc;
  745. return rc;
  746. }
  747. cmDcRC_t cmDevCfgLocDelete( cmDevCfgH_t h, const cmChar_t* locLabelStr )
  748. {
  749. cmDcRC_t rc = kOkDcRC;
  750. cmDcm_t* p = _cmDcmHandleToPtr(h);
  751. cmDcmLoc_t* loc;
  752. // find the loc to delete
  753. if((loc = _cmDcmFindLoc(p,locLabelStr)) == NULL )
  754. return cmErrMsg(&p->err,kLocNotFoundDcRC,"The location '%s' could not be found.",cmStringNullGuard(locLabelStr));
  755. // delete the requested loc. recd
  756. _cmDcmFreeLoc(p,loc);
  757. // if the current location was deleted
  758. if( loc == p->l )
  759. {
  760. unsigned i;
  761. unsigned cli = (p->l - p->loc) + 1;
  762. for(i=cli; i<p->locCnt; ++i)
  763. if( p->loc[i].labelStr != NULL )
  764. {
  765. p->l = p->loc + i;
  766. break;
  767. }
  768. if( i==p->locCnt )
  769. for(i=0; i<cli; ++i)
  770. if( p->loc[i].labelStr != NULL )
  771. {
  772. p->l = p->loc + i;
  773. break;
  774. }
  775. // if everything was deleted
  776. if( i==cli )
  777. {
  778. p->l = p->loc;
  779. p->l->labelStr = cmMemAllocStr("Default");
  780. }
  781. }
  782. return rc;
  783. }
  784. unsigned cmDevCfgLocIndex( cmDevCfgH_t h )
  785. {
  786. cmDcm_t* p = _cmDcmHandleToPtr(h);
  787. unsigned i;
  788. int j = -1;
  789. for(i=0; i<p->locCnt; ++i)
  790. {
  791. if( p->loc[i].labelStr != NULL )
  792. ++j;
  793. if( p->loc + i == p->l )
  794. return j;
  795. }
  796. assert(0);
  797. return cmInvalidIdx;
  798. }
  799. cmDcRC_t cmDevCfgWrite( cmDevCfgH_t h )
  800. {
  801. return kOkDcRC;
  802. }