Bläddra i källkod

cmXScore.h/c : Added 'tied_dur' field to cmXsNote_t for use in determining the length of a MIDI note events.

master
kevin 7 år sedan
förälder
incheckning
84c5097a8d
2 ändrade filer med 59 tillägg och 38 borttagningar
  1. 57
    37
      app/cmXScore.c
  2. 2
    1
      app/cmXScore.h

+ 57
- 37
app/cmXScore.c Visa fil

84
   unsigned                    staff;    // 1=treble 2=bass
84
   unsigned                    staff;    // 1=treble 2=bass
85
   unsigned                    tick;     //
85
   unsigned                    tick;     //
86
   unsigned                    duration; // duration in ticks
86
   unsigned                    duration; // duration in ticks
87
+  unsigned                    tied_dur; // duration in ticks (including all tied notes)
87
   double                      secs;     // absolute time in seconds
88
   double                      secs;     // absolute time in seconds
88
   double                      dsecs;    // delta time in seconds since previous event
89
   double                      dsecs;    // delta time in seconds since previous event
89
   unsigned                    locIdx;   // location index (chords share the same location index)
90
   unsigned                    locIdx;   // location index (chords share the same location index)
90
   double                      rvalue;   // 1/rvalue = rythmic value (1/0.5 double whole 1/1 whole 1/2 half 1/4=quarter note, 1/8=eighth note, ...)
91
   double                      rvalue;   // 1/rvalue = rythmic value (1/0.5 double whole 1/1 whole 1/2 half 1/4=quarter note, 1/8=eighth note, ...)
91
   const cmChar_t*             tvalue;   // text value
92
   const cmChar_t*             tvalue;   // text value
93
+  unsigned                    mf_uid;   // MIDI file uid assigned to this event
92
 
94
 
93
   unsigned                    evenGroupId;   // eveness group id
95
   unsigned                    evenGroupId;   // eveness group id
94
   unsigned                    dynGroupId;    // dynamics group id
96
   unsigned                    dynGroupId;    // dynamics group id
239
     n->mlink = note;
241
     n->mlink = note;
240
   }
242
   }
241
 
243
 
242
-  note->voice = v;
243
-  note->uid   = p->nextUid++;
244
+  note->voice    = v;
245
+  note->uid      = p->nextUid++;
246
+  note->tied_dur = note->duration;
244
 
247
 
245
   return kOkXsRC;
248
   return kOkXsRC;
246
 }
249
 }
605
   note->rvalue   = rvalue;
608
   note->rvalue   = rvalue;
606
   note->tvalue   = tvalue;
609
   note->tvalue   = tvalue;
607
   note->duration = duration;
610
   note->duration = duration;
611
+  note->tied_dur = duration;
608
   note->meas     = meas;
612
   note->meas     = meas;
609
   note->xmlNode  = noteXmlNode;
613
   note->xmlNode  = noteXmlNode;
610
 
614
 
1065
 
1069
 
1066
 bool  _cmXScoreFindTiedNote( cmXScore_t* p, cmXsMeas_t* mp, cmXsNote_t* n0p, bool rptFl )
1070
 bool  _cmXScoreFindTiedNote( cmXScore_t* p, cmXsMeas_t* mp, cmXsNote_t* n0p, bool rptFl )
