Browse Source

cmDevCfg.h/c: Many changes and additions.

master
kevin 11 years ago
parent
commit
a39e5f620c
2 changed files with 232 additions and 33 deletions
  1. 205
    20
      cmDevCfg.c
  2. 27
    13
      cmDevCfg.h

+ 205
- 20
cmDevCfg.c View File

@@ -15,8 +15,8 @@
15 15
 #include "cmAudioPort.h"
16 16
 #include "cmUdpPort.h"
17 17
 #include "cmUdpNet.h"
18
-#include "cmAudioSysMsg.h"
19
-#include "cmAudioSys.h"
18
+#include "cmRtSysMsg.h"
19
+#include "cmRtSys.h"
20 20
 
21 21
 #include "cmDevCfg.h"
22 22
 
@@ -146,6 +146,8 @@ void _cmDcmDuplNet( cmDcmNet_t* d, const cmDcmNet_t* s )
146 146
 {
147 147
   d->sockAddr   = cmMemAllocStr(s->sockAddr);
148 148
   d->portNumber = s->portNumber;
149
+  d->localFl    = s->localFl;
150
+  d->activeFl   = s->activeFl;
149 151
 }
150 152
 
151 153
 
@@ -446,11 +448,11 @@ unsigned cmDevCfgLabelToIndex( cmDevCfgH_t h, cmTypeDcmId_t typeId, const cmChar
446 448
     if( cp->typeId == typeId )
447 449
     {
448 450
       if( strcmp(cp->dcLabelStr,label)==0 )
449
-        break;
451
+        return n;
450 452
       ++n;
451 453
     }
452 454
 
453
-  return n;
455
+  return cmInvalidIdx;
454 456
 }
455 457
 
456 458
 cmDcmCfg_t*  _cmDcmFindOrCreateCfg( cmDcm_t* p, cmTypeDcmId_t typeId, const cmChar_t* dcLabelStr )
@@ -676,6 +678,27 @@ const cmDcmMidi_t* cmDevCfgMidiDevMap( cmDevCfgH_t h, unsigned usrAppId, unsigne
676 678
   return &mp->cfg->u.m;
677 679
 }
678 680
 
681
+const cmDcmMidi_t* cmDevCfgMidiCfgFromLabel( cmDevCfgH_t h, const cmChar_t* cfgLabel )
682
+{
683
+  cmDcm_t*           p = _cmDcmHandleToPtr(h);
684
+  const cmDcmMidi_t* c;
685
+  unsigned           idx;
686
+
687
+  if((idx = cmDevCfgLabelToIndex(h, kMidiDcmTId, cfgLabel )) == cmInvalidIdx )
688
+  {
689
+    cmErrMsg(&p->err,kLabelNotFoundDcRC,"The MIDI cfg. '%s' was not found.",cmStringNullGuard(cfgLabel));
690
+    return NULL;
691
+  }
692
+
693
+  if((c = cmDevCfgMidiCfg(h,idx)) == NULL )
694
+  {
695
+    cmErrMsg(&p->err,kInvalidCfgIdxDcRC,"The MIDI cfg. index %i is invalid.",idx);
696
+    return NULL;
697
+  }
698
+
699
+  return c;
700
+}
701
+
679 702
 
