Переглянути джерело

cmDevCfg.h/c: Many changes and additions to complete implementation.

master
kevin 11 роки тому
джерело
коміт
646f65222e
2 змінених файлів з 257 додано та 55 видалено
  1. 233
    49
      cmDevCfg.c
  2. 24
    6
      cmDevCfg.h

+ 233
- 49
cmDevCfg.c Переглянути файл

6
 #include "cmMem.h"
6
 #include "cmMem.h"
7
 #include "cmMallocDebug.h"
7
 #include "cmMallocDebug.h"
8
 #include "cmLinkedHeap.h"
8
 #include "cmLinkedHeap.h"
9
+#include "cmFileSys.h"
9
 #include "cmJson.h"
10
 #include "cmJson.h"
10
 #include "cmText.h"
11
 #include "cmText.h"
11
 #include "cmThread.h"
12
 #include "cmThread.h"
24
 
25
 
25
 typedef struct cmDcmCfg_str
26
 typedef struct cmDcmCfg_str
26
 {
27
 {
27
-  cmChar_t*     dcLabelStr;
28
+  cmChar_t*     dcLabelStr;   // the cfg label 
28
   unsigned      cfgId;        // unique among all cfg's assigned to a loc
29
   unsigned      cfgId;        // unique among all cfg's assigned to a loc
29
-  cmTypeDcmId_t typeId;
30
-  cmChar_t*     descStr;
30
+  cmTypeDcmId_t typeId;       // the cfg type id (e.g. midi, audio, net, ...)
31
+  cmChar_t*     descStr;      // summary description string 
32
+
33
+  // NOTE: any fields added to this structure, type generic (above) 
34
+  // or type specific (below), must be explicitely duplicated in cmDevCfgLocStore().
31
 
35
 
32
   union
36
   union
33
   {
37
   {
71
 typedef struct
75
 typedef struct
72
 {
76
 {
73
   cmErr_t     err;
77
   cmErr_t     err;
78
+  cmCtx_t*    ctx;
74
   cmDcmLoc_t* loc;
79
   cmDcmLoc_t* loc;
75
   cmDcmLoc_t* clp;
80
   cmDcmLoc_t* clp;
81
+  cmChar_t*   fn;
76
 } cmDcm_t;
82
 } cmDcm_t;
77
 
83
 
78
 
84
 
166
       assert(0);
172
       assert(0);
167
       break;
173
       break;
168
   }
174
   }
175
+
176
+  cmMemFree(cp);
169
 }
177
 }
170
 
178
 
171
 void _cmDcmFreeLoc( cmDcm_t* p, cmDcmLoc_t* lp )
179
 void _cmDcmFreeLoc( cmDcm_t* p, cmDcmLoc_t* lp )
208
   cmDcRC_t rc = kOkDcRC;
216
   cmDcRC_t rc = kOkDcRC;
209
 
217
 
210
   _cmDcmFreeAllLocs(p);
218
   _cmDcmFreeAllLocs(p);
219
+  cmMemFree(p->fn);
211
 
220
 
212
   cmMemFree(p);
221
   cmMemFree(p);
213
   return rc;
222
   return rc;
270
    
279
    
271
 }
280
 }
272
 
281
 
273
-cmDcRC_t cmDevCfgMgrAlloc( cmCtx_t* c, cmDevCfgH_t* hp )
282
+cmDcRC_t _cmDevCfgRead( cmDcm_t* p, cmJsonH_t jsH, const cmJsonNode_t* rootObjPtr );
283
+
284
+cmDcRC_t _cmDevCfgReadFile( cmDcm_t* p, const cmChar_t* fn )
285
+{
286
+  cmDcRC_t rc = kOkDcRC;
287
+
288
+  cmJsonH_t jsH = cmJsonNullHandle;
289
+
290
+  // initialize the JSON tree from the preferences file
291
+  if( cmJsonInitializeFromFile( &jsH, fn, p->ctx ) != kOkJsRC )
292
+  {
293
+    rc = cmErrMsg(&p->err,kJsonFailDcRC,"JSON initialization from '%s' failed.",cmStringNullGuard(fn));
294
+    goto errLabel;
295
+  }
296
+
297
+  if((rc = _cmDevCfgRead(p, jsH, cmJsonRoot(jsH))) != kOkJsRC )
298
+    goto errLabel;
299
+
300
+ errLabel:
301
+  if( cmJsonFinalize(&jsH) != kOkJsRC )
302
+    cmErrMsg(&p->err,kJsonFailDcRC,"JSON finalization failed following dev cfg read.");
303
+
304
+  return rc;
305
+
306
+}
307
+
308
+cmDcRC_t cmDevCfgAlloc( cmCtx_t* c, cmDevCfgH_t* hp, const cmChar_t* fn )
274
 {
309
 {
275
   cmDcRC_t rc;
310
   cmDcRC_t rc;
276
   cmDcmLoc_t* lp;
311
   cmDcmLoc_t* lp;
277
 
312
 
278
-  if((rc = cmDevCfgMgrFree(hp)) != kOkDcRC )
313
+  if((rc = cmDevCfgFree(hp)) != kOkDcRC )
279
     return rc;
314
     return rc;
280
 
315
 
281
   cmDcm_t* p = cmMemAllocZ(cmDcm_t,1);
316
   cmDcm_t* p = cmMemAllocZ(cmDcm_t,1);
282
 
317
 
283
   cmErrSetup(&p->err,&c->rpt,"cmDevCfg");
318
   cmErrSetup(&p->err,&c->rpt,"cmDevCfg");
284
 
319
 
320
+  p->ctx = c;
285
 
321
 
286
-  if((rc = _cmDcmNewLoc(p,"Default", &lp)) != kOkDcRC )
287
-    goto errLabel;
322
+  if( fn != NULL )
323
+  {
324
+    p->fn = cmMemAllocStr(fn);
325
+    
326
+    if( cmFsIsFile(fn) )
327
+    {
328
+      // if the file read fails then reset and go with the default empty setup.
329
+      if(_cmDevCfgReadFile(p,fn) != kOkDcRC )
330
+        _cmDcmFreeAllLocs(p);
331
+    }
332
+  }
333
+
334
+  // if the location array is empty then create a default location
335
+  if( p->loc == NULL )
336
+  {
337
+    if((rc = _cmDcmNewLoc(p,"Default", &lp)) != kOkDcRC )
338
+      goto errLabel;
339
+  }
288
 
340
 
289
   hp->h = p;
341
   hp->h = p;
290
 
342
 
295
   return rc;
347
   return rc;
296
 }
348
 }
