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.

cmUiRtSysMstr.c 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. //| Copyright: (C) 2009-2020 Kevin Larke <contact AT larke DOT org>
  2. //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
  3. #include "cmGlobal.h"
  4. #include "cmFloatTypes.h"
  5. #include "cmRpt.h"
  6. #include "cmErr.h"
  7. #include "cmCtx.h"
  8. #include "cmMem.h"
  9. #include "cmMallocDebug.h"
  10. #include "cmJson.h"
  11. #include "cmThread.h"
  12. #include "cmUdpPort.h"
  13. #include "cmTime.h"
  14. #include "cmRtSysMsg.h"
  15. #include "cmRtNet.h"
  16. #include "cmRtSys.h"
  17. #include "cmUiDrvr.h"
  18. #include "cmUi.h"
  19. #include "cmUiRtSysMstr.h"
  20. enum
  21. {
  22. kLabelAmId,
  23. kInSliderAmId,
  24. kInMeterAmId,
  25. kInToneAmId,
  26. kInPassAmId,
  27. kInMuteAmId,
  28. kOutSliderAmId,
  29. kOutMeterAmId,
  30. kOutToneAmId,
  31. kOutPassAmId,
  32. kOutMuteAmId,
  33. kAmCnt
  34. };
  35. enum
  36. {
  37. kMinDb = 24,
  38. kMaxDb = -24,
  39. kMtrMin = 0,
  40. kMtrMax = 100
  41. };
  42. typedef struct cmAmPanel_str
  43. {
  44. unsigned rtSubIdx;
  45. unsigned panelId;
  46. unsigned updateId;
  47. unsigned wakeupId;
  48. unsigned msgCbId;
  49. unsigned audioCbId;
  50. unsigned updateCnt;
  51. unsigned wakeupCnt;
  52. unsigned msgCbCnt;
  53. unsigned audioCbCnt;
  54. unsigned baseOutId;
  55. unsigned iDevIdx;
  56. unsigned oDevIdx;
  57. unsigned iChCnt;
  58. unsigned oChCnt;
  59. unsigned a[ kAmCnt ];
  60. struct cmAmPanel_str* link;
  61. } cmAmPanel_t;
  62. typedef struct
  63. {
  64. cmErr_t err;
  65. unsigned appId;
  66. cmUiH_t uiH;
  67. cmRtSysH_t asH;
  68. unsigned nextId;
  69. cmAmPanel_t* list;
  70. } cmAm_t;
  71. cmUiRtMstrH_t cmUiRtMstrNullHandle = cmSTATIC_NULL_HANDLE;
  72. cmAm_t* _cmUiAmHandleToPtr( cmUiRtMstrH_t h )
  73. {
  74. cmAm_t* p = (cmAm_t*)h.h;
  75. assert( p!=NULL);
  76. return p;
  77. }
  78. cmAmRC_t _cmUiAmFreePanels( cmAm_t* p, bool callDriverFl )
  79. {
  80. cmAmRC_t rc = kOkAmRC;
  81. cmAmPanel_t* pp = p->list;
  82. while( pp != NULL )
  83. {
  84. cmAmPanel_t* np = pp->link;
  85. unsigned panelId = pp->panelId;
  86. if( callDriverFl )
  87. if( cmUiClearPanel( p->uiH, p->appId, panelId ) != kOkUiRC )
  88. {
  89. rc = cmErrMsg(&p->err,kUiFailAmRC,"The panel %i clear failed.",panelId);
  90. goto errLabel;
  91. }
  92. cmMemFree(pp);
  93. pp = np;
  94. }
  95. p->nextId = 0;
  96. p->list = NULL;
  97. errLabel:
  98. return rc;
  99. }
  100. cmAmRC_t _cmUiAmFree( cmAm_t* p )
  101. {
  102. _cmUiAmFreePanels(p,false);
  103. if( cmUiDestroyApp( p->uiH, p->appId ) != kOkUiRC )
  104. cmErrMsg(&p->err,kUiFailAmRC,"UI Mgr. app destroy failed.");
  105. cmMemFree(p);
  106. return kOkAmRC;
  107. }
  108. cmAmRC_t cmUiRtSysMstrAlloc( cmCtx_t* ctx, cmUiRtMstrH_t* hp, cmUiH_t uiH, cmRtSysH_t asH, unsigned appId )
  109. {
  110. cmAmRC_t rc = kOkAmRC;
  111. if((rc = cmUiRtSysMstrFree(hp)) != kOkAmRC )
  112. return rc;
  113. cmAm_t* p = cmMemAllocZ(cmAm_t,1);
  114. cmErrSetup(&p->err,&ctx->rpt,"Audio System Master UI");
  115. p->appId = appId;
  116. p->uiH = uiH;
  117. p->asH = asH;
  118. p->nextId = 0;
  119. // allocate the UI Mgr. app. slot for the audio system master control UI.
  120. if( cmUiCreateApp( uiH, appId, cmInvalidId ) != kOkUiRC )
  121. {
  122. rc = cmErrMsg(&p->err,kUiFailAmRC,"The UI Mgr. failed while creating the Audio System UI app. slot.");
  123. goto errLabel;
  124. }
  125. hp->h = p;
  126. errLabel:
  127. if( rc != kOkAmRC )
  128. _cmUiAmFree(p);
  129. return rc;
  130. }
  131. cmAmRC_t cmUiRtSysMstrFree( cmUiRtMstrH_t* hp )
  132. {
  133. cmAmRC_t rc = kOkAmRC;
  134. if(hp==NULL || cmUiRtSysMstrIsValid(*hp)==false )
  135. return kOkAmRC;
  136. cmAm_t* p = _cmUiAmHandleToPtr(*hp);
  137. if((rc = _cmUiAmFree(p)) != kOkAmRC )
  138. return rc;
  139. hp->h = NULL;
  140. return rc;
  141. }
  142. bool cmUiRtSysMstrIsValid( cmUiRtMstrH_t h )
  143. { return h.h != NULL; }
  144. cmAmRC_t cmUiRtSysMstrInitialize( cmUiRtMstrH_t amH, const cmRtSysCtx_t* c, const cmChar_t* inDevLabel, const cmChar_t* outDevLabel )
  145. {
  146. cmAmRC_t rc = kOkAmRC;
  147. cmAm_t* p = _cmUiAmHandleToPtr(amH);
  148. cmUiH_t uiH = p->uiH;
  149. unsigned panelId = cmInvalidId;
  150. unsigned colW = 50;
  151. unsigned ctlW = 45;
  152. unsigned n = 31;
  153. cmChar_t chNumStr[ n+1 ];
  154. int w;
  155. cmAmPanel_t* pp = NULL;
  156. // This function is called once for each audio sub-system.
  157. // If this is the first call in the sequence then clear the previous setup.
  158. if( c->rtSubIdx == 0 )
  159. {
  160. if((rc = _cmUiAmFreePanels(p,true)) != kOkAmRC )
  161. goto errLabel;
  162. assert(p->list == NULL );
  163. }
  164. // create the panel recd and link it to the beginning of the list
  165. pp = cmMemAllocZ(cmAmPanel_t,1);
  166. pp->link = p->list;
  167. p->list = pp;
  168. pp->rtSubIdx = c->rtSubIdx;
  169. pp->iDevIdx = c->ss->args.inDevIdx;
  170. pp->oDevIdx = c->ss->args.outDevIdx;
  171. pp->iChCnt = c->iChCnt;
  172. pp->oChCnt = c->oChCnt;
  173. pp->panelId = p->nextId++;
  174. pp->updateId = p->nextId++;
  175. pp->wakeupId = p->nextId++;
  176. pp->msgCbId = p->nextId++;
  177. pp->audioCbId = p->nextId++;
  178. pp->a[kLabelAmId] = p->nextId;
  179. pp->a[kInSliderAmId] = p->nextId += c->iChCnt;
  180. pp->a[kInMeterAmId] = p->nextId += c->iChCnt;
  181. pp->a[kInToneAmId] = p->nextId += c->iChCnt;
  182. pp->a[kInPassAmId] = p->nextId += c->iChCnt;
  183. pp->a[kInMuteAmId] = p->nextId += c->iChCnt;
  184. pp->baseOutId = p->nextId += c->iChCnt;
  185. pp->a[kOutSliderAmId] = pp->baseOutId;
  186. pp->a[kOutMeterAmId] = p->nextId += c->oChCnt;
  187. pp->a[kOutToneAmId] = p->nextId += c->oChCnt;
  188. pp->a[kOutPassAmId] = p->nextId += c->oChCnt;
  189. pp->a[kOutMuteAmId] = p->nextId += c->oChCnt;
  190. p->nextId += c->oChCnt;
  191. panelId = pp->panelId;
  192. if( cmUiCreatePanel(uiH, p->appId, panelId, "Master", 0 ) != kOkUiRC )
  193. {
  194. rc = cmErrMsg(&p->err,kUiFailAmRC,"Panel %i create failed.",panelId);
  195. goto errLabel;
  196. }
  197. cmUiSetFillRows( uiH, p->appId, panelId, true );
  198. cmUiCreateProgress(uiH, p->appId, panelId, pp->updateId, "Update", 0, 0, 1, 0 );
  199. cmUiCreateProgress(uiH, p->appId, panelId, pp->wakeupId, "Wakeup", 0, 0, 1, 0 );
  200. cmUiCreateProgress(uiH, p->appId, panelId, pp->msgCbId, "Message", 0, 0, 1, 0 );
  201. cmUiCreateProgress(uiH, p->appId, panelId, pp->audioCbId,"Audio", 0, 0, 1, 0 );
  202. cmUiSetFillRows( uiH, p->appId, panelId, false );
  203. cmUiNewLine( uiH, p->appId, panelId );
  204. cmUiCreateLabel( uiH, p->appId, panelId, cmInvalidId, inDevLabel, kInsideUiFl | kLeftUiFl );
  205. cmUiNewLine( uiH, p->appId, panelId );
  206. unsigned i;
  207. for(i=0; i<c->iChCnt; ++i)
  208. {
  209. snprintf(chNumStr,n,"%i",i);
  210. cmUiSetNextW( uiH, p->appId, panelId, ctlW );
  211. cmUiCreateLabel( uiH, p->appId, panelId, cmInvalidId, chNumStr, 0 );
  212. cmUiCreateVSlider(uiH, p->appId, panelId, pp->a[kInSliderAmId] + i, NULL, 0, kMinDb, kMaxDb, 0.1, 0 );
  213. cmUiPlaceRight( uiH, p->appId, panelId );
  214. cmUiCreateVMeter( uiH, p->appId, panelId, pp->a[kInMeterAmId] + i, NULL, 0, kMtrMin, kMtrMax, 0 );
  215. w = cmUiSetW( uiH, p->appId, panelId, ctlW );
  216. cmUiCreateCheck( uiH, p->appId, panelId, pp->a[kInToneAmId] + i, "T", 0, false );
  217. cmUiCreateCheck( uiH, p->appId, panelId, pp->a[kInPassAmId] + i, "P", 0, false );
  218. cmUiCreateCheck( uiH, p->appId, panelId, pp->a[kInMuteAmId] + i, "M", 0, false );
  219. cmUiSetW( uiH, p->appId, panelId, w );
  220. cmUiSetBaseCol( uiH, p->appId, panelId, 5 + (i+1)*colW);
  221. }
  222. cmUiSetBaseCol( uiH, p->appId, panelId, 0);
  223. cmUiNewLine( uiH, p->appId, panelId );
  224. cmUiCreateLabel( uiH,p->appId, panelId, cmInvalidId, outDevLabel, kInsideUiFl | kLeftUiFl );
  225. cmUiNewLine( uiH, p->appId, panelId );
  226. for(i=0; i<c->oChCnt; ++i)
  227. {
  228. snprintf(chNumStr,n,"%i",i);
  229. cmUiSetNextW( uiH, p->appId, panelId, ctlW );
  230. cmUiCreateLabel( uiH, p->appId, panelId, cmInvalidId, chNumStr, 0 );
  231. cmUiCreateVSlider(uiH, p->appId, panelId, pp->a[kOutSliderAmId] + i, NULL, 0, kMinDb, kMaxDb, 0.1, 0 );
  232. cmUiPlaceRight( uiH, p->appId, panelId );
  233. cmUiCreateVMeter( uiH, p->appId, panelId, pp->a[kOutMeterAmId] + i, NULL, 0, kMtrMin, kMtrMax, 0 );
  234. w = cmUiSetW( uiH, p->appId, panelId, ctlW );
  235. cmUiCreateCheck( uiH, p->appId, panelId, pp->a[kOutToneAmId] + i, "T", 0, false );
  236. cmUiCreateCheck( uiH, p->appId, panelId, pp->a[kOutPassAmId] + i, "P", 0, false );
  237. cmUiCreateCheck( uiH, p->appId, panelId, pp->a[kOutMuteAmId] + i, "M", 0, false );
  238. cmUiSetW( uiH, p->appId, panelId, w );
  239. cmUiSetBaseCol( uiH, p->appId, panelId, 5 + (i+1)*colW);
  240. }
  241. errLabel:
  242. return rc;
  243. }
  244. cmAmPanel_t* _cmUiAmFindPanel( cmAm_t* p, unsigned panelId, bool errFl )
  245. {
  246. cmAmPanel_t* pp = p->list;
  247. for(; pp!=NULL; pp=pp->link)
  248. if( pp->panelId == panelId )
  249. return pp;
  250. if( errFl )
  251. cmErrMsg(&p->err,kPanelNotFoundAmRC,"The panel %i was not found.",panelId);
  252. return NULL;
  253. }
  254. unsigned _cmUiAmCtlTypeId( cmAm_t* p, cmAmPanel_t* pp, cmUiCId_t cId, unsigned usrId,
  255. unsigned sliderId, unsigned toneId, unsigned passId, unsigned muteId )
  256. {
  257. switch( cId )
  258. {
  259. case kSliderUiCId:
  260. assert( pp->a[sliderId] <= usrId && usrId < pp->a[sliderId]+pp->oChCnt);
  261. return sliderId;
  262. break;
  263. case kCheckUiCId:
  264. if( pp->a[toneId] <= usrId && usrId < pp->a[toneId]+pp->oChCnt )
  265. return toneId;
  266. if( pp->a[passId] <= usrId && usrId < pp->a[passId]+pp->oChCnt )
  267. return passId;
  268. if( pp->a[muteId] <= usrId && usrId < pp->a[muteId]+pp->oChCnt )
  269. return muteId;
  270. break;
  271. default:
  272. break;
  273. }
  274. return cmInvalidId;
  275. }
  276. cmUiRC_t cmUiRtSysMstrOnUiEvent( cmUiRtMstrH_t h, const cmUiDriverArg_t* a )
  277. {
  278. cmUiRC_t rc = kOkUiRC;
  279. cmAm_t* p = _cmUiAmHandleToPtr(h);
  280. cmAmPanel_t* pp;
  281. cmRtSysMstr_t r;
  282. unsigned typeId;
  283. bool tabSelFl = a->dId==kSetValDId && a->cId == kPanelUiCId;
  284. if((pp = _cmUiAmFindPanel( p, a->panelId, !tabSelFl )) == NULL)
  285. {
  286. if( tabSelFl )
  287. return kOkUiRC;
  288. return cmErrLastRC(&p->err);
  289. }
  290. // if the panel tab was selected/deslected ival will be equal to 1/0
  291. if( a->usrId == pp->panelId )
  292. {
  293. cmRtSysStatusNotifyEnable(p->asH, pp->rtSubIdx, a->ival );
  294. return rc;
  295. }
  296. // based on the usrId determine which control generated the event
  297. if( a->usrId >= pp->baseOutId )
  298. typeId = _cmUiAmCtlTypeId(p,pp,a->cId,a->usrId,kOutSliderAmId,kOutToneAmId,kOutPassAmId,kOutMuteAmId);
  299. else
  300. typeId = _cmUiAmCtlTypeId(p,pp,a->cId,a->usrId,kInSliderAmId,kInToneAmId,kInPassAmId,kInMuteAmId);
  301. // this control is not a slider or check btn so ignore it
  302. if( typeId == cmInvalidId )
  303. return rc;
  304. unsigned asInFl = 0;
  305. unsigned asCtlId = cmInvalidId;
  306. unsigned asCh = a->usrId - pp->a[typeId];
  307. double asValue = 0;
  308. switch( typeId )
  309. {
  310. case kInSliderAmId:
  311. asInFl = 1;
  312. asCtlId = kSliderUiRtId;
  313. asValue = a->fval;
  314. break;
  315. case kInToneAmId:
  316. asInFl = 1;
  317. asCtlId = kToneUiRtId;
  318. asValue = a->ival;
  319. break;
  320. case kInPassAmId:
  321. asInFl = 1;
  322. asCtlId = kPassUiRtId;
  323. asValue = a->ival;
  324. break;
  325. case kInMuteAmId:
  326. asInFl = 1;;
  327. asCtlId = kMuteUiRtId;
  328. asValue = a->ival;
  329. break;
  330. case kOutSliderAmId:
  331. asCtlId = kSliderUiRtId;
  332. asValue = a->fval;
  333. break;
  334. case kOutToneAmId:
  335. asCtlId = kToneUiRtId;
  336. asValue = a->ival;
  337. break;
  338. case kOutPassAmId:
  339. asCtlId = kPassUiRtId;
  340. asValue = a->ival;
  341. break;
  342. case kOutMuteAmId:
  343. asCtlId = kMuteUiRtId;
  344. asValue = a->ival;
  345. break;
  346. }
  347. unsigned asDevIdx = asInFl ? pp->iDevIdx : pp->oDevIdx;
  348. r.hdr.rtSubIdx = pp->rtSubIdx;
  349. r.hdr.selId = kUiMstrSelRtId;
  350. r.devIdx = asDevIdx;
  351. r.chIdx = asCh;
  352. r.inFl = asInFl;
  353. r.ctlId = asCtlId;
  354. r.value = asValue;
  355. if( cmRtSysDeliverMsg(p->asH, &r, sizeof(r), cmInvalidId ) != kOkRtRC )
  356. rc = cmErrMsg(&p->err,kSubSysFailUiRC,"Audio System master control UI message delivery to the audio system failed.");
  357. return rc;
  358. }
  359. int _cmUiAmLinToDb( double v )
  360. {
  361. if( v <= 0 )
  362. return 0;
  363. v = round(20.0*log10(v)+100.0);
  364. return cmMin(kMtrMax,cmMax(kMtrMin,v));
  365. }
  366. cmUiRC_t cmUiRtSysMstrOnStatusEvent( cmUiRtMstrH_t h, const cmRtSysStatus_t* m, const double* iMeterArray, const double* oMeterArray )
  367. {
  368. cmAm_t* p = _cmUiAmHandleToPtr(h);
  369. cmAmPanel_t* pp = p->list;
  370. for(; pp!=NULL; pp=pp->link)
  371. if(pp->rtSubIdx == m->hdr.rtSubIdx )
  372. break;
  373. if( pp == NULL )
  374. return cmErrMsg(&p->err,kPanelNotFoundUiRC,"The panel associated with Audio system index %i could not be found.",m->hdr.rtSubIdx);
  375. cmUiSetInt(p->uiH, p->appId, pp->updateId, m->updateCnt != pp->updateCnt );
  376. cmUiSetInt(p->uiH, p->appId, pp->wakeupId, m->wakeupCnt != pp->wakeupCnt );
  377. cmUiSetInt(p->uiH, p->appId, pp->msgCbId, m->msgCbCnt != pp->msgCbCnt );
  378. cmUiSetInt(p->uiH, p->appId, pp->audioCbId, m->audioCbCnt != pp->audioCbCnt );
  379. pp->updateCnt = m->updateCnt;
  380. pp->wakeupCnt = m->wakeupCnt;
  381. pp->msgCbCnt = m->msgCbCnt;
  382. pp->audioCbCnt= m->audioCbCnt;
  383. unsigned i;
  384. for(i=0; i<m->iMeterCnt; ++i)
  385. cmUiSetInt(p->uiH, p->appId, pp->a[kInMeterAmId]+i, _cmUiAmLinToDb(iMeterArray[i]) );
  386. for(i=0; i<m->oMeterCnt; ++i)
  387. cmUiSetInt(p->uiH, p->appId, pp->a[kOutMeterAmId]+i, _cmUiAmLinToDb(oMeterArray[i]) );
  388. return kOkUiRC;
  389. }
  390. void cmUiRtSysMstrClearStatus( cmUiRtMstrH_t h )
  391. {
  392. cmAm_t* p = _cmUiAmHandleToPtr(h);
  393. cmAmPanel_t* pp = p->list;
  394. for(; pp!=NULL; pp=pp->link)
  395. {
  396. cmUiSetInt(p->uiH, p->appId, pp->updateId, 0 );
  397. cmUiSetInt(p->uiH, p->appId, pp->wakeupId, 0 );
  398. cmUiSetInt(p->uiH, p->appId, pp->msgCbId, 0 );
  399. cmUiSetInt(p->uiH, p->appId, pp->audioCbId, 0 );
  400. }
  401. }