680 703
 cmDcRC_t cmDevCfgNameAudioPort( 
681 704
   cmDevCfgH_t     h,
@@ -687,24 +710,27 @@ cmDcRC_t cmDevCfgNameAudioPort(
687 710
   unsigned        devFramesPerCycle,
688 711
   unsigned        dspFramesPerCycle,
689 712
   unsigned        audioBufCnt,
690
-  double          srate  )
713
+  double          srate,
714
+  bool            activeFl )
691 715
 {
692 716
   cmDcm_t*    p = _cmDcmHandleToPtr(h);
693 717
   cmDcmCfg_t* cp;
694
-  unsigned    inDevIdx;
695
-  unsigned    outDevIdx;
718
+  unsigned    inDevIdx   = cmInvalidIdx;
719
+  unsigned    outDevIdx  = cmInvalidIdx;
696 720
 
697 721
   // validate the label
698 722
   if((dcLabelStr = _cmDcmTrimLabel(p,dcLabelStr,"Audio cfg")) == NULL)
699 723
     return cmErrLastRC(&p->err);
700 724
 
701 725
   // validate the input device
702
-  if(( inDevIdx = cmApDeviceLabelToIndex(inDevNameStr)) == cmInvalidIdx )
703
-    return cmErrMsg(&p->err, kInvalidArgDcRC,"The input audio device name '%s' is not valid.",cmStringNullGuard(inDevNameStr));
726
+  if( inDevNameStr != NULL )
727
+    if(( inDevIdx = cmApDeviceLabelToIndex(inDevNameStr)) == cmInvalidIdx )
728
+      return cmErrMsg(&p->err, kInvalidArgDcRC,"The input audio device name '%s' is not valid.",cmStringNullGuard(inDevNameStr));
704 729
 
705 730
   // validate the output device
706
-  if(( outDevIdx = cmApDeviceLabelToIndex(outDevNameStr)) == cmInvalidIdx )
707
-    return cmErrMsg(&p->err, kInvalidArgDcRC,"The output audio device name '%s' is not valid.",cmStringNullGuard(outDevNameStr));
731
+  if( outDevNameStr != NULL )
732
+    if(( outDevIdx = cmApDeviceLabelToIndex(outDevNameStr)) == cmInvalidIdx )
733
+      return cmErrMsg(&p->err, kInvalidArgDcRC,"The output audio device name '%s' is not valid.",cmStringNullGuard(outDevNameStr));
708 734
 
709 735
   // validate the msg byte cnt
710 736
   if( msgQueueByteCnt == 0 )
@@ -730,8 +756,9 @@ cmDcRC_t cmDevCfgNameAudioPort(
730 756
   unsigned inChCnt  = cmApDeviceChannelCount( inDevIdx,  true );
731 757
   unsigned outChCnt = cmApDeviceChannelCount( outDevIdx, false );
732 758
 
733
-  cp->u.a.inDevLabelStr                  = cmMemAllocStr(inDevNameStr);
734
-  cp->u.a.outDevLabelStr                 = cmMemAllocStr(outDevNameStr);
759
+  cp->u.a.inDevLabelStr                  = cmMemAllocStr(inDevNameStr==NULL?"":inDevNameStr);
760
+  cp->u.a.outDevLabelStr                 = cmMemAllocStr(outDevNameStr==NULL?"":outDevNameStr);
761
+  cp->u.a.activeFl                       = activeFl;
735 762
   cp->u.a.audioSysArgs.rpt               = p->err.rpt;
736 763
   cp->u.a.audioSysArgs.inDevIdx          = inDevIdx;
737 764
   cp->u.a.audioSysArgs.outDevIdx         = outDevIdx;
@@ -741,7 +768,7 @@ cmDcRC_t cmDevCfgNameAudioPort(
741 768
   cp->u.a.audioSysArgs.dspFramesPerCycle = dspFramesPerCycle;
742 769
   cp->u.a.audioSysArgs.audioBufCnt       = audioBufCnt;
743 770
   cp->u.a.audioSysArgs.srate             = srate;
744
-  cp->descStr = cmTsPrintfP(cp->descStr,"In: Chs:%i %s\nOut: Chs:%i %s",inChCnt,inDevNameStr,outChCnt,outDevNameStr);
771
+  cp->descStr = cmTsPrintfP(cp->descStr,"%sIn: Chs:%i %s\nOut: Chs:%i %s",activeFl?"":"INACTIVE ",inChCnt,cp->u.a.inDevLabelStr,outChCnt,cp->u.a.outDevLabelStr);
745 772
   return kOkDcRC;  
746 773
 }
747 774
 
@@ -794,6 +821,115 @@ unsigned   cmDevCfgAudioGetDefaultCfgIndex( cmDevCfgH_t h )
794 821
   return cmInvalidIdx;
795 822
 }
796 823
 
824
+bool  cmDevCfgAudioIsDeviceActive( cmDevCfgH_t h, const cmChar_t* devNameStr, bool inputFl )
825
+{
826
+  cmDcm_t*    p  = _cmDcmHandleToPtr(h);
827
+
828
+  assert( p->clp != NULL );
829
+
830
+  cmDcmCfg_t* cp = p->clp->cfg;
831
+  unsigned    i;
832
+
833
+  for(i=0; cp!=NULL; cp=cp->next)
834
+    if( cp->typeId == kAudioDcmTId )
835
+    {
836
+      bool fl;
837
+
838
+      if( inputFl )
839
+        fl = strcmp(devNameStr,cp->u.a.inDevLabelStr)==0;
840
+      else
841
+        fl = strcmp(devNameStr,cp->u.a.outDevLabelStr)==0;
842
+
843
+      if( fl )
844
+        return cp->u.a.activeFl;
845
+      
846
+      ++i;
847
+    }
848
+
849
+  return false;
850
+}
851
+
852
+unsigned            cmDevCfgAudioActiveCount( cmDevCfgH_t h )
853
+{
854
+  cmDcm_t*    p  = _cmDcmHandleToPtr(h);
855
+
856
+  assert( p->clp != NULL );
857
+
858
+  cmDcmCfg_t* cp = p->clp->cfg;
859
+  unsigned    n;
860
+
861
+  for(n=0; cp!=NULL; cp=cp->next)
862
+    if( cp->typeId == kAudioDcmTId && cp->u.a.activeFl )
863
+      ++n;
864
+
865
+  return n;
866
+}
867
+
868
+const cmChar_t*     cmDevCfgAudioActiveLabel( cmDevCfgH_t h, unsigned idx )
869
+{
870
+  cmDcm_t*    p  = _cmDcmHandleToPtr(h);
871
+
872
+  assert( p->clp != NULL );
873
+
874
+  cmDcmCfg_t* cp = p->clp->cfg;
875
+  unsigned    i;
876
+
877
+  for(i=0; cp!=NULL; cp=cp->next)
878
+    if( cp->typeId == kAudioDcmTId && cp->u.a.activeFl )
879
+    {
880
+      if( i == idx )
881
+        return cp->dcLabelStr;
882
+      ++i;
883
+    }
884
+
885
+  assert(0);
886
+  return NULL;
887
+}
888
+
889
+const cmDcmAudio_t* cmDevCfgAudioActiveCfg(   cmDevCfgH_t h, unsigned idx )
890
+{
891
+  cmDcm_t*    p  = _cmDcmHandleToPtr(h);
892
+
893
+  assert( p->clp != NULL );
894
+
895
+  cmDcmCfg_t* cp = p->clp->cfg;
896
+  unsigned    i;
897
+
898
+  for(i=0; cp!=NULL; cp=cp->next)
899
+    if( cp->typeId == kAudioDcmTId && cp->u.a.activeFl )
900
+    {
901
+      if( i == idx )
902
+        return &cp->u.a;
903
+      ++i;
904
+    }
905
+
906
+  assert(0);
907
+  return NULL;
908
+}
909
+
910
+unsigned  cmDevCfgAudioActiveIndex( cmDevCfgH_t h, const cmChar_t* cfgLabel )
911
+{
912
+  cmDcm_t*    p  = _cmDcmHandleToPtr(h);
913
+
914
+  if( cfgLabel == NULL )
915
+    return cmInvalidIdx;
916
+
917
+  assert( p->clp != NULL );
918
+
919
+  cmDcmCfg_t* cp = p->clp->cfg;
920
+  unsigned    i;
921
+
922
+  for(i=0; cp!=NULL; cp=cp->next)
923
+    if( cp->typeId == kAudioDcmTId && cp->u.a.activeFl)
924
+    {
925
+      if( cp->dcLabelStr!=NULL && strcmp(cp->dcLabelStr,cfgLabel) == 0 )
926
+        return i;
927
+      ++i;
928
+    }
929
+
930
+  return cmInvalidIdx;
931
+}
932
+
797 933
 
798 934
 const cmDcmAudio_t* cmDevCfgAudioCfg( cmDevCfgH_t h, unsigned cfgIdx )
799 935
 {
@@ -822,7 +958,9 @@ cmDcRC_t cmDevCfgNameNetPort(
822 958
   cmDevCfgH_t      h,
823 959
   const cmChar_t* dcLabelStr,
824 960
   const cmChar_t* sockAddr,
825
-  unsigned        portNumber )
961
+  unsigned        portNumber,
962
+  bool            localFl,
963
+  bool            activeFl)
826 964
 {
827 965
 
828 966
   cmDcm_t* p = _cmDcmHandleToPtr(h);
@@ -832,7 +970,7 @@ cmDcRC_t cmDevCfgNameNetPort(
832 970
     return cmErrMsg(&p->err,kInvalidArgDcRC,"The network port number %i is invalid. The valid IP port number range is:0-0xffff.");
833 971
 
834 972
   // validate the label
835
-  if((dcLabelStr = _cmDcmTrimLabel(p,dcLabelStr,"MIDI cfg")) == NULL)
973
+  if((dcLabelStr = _cmDcmTrimLabel(p,dcLabelStr,"Net cfg")) == NULL)
836 974
     return cmErrLastRC(&p->err);
837 975
 
838 976
   // if dcLabelStr is already in use for this location and type then update
@@ -840,14 +978,54 @@ cmDcRC_t cmDevCfgNameNetPort(
840 978
   if((cp = _cmDcmFindOrCreateCfg(p,kNetDcmTId, dcLabelStr)) == NULL )
841 979
     return cmErrLastRC(&p->err);
842 980
 
843
-  cp->u.n.sockAddr = cmMemAllocStr(sockAddr);
981
+  cp->u.n.sockAddr   = cmMemAllocStr(sockAddr);
844 982
   cp->u.n.portNumber = portNumber;
845
-  cp->descStr = cmTsPrintfP(cp->descStr,"%s:%i",sockAddr,portNumber);
983
+  cp->u.n.localFl    = localFl;
984
+  cp->u.n.activeFl   = activeFl;
985
+  cp->descStr = cmTsPrintfP(cp->descStr,"%s %s %s:%i",activeFl?"":"INACTIVE",localFl?"local":"remote",sockAddr,portNumber);
846 986
   
847 987
 
848 988
   return kOkDcRC;
849 989
 }
850 990
 
991
+unsigned          cmDevCfgNetActiveCount( cmDevCfgH_t h )
992
+{
993
+  cmDcm_t* p = _cmDcmHandleToPtr(h);
994
+
995
+  assert( p->clp != NULL );
996
+
997
+  cmDcmCfg_t* cp = p->clp->cfg;
998
+  unsigned    n;
999
+
1000
+  for(n=0; cp!=NULL; cp=cp->next)
1001
+    if( cp->typeId == kNetDcmTId && cp->u.a.activeFl )
1002
+      ++n;
1003
+
1004
+  return n;
1005
+}
1006
+
1007
+const cmDcmNet_t* cmDevCfgNetActiveCfg( cmDevCfgH_t h, unsigned idx )
1008
+{
1009
+  cmDcm_t* p = _cmDcmHandleToPtr(h);
1010
+
1011
+  assert( p->clp != NULL );
1012
+
1013
+  cmDcmCfg_t* cp = p->clp->cfg;
1014
+  unsigned    i;
1015
+
1016
+  for(i=0; cp!=NULL; cp=cp->next)
1017
+    if( cp->typeId == kNetDcmTId && cp->u.a.activeFl )
1018
+    {
1019
+      if( i == idx )
1020
+        return &cp->u.n;
1021
+      ++i;
1022
+    }
1023
+
1024
+  assert(0);
1025
+  return NULL;
1026
+}
1027
+
1028
+
851 1029
 const cmDcmNet_t* cmDevCfgNetCfg( cmDevCfgH_t h, unsigned cfgIdx )
852 1030
 {
853 1031
   cmDcm_t* p = _cmDcmHandleToPtr(h);
@@ -1159,6 +1337,7 @@ cmDcRC_t _cmDevCfgRead( cmDcm_t* p, cmJsonH_t jsH, const cmJsonNode_t* rootObjPt
1159 1337
               "dspFramesPerCycle", kIntTId,    &a.audioSysArgs.dspFramesPerCycle,
1160 1338
               "audioBufCnt",       kIntTId,    &a.audioSysArgs.audioBufCnt,
1161 1339
               "srate",             kRealTId,   &a.audioSysArgs.srate,
1340
+              "active",            kBoolTId,   &a.activeFl,
1162 1341
               NULL ) != kOkJsRC )
1163 1342
           {
1164 1343
             rc = _cmDcmJsonSyntaxErr(p,errLabelPtr);
@@ -1171,7 +1350,8 @@ cmDcRC_t _cmDevCfgRead( cmDcm_t* p, cmJsonH_t jsH, const cmJsonNode_t* rootObjPt
1171 1350
                 a.audioSysArgs.devFramesPerCycle,
1172 1351
                 a.audioSysArgs.dspFramesPerCycle,
1173 1352
                 a.audioSysArgs.audioBufCnt,
1174
-                a.audioSysArgs.srate )) != kOkDcRC )
1353
+                a.audioSysArgs.srate,
1354
+                a.activeFl)) != kOkDcRC )
1175 1355
           {
1176 1356
             goto errLabel;
1177 1357
           }
