libcm is a C development framework with an emphasis on audio signal processing applications.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

cmAudDspIF.c 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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 "cmPrefix.h"
  4. #include "cmGlobal.h"
  5. #include "cmFloatTypes.h"
  6. #include "cmRpt.h"
  7. #include "cmErr.h"
  8. #include "cmCtx.h"
  9. #include "cmMem.h"
  10. #include "cmMallocDebug.h"
  11. #include "cmFileSys.h"
  12. #include "cmJson.h"
  13. #include "cmThread.h"
  14. #include "dsp/cmDspValue.h"
  15. #include "cmMsgProtocol.h"
  16. #include "cmAudDspIF.h"
  17. cmAiH_t cmAiNullHandle = cmSTATIC_NULL_HANDLE;
  18. typedef struct
  19. {
  20. cmErr_t err;
  21. cmAdIfParm_t parms;
  22. cmJsonH_t jsH;
  23. } cmAi_t;
  24. cmAi_t* _cmAiHandleToPtr( cmAiH_t h )
  25. {
  26. cmAi_t* p = (cmAi_t*)h.h;
  27. assert(p != NULL);
  28. return p;
  29. }
  30. // Dispatch a message to the client application.
  31. // This function is called from within cmTsQueueDequeueMsg() which is called
  32. // by cmAdIfDispatchMsgToHost().
  33. cmRC_t _cmAiDispatchMsgToClient(void* cbDataPtr, unsigned msgByteCnt, const void* msgDataPtr )
  34. {
  35. cmAi_t* p = (cmAi_t*)cbDataPtr;
  36. cmDspUiHdr_t* m = (cmDspUiHdr_t*)msgDataPtr;
  37. cmRC_t rc = cmOkRC;
  38. switch( m->uiId )
  39. {
  40. case kStatusSelAsId:
  41. {
  42. // handle a status mesage
  43. const char* base = (const char*)msgDataPtr;
  44. const cmAudioSysStatus_t* st = (const cmAudioSysStatus_t*)(base + (2 * sizeof(unsigned)));
  45. const double* iMeterArray = (const double*)(st + 1);
  46. const double* oMeterArray = iMeterArray + st->iMeterCnt;
  47. rc = p->parms.dispatchRecd.statusFunc(p->parms.dispatchRecd.cbDataPtr, st, iMeterArray, oMeterArray );
  48. }
  49. break;
  50. case kSsInitSelAsId:
  51. {
  52. // handle an ssInit message
  53. const cmAudioSysSsInitMsg_t* sip = (const cmAudioSysSsInitMsg_t*)msgDataPtr;
  54. const char* iDevLabel = (const char*)(sip+1);
  55. const char* oDevLabel = iDevLabel + strlen(iDevLabel) + 1;
  56. rc = p->parms.dispatchRecd.ssInitFunc(p->parms.dispatchRecd.cbDataPtr, sip, iDevLabel, oDevLabel );
  57. }
  58. break;
  59. case kUiSelAsId:
  60. {
  61. bool jsFl = false;
  62. cmDsvRC_t rc = kOkDsvRC;
  63. // if the value associated with this msg is a mtx then set
  64. // its mtx data area pointer to just after the msg header.
  65. if( cmDsvIsJson(&m->value) )
  66. {
  67. rc = cmDsvDeserializeJson(&m->value,p->jsH);
  68. jsFl = true;
  69. }
  70. else
  71. rc = cmDsvDeserializeInPlace(&m->value,msgByteCnt-sizeof(cmDspUiHdr_t));
  72. if( rc != kOkDsvRC )
  73. cmErrMsg(&p->err,kDeserialFailAiRC,"Deserialize failed.");
  74. else
  75. rc = p->parms.dispatchRecd.uiFunc(p->parms.dispatchRecd.cbDataPtr,m);
  76. if( jsFl )
  77. cmJsonClearTree(p->jsH);
  78. }
  79. break;
  80. default:
  81. cmErrMsg(&p->err,kUnknownMsgTypeAiRC,"The message type %i is unknown.",m->uiId);
  82. break;
  83. }
  84. return rc;
  85. }
  86. cmAiRC_t _cmAdIfReadCfgFile( cmAi_t* p, cmCtx_t* ctx )
  87. {
  88. cmAiRC_t rc = kOkAiRC;
  89. const cmChar_t* sysJsFn = NULL;
  90. cmJsonH_t jsH = cmJsonNullHandle;
  91. cmJsonNode_t* audDspNodePtr = NULL;
  92. //const cmChar_t* errLabelPtr = NULL;
  93. // form the audio dsp resource file name
  94. if((sysJsFn = cmFsMakeFn( cmFsPrefsDir(),cmAudDspSys_FILENAME,NULL,NULL)) == NULL )
  95. {
  96. rc = cmErrMsg(&p->err,kFileSysFailAiRC,"Unable to form the audio dsp system resource file name.");
  97. goto errLabel;
  98. }
  99. // open the audio dsp resource file
  100. if(cmJsonInitializeFromFile(&jsH,sysJsFn,ctx) != kOkJsRC )
  101. {
  102. rc = cmErrMsg(&p->err,kJsonFailAiRC,"Unable to open the audio dsp resource file: '%s'.",cmStringNullGuard(sysJsFn));
  103. goto errLabel;
  104. }
  105. // locate the aud_dsp container object
  106. if( cmJsonNodeMember( cmJsonRoot(jsH), "aud_dsp", &audDspNodePtr ) != kOkJsRC )
  107. {
  108. rc = cmErrMsg(&p->err,kJsonFailAiRC,"The audio DSP system resource file '%s' does not contain an 'aud_dsp' object.",cmStringNullGuard(sysJsFn));
  109. goto errLabel;
  110. }
  111. /*
  112. // locate the read the aud_dsp sub-elements
  113. if( cmJsonMemberValues( audDspNodePtr, &errLabelPtr,
  114. "msgQueueByteCnt", kIntTId, &p->msgQueueByteCnt,
  115. NULL ) != kOkJsRC )
  116. {
  117. rc = cmErrMsg(&p->err,kJsonFailAiRC,"Syntax error while parsing the top level fields in the audio DSP system resource file:%s.",cmStringNullGuard(sysJsFn));
  118. goto errLabel;
  119. }
  120. */
  121. errLabel:
  122. if( cmJsonFinalize(&jsH) != kOkJsRC )
  123. rc = cmErrMsg(&p->err,kJsonFailAiRC,"JSON finalization failed.");
  124. if( sysJsFn != NULL )
  125. cmFsFreeFn(sysJsFn);
  126. return rc;
  127. }
  128. cmAiRC_t _cmAdIfSendIntMsg(cmAiH_t h, unsigned selId, unsigned asSubIdx, unsigned flags, unsigned iv, double dv, const cmChar_t* str )
  129. {
  130. cmAi_t* p = _cmAiHandleToPtr( h );
  131. cmDspValue_t v;
  132. if(str != NULL )
  133. cmDsvSetStrcz(&v,str);
  134. else
  135. if(iv == cmInvalidIdx )
  136. cmDsvSetDouble(&v,dv);
  137. else
  138. cmDsvSetUInt(&v,iv);
  139. if( cmMsgSend(&p->err,asSubIdx,kUiSelAsId,selId,flags,cmInvalidId,cmInvalidId,&v,p->parms.audDspFunc,p->parms.audDspFuncDataPtr) != kOkMsgRC )
  140. return cmErrMsg(&p->err,kSendFailAiRC,"The integer message sel id:%i value:%i transmission failed.",selId,iv);
  141. return kOkAiRC;
  142. }
  143. cmAiRC_t _cmAdIfFree( cmAi_t* p )
  144. {
  145. cmAiRC_t rc = kOkAiRC;
  146. if( cmJsonFinalize(&p->jsH) != kOkJsRC )
  147. {
  148. rc = cmErrMsg(&p->err,kJsonFailAiRC,"JSON finalization failed.");
  149. goto errLabel;
  150. }
  151. cmMemFree(p);
  152. errLabel:
  153. return rc;
  154. }
  155. cmAiRC_t cmAdIfAllocate( cmCtx_t* ctx, cmAiH_t* hp, const cmAdIfParm_t* parms )
  156. {
  157. cmAiRC_t rc;
  158. if((rc = cmAdIfFree(hp)) != kOkAiRC )
  159. return rc;
  160. cmAi_t* p = cmMemAllocZ(cmAi_t,1);
  161. cmErrSetup(&p->err,&ctx->rpt,"Audio DSP Interface");
  162. p->parms = *parms;
  163. // read the system configuration file
  164. if((rc = _cmAdIfReadCfgFile(p, ctx )) != kOkAiRC )
  165. goto errLabel;
  166. // initialize a JSON tree for use in deserializing JSON messages
  167. if((rc = cmJsonInitialize( &p->jsH, ctx )) != kOkJsRC )
  168. {
  169. rc = cmErrMsg(&p->err,kJsonFailAiRC,"JSON initialization failed.");
  170. goto errLabel;
  171. }
  172. hp->h = p;
  173. errLabel:
  174. if( rc != kOkAiRC )
  175. _cmAdIfFree(p);
  176. return rc;
  177. }
  178. cmAiRC_t cmAdIfFree( cmAiH_t* hp )
  179. {
  180. cmAiRC_t rc = kOkAiRC;
  181. if( hp==NULL || cmAdIfIsValid(*hp)==false )
  182. return kOkAiRC;
  183. cmAi_t* p = _cmAiHandleToPtr(*hp);
  184. if((rc = _cmAdIfFree(p)) != kOkAiRC )
  185. return rc;
  186. hp->h = NULL;
  187. return rc;
  188. }
  189. bool cmAdIfIsValid( cmAiH_t h )
  190. { return h.h != NULL; }
  191. cmAiRC_t cmAdIfRecvAudDspMsg( cmAiH_t h, unsigned msgByteCnt, const void* msg )
  192. {
  193. cmAi_t* p = _cmAiHandleToPtr(h);
  194. cmAiRC_t rc = kOkAiRC;
  195. _cmAiDispatchMsgToClient(p,msgByteCnt,msg);
  196. return rc;
  197. }
  198. cmAiRC_t cmAdIfDeviceReport( cmAiH_t h )
  199. { return _cmAdIfSendIntMsg(h,kDevReportDuiId,cmInvalidIdx,0,cmInvalidIdx,0.0,NULL); }
  200. cmAiRC_t cmAdIfSetAudioSysCfg( cmAiH_t h, unsigned asCfgIdx )
  201. { return _cmAdIfSendIntMsg(h,kSetAudioCfgDuiId,cmInvalidIdx,0,asCfgIdx,0.0,NULL); }
  202. cmAiRC_t cmAdIfSetAudioDevice( cmAiH_t h, unsigned asSubIdx, bool inputFl, unsigned devIdx )
  203. { return _cmAdIfSendIntMsg(h,kSetAudioDevDuiId,asSubIdx,inputFl,devIdx,0.0,NULL); }
  204. cmAiRC_t cmAdIfSetSampleRate( cmAiH_t h, unsigned asSubIdx, double srate )
  205. { return _cmAdIfSendIntMsg(h,kSetSampleRateDuiId,asSubIdx,0,cmInvalidIdx,srate,NULL); }
  206. cmAiRC_t cmAdIfLoadProgram( cmAiH_t h, unsigned asSubIdx, unsigned pgmIdx )
  207. { return _cmAdIfSendIntMsg(h,kSetPgmDuiId,asSubIdx,0,pgmIdx,0.0,NULL); }
  208. cmAiRC_t cmAdIfPrintPgm( cmAiH_t h,unsigned asSubIdx, const cmChar_t* fn )
  209. { return _cmAdIfSendIntMsg(h,kPrintPgmDuiId,asSubIdx,0,cmInvalidIdx,0.0,fn); }
  210. cmAiRC_t cmAdIfEnableAudio( cmAiH_t h, bool enableFl )
  211. { return _cmAdIfSendIntMsg(h,kEnableDuiId,cmInvalidIdx,enableFl,cmInvalidIdx,0.0,NULL); }
  212. cmAiRC_t cmAdIfEnableStatusNotify( cmAiH_t h, bool enableFl )
  213. { return _cmAdIfSendIntMsg(h,kSetNotifyEnableDuiId,cmInvalidIdx,enableFl,cmInvalidIdx,0.0,NULL); }
  214. cmAiRC_t cmAdIfSendMsgToAudioDSP(
  215. cmAiH_t h,
  216. unsigned asSubIdx,
  217. unsigned msgTypeId,
  218. unsigned selId,
  219. unsigned flags,
  220. unsigned instId,
  221. unsigned instVarId,
  222. const cmDspValue_t* valPtr )
  223. {
  224. cmAiRC_t rc = kOkAiRC;
  225. cmAi_t* p = _cmAiHandleToPtr(h);
  226. if( cmMsgSend( &p->err, asSubIdx, msgTypeId,selId,flags,instId,instVarId,valPtr, p->parms.audDspFunc, p->parms.audDspFuncDataPtr ) != kOkMsgRC )
  227. rc = cmErrMsg(&p->err, kSendFailAiRC, "A UI message intened for the the audio DSP system was not successfully delivered.");
  228. return rc;
  229. }
  230. cmAiRC_t cmAdIfDispatchMsgToHost( cmAiH_t h )
  231. { return _cmAdIfSendIntMsg(h,kClientMsgPollDuiId,cmInvalidIdx,0,cmInvalidIdx,0.0,NULL); }