1067
 {
1071
 {
1072
+  cmXsNote_t* nbp       = n0p;
1068
   cmXsNote_t* nnp       = n0p->slink;  // begin w/ note following np
1073
   cmXsNote_t* nnp       = n0p->slink;  // begin w/ note following np
1069
   unsigned    measNumb  = mp->number;
1074
   unsigned    measNumb  = mp->number;
1070
   cmChar_t    acc       = n0p->alter==-1?'b' : (n0p->alter==1?'#':' ');
1075
   cmChar_t    acc       = n0p->alter==-1?'b' : (n0p->alter==1?'#':' ');
1093
       // if this note is tied to the originating note (np)
1098
       // if this note is tied to the originating note (np)
1094
       if( nnp->voice->id == n0p->voice->id && nnp->step == n0p->step && nnp->octave == n0p->octave )
1099
       if( nnp->voice->id == n0p->voice->id && nnp->step == n0p->step && nnp->octave == n0p->octave )
1095
       {
1100
       {
1096
-        nnp->flags |= kTieProcXsFl;
1097
-        nnp->flags  = cmClrFlag(nnp->flags,kOnsetXsFl);
1098
-        n0p->tied   = nnp;
1101
+        nnp->flags    |= kTieProcXsFl;
1102
+        nnp->flags     = cmClrFlag(nnp->flags,kOnsetXsFl);
1103
+        n0p->tied      = nnp;
1104
+        nbp->tied_dur += nnp->duration;
1105
+        nnp->tied_dur  = 0;
1099
 
1106
 
1100
         if( rptFl )
1107
         if( rptFl )
1101
           printf("---> %i %i %s ",nnp->meas->number,nnp->tick,cmMidiToSciPitch(nnp->pitch,NULL,0));
1108
           printf("---> %i %i %s ",nnp->meas->number,nnp->tick,cmMidiToSciPitch(nnp->pitch,NULL,0));
1118
 
1125
 
1119
 void  _cmXScoreResolveTiesAndLoc( cmXScore_t* p )
1126
 void  _cmXScoreResolveTiesAndLoc( cmXScore_t* p )
1120
 {
1127
 {
1121
-  unsigned n   = 0;
1122
-  unsigned m   = 0;
1123
-  bool     rptFl = false;
1124
-  cmXsPart_t* pp = p->partL;
1128
+  unsigned    n     = 0;        // count of notes which begin a tie
1129
+  unsigned    m     = 0;        // count of tied notes that are correctly terminated.
1130
+  bool        rptFl = false;
1131
+  cmXsPart_t* pp    = p->partL;
1125
 
1132
 
1126
   // for each part
1133
   // for each part
1127
   for(; pp!=NULL; pp=pp->link)
1134
   for(; pp!=NULL; pp=pp->link)
1227
           && cmIsFlag(np->flags,kOnsetXsFl)
1234
           && cmIsFlag(np->flags,kOnsetXsFl)
1228
           && knp->pitch == np->pitch
1235
           && knp->pitch == np->pitch
1229
           && knp->tick >= np->tick 
1236
           && knp->tick >= np->tick 
1230
-          && knp->tick <  (np->tick + np->duration)  )
1237
+          && knp->tick <  (np->tick + np->tied_dur)  )
1231
         {
1238
         {
1232
           return np;
1239
           return np;
1233
         }
1240
         }
1256
         if( cmIsFlag(np->flags,kOnsetXsFl) && (fnp = _cmXScoreFindOverlappingNote(p,np)) != NULL)
1263
         if( cmIsFlag(np->flags,kOnsetXsFl) && (fnp = _cmXScoreFindOverlappingNote(p,np)) != NULL)
1257
         {
1264
         {
1258
           // is np entirely contained inside fnp
1265
           // is np entirely contained inside fnp
1259
-          bool embeddedFl = fnp->tick + fnp->duration > np->tick + np->duration;
1266
+          bool embeddedFl = fnp->tick + fnp->tied_dur > np->tick + np->tied_dur;
1260
           
1267
           
1261
           //printf("bar=%3i %4s voice:%2i %2i : %7i %7i : %7i %7i : %7i : %c \n",np->meas->number,cmMidiToSciPitch(np->pitch,NULL,0),np->voice->id,fnp->voice->id,fnp->tick,fnp->tick+fnp->duration,np->tick,np->tick+np->duration, (fnp->tick+fnp->duration) - np->tick, embeddedFl ? 'E' : 'O');
1268
           //printf("bar=%3i %4s voice:%2i %2i : %7i %7i : %7i %7i : %7i : %c \n",np->meas->number,cmMidiToSciPitch(np->pitch,NULL,0),np->voice->id,fnp->voice->id,fnp->tick,fnp->tick+fnp->duration,np->tick,np->tick+np->duration, (fnp->tick+fnp->duration) - np->tick, embeddedFl ? 'E' : 'O');
1262
 
1269
 
1270
           }
1277
           }
1271
           else
1278
           else
1272
           {
1279
           {
1273
-            int d = (fnp->tick+fnp->duration) - np->tick;
1280
+            int d = (fnp->tick+fnp->tied_dur) - np->tick;
1274
 
1281
 
1275
             // shorten the first note
1282
             // shorten the first note
1276
-            if( d > 0 && d < fnp->duration )
1277
-              fnp->duration -= d;
1283
+            if( d > 0 && d < fnp->tied_dur )
1284
+              fnp->tied_dur -= d;
1278
 
1285
 
1279
             // move the second note just past it
1286
             // move the second note just past it
1280
-            np->tick       = fnp->tick + fnp->duration + 1;
1287
+            np->tick       = fnp->tick + fnp->tied_dur + 1;
1281
           }
1288
           }
1282
         }
1289
         }
1283
     }
1290
     }