297
 
349
 
298
-cmDcRC_t cmDevCfgMgrFree( cmDevCfgH_t* hp )
350
+cmDcRC_t cmDevCfgFree( cmDevCfgH_t* hp )
299
 {
351
 {
300
   cmDcRC_t rc = kOkDcRC;
352
   cmDcRC_t rc = kOkDcRC;
301
   if( hp == NULL || cmDevCfgIsValid(*hp)==false )
353
   if( hp == NULL || cmDevCfgIsValid(*hp)==false )
436
   cp->dcLabelStr = cmMemAllocStr(dcLabelStr);
488
   cp->dcLabelStr = cmMemAllocStr(dcLabelStr);
437
   cp->cfgId      = newCfgId;
489
   cp->cfgId      = newCfgId;
438
   cp->typeId     = typeId;
490
   cp->typeId     = typeId;
439
-  
491
+
440
   // link to the end of the loc's cfg list
492
   // link to the end of the loc's cfg list
441
   if( ep == NULL )
493
   if( ep == NULL )
442
     p->clp->cfg = cp;
494
     p->clp->cfg = cp;
643
   unsigned    outDevIdx;
695
   unsigned    outDevIdx;
644
 
696
 
645
   // validate the label
697
   // validate the label
646
-  if((dcLabelStr = _cmDcmTrimLabel(p,dcLabelStr,"MIDI cfg")) == NULL)
698
+  if((dcLabelStr = _cmDcmTrimLabel(p,dcLabelStr,"Audio cfg")) == NULL)
647
     return cmErrLastRC(&p->err);
699
     return cmErrLastRC(&p->err);
648
 
700
 
649
   // validate the input device
701
   // validate the input device
654
   if(( outDevIdx = cmApDeviceLabelToIndex(outDevNameStr)) == cmInvalidIdx )
706
   if(( outDevIdx = cmApDeviceLabelToIndex(outDevNameStr)) == cmInvalidIdx )
655
     return cmErrMsg(&p->err, kInvalidArgDcRC,"The output audio device name '%s' is not valid.",cmStringNullGuard(outDevNameStr));
707
     return cmErrMsg(&p->err, kInvalidArgDcRC,"The output audio device name '%s' is not valid.",cmStringNullGuard(outDevNameStr));
656
 
708
 
709
+  // validate the msg byte cnt
710
+  if( msgQueueByteCnt == 0 )
711
+    return cmErrMsg(&p->err, kInvalidArgDcRC,"The 'message queue size' must be greater than zero.");
712
+
713
+  // validate the dev. frames per cycle
714
+  if( devFramesPerCycle == 0 )
715
+    return cmErrMsg(&p->err, kInvalidArgDcRC,"The 'device frames per cycle' must be greater than zero.");
716
+  
717
+  // validate the dsp frames per cycle
718
+  if( dspFramesPerCycle == 0 || ((devFramesPerCycle/dspFramesPerCycle) * dspFramesPerCycle != devFramesPerCycle) )
719
+    return cmErrMsg(&p->err, kInvalidArgDcRC,"The 'DSP frames per cycle' must be greater than zero and an integer factor of 'Device frames per cycle.'.");
720
+
721
+  // validate the sample rate
722
+  if( srate == 0 )
723
+    return cmErrMsg(&p->err, kInvalidArgDcRC,"The audio sample rate must be greater than zero.");
724
+
657
   // if dcLabelStr is already in use for this location and type then update
725
   // if dcLabelStr is already in use for this location and type then update
658
   // the assoc'd recd otherwise create a new one.
726
   // the assoc'd recd otherwise create a new one.
659
   if((cp = _cmDcmFindOrCreateCfg(p,kAudioDcmTId, dcLabelStr)) == NULL )
727
   if((cp = _cmDcmFindOrCreateCfg(p,kAudioDcmTId, dcLabelStr)) == NULL )
660
     return cmErrLastRC(&p->err);
728
     return cmErrLastRC(&p->err);
661
 
729
 
730
+  unsigned inChCnt  = cmApDeviceChannelCount( inDevIdx,  true );
731
+  unsigned outChCnt = cmApDeviceChannelCount( outDevIdx, false );
732
+
662
   cp->u.a.inDevLabelStr                  = cmMemAllocStr(inDevNameStr);
733
   cp->u.a.inDevLabelStr                  = cmMemAllocStr(inDevNameStr);
663
   cp->u.a.outDevLabelStr                 = cmMemAllocStr(outDevNameStr);
734
   cp->u.a.outDevLabelStr                 = cmMemAllocStr(outDevNameStr);
664
   cp->u.a.audioSysArgs.rpt               = p->err.rpt;
735
   cp->u.a.audioSysArgs.rpt               = p->err.rpt;
670
   cp->u.a.audioSysArgs.dspFramesPerCycle = dspFramesPerCycle;
741
   cp->u.a.audioSysArgs.dspFramesPerCycle = dspFramesPerCycle;
671
   cp->u.a.audioSysArgs.audioBufCnt       = audioBufCnt;
742
   cp->u.a.audioSysArgs.audioBufCnt       = audioBufCnt;
672
   cp->u.a.audioSysArgs.srate             = srate;
743
   cp->u.a.audioSysArgs.srate             = srate;
673
-  cp->descStr = cmTsPrintfP(cp->descStr,"In:%s Out:%s",inDevNameStr,outDevNameStr);
744
+  cp->descStr = cmTsPrintfP(cp->descStr,"In: Chs:%i %s\nOut: Chs:%i %s",inChCnt,inDevNameStr,outChCnt,outDevNameStr);
674
   return kOkDcRC;  
745
   return kOkDcRC;  
675
 }
746
 }
