libcm is a C development framework with an emphasis on audio signal processing applications.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cmDspUi.c 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. #include "cmPrefix.h"
  2. #include "cmGlobal.h"
  3. #include "cmFloatTypes.h"
  4. #include "cmRpt.h"
  5. #include "cmErr.h"
  6. #include "cmCtx.h"
  7. #include "cmMem.h"
  8. #include "cmMallocDebug.h"
  9. #include "cmLinkedHeap.h"
  10. #include "cmJson.h"
  11. #include "cmSymTbl.h"
  12. #include "cmPrefs.h"
  13. #include "cmDspValue.h"
  14. #include "cmMsgProtocol.h"
  15. #include "cmProcObj.h"
  16. #include "cmDspCtx.h"
  17. #include "cmDspClass.h"
  18. #include "cmDspUi.h"
  19. #include "cmThread.h"
  20. #include "cmUdpPort.h"
  21. #include "cmUdpNet.h"
  22. #include "cmAudioSys.h"
  23. /*
  24. // buffer layout is:
  25. // [ cmDspUiHdr_t <data> ]
  26. // The format of the <data> is determiend by hdr.value.
  27. // Since hdr.value is the last field in the cmDspUiHdr_t record
  28. // the data follows this value.
  29. cmDspRC_t cmDspMsgSend(
  30. cmErr_t* err,
  31. unsigned asSubIdx,
  32. unsigned msgTypeId,
  33. unsigned selId,
  34. unsigned flags,
  35. unsigned instId,
  36. unsigned instVarId,
  37. const cmDspValue_t* valPtr,
  38. cmRC_t (*sendFunc)(void* cbDataPtr, const void* msgArray[], unsigned msgByteCntArray[], unsigned segCnt ),
  39. void* cbDataPtr )
  40. {
  41. unsigned bufByteCnt = sizeof(cmDspUiHdr_t);
  42. unsigned dataByteCnt = 0;
  43. if( valPtr != NULL )
  44. dataByteCnt = cmDsvSerialDataByteCount(valPtr);
  45. bufByteCnt += dataByteCnt;
  46. char buf[ bufByteCnt ];
  47. cmDspUiHdr_t* hdr = (cmDspUiHdr_t*)buf;
  48. hdr->asSubIdx = asSubIdx;
  49. hdr->uiId = msgTypeId; // see kXXXSelAsId identifiers in cmAudioSys.h
  50. hdr->selId = selId; // if msgTypeId==kUiSelAsId then see kXXXDuId in cmDspUi.h
  51. hdr->flags = flags;
  52. hdr->instId = instId;
  53. hdr->instVarId = instVarId;
  54. if( valPtr == NULL )
  55. cmDsvSetNull(&hdr->value);
  56. else
  57. {
  58. // this function relies on the 'hdr.value' field being the last field in the 'hdr'.
  59. if( cmDsvSerialize( valPtr, &hdr->value, sizeof(cmDspValue_t) + dataByteCnt) != kOkDsvRC )
  60. return cmErrMsg(err,kSerializeUiMsgFailDspRC,"An attempt to serialize a UI msg failed.");
  61. }
  62. const void* vp = buf;
  63. if( sendFunc(cbDataPtr,&vp,&bufByteCnt,1) != cmOkRC )
  64. return cmErrMsg(err,kSendToHostFailDspRC,"An attempt to transmit a msg to the host failed.");
  65. return kOkDspRC;
  66. }
  67. */
  68. // This function is passed to cmDspMsgSend() by _cmDspUiMsg().
  69. // It is used to coerce the callback data ptr 'cbDataPtr' into a
  70. // cmAudioSysCtx_str* for calling back into cmDspSys. It then translates
  71. // the result code from a cmAsRC_t to a cmRC_t.
  72. cmMsgRC_t _cmDspUiDspToHostCb( void* cbDataPtr, unsigned msgByteCnt, const void* msg)
  73. {
  74. struct cmAudioSysCtx_str* asCtx = (struct cmAudioSysCtx_str*)cbDataPtr;
  75. cmMsgRC_t rc = kOkMsgRC;
  76. if(asCtx->dspToHostFunc(asCtx, &msg, &msgByteCnt, 1) != kOkAsRC )
  77. rc = kSendFailMsgRC;
  78. return rc;
  79. }
  80. cmDspRC_t _cmDspUiMsg(cmDspCtx_t* ctx, unsigned msgTypeId, unsigned selId, unsigned flags, cmDspInst_t* inst, unsigned instVarId, const cmDspValue_t* valPtr )
  81. {
  82. return cmMsgSend(
  83. &ctx->cmCtx->err,
  84. ctx->ctx->asSubIdx,
  85. msgTypeId,
  86. selId,
  87. flags,
  88. inst==NULL ? cmInvalidId : inst->id,
  89. instVarId,
  90. valPtr,
  91. _cmDspUiDspToHostCb,
  92. ctx->ctx );
  93. }
  94. // buffer layout is:
  95. // [ cmDspUiHdr_t <data> ]
  96. // The format of the <data> is determiend by hdr.value.
  97. // Since hdr.value is the last field in the cmDspUiHdr_t record
  98. // the data follows this value.
  99. /*
  100. cmDspRC_t _cmDspUiMsg(cmDspCtx_t* ctx, unsigned msgTypeId, unsigned selId, unsigned flags, cmDspInst_t* inst, unsigned instVarId, const cmDspValue_t* valPtr )
  101. {
  102. unsigned bufByteCnt = sizeof(cmDspUiHdr_t);
  103. unsigned dataByteCnt = 0;
  104. if( valPtr != NULL )
  105. dataByteCnt = cmDsvSerialDataByteCount(valPtr);
  106. bufByteCnt += dataByteCnt;
  107. char buf[ bufByteCnt ];
  108. cmDspUiHdr_t* hdr = (cmDspUiHdr_t*)buf;
  109. hdr->asSubIdx = ctx->ctx->asSubIdx;
  110. hdr->uiId = msgTypeId; // see kXXXSelAsId identifiers in cmAudioSys.h
  111. hdr->selId = selId; // if msgTypeId==kUiSelAsId then see kXXXDuId in cmDspUi.h
  112. hdr->flags = flags;
  113. hdr->instId = inst==NULL ? cmInvalidId : inst->id;
  114. hdr->instVarId = instVarId;
  115. if( valPtr == NULL )
  116. cmDsvSetNull(&hdr->value);
  117. else
  118. {
  119. // this function relies on the 'hdr.value' field being the last field in the 'hdr'.
  120. if( cmDsvSerialize( valPtr, &hdr->value, sizeof(cmDspValue_t) + dataByteCnt) != kOkDsvRC )
  121. {
  122. if( inst == NULL )
  123. return cmErrMsg(&ctx->cmCtx->err,kSerializeUiMsgFailDspRC,"An attempt to serialize a UI msg failed.");
  124. else
  125. return cmDspInstErr(ctx,inst,kSerializeUiMsgFailDspRC,"An attempt to serialize a msg for '%s' failed.",inst->classPtr->labelStr);
  126. }
  127. }
  128. const void* vp = buf;
  129. if( ctx->ctx->dspToHostFunc(ctx->ctx,&vp,&bufByteCnt,1) != kOkAsRC )
  130. {
  131. if( inst == NULL )
  132. return cmErrMsg(&ctx->cmCtx->err,kSendToHostFailDspRC,"An attempt to transmit a msg to the host failed.");
  133. else
  134. return cmDspInstErr(ctx,inst,kSendToHostFailDspRC,"An attempt to transmit a msg to the host failed.");
  135. }
  136. return kOkDspRC;
  137. }
  138. */
  139. cmDspRC_t _cmDspUiUseInstSymbolAsLabel( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned lblVarId, const cmChar_t* ctlTypeStr )
  140. {
  141. if( inst->symId != cmInvalidId )
  142. {
  143. cmDspValue_t v;
  144. // use the instance symbol as the default UI control label
  145. const cmChar_t* label = cmDspDefaultStrcz(inst,lblVarId);
  146. if( label == NULL )
  147. label = cmSymTblLabel(ctx->stH,inst->symId);
  148. if(label != NULL )
  149. {
  150. cmDsvSetStrcz(&v,label);
  151. if( _cmDspUiMsg(ctx, kUiSelAsId, kValueDuiId, 0, inst, lblVarId, &v ) != kOkDspRC )
  152. return cmDspInstErr(ctx,inst,kUiEleCreateFailDspRC,"%s label UI elment create failed.", ctlTypeStr);
  153. }
  154. }
  155. return kOkDspRC;
  156. }
  157. cmDspRC_t cmDspSendValueToAudioSys( cmDspCtx_t* ctx, unsigned msgTypeId, unsigned selId, unsigned valId, const cmDspValue_t* valPtr )
  158. { return _cmDspUiMsg(ctx, msgTypeId, selId, 0, NULL, valId, valPtr ); }
  159. cmDspRC_t cmDspUiConsolePrint( cmDspCtx_t* ctx, cmChar_t* text )
  160. {
  161. cmDspValue_t v;
  162. cmDsvSetStrz(&v,text);
  163. return _cmDspUiMsg( ctx, kUiSelAsId, kPrintDuiId, 0, NULL, cmInvalidId, &v );
  164. }
  165. cmDspRC_t cmDspUiSendValue( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned varId, const cmDspValue_t* valPtr )
  166. { return _cmDspUiMsg(ctx, kUiSelAsId, kValueDuiId, 0, inst, varId, valPtr ); }
  167. cmDspRC_t cmDspUiSendVar( cmDspCtx_t* ctx, cmDspInst_t* inst, cmDspVar_t* var )
  168. { return _cmDspUiMsg(ctx, kUiSelAsId, kValueDuiId, 0, inst, var->constId, &var->value ); }
  169. cmDspRC_t cmDspUiScalarCreate( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned ctlDuiId, unsigned minVarId, unsigned maxVarId, unsigned stpVarId, unsigned valVarId, unsigned lblVarId )
  170. {
  171. cmDspRC_t rc;
  172. unsigned arr[] = { minVarId, maxVarId, stpVarId, valVarId, lblVarId };
  173. cmDspValue_t v;
  174. unsigned vn = sizeof(arr)/sizeof(arr[0]);
  175. cmDsvSetUIntMtx(&v,arr,vn,1);
  176. // tell the UI to create a slider control
  177. if((rc = _cmDspUiMsg( ctx, kUiSelAsId, ctlDuiId, 0, inst, cmInvalidId, &v )) != kOkDspRC )
  178. return cmDspInstErr(ctx,inst,kUiEleCreateFailDspRC,"Scalar UI element create failed.");
  179. // use instance symbol as default label
  180. if((rc = _cmDspUiUseInstSymbolAsLabel(ctx, inst, lblVarId, "Scalar")) != kOkDspRC )
  181. return rc;
  182. // Set the kUiDsvFl on the variables used for the min/max/def/val for this scalar
  183. // Setting this flag will cause their values to be sent to the UI whenever they change.
  184. cmDspInstVarSetFlags( ctx, inst, minVarId, kUiDsvFl );
  185. cmDspInstVarSetFlags( ctx, inst, maxVarId, kUiDsvFl );
  186. cmDspInstVarSetFlags( ctx, inst, stpVarId, kUiDsvFl );
  187. cmDspInstVarSetFlags( ctx, inst, valVarId, kUiDsvFl );
  188. return rc;
  189. }
  190. cmDspRC_t cmDspUiTextCreate( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned valVarId, unsigned lblVarId )
  191. {
  192. cmDspRC_t rc;
  193. unsigned arr[] = { valVarId, lblVarId };
  194. cmDspValue_t v;
  195. unsigned vn = sizeof(arr)/sizeof(arr[0]);
  196. cmDsvSetUIntMtx(&v,arr,vn,1);
  197. // tell the UI to create a text control
  198. if((rc = _cmDspUiMsg( ctx, kUiSelAsId, kTextDuiId, 0, inst, cmInvalidId, &v )) != kOkDspRC )
  199. return cmDspInstErr(ctx,inst,kUiEleCreateFailDspRC,"Text UI element create failed.");
  200. // use instance symbol as default label
  201. if((rc = _cmDspUiUseInstSymbolAsLabel(ctx, inst, lblVarId, "Text")) != kOkDspRC )
  202. return rc;
  203. // Set the kUiDsvFl on the variables used for the min/max/def/val for this scalar
  204. // Setting this flag will cause their values to be sent to the UI whenever they change.
  205. cmDspInstVarSetFlags( ctx, inst, valVarId, kUiDsvFl );
  206. return rc;
  207. }
  208. cmDspRC_t cmDspUiFnameCreate( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned valVarId, unsigned patVarId, unsigned dirVarId )
  209. {
  210. cmDspRC_t rc = kOkDspRC;
  211. unsigned arr[] = { valVarId, patVarId, dirVarId };
  212. unsigned vn = sizeof(arr)/sizeof(arr[0]);
  213. cmDspValue_t v;
  214. unsigned i;
  215. cmDsvSetUIntMtx(&v,arr,vn,1);
  216. if((rc = _cmDspUiMsg(ctx, kUiSelAsId, kFnameDuiId, 0, inst, cmInvalidId, &v )) != kOkDspRC )
  217. return cmDspInstErr(ctx,inst,kUiEleCreateFailDspRC,"File/Directory chooser UI element create failed.");
  218. // set the kDsvUiFl in the variabes which update the UI
  219. for(i=0; i<vn; ++i)
  220. cmDspInstVarSetFlags( ctx, inst, arr[i], kUiDsvFl );
  221. return rc;
  222. }
  223. cmDspRC_t cmDspUiMsgListCreate( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned height, unsigned listVarId, unsigned selVarId )
  224. {
  225. cmDspRC_t rc = kOkDspRC;
  226. unsigned arr[] = { height, selVarId, listVarId };
  227. unsigned vn = sizeof(arr)/sizeof(arr[0]);
  228. cmDspValue_t v;
  229. unsigned i;
  230. cmDsvSetUIntMtx(&v,arr,vn,1);
  231. if((rc = _cmDspUiMsg(ctx, kUiSelAsId, kMsgListDuiId, 0, inst, cmInvalidId, &v )) != kOkDspRC )
  232. return cmDspInstErr(ctx,inst,kUiEleCreateFailDspRC,"Msg List UI element create failed.");
  233. // set the kDsvUiFl in the variabes which update the UI
  234. for(i=1; i<vn; ++i)
  235. cmDspInstVarSetFlags( ctx, inst, arr[i], kUiDsvFl );
  236. return rc;
  237. }
  238. cmDspRC_t cmDspUiMeterCreate( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned minVarId, unsigned maxVarId, unsigned valVarId, unsigned lblVarId )
  239. {
  240. cmDspRC_t rc;
  241. unsigned arr[] = { minVarId, maxVarId, valVarId, lblVarId };
  242. cmDspValue_t v;
  243. unsigned vn = sizeof(arr)/sizeof(arr[0]);
  244. cmDsvSetUIntMtx(&v,arr,vn,1);
  245. // tell the UI to create a meter control
  246. if((rc = _cmDspUiMsg( ctx, kUiSelAsId, kMeterDuiId, 0, inst, cmInvalidId, &v )) != kOkDspRC )
  247. return cmDspInstErr(ctx,inst,kUiEleCreateFailDspRC,"Meter UI element create failed.");
  248. // use instance symbol as default label
  249. if((rc = _cmDspUiUseInstSymbolAsLabel(ctx, inst, lblVarId, "Meter")) != kOkDspRC )
  250. return rc;
  251. // Set the kUiDsvFl on the variables used for the min/max/val for this meter
  252. // Setting this flag will cause their values to be sent to the UI whenever they change.
  253. cmDspInstVarSetFlags( ctx, inst, minVarId, kUiDsvFl );
  254. cmDspInstVarSetFlags( ctx, inst, maxVarId, kUiDsvFl );
  255. cmDspInstVarSetFlags( ctx, inst, valVarId, kUiDsvFl );
  256. return rc;
  257. }
  258. cmDspRC_t cmDspUiButtonCreate( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned typeDuiId, unsigned outVarId, unsigned lblVarId )
  259. {
  260. cmDspRC_t rc;
  261. unsigned arr[] = { outVarId, lblVarId };
  262. cmDspValue_t v;
  263. unsigned vn = sizeof(arr)/sizeof(arr[0]);
  264. cmDsvSetUIntMtx(&v, arr, vn, 1);
  265. // tell the UI to create a button control
  266. if((rc = _cmDspUiMsg( ctx, kUiSelAsId, typeDuiId, 0, inst, cmInvalidId, &v )) != kOkDspRC )
  267. return cmDspInstErr(ctx,inst,kUiEleCreateFailDspRC,"Button UI element create failed.");
  268. // use instance symbol as default label
  269. if((rc = _cmDspUiUseInstSymbolAsLabel(ctx, inst, lblVarId, "Button" )) != kOkDspRC )
  270. return rc;
  271. // Set the kUiDsvFl on the variables used for the val for this button
  272. // Setting this flag will cause their values to be sent to the UI whenever they change.
  273. cmDspInstVarSetFlags( ctx, inst, outVarId, kUiDsvFl );
  274. return rc;
  275. }
  276. cmDspRC_t cmDspUiLabelCreate( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned lblVarId, unsigned alignVarId )
  277. {
  278. cmDspRC_t rc;
  279. unsigned arr[] = { lblVarId, alignVarId };
  280. cmDspValue_t v;
  281. unsigned vn = sizeof(arr)/sizeof(arr[0]);
  282. cmDsvSetUIntMtx(&v, arr, vn, 1);
  283. // tell the UI to create a button control
  284. if((rc = _cmDspUiMsg( ctx, kUiSelAsId, kLabelDuiId, 0, inst, cmInvalidId, &v )) != kOkDspRC )
  285. return cmDspInstErr(ctx,inst,kUiEleCreateFailDspRC,"Button UI element create failed.");
  286. // use instance symbol as default label
  287. if((rc = _cmDspUiUseInstSymbolAsLabel(ctx, inst, lblVarId, "Label" )) != kOkDspRC )
  288. return rc;
  289. // Set the kUiDsvFl on the variables used for the val for this button
  290. // Setting this flag will cause their values to be sent to the UI whenever they change.
  291. cmDspInstVarSetFlags( ctx, inst, lblVarId, kUiDsvFl );
  292. cmDspInstVarSetFlags( ctx, inst, alignVarId, kUiDsvFl );
  293. return rc;
  294. }
  295. cmDspRC_t cmDspUiTimeLineCreate( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned valVarId, unsigned lblVarId )
  296. {
  297. cmDspRC_t rc;
  298. unsigned arr[] = { valVarId, lblVarId };
  299. cmDspValue_t v;
  300. unsigned vn = sizeof(arr)/sizeof(arr[0]);
  301. cmDsvSetUIntMtx(&v,arr,vn,1);
  302. // tell the UI to create a time-line control
  303. if((rc = _cmDspUiMsg( ctx, kUiSelAsId, kTimeLineDuiId, 0, inst, cmInvalidId, &v )) != kOkDspRC )
  304. return cmDspInstErr(ctx,inst,kUiEleCreateFailDspRC,"Time Line UI element create failed.");
  305. // use instance symbol as default label
  306. if((rc = _cmDspUiUseInstSymbolAsLabel(ctx, inst, lblVarId, "TimeLine")) != kOkDspRC )
  307. return rc;
  308. // Set the kUiDsvFl on the variables used for the min/max/def/val for this scalar
  309. // Setting this flag will cause their values to be sent to the UI whenever they change.
  310. cmDspInstVarSetFlags( ctx, inst, valVarId, kUiDsvFl );
  311. return rc;
  312. }
  313. cmDspRC_t cmDspUiNewColumn( cmDspCtx_t* ctx, unsigned colW )
  314. {
  315. cmDspRC_t rc = kOkDspRC;
  316. cmDspValue_t val;
  317. cmDsvSetUInt(&val,colW);
  318. if((rc = _cmDspUiMsg(ctx, kUiSelAsId, kColumnDuiId, 0, NULL, cmInvalidId, &val )) != kOkDspRC )
  319. return cmErrMsg(&ctx->cmCtx->err,kUiEleCreateFailDspRC,"New UI column request failed.");
  320. return rc;
  321. }
  322. cmDspRC_t cmDspUiInsertHorzBorder( cmDspCtx_t* ctx )
  323. {
  324. cmDspRC_t rc = kOkDspRC;
  325. if((rc = _cmDspUiMsg(ctx, kUiSelAsId, kHBorderDuiId, 0, NULL, cmInvalidId, NULL )) != kOkDspRC )
  326. return cmErrMsg(&ctx->cmCtx->err,kUiEleCreateFailDspRC,"Horizontal border request failed.");
  327. return rc;
  328. }
  329. cmDspRC_t cmDspUiNewPage( cmDspCtx_t* ctx, const cmChar_t* title )
  330. {
  331. cmDspRC_t rc = kOkDspRC;
  332. cmDspValue_t v;
  333. cmDsvSetStrcz(&v,title==NULL ? "Controls" : title );
  334. if((rc = _cmDspUiMsg(ctx, kUiSelAsId, kPageDuiId, 0, NULL, cmInvalidId, &v )) != kOkDspRC )
  335. return cmErrMsg(&ctx->cmCtx->err,kUiEleCreateFailDspRC,"New page request failed.");
  336. return rc;
  337. }