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.

cmDspUi.c 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  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 tlFileVarId, unsigned audPathVarId, unsigned selVarId, unsigned cursVarId )
  296. {
  297. cmDspRC_t rc;
  298. unsigned arr[] = { tlFileVarId, audPathVarId, selVarId, cursVarId };
  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, tlFileVarId, kUiDsvFl );
  311. cmDspInstVarSetFlags( ctx, inst, audPathVarId, kUiDsvFl );
  312. cmDspInstVarSetFlags( ctx, inst, selVarId, kUiDsvFl );
  313. cmDspInstVarSetFlags( ctx, inst, cursVarId, kUiDsvFl );
  314. return rc;
  315. }
  316. 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 )
  317. {
  318. cmDspRC_t rc;
  319. unsigned arr[] = { scFileVarId, selVarId, smpIdxVarId, pitchVarId, velVarId, locIdxVarId, evtIdxVarId, dynVarId, valTypeVarId, valueVarId };
  320. cmDspValue_t v;
  321. unsigned vn = sizeof(arr)/sizeof(arr[0]);
  322. cmDsvSetUIntMtx(&v,arr,vn,1);
  323. // tell the UI to create a score control
  324. if((rc = _cmDspUiMsg( ctx, kUiSelAsId, kScoreDuiId, 0, inst, cmInvalidId, &v )) != kOkDspRC )
  325. return cmDspInstErr(ctx,inst,kUiEleCreateFailDspRC,"Score UI element create failed.");
  326. // Set the kUiDsvFl on the variables used for the min/max/def/val for this scalar
  327. // Setting this flag will cause their values to be sent to the UI whenever they change.
  328. cmDspInstVarSetFlags( ctx, inst, scFileVarId, kUiDsvFl );
  329. cmDspInstVarSetFlags( ctx, inst, selVarId, kUiDsvFl );
  330. cmDspInstVarSetFlags( ctx, inst, smpIdxVarId, kUiDsvFl );
  331. cmDspInstVarSetFlags( ctx, inst, pitchVarId, kUiDsvFl );
  332. cmDspInstVarSetFlags( ctx, inst, velVarId, kUiDsvFl );
  333. cmDspInstVarSetFlags( ctx, inst, locIdxVarId, kUiDsvFl );
  334. cmDspInstVarSetFlags( ctx, inst, evtIdxVarId, kUiDsvFl );
  335. cmDspInstVarSetFlags( ctx, inst, dynVarId, kUiDsvFl );
  336. cmDspInstVarSetFlags( ctx, inst, valTypeVarId, kUiDsvFl );
  337. cmDspInstVarSetFlags( ctx, inst, valueVarId, kUiDsvFl );
  338. return rc;
  339. }
  340. cmDspRC_t cmDspUiNewColumn( cmDspCtx_t* ctx, unsigned colW )
  341. {
  342. cmDspRC_t rc = kOkDspRC;
  343. cmDspValue_t val;
  344. cmDsvSetUInt(&val,colW);
  345. if((rc = _cmDspUiMsg(ctx, kUiSelAsId, kColumnDuiId, 0, NULL, cmInvalidId, &val )) != kOkDspRC )
  346. return cmErrMsg(&ctx->cmCtx->err,kUiEleCreateFailDspRC,"New UI column request failed.");
  347. return rc;
  348. }
  349. cmDspRC_t cmDspUiInsertHorzBorder( cmDspCtx_t* ctx )
  350. {
  351. cmDspRC_t rc = kOkDspRC;
  352. if((rc = _cmDspUiMsg(ctx, kUiSelAsId, kHBorderDuiId, 0, NULL, cmInvalidId, NULL )) != kOkDspRC )
  353. return cmErrMsg(&ctx->cmCtx->err,kUiEleCreateFailDspRC,"Horizontal border request failed.");
  354. return rc;
  355. }
  356. cmDspRC_t cmDspUiNewPage( cmDspCtx_t* ctx, const cmChar_t* title )
  357. {
  358. cmDspRC_t rc = kOkDspRC;
  359. cmDspValue_t v;
  360. cmDsvSetStrcz(&v,title==NULL ? "Controls" : title );
  361. if((rc = _cmDspUiMsg(ctx, kUiSelAsId, kPageDuiId, 0, NULL, cmInvalidId, &v )) != kOkDspRC )
  362. return cmErrMsg(&ctx->cmCtx->err,kUiEleCreateFailDspRC,"New page request failed.");
  363. return rc;
  364. }