676
 
747
 
748
+
749
+
750
+cmDcRC_t            cmDevCfgAudioSetDefaultCfgIndex( cmDevCfgH_t h, unsigned cfgIdx )
751
+{
752
+  cmDcm_t*    p  = _cmDcmHandleToPtr(h);
753
+
754
+  assert( p->clp != NULL );
755
+
756
+  cmDcmCfg_t* cp = p->clp->cfg;
757
+  unsigned    i;
758
+
759
+  for(i=0; cp!=NULL; cp=cp->next)
760
+    if( cp->typeId == kAudioDcmTId )
761
+    {
762
+      if( i == cfgIdx )
763
+        cp->u.a.dfltFl = true;
764
+      else
765
+      {
766
+        if( cp->u.a.dfltFl )
767
+          cp->u.a.dfltFl = false;
768
+      }
769
+
770
+      ++i;
771
+    }
772
+  
773
+
774
+  return kOkDcRC;
775
+}
776
+
777
+unsigned   cmDevCfgAudioGetDefaultCfgIndex( cmDevCfgH_t h )
778
+{
779
+  cmDcm_t*    p  = _cmDcmHandleToPtr(h);
780
+
781
+  assert( p->clp != NULL );
782
+
783
+  cmDcmCfg_t* cp = p->clp->cfg;
784
+  unsigned    i;
785
+
786
+  for(i=0; cp!=NULL; cp=cp->next)
787
+    if( cp->typeId == kAudioDcmTId )
788
+    {
789
+      if( cp->u.a.dfltFl )
790
+        return i;
791
+
792
+      ++i;
793
+    }
794
+  return cmInvalidIdx;
795
+}
796
+
797
+
677
 const cmDcmAudio_t* cmDevCfgAudioCfg( cmDevCfgH_t h, unsigned cfgIdx )
798
 const cmDcmAudio_t* cmDevCfgAudioCfg( cmDevCfgH_t h, unsigned cfgIdx )
678
 {
799
 {
679
   cmDcm_t* p = _cmDcmHandleToPtr(h);
800
   cmDcm_t* p = _cmDcmHandleToPtr(h);
697
 }
818
 }
698
 
819
 
699
 
820
 
700
-cmDcRC_t cmDevCfgNetPort(
821
+cmDcRC_t cmDevCfgNameNetPort(
701
   cmDevCfgH_t      h,
822
   cmDevCfgH_t      h,
702
   const cmChar_t* dcLabelStr,
823
   const cmChar_t* dcLabelStr,
703
   const cmChar_t* sockAddr,
824
   const cmChar_t* sockAddr,
716
 
837
 
717
   // if dcLabelStr is already in use for this location and type then update
838
   // if dcLabelStr is already in use for this location and type then update
718
   // the assoc'd recd otherwise create a new one.
839
   // the assoc'd recd otherwise create a new one.
719
-  if((cp = _cmDcmFindOrCreateCfg(p,kAudioDcmTId, dcLabelStr)) == NULL )
840
+  if((cp = _cmDcmFindOrCreateCfg(p,kNetDcmTId, dcLabelStr)) == NULL )
720
     return cmErrLastRC(&p->err);
841
     return cmErrLastRC(&p->err);
721
 
842
 
722
   cp->u.n.sockAddr = cmMemAllocStr(sockAddr);
843
   cp->u.n.sockAddr = cmMemAllocStr(sockAddr);
760
 }
881
 }
761
 const cmChar_t* cmDevCfgLocLabel(  cmDevCfgH_t h, unsigned locIdx )
882
 const cmChar_t* cmDevCfgLocLabel(  cmDevCfgH_t h, unsigned locIdx )
