libcm is a C development framework with an emphasis on audio signal processing applications.
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

cmDspUi.c 16KB

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