@@ -1182,13 +1362,15 @@ cmDcRC_t _cmDevCfgRead( cmDcm_t* p, cmJsonH_t jsH, const cmJsonNode_t* rootObjPt
1182 1362
           if( cmJsonMemberValues( cfgObjNp, &errLabelPtr,
1183 1363
               "sockAddr",   kStringTId, &n.sockAddr,
1184 1364
               "portNumber", kIntTId,    &n.portNumber,
1365
+              "localFl",    kBoolTId,   &n.localFl,
1366
+              "activeFl",   kBoolTId,   &n.activeFl,
1185 1367
               NULL ) != kOkJsRC )
1186 1368
           {
1187 1369
             rc = _cmDcmJsonSyntaxErr(p,errLabelPtr);
1188 1370
             goto errLabel;
1189 1371
           }
1190 1372
 
1191
-          if((rc = cmDevCfgNameNetPort(h,dcLabelStr,n.sockAddr,n.portNumber)) != kOkDcRC )
1373
+          if((rc = cmDevCfgNameNetPort(h,dcLabelStr,n.sockAddr,n.portNumber,n.localFl,n.activeFl)) != kOkDcRC )
1192 1374
             goto errLabel;
1193 1375
 
1194 1376
           break;
@@ -1287,6 +1469,7 @@ cmDcRC_t _cmDevCfgWrite( cmDcm_t* p, cmJsonH_t jsH, cmJsonNode_t* rootObjPtr )
1287 1469
             "dspFramesPerCycle", kIntTId,    cp->u.a.audioSysArgs.dspFramesPerCycle,
1288 1470
             "audioBufCnt",       kIntTId,    cp->u.a.audioSysArgs.audioBufCnt,
1289 1471
             "srate",             kRealTId,   cp->u.a.audioSysArgs.srate,
1472
+            "active",            kBoolTId,   cp->u.a.activeFl,
1290 1473
             NULL );