1404
       {
1411
       {
1405
         if( cmIsFlag(np->flags,kMetronomeXsFl) )
1412
         if( cmIsFlag(np->flags,kMetronomeXsFl) )
1406
         {
1413
         {
1407
-          double bps =  np->duration / 60.0;
1414
+          double bps =  np->tied_dur / 60.0;
1408
 
1415
 
1409
           // t   b  t
1416
           // t   b  t
1410
           // - = -  -
1417
           // - = -  -
1418
           {
1425
           {
1419
             onset_secs += (np->tick - tick0) / ticks_per_sec;
1426
             onset_secs += (np->tick - tick0) / ticks_per_sec;
1420
             tick0       = np->tick;
1427
             tick0       = np->tick;
1421
-            cmFilePrintf(fH,"n %f %f %i %s %s\n",onset_secs,np->duration/ticks_per_sec,np->uid,cmMidiToSciPitch(np->pitch,NULL,0),cmIsFlag(np->flags,kGraceXsFl)?"G":"N");
1428
+            cmFilePrintf(fH,"n %f %f %i %s %s\n",onset_secs,np->tied_dur/ticks_per_sec,np->uid,cmMidiToSciPitch(np->pitch,NULL,0),cmIsFlag(np->flags,kGraceXsFl)?"G":"N");
1422
           }
1429
           }
1423
         }
1430
         }
1424
       }
1431
       }
1700
               
1707
               
1701
             // set each grace note to have 1/20 of a second duration
1708
             // set each grace note to have 1/20 of a second duration
1702
             if( cmIsFlag(np->flags,kGraceXsFl) )
1709
             if( cmIsFlag(np->flags,kGraceXsFl) )
1703
-              np->duration = floor(ticksPerSec * graceDurSec);
1710
+              np->duration = np->tied_dur = floor(ticksPerSec * graceDurSec);
1704
 
1711
 
1705
             gN += 1;
1712
             gN += 1;
1706
           } 
1713
           } 
2938
     note->voice->id,
2945
     note->voice->id,
2939
     note->locIdx,
2946
     note->locIdx,
2940
     note->tick,
2947
     note->tick,
2941
-    note->duration,
2948
+    note->tied_dur,
2942
     note->rvalue,
2949
     note->rvalue,
2943
     N,B,R,G,D,C,e,d,t,P,s,S,H,T0,T1,O);
2950
     N,B,R,G,D,C,e,d,t,P,s,S,H,T0,T1,O);
2944
 
2951
 