762
 {
883
 {
763
-  unsigned n = 0;
764
   cmDcm_t* p = _cmDcmHandleToPtr(h);
884
   cmDcm_t* p = _cmDcmHandleToPtr(h);
765
   const cmDcmLoc_t* lp = p->loc;
885
   const cmDcmLoc_t* lp = p->loc;
766
-  for(; lp!=NULL; lp=lp->next)
767
-    if( n == locIdx )
886
+  unsigned i;
887
+  for(i=0; lp!=NULL; lp=lp->next,++i)
888
+    if( i == locIdx )
768
       return lp->labelStr;
889
       return lp->labelStr;
769
 
890
 
770
   assert(0);
891
   assert(0);
772
 }
893
 }
773
 
894
 
774
 
895
 
775
-cmDcmLoc_t* _cmDcmLocLabelToPtr( cmDcm_t* p, const cmChar_t* locLabelStr)
896
+cmDcmLoc_t* _cmDcmLocLabelToPtr( cmDcm_t* p, const cmChar_t* locLabelStr, bool errFl)
776
 {
897
 {
777
   if((locLabelStr = _cmDcmTrimLabel(p,locLabelStr,"location")) == NULL )
898
   if((locLabelStr = _cmDcmTrimLabel(p,locLabelStr,"location")) == NULL )
778
     return NULL;
899
     return NULL;
782
     if( strcmp(lp->labelStr,locLabelStr) == 0 )
903
     if( strcmp(lp->labelStr,locLabelStr) == 0 )
783
       return lp;
904
       return lp;
784
 
905
 
785
-  cmErrMsg(&p->err,kLabelNotFoundDcRC,"The location label '%s' was not found.",locLabelStr);
906
+  if( errFl )
907
+    cmErrMsg(&p->err,kLabelNotFoundDcRC,"The location label '%s' was not found.",locLabelStr);
786
 
908
 
787
   return NULL;
909
   return NULL;
788
 }
910
 }
795
   unsigned i,j;
917
   unsigned i,j;
796
 
918
 
797
   // if this location label is already in use then it has already been stored.
919
   // if this location label is already in use then it has already been stored.
798
-  if( _cmDcmLocLabelToPtr(p,locLabelStr) != NULL )
920
+  if( _cmDcmLocLabelToPtr(p,locLabelStr,false) != NULL )
799
     return kOkDcRC;
921
     return kOkDcRC;
800
 
922
 
801
   // store the current loc ptr
923
   // store the current loc ptr