1291 1474
           break;
1292 1475
 
@@ -1294,6 +1477,8 @@ cmDcRC_t _cmDevCfgWrite( cmDcm_t* p, cmJsonH_t jsH, cmJsonNode_t* rootObjPtr )
1294 1477
           cmJsonInsertPairs(jsH, cfgObjNp,
1295 1478
             "sockAddr",  kStringTId, cp->u.n.sockAddr,
1296 1479
             "portNumber",kIntTId,    cp->u.n.portNumber,
1480
+            "localFl",   kBoolTId,   cp->u.n.localFl,
1481
+            "activeFl",  kBoolTId,   cp->u.n.activeFl,
1297 1482
             NULL );
1298 1483
           break;
1299 1484
 

+ 27
- 13
cmDevCfg.h View File

@@ -11,7 +11,7 @@ extern "C" {
11 11
        The device record identifies a particlar device
12 12
        end-point or pre-configured setup.  The 'cfg label'
13 13
        associated with this setup allows an application
14
-       to refer to the setup by name.  This releives the
14
+       to refer to the setup by name.  This relieves the
15 15
        application from having to handle the details of
16 16
        forming, storing, and maintaining device configurations.
17 17
 
@@ -37,7 +37,7 @@ extern "C" {
37 37
    */
38 38
 
39 39
 
40
-  struct cmAudioSysArgs_str;
40
+  struct cmRtSysArgs_str;
41 41
 
42 42
   enum
43 43
   {
@@ -76,16 +76,19 @@ extern "C" {
76 76
 
77 77
   typedef struct
78 78
   {
79
-    cmChar_t*        inDevLabelStr;  // Input audio device label.
80
-    cmChar_t*        outDevLabelStr; // Output audio device label.
81
-    cmAudioSysArgs_t audioSysArgs;   // Audio system  cfg recd
82
-    bool             dfltFl;         // true if this is the default audio cfg.
79
+    cmChar_t*     inDevLabelStr;  // Input audio device label.
80
+    cmChar_t*     outDevLabelStr; // Output audio device label.
81
+    cmRtSysArgs_t audioSysArgs;   // Audio system  cfg recd
82
+    bool          dfltFl;         // true if this is the default audio cfg.
83
+    bool          activeFl;
83 84
   } cmDcmAudio_t;
84 85
 
85 86
   typedef struct              
86 87
   {
87
-    cmChar_t* sockAddr;   // Remote socket address.
88
-    unsigned  portNumber; // Remote socket port number
88
+    cmChar_t* sockAddr;   // socket address.
89
+    unsigned  portNumber; // socket port number
90
+    bool      localFl;    // this is the local port
91
+    bool      activeFl;   // this port is active/inactive
89 92
   } cmDcmNet_t;
90 93
 
91 94
   extern cmDevCfgH_t cmDevCfgNullHandle;
@@ -128,6 +131,8 @@ extern "C" {
128 131
   const cmDcmMidi_t* cmDevCfgMidiCfg( cmDevCfgH_t h, unsigned cfgIdx );
129 132
   const cmDcmMidi_t* cmDevCfgMidiMap( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId );
130 133
   
134
+  const cmDcmMidi_t* cmDevCfgMidiCfgFromLabel( cmDevCfgH_t h, const cmChar_t* cfgLabel );
135
+
131 136
 
132 137
   cmDcRC_t cmDevCfgNameAudioPort( 
133 138
     cmDevCfgH_t     h,
@@ -139,22 +144,31 @@ extern "C" {
139 144
     unsigned        devFramesPerCycle,
140 145
     unsigned        dspFramesPerCycle,
141 146
     unsigned        audioBufCnt,
142
-    double          srate  );
147
+    double          srate,
148
+    bool            activeFl );
143 149
 
144
-  cmDcRC_t            cmDevCfgAudioSetDefaultCfgIndex( cmDevCfgH_t h, unsigned cfgIdx );
145
-  unsigned            cmDevCfgAudioGetDefaultCfgIndex( cmDevCfgH_t h );
150
+  bool                cmDevCfgAudioIsDeviceActive( cmDevCfgH_t h, const cmChar_t* devNameStr, bool inputFl );
151
+  unsigned            cmDevCfgAudioActiveCount( cmDevCfgH_t h );
152
+  const cmChar_t*     cmDevCfgAudioActiveLabel( cmDevCfgH_t h, unsigned idx );
153
+  const cmDcmAudio_t* cmDevCfgAudioActiveCfg(   cmDevCfgH_t h, unsigned idx );
154
+  unsigned            cmDevCfgAudioActiveIndex( cmDevCfgH_t h, const cmChar_t* cfgLabel );
146 155
 
147 156
   const cmDcmAudio_t* cmDevCfgAudioCfg( cmDevCfgH_t h, unsigned cfgIdx );
148 157
   const cmDcmAudio_t* cmDevCfgAudioMap( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId );
149 158
   
150 159
 
151
-  const struct cmAudioSysArgs_str* cmDevCfgAudioSysArgs( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId );
160
+  const struct cmRtSysArgs_str* cmDevCfgRtSysArgs( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId );
152 161
 
153 162
   cmDcRC_t cmDevCfgNameNetPort(
154 163
     cmDevCfgH_t      h,
155 164
     const cmChar_t* dcLabelStr,
156 165
     const cmChar_t* sockAddr,
157
-    unsigned        portNumber );
166
+    unsigned        portNumber,
167
+    bool            localFl,
168
+    bool            activeFl);
169
+
170
+  unsigned          cmDevCfgNetActiveCount( cmDevCfgH_t h );
171
+  const cmDcmNet_t* cmDevCfgNetActiveCfg( cmDevCfgH_t h, unsigned idx );
158 172
 
159 173
   const cmDcmNet_t* cmDevCfgNetCfg( cmDevCfgH_t h, unsigned cfgIdx );
160 174
   const cmDcmNet_t* cmDevCfgNetMap( cmDevCfgH_t h, unsigned usrAppId, unsigned usrMapId );

Loading…
Cancel
Save