3072
         {
3079
         {
3073
           case kOnsetXsFl:
3080
           case kOnsetXsFl:
3074
             {
3081
             {
3075
-              if( cmMidiFileInsertTrackChMsg(mfH, 1, np->tick,                kNoteOnMdId,  np->pitch, np->vel ) != kOkMfRC
3076
-                ||cmMidiFileInsertTrackChMsg(mfH, 1, np->tick + np->duration, kNoteOffMdId, np->pitch, 0 )       != kOkMfRC )
3082
+              if( np->tied_dur <= 0 )
3083
+                cmErrWarnMsg(&p->err,kOkXsRC,"A zero length note was encountered bar:%i tick:%i %s",np->meas->number,np->tick,cmMidiToSciPitch(np->pitch,NULL,0));
3084
+              
3085
+              if( cmMidiFileInsertTrackChMsg(mfH, 1, np->tick,                kNoteOnMdId,  np->pitch, np->vel, &np->mf_uid ) != kOkMfRC
3086
+                ||cmMidiFileInsertTrackChMsg(mfH, 1, np->tick + np->tied_dur, kNoteOffMdId, np->pitch, 0, &np->mf_uid )       != kOkMfRC )
3077
               {
3087
               {
3078
                 rc = kMidiFailXsRC;
3088
                 rc = kMidiFailXsRC;
3079
               }
3089
               }
3084
           case kDampUpDnXsFl:
3094
           case kDampUpDnXsFl:
3085
           case kSostDnXsFl:
3095
           case kSostDnXsFl:
3086
             {
3096
             {
3097
+              if( np->duration <= 0 )
3098
+                cmErrWarnMsg(&p->err,kOkXsRC,"A zero length pedal event was encountered bar:%i tick:%i",np->meas->number,np->tick);
3099
+              
3087
               cmMidiByte_t d0     = cmIsFlag(np->flags,kSostDnXsFl) ? kSostenutoCtlMdId : kSustainCtlMdId;              
3100
               cmMidiByte_t d0     = cmIsFlag(np->flags,kSostDnXsFl) ? kSostenutoCtlMdId : kSustainCtlMdId;              
3088
-              if( (cmMidiFileInsertTrackChMsg(mfH, 1, np->tick,                kCtlMdId, d0, 127 ) != kOkMfRC )
3089
-                ||(cmMidiFileInsertTrackChMsg(mfH, 1, np->tick + np->duration, kCtlMdId, d0,   0 ) != kOkMfRC ) )
3101
+              if( (cmMidiFileInsertTrackChMsg(mfH, 1, np->tick,                kCtlMdId, d0, 127, &np->mf_uid ) != kOkMfRC )
3102
+                ||(cmMidiFileInsertTrackChMsg(mfH, 1, np->tick + np->duration, kCtlMdId, d0,   0, &np->mf_uid ) != kOkMfRC ) )
3090
               {
3103
               {
3091
                 rc = kMidiFailXsRC;
3104
                 rc = kMidiFailXsRC;
3092
               }
3105
               }
3094
             break;
3107
             break;
3095
 
3108
 
3096
           case kMetronomeXsFl:
3109
           case kMetronomeXsFl:
3097
-            if( cmMidFileInsertTrackTempoMsg(mfH, 0, np->tick, np->duration ) != kOkMfRC )
3110
+            if( cmMidFileInsertTrackTempoMsg(mfH, 0, np->tick, np->duration, &np->mf_uid ) != kOkMfRC )
3098
               rc = kMidiFailXsRC;            
3111
               rc = kMidiFailXsRC;            
3099
             break;
3112
             break;
3100
             
3113
             
3141
   unsigned         voice;     // score voice number
3154
   unsigned         voice;     // score voice number
3142
   unsigned         d0;        // MIDI d0   (barNumb)
3155
   unsigned         d0;        // MIDI d0   (barNumb)
3143
   unsigned         d1;        // MIDI d1
3156
   unsigned         d1;        // MIDI d1
3157
+  unsigned         mf_uid;
3144
   struct cmXsSvgEvt_str* link;
3158
   struct cmXsSvgEvt_str* link;
3145
 } cmXsSvgEvt_t;
3159
 } cmXsSvgEvt_t;
3146
 
3160
 
3162
   unsigned        noteHeight = 10;
3176
   unsigned        noteHeight = 10;
3163
   cmChar_t*       fn0        = cmMemAllocStr( fn );  
3177
   cmChar_t*       fn0        = cmMemAllocStr( fn );  
3164
   const cmChar_t* svgFn      = cmFsMakeFn(dir,fn0 = cmTextAppendSS(fn0,"_midi_svg"),"html",NULL);
3178
   const cmChar_t* svgFn      = cmFsMakeFn(dir,fn0 = cmTextAppendSS(fn0,"_midi_svg"),"html",NULL);
3165
-  const cmChar_t* cssFn      = cmFsMakeFn(NULL,fn,"css",NULL);
3179
+  const cmChar_t* cssFn      = cmFsMakeFn(NULL,"score_midi_svg","css",NULL);
3166
   cmChar_t*       t0         = NULL;  // temporary dynamic string
3180
   cmChar_t*       t0         = NULL;  // temporary dynamic string
3167
 
3181
 
3168
   cmMemFree(fn0);
3182
   cmMemFree(fn0);
3193
           if( cmSvgWriterRect(svgH, e->tick, e->d0 * noteHeight,  e->durTicks,  noteHeight-1, t0 ) != kOkSvgRC )
3207
           if( cmSvgWriterRect(svgH, e->tick, e->d0 * noteHeight,  e->durTicks,  noteHeight-1, t0 ) != kOkSvgRC )
3194
             rc = kSvgFailXsRC;
3208
             rc = kSvgFailXsRC;
3195
           else
3209
           else
3196
-            if( cmSvgWriterText(svgH, e->tick + e->durTicks/2, e->d0 * noteHeight + noteHeight/2, cmMidiToSciPitch( e->d0, NULL, 0), "pitch") != kOkSvgRC )
3210
+          {
3211
+            t0 = cmTsPrintfP(t0,"%s %i",cmMidiToSciPitch( e->d0, NULL, 0),e->mf_uid);
3212
+            
3213
+            if( cmSvgWriterText(svgH, e->tick + e->durTicks/2, e->d0 * noteHeight + noteHeight/2, t0, "pitch") != kOkSvgRC )
3197
               rc = kSvgFailXsRC;
3214
               rc = kSvgFailXsRC;
3215
+          }
3198
         }
3216
         }
3199
         break;
3217
         break;
3200
 
3218
 
3241
 }
3259
 }