812
   {
934
   {
813
     cmDcmCfg_t* ncp;
935
     cmDcmCfg_t* ncp;
814
 
936
 
937
+    // this will always create (never find) a new cfg recd
815
     if((ncp = _cmDcmFindOrCreateCfg(p,ocp->typeId, ocp->dcLabelStr)) == NULL )
938
     if((ncp = _cmDcmFindOrCreateCfg(p,ocp->typeId, ocp->dcLabelStr)) == NULL )
816
     {
939
     {
817
       rc = cmErrLastRC(&p->err);
940
       rc = cmErrLastRC(&p->err);
818
       goto errLabel;
941
       goto errLabel;
819
     }
942
     }
943
+
944
+    // duplicate the desc. string
945
+    ncp->descStr = cmMemAllocStr(ocp->descStr);
820
     
946
     
821
     switch( ncp->typeId )
947
     switch( ncp->typeId )
822
     {
948
     {
869
   cmDcm_t*     p = _cmDcmHandleToPtr(h);
995
   cmDcm_t*     p = _cmDcmHandleToPtr(h);
870
   cmDcmLoc_t* lp;
996
   cmDcmLoc_t* lp;
871
 
997
 
872
-  if((lp = _cmDcmLocLabelToPtr(p,locLabelStr)) == NULL)
998
+  if((lp = _cmDcmLocLabelToPtr(p,locLabelStr,true)) == NULL)
873
     return cmErrLastRC(&p->err);
999
     return cmErrLastRC(&p->err);
874
 
1000
 
875
   p->clp = lp;
1001
   p->clp = lp;
881
   cmDcm_t*     p = _cmDcmHandleToPtr(h);
1007
   cmDcm_t*     p = _cmDcmHandleToPtr(h);
882
   cmDcmLoc_t* lp;
1008
   cmDcmLoc_t* lp;
883
 
1009
 
884
-  if((lp = _cmDcmLocLabelToPtr(p,locLabelStr)) == NULL )
1010
+  if((lp = _cmDcmLocLabelToPtr(p,locLabelStr,true)) == NULL )
885
     return cmErrLastRC(&p->err);
1011
     return cmErrLastRC(&p->err);
886
 
1012
 
887
   _cmDcmFreeLoc(p,lp);
1013
   _cmDcmFreeLoc(p,lp);
908
 cmDcRC_t _cmDcmJsonSyntaxErr( cmDcm_t* p, const cmChar_t* tagStr )
1034
 cmDcRC_t _cmDcmJsonSyntaxErr( cmDcm_t* p, const cmChar_t* tagStr )
909
 { return cmErrMsg(&p->err,kJsonFailDcRC,"JSON syntax error '%s' not found.",tagStr); }
1035
 { return cmErrMsg(&p->err,kJsonFailDcRC,"JSON syntax error '%s' not found.",tagStr); }
910
 
1036
 
911
-cmDcRC_t _cmDevCfgRead( cmDevCfgH_t h, cmJsonH_t jsH, const cmJsonNode_t* rootObjPtr )
1037
+cmDcRC_t _cmDevCfgRead( cmDcm_t* p, cmJsonH_t jsH, const cmJsonNode_t* rootObjPtr )
912
 {
1038
 {
913
   cmDcRC_t        rc          = kOkDcRC;
1039
   cmDcRC_t        rc          = kOkDcRC;
914
   const cmChar_t* errLabelPtr = NULL;
1040
   const cmChar_t* errLabelPtr = NULL;
915
   cmJsonNode_t* cfgNp, *locArrNp;
1041
   cmJsonNode_t* cfgNp, *locArrNp;
916
   unsigned i,j;
1042
   unsigned i,j;
917
-
918
-  cmDcm_t* p = _cmDcmHandleToPtr(h);
1043
+  cmDevCfgH_t h;
1044
+  h.h = p;
919
 
1045
 
920
   // clear the all locations
1046
   // clear the all locations
921
   _cmDcmFreeAllLocs(p);
1047
   _cmDcmFreeAllLocs(p);
931
   for(i=0; i<cmJsonChildCount(locArrNp); ++i)
1057
   for(i=0; i<cmJsonChildCount(locArrNp); ++i)
932
   {
1058
   {
933
     cmJsonNode_t* locObjNp, *cfgArrNp;
1059
     cmJsonNode_t* locObjNp, *cfgArrNp;
934
-    const cmChar_t* label = NULL;
1060
+    const cmChar_t* locLabelStr = NULL;
935
 
1061
 
936
     // get the loc object
1062
     // get the loc object
937
     if((locObjNp = cmJsonArrayElement(locArrNp,i)) == NULL || cmJsonIsObject(locObjNp)==false )
1063
     if((locObjNp = cmJsonArrayElement(locArrNp,i)) == NULL || cmJsonIsObject(locObjNp)==false )
939
 
1065
 
940
     // read the loc object fields
1066
     // read the loc object fields
941
     if( cmJsonMemberValues(locObjNp, &errLabelPtr,  
1067
     if( cmJsonMemberValues(locObjNp, &errLabelPtr,  
942
-        "label", kStringTId, &label,
1068
+        "label", kStringTId, &locLabelStr,
943
         "cfg",   kArrayTId,  &cfgArrNp,
1069
         "cfg",   kArrayTId,  &cfgArrNp,
944
-        NULL ) == kOkJsRC )
1070
+        NULL ) != kOkJsRC )
945
     { return _cmDcmJsonNotFound(p,errLabelPtr); }
1071
     { return _cmDcmJsonNotFound(p,errLabelPtr); }
946
 
1072
 
947
     // create a new location recd
1073
     // create a new location recd
948
     cmDcmLoc_t* locPtr = NULL;
1074
     cmDcmLoc_t* locPtr = NULL;
949
-    if((rc = _cmDcmNewLoc(p,label,&locPtr)) == kOkDcRC )
950
-      return cmErrMsg(&p->err,kJsonFailDcRC,"Location '%s' create failed.",cmStringNullGuard(label));
1075
+    if((rc = _cmDcmNewLoc(p,locLabelStr,&locPtr)) != kOkDcRC )
1076
+      return cmErrMsg(&p->err,kJsonFailDcRC,"Location '%s' create failed.",cmStringNullGuard(locLabelStr));
951
 
1077
 
952
     /*
1078
     /*
953
     // read each app object
1079
     // read each app object
998
         "cfgId",  kIntTId,    &cfgId,
1124
         "cfgId",  kIntTId,    &cfgId,
999
         "typeId", kIntTId,    &typeId,
1125
         "typeId", kIntTId,    &typeId,
1000
         "desc",   kStringTId, &descStr,
1126
         "desc",   kStringTId, &descStr,
1001
-          NULL ) == kOkJsRC )
1127
+          NULL ) != kOkJsRC )
1002
       { _cmDcmJsonSyntaxErr(p,errLabelPtr); }
1128
       { _cmDcmJsonSyntaxErr(p,errLabelPtr); }
1003
 
1129
 
1004
       cmDcmMidi_t  m;
1130
       cmDcmMidi_t  m;
1005
       cmDcmAudio_t a;
1131
       cmDcmAudio_t a;
1006
       cmDcmNet_t   n;
1132
       cmDcmNet_t   n;
1007
-
1133
+      
1008
       switch( typeId )
1134
       switch( typeId )
1009
       {
1135
       {
1010
         case kMidiDcmTId:   
1136
         case kMidiDcmTId:   
1011
           if( cmJsonMemberValues( cfgObjNp, &errLabelPtr,
1137
           if( cmJsonMemberValues( cfgObjNp, &errLabelPtr,
1012
               "devLabelStr", kStringTId, &m.devLabelStr,
1138
               "devLabelStr", kStringTId, &m.devLabelStr,
1013
               "portLabelStr",kStringTId, &m.portLabelStr,
1139
               "portLabelStr",kStringTId, &m.portLabelStr,
1140
+              "inputFl",     kBoolTId,   &m.inputFl,
1014
               NULL) != kOkJsRC )
1141
               NULL) != kOkJsRC )
1015
-          {}
1142
+          {
1143
+            rc = _cmDcmJsonSyntaxErr(p,errLabelPtr);
1144
+            goto errLabel;
1145
+          }
1016
           
1146
           
1017
-          cmDevCfgNameMidiPort(h,label,m.devLabelStr,m.portLabelStr,m.inputFl);
1147
+          if((rc = cmDevCfgNameMidiPort(h,dcLabelStr,m.devLabelStr,m.portLabelStr,m.inputFl)) != kOkDcRC )
1148
+            goto errLabel;
1018
           
1149
           
1019
           break;
1150
           break;
1020
             
1151
             
1027
               "devFramesPerCycle", kIntTId,    &a.audioSysArgs.devFramesPerCycle,
1158
               "devFramesPerCycle", kIntTId,    &a.audioSysArgs.devFramesPerCycle,
1028
               "dspFramesPerCycle", kIntTId,    &a.audioSysArgs.dspFramesPerCycle,
1159
               "dspFramesPerCycle", kIntTId,    &a.audioSysArgs.dspFramesPerCycle,
1029
               "audioBufCnt",       kIntTId,    &a.audioSysArgs.audioBufCnt,
1160
               "audioBufCnt",       kIntTId,    &a.audioSysArgs.audioBufCnt,
1030
-              "srate",             kIntTId,    &a.audioSysArgs.srate ) == kOkJsRC )
1031
-          {}
1032
-
1033
-          cmDevCfgNameAudioPort(h,label,a.inDevLabelStr,a.outDevLabelStr,
1034
-            a.audioSysArgs.syncInputFl,
1035
-            a.audioSysArgs.msgQueueByteCnt,
1036
-            a.audioSysArgs.devFramesPerCycle,
1037
-            a.audioSysArgs.dspFramesPerCycle,
1038
-            a.audioSysArgs.audioBufCnt,
1039
-            a.audioSysArgs.srate );
1161
+              "srate",             kRealTId,   &a.audioSysArgs.srate,
1162
+              NULL ) != kOkJsRC )
1163
+          {
1164
+            rc = _cmDcmJsonSyntaxErr(p,errLabelPtr);
1165
+            goto errLabel;
1166
+          }
1167
+
1168
+          if((rc = cmDevCfgNameAudioPort(h,dcLabelStr,a.inDevLabelStr,a.outDevLabelStr,
1169
+                a.audioSysArgs.syncInputFl,
1170
+                a.audioSysArgs.msgQueueByteCnt,
1171
+                a.audioSysArgs.devFramesPerCycle,
1172
+                a.audioSysArgs.dspFramesPerCycle,
1173
+                a.audioSysArgs.audioBufCnt,
1174
+                a.audioSysArgs.srate )) != kOkDcRC )
1175
+          {
1176
+            goto errLabel;
1177
+          }
1040
 
1178
 
1041
           break;
1179
           break;
1042
 
1180
 
1045
               "sockAddr",   kStringTId, &n.sockAddr,
1183
               "sockAddr",   kStringTId, &n.sockAddr,
1046
               "portNumber", kIntTId,    &n.portNumber,
1184
               "portNumber", kIntTId,    &n.portNumber,
1047
               NULL ) != kOkJsRC )
1185
               NULL ) != kOkJsRC )
1048
-          {}
1186
+          {
1187
+            rc = _cmDcmJsonSyntaxErr(p,errLabelPtr);
1188
+            goto errLabel;
1189
+          }
1049
 
1190
 
1050
-          cmDevCfgNetPort(h,label,n.sockAddr,n.portNumber);
1191
+          if((rc = cmDevCfgNameNetPort(h,dcLabelStr,n.sockAddr,n.portNumber)) != kOkDcRC )
1192
+            goto errLabel;
1051
 
1193
 
1052
           break;
1194
           break;
1053
 
1195
 
1058
     }    
1200
     }    
1059
   }
1201
   }
1060
 
1202
 
1203
+ errLabel:
1061
   return kOkDcRC;
1204
   return kOkDcRC;
1062
 }
1205
 }
1063
 
1206
 
1064
 cmDcRC_t _cmDevCfgWrite( cmDcm_t* p, cmJsonH_t jsH, cmJsonNode_t* rootObjPtr )
1207
 cmDcRC_t _cmDevCfgWrite( cmDcm_t* p, cmJsonH_t jsH, cmJsonNode_t* rootObjPtr )
1065
 {
1208
 {
1066
   cmDcRC_t rc = kOkDcRC;
1209
   cmDcRC_t rc = kOkDcRC;
1067
-  const cmDcmLoc_t* lp;
1210
+  const cmDcmLoc_t* lp = p->loc;
1068
   
1211
   
1069
   cmJsonNode_t* cfgNp = cmJsonInsertPairObject(jsH, rootObjPtr, "cfg" );
1212
   cmJsonNode_t* cfgNp = cmJsonInsertPairObject(jsH, rootObjPtr, "cfg" );
1070
 
1213
 
1077
     cmJsonNode_t* locObjNp = cmJsonCreateObject(jsH,locArrNp);
1220
     cmJsonNode_t* locObjNp = cmJsonCreateObject(jsH,locArrNp);
1078
 
1221
 
1079
     // set the loc label
1222
     // set the loc label
1080
-    cmJsonInsertPairString(jsH, locObjNp, lp->labelStr, "label" );
1223
+    cmJsonInsertPairString(jsH, locObjNp, "label", lp->labelStr );
1081
 
1224
 
1082
     /*
1225
     /*
1083
     // create the 'loc.app[]' array
1226
     // create the 'loc.app[]' array
1143
             "devFramesPerCycle", kIntTId,    cp->u.a.audioSysArgs.devFramesPerCycle,
1286
             "devFramesPerCycle", kIntTId,    cp->u.a.audioSysArgs.devFramesPerCycle,
1144
             "dspFramesPerCycle", kIntTId,    cp->u.a.audioSysArgs.dspFramesPerCycle,
1287
             "dspFramesPerCycle", kIntTId,    cp->u.a.audioSysArgs.dspFramesPerCycle,
1145
             "audioBufCnt",       kIntTId,    cp->u.a.audioSysArgs.audioBufCnt,
1288
             "audioBufCnt",       kIntTId,    cp->u.a.audioSysArgs.audioBufCnt,
1146
-            "srate",             kIntTId,    cp->u.a.audioSysArgs.srate,
1289
+            "srate",             kRealTId,   cp->u.a.audioSysArgs.srate,
1147
             NULL );
1290
             NULL );
1148
           break;
1291
           break;
1149
 
1292
 
1163
   return rc;
1306
   return rc;
1164
 }
1307
 }
1165
 
1308
 
1166
-cmDcRC_t cmDevCfgWrite( cmDevCfgH_t h )
1309
+cmDcRC_t cmDevCfgWrite( cmDevCfgH_t h, const cmChar_t* fn )
1167
 {
1310
 {
1168
   cmDcRC_t rc = kOkDcRC;
1311
   cmDcRC_t rc = kOkDcRC;
1312
+  cmDcm_t* p = _cmDcmHandleToPtr(h);
1313
+
1314
+  cmJsonH_t jsH = cmJsonNullHandle;
1315
+
1316
+  if( fn == NULL )
1317
+    fn = p->fn;
1318
+
1319
+  // validate the filename
1320
+  if( fn == NULL || strlen(fn)==0 )
1321
+    return cmErrMsg(&p->err,kInvalidFnDcRC,"No output file name was provided.");
1322
+
1323
+  // create a json object
1324
+  if( cmJsonInitialize( &jsH, p->ctx ) != kOkJsRC )
1325
+  {
1326
+    rc = cmErrMsg(&p->err,kJsonFailDcRC,"An empty JSON tree could not be created.");
1327
+    goto errLabel;
1328
+  }
1329
+
1330
+  // insert a wrapper object as the root
1331
+  if( cmJsonCreateObject( jsH, NULL ) == NULL )
1332
+  {
1333
+    rc = cmErrMsg(&p->err,kJsonFailDcRC,"The JSON root object could not be created.");
1334
+    goto errLabel;
1335
+  }
1336
+
1337
+  // fill the JSON tree
1338
+  if((rc = _cmDevCfgWrite(p,jsH,cmJsonRoot(jsH))) != kOkDcRC )
1339
+    goto errLabel;
1340
+
1341
+  // write the output file
1342
+  if( cmJsonWrite(jsH, cmJsonRoot(jsH), fn ) != kOkJsRC )
1343
+  {
1344
+    rc = cmErrMsg(&p->err,kJsonFailDcRC,"The JSON file write failed on '%s'.",cmStringNullGuard(fn));
1345
+    goto errLabel;
1346
+  }
1347
+  
1348
+  
1349
+ errLabel:
1350
+  if( cmJsonFinalize(&jsH) != kOkJsRC )
1351
+    cmErrMsg(&p->err,kJsonFailDcRC,"JSON tree finalization failed.");
1352
+
1169
   return rc;
1353
   return rc;
1170
 }
1354
 }

+ 24
- 6
cmDevCfg.h Переглянути файл

50
     kInvalidUserMapIdRC,
50
     kInvalidUserMapIdRC,
51
     kInvalidArgDcRC,
51
     kInvalidArgDcRC,
52
     kInvalidCfgIdxDcRC,
52
     kInvalidCfgIdxDcRC,
53
-    kJsonFailDcRC
53
+    kJsonFailDcRC,
54
+    kInvalidFnDcRC
54
   };
55
   };
55
 
56
 
56
   typedef enum
57
   typedef enum
78
     cmChar_t*        inDevLabelStr;  // Input audio device label.
79
     cmChar_t*        inDevLabelStr;  // Input audio device label.
79
     cmChar_t*        outDevLabelStr; // Output audio device label.
80
     cmChar_t*        outDevLabelStr; // Output audio device label.
80
     cmAudioSysArgs_t audioSysArgs;   // Audio system  cfg recd
81
     cmAudioSysArgs_t audioSysArgs;   // Audio system  cfg recd
82
+    bool             dfltFl;         // true if this is the default audio cfg.
81
   } cmDcmAudio_t;
83
   } cmDcmAudio_t;
82
 
84
 
83
   typedef struct              
85
   typedef struct              
88
 
90
 
89
   extern cmDevCfgH_t cmDevCfgNullHandle;
91
   extern cmDevCfgH_t cmDevCfgNullHandle;
90
 
92
 
91
-  cmDcRC_t cmDevCfgMgrAlloc( cmCtx_t* c, cmDevCfgH_t* hp );
92
-  cmDcRC_t cmDevCfgMgrFree( cmDevCfgH_t* hp );
93
+  cmDcRC_t cmDevCfgAlloc( cmCtx_t* c, cmDevCfgH_t* hp, const cmChar_t* fn );
94
+  cmDcRC_t cmDevCfgFree( cmDevCfgH_t* hp );
93
   bool     cmDevCfgIsValid( cmDevCfgH_t h );
95
   bool     cmDevCfgIsValid( cmDevCfgH_t h );
94
 
96
 
95
   // Return the count of cfg records for the given type in the current location.
97
   // Return the count of cfg records for the given type in the current location.
139
     unsigned        audioBufCnt,
141
     unsigned        audioBufCnt,
140
     double          srate  );
142
     double          srate  );
141
 
143
 
144
+  cmDcRC_t            cmDevCfgAudioSetDefaultCfgIndex( cmDevCfgH_t h, unsigned cfgIdx );
145
+  unsigned            cmDevCfgAudioGetDefaultCfgIndex( cmDevCfgH_t h );
146
+
142
   const cmDcmAudio_t* cmDevCfgAudioCfg( cmDevCfgH_t h, unsigned cfgIdx );
147
   const cmDcmAudio_t* cmDevCfgAudioCfg( cmDevCfgH_t h, unsigned cfgIdx );
143
   const cmDcmAudio_t* cmDevCfgAudioMap( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId );
148
   const cmDcmAudio_t* cmDevCfgAudioMap( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId );
149
+  
144
 
150
 
145
   const struct cmAudioSysArgs_str* cmDevCfgAudioSysArgs( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId );
151
   const struct cmAudioSysArgs_str* cmDevCfgAudioSysArgs( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId );
146
 
152
 
147
-  cmDcRC_t cmDevCfgNetPort(
153
+  cmDcRC_t cmDevCfgNameNetPort(
148
     cmDevCfgH_t      h,
154
     cmDevCfgH_t      h,
149
     const cmChar_t* dcLabelStr,
155
     const cmChar_t* dcLabelStr,
150
     const cmChar_t* sockAddr,
156
     const cmChar_t* sockAddr,
153
   const cmDcmNet_t* cmDevCfgNetCfg( cmDevCfgH_t h, unsigned cfgIdx );
159
   const cmDcmNet_t* cmDevCfgNetCfg( cmDevCfgH_t h, unsigned cfgIdx );
154
   const cmDcmNet_t* cmDevCfgNetMap( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId );
160
   const cmDcmNet_t* cmDevCfgNetMap( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId );
155
 
161
 
162
+  //---------------------------------------------------------------------------------------
156
   // Location Management Functions:
163
   // Location Management Functions:
157
-  // Store and recall groups cfg records.
164
+  // Store and recall groups of cfg records.
158
 
165
 
166
+  // Return a count of the current number of locations.
159
   unsigned        cmDevCfgLocCount(  cmDevCfgH_t h );
167
   unsigned        cmDevCfgLocCount(  cmDevCfgH_t h );
168
+
169
+  // Given a location index (0 to cmDevCfgLocCount()-1) return the locations label.
160
   const cmChar_t* cmDevCfgLocLabel(  cmDevCfgH_t h, unsigned locIdx );
170
   const cmChar_t* cmDevCfgLocLabel(  cmDevCfgH_t h, unsigned locIdx );
171
+
172
+  // If 'locLabelStr' has already been used then this function does nothing and returns.
173
+  // otherwise the current location is duplicated and the duplicate is named 'locLabelStr'.
161
   cmDcRC_t        cmDevCfgLocStore(  cmDevCfgH_t h, const cmChar_t* locLabelStr );
174
   cmDcRC_t        cmDevCfgLocStore(  cmDevCfgH_t h, const cmChar_t* locLabelStr );
175
+
176
+  // Make the location named 'locLabelStr' the current location.
162
   cmDcRC_t        cmDevCfgLocRecall( cmDevCfgH_t h, const cmChar_t* locLabelStr );
177
   cmDcRC_t        cmDevCfgLocRecall( cmDevCfgH_t h, const cmChar_t* locLabelStr );
178
+
179
+  // Delete the location named by 'locLabelStr'.
163
   cmDcRC_t        cmDevCfgLocDelete( cmDevCfgH_t h, const cmChar_t* locLabelStr );
180
   cmDcRC_t        cmDevCfgLocDelete( cmDevCfgH_t h, const cmChar_t* locLabelStr );
164
 
181
 
165
   // Return the current location index
182
   // Return the current location index
166
   unsigned        cmDevCfgLocCurIndex(  cmDevCfgH_t h );
183
   unsigned        cmDevCfgLocCurIndex(  cmDevCfgH_t h );
167
 
184
 
168
-  cmDcRC_t cmDevCfgWrite( cmDevCfgH_t h );
185
+  // Set 'fn' to NULL to use filename from cmDevCfgAlloc()
186
+  cmDcRC_t cmDevCfgWrite( cmDevCfgH_t h, const cmChar_t* fn );
169
   
187
   
170
 
188
 
171
 #ifdef __cplusplus
189
 #ifdef __cplusplus

Завантаження…
Відмінити
Зберегти