3242
 
3260
 
3243
 
3261
 
3244
-void _cmXsPushSvgEvent( cmXScore_t* p, cmXsMidiFile_t* mf, unsigned flags, unsigned tick, unsigned durTick, unsigned voice, unsigned d0, unsigned d1 )
3262
+void _cmXsPushSvgEvent( cmXScore_t* p, cmXsMidiFile_t* mf, unsigned flags, unsigned tick, unsigned durTick, unsigned voice, unsigned d0, unsigned d1, unsigned mf_uid )
3245
 {
3263
 {
3246
   cmXsSvgEvt_t* e = cmLhAllocZ(p->lhH,cmXsSvgEvt_t,1);
3264
   cmXsSvgEvt_t* e = cmLhAllocZ(p->lhH,cmXsSvgEvt_t,1);
3247
   e->flags    = flags;
3265
   e->flags    = flags;
3250
   e->voice    = voice;
3268
   e->voice    = voice;
3251
   e->d0       = d0;       // note=pitch bar=number pedal=ctl# metronome=BPM 
3269
   e->d0       = d0;       // note=pitch bar=number pedal=ctl# metronome=BPM 
3252
   e->d1       = d1;
3270
   e->d1       = d1;
3271
+  e->mf_uid   = mf_uid;
3272
+  
3253
   if( mf->eol != NULL )
3273
   if( mf->eol != NULL )
3254
     mf->eol->link = e;
3274
     mf->eol->link = e;
3255
   else
3275
   else
3286
         if( cmIsFlag(note->flags,kMetronomeXsFl) )
3306
         if( cmIsFlag(note->flags,kMetronomeXsFl) )
3287
         {
3307
         {
3288
           // set BPM as d0
3308
           // set BPM as d0
3289
-          _cmXsPushSvgEvent(p,&mf,note->flags,note->tick,0,0,note->duration,0);
3309
+          _cmXsPushSvgEvent(p,&mf,note->flags,note->tick,0,0,note->duration,0,note->mf_uid);
3290
           continue;
3310
           continue;
3291
           
3311
           
3292
         }
3312
         }
3295
         if( cmIsFlag(note->flags,kOnsetXsFl) )
3315
         if( cmIsFlag(note->flags,kOnsetXsFl) )
3296
         {
3316
         {
3297
           unsigned d0      =  cmSciPitchToMidiPitch( note->step, note->alter, note->octave );
3317
           unsigned d0      =  cmSciPitchToMidiPitch( note->step, note->alter, note->octave );
3298
-          unsigned durTick = note->duration;
3318
+          unsigned durTick = note->tied_dur;
3299
           if( note->tied != NULL )
3319
           if( note->tied != NULL )
3300
           {
3320
           {
3301
             cmXsNote_t* tn = note->tied;
3321
             cmXsNote_t* tn = note->tied;
3302
             for(; tn!=NULL; tn=tn->tied)
3322
             for(; tn!=NULL; tn=tn->tied)
3303
-              durTick += tn->duration;
3323
+              durTick += tn->tied_dur;
3304
           }
3324
           }
3305
-          _cmXsPushSvgEvent(p,&mf,note->flags,note->tick,durTick,note->voice->id,d0,note->vel);
3325
+          _cmXsPushSvgEvent(p,&mf,note->flags,note->tick,durTick,note->voice->id,d0,note->vel,note->mf_uid);
3306
           continue;
3326
           continue;
3307
         }
3327
         }
3308
 
3328
 
3309
         // if this is a bar event
3329
         // if this is a bar event
3310
         if( cmIsFlag(note->flags,kBarXsFl) )
3330
         if( cmIsFlag(note->flags,kBarXsFl) )
3311
         {
3331
         {
3312
-          _cmXsPushSvgEvent(p,&mf,note->flags,note->tick,0,0,note->meas->number,0);
3332
+          _cmXsPushSvgEvent(p,&mf,note->flags,note->tick,0,0,note->meas->number,0, note->mf_uid);
3313
           continue;
3333
           continue;
3314
         }
3334
         }
3315
 
3335
 
3317
         if( cmIsFlag(note->flags,kDampDnXsFl|kDampUpDnXsFl|kSostDnXsFl) )
3337
         if( cmIsFlag(note->flags,kDampDnXsFl|kDampUpDnXsFl|kSostDnXsFl) )
3318
         {
3338
         {
3319
           unsigned d0 = cmIsFlag(note->flags,kSostDnXsFl) ? kSostenutoCtlMdId : kSustainCtlMdId;          
3339
           unsigned d0 = cmIsFlag(note->flags,kSostDnXsFl) ? kSostenutoCtlMdId : kSustainCtlMdId;          
3320
-          _cmXsPushSvgEvent(p,&mf,note->flags,note->tick,note->duration,0,d0,127);
3340
+          _cmXsPushSvgEvent(p,&mf,note->flags,note->tick,note->duration,0,d0,127,note->mf_uid);
3321
           continue;
3341
           continue;
3322
         }
3342
         }
3323
         
3343
         
3353
   // assign durations to pedal down events
3373
   // assign durations to pedal down events
3354
   _cmXScoreProcessPedals(_cmXScoreHandleToPtr(h));
3374
   _cmXScoreProcessPedals(_cmXScoreHandleToPtr(h));
3355
 
3375
 
3356
-  // remove some notes which share a pitch which are overlapped or embedded
3376
+  // remove some notes which share a pitch and are overlapped or embedded within another note.
3357
   _cmXScoreProcessOverlappingNotes(_cmXScoreHandleToPtr(h));
3377
   _cmXScoreProcessOverlappingNotes(_cmXScoreHandleToPtr(h));
3358
 
3378
 
3359
   if( csvOutFn != NULL )
3379
   if( csvOutFn != NULL )
3381
   if( midiOutFn != NULL )
3401
   if( midiOutFn != NULL )
3382
   {
3402
   {
3383
     cmFileSysPathPart_t* pp = cmFsPathParts(midiOutFn);
3403
     cmFileSysPathPart_t* pp = cmFsPathParts(midiOutFn);
3384
-    
3385
-    _cmXScoreGenSvg( ctx, h, pp->dirStr, pp->fnStr );
3386
 
3404
 
3387
     _cmXsWriteMidiFile(ctx, h, pp->dirStr, pp->fnStr );
3405
     _cmXsWriteMidiFile(ctx, h, pp->dirStr, pp->fnStr );
3406
+    
3407
+    _cmXScoreGenSvg( ctx, h, pp->dirStr, pp->fnStr );
3388
 
3408
 
3389
     cmFsFreePathParts(pp);
3409
     cmFsFreePathParts(pp);
3390
     
3410
     
3391
   }
3411
   }
3392
   
3412
   
3393
-  //cmXScoreReport(h,&ctx->rpt,true);
3413
+  cmXScoreReport(h,&ctx->rpt,true);
3394
 
3414
 
3395
  errLabel:
3415
  errLabel:
3396
   return cmXScoreFinalize(&h);
3416
   return cmXScoreFinalize(&h);

+ 2
- 1
app/cmXScore.h Visa fil

19
     kMidiFailXsRC,
19
     kMidiFailXsRC,
20
     kFileFailXsRC,
20
     kFileFailXsRC,
21
     kSvgFailXsRC,
21
     kSvgFailXsRC,
22
-    kOverlapWarnXsRC
22
+    kOverlapWarnXsRC,
23
+    kZeroLengthEventXsRC
23
   };
24
   };
24
 
25
 
25
   typedef cmRC_t     cmXsRC_t;
26
   typedef cmRC_t     cmXsRC_t;

Laddar…
Avbryt
Spara