Browse Source

cmXScore.h : Added cmXScoreMergedEditFiles().

master
kevin 3 years ago
parent
commit
033204dd04
2 changed files with 578 additions and 63 deletions
  1. 574
    62
      src/app/cmXScore.c
  2. 4
    1
      src/app/cmXScore.h

+ 574
- 62
src/app/cmXScore.c View File

110
   unsigned                    locIdx;   // location index (chords share the same location index)
110
   unsigned                    locIdx;   // location index (chords share the same location index)
111
   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, ...)
111
   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, ...)
112
   const cmChar_t*             tvalue;   // text value
112
   const cmChar_t*             tvalue;   // text value
113
+  const cmChar_t*             editStr;  // merged manual edit string
113
 
114
 
114
   unsigned                    evenGroupId;   // eveness group id
115
   unsigned                    evenGroupId;   // eveness group id
115
   unsigned                    dynGroupId;    // dynamics group id
116
   unsigned                    dynGroupId;    // dynamics group id
116
   unsigned                    tempoGroupId;  // tempo group id
117
   unsigned                    tempoGroupId;  // tempo group id
117
   unsigned                    graceGroupId;  // grace note group id
118
   unsigned                    graceGroupId;  // grace note group id
118
 
119
 
120
+
119
   struct cmXsVoice_str*       voice;    // voice this note belongs to
121
   struct cmXsVoice_str*       voice;    // voice this note belongs to
120
   struct cmXsMeas_str*        meas;     // measure this note belongs to
122
   struct cmXsMeas_str*        meas;     // measure this note belongs to
121
 
123
 
230
   return NULL;
232
   return NULL;
231
 }
233
 }
232
 
234
 
235
+cmXsMeas_t* _cmXsFindMeas( cmXsPart_t* part, unsigned measNumb )
236
+{
237
+  cmXsMeas_t* m = part->measL;
238
+  for(; m!=NULL; m=m->link)
239
+    if( m->number == measNumb )
240
+      return m;
241
+
242
+  return NULL;
243
+}
244
+
245
+cmXsNote_t* _cmXsFindNote( cmXsMeas_t* m, unsigned idx, unsigned midi, double rval, unsigned durtn, unsigned* idxRef )
246
+{
247
+  unsigned i;
248
+  cmXsNote_t* np = m->noteL;
249
+  for(i=0; np!=NULL; np=np->slink,++i)
250
+  {
251
+    //printf("idx:%i %i midi:%i %i rval:%f %f durtn:%i %i\n", i,idx, np->pitch,midi, np->rvalue,rval, np->tied_dur,durtn);
252
+    if( i>=idx && np->pitch==midi && np->rvalue==rval && np->tied_dur==durtn )
253
+    {
254
+      *idxRef = i;
255
+      return np;
256
+    }
257
+  }
258
+  
259
+  return NULL;  
260
+}
261
+
233
 cmXsRC_t _cmXScorePushNote( cmXScore_t* p, cmXsMeas_t* meas, unsigned voiceId, cmXsNote_t* note )
262
 cmXsRC_t _cmXScorePushNote( cmXScore_t* p, cmXsMeas_t* meas, unsigned voiceId, cmXsNote_t* note )
234
 {
263
 {
235
   cmXsVoice_t* v;
264
   cmXsVoice_t* v;
612
   cmXsNote_t* note = cmLhAllocZ(p->lhH,cmXsNote_t,1);
641
   cmXsNote_t* note = cmLhAllocZ(p->lhH,cmXsNote_t,1);
613
   unsigned    voiceId;
642
   unsigned    voiceId;
614
 
643
 
644
+  note->pitch   = kInvalidMidiPitch;
615
   note->meas    = meas;
645
   note->meas    = meas;
616
   note->xmlNode = nnp;
646
   note->xmlNode = nnp;
617
 
647
 
686
   cmXsNote_t* note    = cmLhAllocZ(p->lhH,cmXsNote_t,1);
716
   cmXsNote_t* note    = cmLhAllocZ(p->lhH,cmXsNote_t,1);
687
   unsigned    voiceId = 0;    // non-note's are always assigned to voiceId=0;
717
   unsigned    voiceId = 0;    // non-note's are always assigned to voiceId=0;
688
 
718
 
719
+  note->pitch    = kInvalidMidiPitch;
689
   note->tick     = tick;
720
   note->tick     = tick;
690
   note->staff    = staff;
721
   note->staff    = staff;
691
   note->flags    = flags;
722
   note->flags    = flags;
798
 
829
 
799
       flags = kSectionXsFl;
830
       flags = kSectionXsFl;
800
     }
831
     }
832
+    else
833
+    {
834
+      // we only care about 'words' in 'enclosures'
835
+      pushFl = false;
836
+    }
801
   }
837
   }
802
   else
838
   else
803
 
839
 
2028
 //-------------------------------------------------------------------------------------------
2064
 //-------------------------------------------------------------------------------------------
2029
 
2065
 
2030
 
2066
 
2031
-typedef struct
2067
+typedef struct _cmXsReorder_str
2032
 {
2068
 {
2033
   unsigned    idx;      // Fields from the reordering input file which are
2069
   unsigned    idx;      // Fields from the reordering input file which are
2034
   unsigned    voice;    // used to match the reorder record to 
2070
   unsigned    voice;    // used to match the reorder record to 
2046
   unsigned    graceFlags;   // 0=ignore See kXXXGraceXsFl
2082
   unsigned    graceFlags;   // 0=ignore See kXXXGraceXsFl
2047
   unsigned    graceGroupId; // 0=ignore >0=grace note group id
2083
   unsigned    graceGroupId; // 0=ignore >0=grace note group id
2048
   unsigned    pitch;        // 0=ignore >0 new pitch
2084
   unsigned    pitch;        // 0=ignore >0 new pitch
2085
+
2086
+  const char* editStr;
2087
+
2088
+  struct _cmXsReorder_str* link;
2049
 } cmXsReorder_t;
2089
 } cmXsReorder_t;
2050
 
2090
 
2091
+typedef struct _cmXsReorderMeas_str
2092
+{
2093
+  unsigned                     measNumb;
2094
+  cmXsReorder_t*               beg;
2095
+  cmXsReorder_t*               end;
2096
+  struct _cmXsReorderMeas_str* link;
2097
+} cmXsReorderMeas_t;
2098
+
2099
+typedef struct
2100
+{
2101
+  cmXsReorderMeas_t* beg;
2102
+  cmXsReorderMeas_t* end;
2103
+} cmXsReorderFile_t;
2104
+
2051
 typedef struct _cmXScoreDynMark_str
2105
 typedef struct _cmXScoreDynMark_str
2052
 {
2106
 {
2053
   const cmChar_t* mark;   //
2107
   const cmChar_t* mark;   //
2088
   
2142
   
2089
 };
2143
 };
2090
 
2144
 
2145
+cmXsReorderMeas_t* _cmXsReorderFileAllocMeas( cmXScore_t* p, cmXsReorderFile_t* rfp, unsigned measNumb )
2146
+{
2147
+  cmXsReorderMeas_t* m = cmLhAllocZ(p->lhH,cmXsReorderMeas_t,1);
2148
+  m->measNumb          = measNumb;
2149
+            
2150
+  if( rfp->end == NULL )
2151
+  {
2152
+    rfp->beg = m;
2153
+    rfp->end = m;
2154
+  }
2155
+  else
2156
+  {
2157
+    rfp->end->link = m;
2158
+    rfp->end = m;
2159
+  }
2160
+  return m;
2161
+}
2162
+
2163
+cmXsReorderMeas_t* _cmXsReorderFileFindMeas( cmXsReorderFile_t* rfp, unsigned measNumb )
2164
+{
2165
+  cmXsReorderMeas_t* m = rfp->beg;
2166
+  for(; m!=NULL; m=m->link)
2167
+    if( m->measNumb == measNumb )
2168
+      return m;
2169
+
2170
+  return NULL;
2171
+}
2172
+
2173
+
2174
+cmXsReorder_t* _cmXsReorderMeasAllocEvent( cmXScore_t* p, cmXsReorderMeas_t* m )
2175
+{
2176
+  cmXsReorder_t* r = cmLhAllocZ(p->lhH, cmXsReorder_t,1);
2177
+
2178
+  r->midi = kInvalidMidiPitch;
2179
+  
2180
+  if( m->end == NULL )
2181
+  {
2182
+    m->beg = r;
2183
+    m->end = r;
2184
+  }
2185
+  else
2186
+  {
2187
+    m->end->link = r;
2188
+    m->end = r;
2189
+  }
2190
+
2191
+  return r;
2192
+}
2193
+
2194
+// find key in meas (m) by searching after event idx0.
2195
+cmXsReorder_t* _cmXsReorderFindEvent( cmXsReorderMeas_t* m, unsigned idx0, cmXsReorder_t* key )
2196
+{
2197
+  cmXsReorder_t* r;
2198
+  for(r=m->beg; r!=NULL; r=r->link)
2199
+    if( r->idx >= idx0 && r->midi==key->midi && r->rval==key->rval && r->durtn==key->durtn )
2200
+      return r;
2201
+
2202
+  return NULL;
2203
+}
2204
+
2205
+cmXsReorder_t* _cmXsReorderMeasPop( cmXsReorderMeas_t* m )
2206
+{
2207
+  cmXsReorder_t* r0 = NULL;
2208
+  cmXsReorder_t* r  = NULL;
2209
+  for(r=m->beg; r!=NULL; r=r->link)
2210
+  {
2211
+    if( r == m->end )
2212
+      break;
2213
+    r0 = r;
2214
+  }
2215
+
2216
+  if( r0 == NULL )
2217
+  {
2218
+    m->beg = NULL;
2219
+    m->end = NULL;
2220
+  }
2221
+  else
2222
+  {
2223
+    m->end       = r0;
2224
+    m->end->link = NULL;
2225
+  }
2226
+
2227
+  return r;
2228
+}
2091
 
2229
 
2092
 cmXsNote_t*  _cmXsReorderFindNote( cmXScore_t* p, unsigned measNumb, const cmXsReorder_t* r, unsigned iii )
2230
 cmXsNote_t*  _cmXsReorderFindNote( cmXScore_t* p, unsigned measNumb, const cmXsReorder_t* r, unsigned iii )
2093
 {
2231
 {
2138
 {
2276
 {
2139
   // Create a new score event record
2277
   // Create a new score event record
2140
   cmXsNote_t* nn = cmLhAllocZ(p->lhH,cmXsNote_t,1);
2278
   cmXsNote_t* nn = cmLhAllocZ(p->lhH,cmXsNote_t,1);
2141
-  
2279
+
2280
+  nn->pitch = kInvalidMidiPitch;
2142
   nn->uid   = p->nextUid++;
2281
   nn->uid   = p->nextUid++;
2143
   nn->voice = r->note->voice;
2282
   nn->voice = r->note->voice;
2144
   nn->meas  = r->note->meas;
2283
   nn->meas  = r->note->meas;
2165
   
2304
   
2166
 }
2305
 }
2167
 
2306
 
2168
-cmXsRC_t _cmXScoreReorderMeas( cmXScore_t* p, unsigned measNumb, cmXsReorder_t* rV, unsigned rN )
2307
+cmXsRC_t _cmXScoreReorderMeas( cmXScore_t* p, cmXsReorderMeas_t* m )
2308
+{
2309
+  unsigned i;
2310
+  cmXsReorder_t* r;
2311
+  
2312
+  if( m->beg == NULL )
2313
+    return kOkXsRC;
2314
+
2315
+  // set the 'note' field on each cmXsReorder_t record
2316
+  for(r=m->beg,i=0; r!=NULL; r=r->link,++i)
2317
+    if((r->note = _cmXsReorderFindNote(p,m->measNumb,r,i)) == NULL )
2318
+      return kSyntaxErrorXsRC;
2319
+
2320
+  // remove deleted notes
2321
+  for(r=m->beg; r!=NULL; r=r->link)
2322
+    if( cmIsFlag(r->newFlags,kDeleteXsFl) )
2323
+      if( _cmXScoreRemoveNote( r->note ) != kOkXsRC )
2324
+        return cmErrMsg(&p->err,kSyntaxErrorXsRC,"Event marked to skip was not found in measure: %i",m->measNumb);
2325
+      
2326
+  cmXsMeas_t* mp  = m->beg->note->meas;
2327
+  cmXsNote_t* n0p = NULL;
2328
+
2329
+  assert( mp->number == m->measNumb );
2330
+
2331
+  // Reassign the slink of the cmXsNote_t records in this measure
2332
+  // according to their order in rV[].
2333
+  for(r=m->beg; r!=NULL; r=r->link)
2334
+  {
2335
+    
2336
+    if( cmIsFlag(r->newFlags,kDeleteXsFl) )
2337
+      continue;
2338
+    
2339
+    if( n0p == NULL )
2340
+      mp->noteL = r->note;
2341
+    else
2342
+      n0p->slink = r->note;
2343
+
2344
+    // if a new tick was specified 
2345
+    if( r->newTick != 0 )
2346
+      r->note->tick = r->newTick;
2347
+
2348
+    // if a dynamic or velocity mark was included
2349
+    if( r->dynIdx != cmInvalidIdx )
2350
+    {
2351
+      r->note->dynamics = _cmXScoreDynMarkArray[ r->dynIdx ].dyn;
2352
+      r->note->vel      = _cmXScoreDynMarkArray[ r->dynIdx ].vel;
2353
+    }
2354
+
2355
+    // Set the dynamic fork begin/end flags for later _cmXScoreProcessDynamicForks()
2356
+    if( cmIsFlag(r->newFlags,kDynBegForkXsFl) )
2357
+      r->note->flags = cmSetFlag(r->note->flags,kDynBegForkXsFl); 
2358
+
2359
+    if( cmIsFlag(r->newFlags,kDynEndForkXsFl) )
2360
+      r->note->flags = cmSetFlag(r->note->flags,kDynEndForkXsFl); 
2361
+
2362
+    
2363
+    // if the tie end flag was set
2364
+    if( cmIsFlag(r->newFlags,kTieEndXsFl) )
2365
+    {
2366
+      r->note->flags |= kTieEndXsFl;
2367
+      r->note->flags  = cmClrFlag( r->note->flags, kOnsetXsFl );
2368
+      r->newFlags     = cmClrFlag( r->newFlags,    kTieEndXsFl);
2369
+    }
2370
+
2371
+    // if a new note value was specified
2372
+    if( r->pitch != 0 )
2373
+      r->note->pitch = r->pitch;
2374
+    
2375
+    r->note->flags        |= r->graceFlags;
2376
+    r->note->graceGroupId  = r->graceGroupId;
2377
+
2378
+
2379
+    
2380
+    n0p        = r->note;
2381
+    n0p->slink = NULL;
2382
+  }
2383
+
2384
+  
2385
+  // Insert new note records for pedal up/dn events.
2386
+  for(r=m->beg; r!=NULL; r=r->link)    
2387
+  {
2388
+    if( r->newFlags != 0 )
2389
+    {
2390
+      if( cmIsFlag(r->newFlags,kDampDnXsFl ) )
2391
+        _cmXScoreInsertPedalEvent(p,r,kDampDnXsFl);
2392
+
2393
+      if( cmIsFlag(r->newFlags,kSostDnXsFl ) )
2394
+        _cmXScoreInsertPedalEvent(p,r,kSostDnXsFl);
2395
+      
2396
+      if( cmIsFlag(r->newFlags,kDampUpXsFl ) )
2397
+        _cmXScoreInsertPedalEvent(p,r,kDampUpXsFl);
2398
+
2399
+      if( cmIsFlag(r->newFlags,kSostUpXsFl ) )
2400
+        _cmXScoreInsertPedalEvent(p,r,kSostUpXsFl);      
2401
+    }
2402
+  }
2403
+
2404
+  return kOkXsRC;
2405
+
2406
+}
2407
+
2408
+cmXsRC_t _cmXScoreReorderMeas0( cmXScore_t* p, unsigned measNumb, cmXsReorder_t* rV, unsigned rN )
2169
 {
2409
 {
2170
   unsigned i;
2410
   unsigned i;
2171
 
2411
 
2266
 
2506
 
2267
 }
2507
 }
2268
 
2508
 
2269
-cmXsRC_t _cmXScoreReorderParseDyn(cmXScore_t* p, const cmChar_t* b, unsigned lineNumb, unsigned* dynIdxRef, unsigned* flagsRef, int measNumb )
2509
+
2510
+cmXsRC_t _cmXScoreReorderParseDyn(cmXScore_t* p, const cmChar_t* b, unsigned lineNumb, char** s0, unsigned* dynIdxRef, unsigned* flagsRef, int measNumb )
2270
 {
2511
 {
2271
-  cmXsRC_t        rc        = kOkXsRC;
2272
-  const cmChar_t* s         = NULL;
2273
-  bool            begForkFl = false;
2274
-  bool            endForkFl = false;
2512
+  cmXsRC_t  rc        = kOkXsRC;
2513
+  cmChar_t* s         = NULL;
2514
+  bool      begForkFl = false;
2515
+  bool      endForkFl = false;
2275
     
2516
     
2276
-
2277
   *dynIdxRef = cmInvalidIdx;
2517
   *dynIdxRef = cmInvalidIdx;
2278
 
2518
 
2279
   // locate the '!' which indicates the start of a dynamic marking
2519
   // locate the '!' which indicates the start of a dynamic marking
2280
   if( (s = strchr(b,'!')) == NULL )
2520
   if( (s = strchr(b,'!')) == NULL )
2281
     return rc;
2521
     return rc;
2522
+
2523
+  if( *s0==NULL || s<*s0 )    
2524
+    *s0 = s;
2282
   
2525
   
2283
   ++s; // increment past the '!'
2526
   ++s; // increment past the '!'
2284
   
2527
   
2373
 }
2616
 }
2374
 
2617
 
2375
 
2618
 
2376
-cmXsRC_t  _cmXScoreReorderParseFlags(cmXScore_t* p, const cmChar_t* b, unsigned line, unsigned* newFlagsRef )
2619
+cmXsRC_t  _cmXScoreReorderParseFlags(cmXScore_t* p, const cmChar_t* b, unsigned line, char** s0, unsigned* newFlagsRef )
2377
 {
2620
 {
2378
-  cmXsRC_t rc = kOkXsRC;
2379
-  const cmChar_t* s;
2380
-  bool doneFl = false;
2381
-  unsigned i = 0;
2382
-  
2621
+  cmXsRC_t  rc     = kOkXsRC;
2622
+  cmChar_t* s;
2623
+  bool      doneFl = false;
2624
+  unsigned  i      = 0;
2625
+
2383
   *newFlagsRef = 0;
2626
   *newFlagsRef = 0;
2384
   
2627
   
2385
   // tilde indicates a pedal event
2628
   // tilde indicates a pedal event
2386
   if((s = strchr(b,'~')) == NULL )
2629
   if((s = strchr(b,'~')) == NULL )
2387
     return rc;
2630
     return rc;
2388
 
2631
 
2632
+  if( *s0==NULL || s<*s0)
2633
+    *s0 = s;
2634
+  
2389
   do
2635
   do
2390
   {
2636
   {
2391
     ++s;
2637
     ++s;
2434
   return rc;
2680
   return rc;
2435
 }
2681
 }
2436
 
2682
 
2437
-cmXsRC_t  _cmXScoreReorderParseTick(cmXScore_t* p, const cmChar_t* b, unsigned line, unsigned* tickRef )
2683
+cmXsRC_t  _cmXScoreReorderParseTick(cmXScore_t* p, const cmChar_t* b, unsigned line, char** s0, unsigned* tickRef )
2438
 {
2684
 {
2439
   cmXsRC_t rc = kOkXsRC;
2685
   cmXsRC_t rc = kOkXsRC;
2440
-  const cmChar_t* s;
2686
+  cmChar_t* s;
2441
 
2687
 
2442
   if((s = strchr(b,'@')) == NULL )
2688
   if((s = strchr(b,'@')) == NULL )
2443
     return rc;
2689
     return rc;
2444
 
2690
 
2691
+  if( *s0 == NULL || s<*s0 )
2692
+    *s0 = s;
2693
+  
2445
   ++s;
2694
   ++s;
2446
 
2695
 
2447
   if(!isdigit(*s))
2696
   if(!isdigit(*s))
2453
   return rc;
2702
   return rc;
2454
 }
2703
 }
2455
 
2704
 
2456
-cmXsRC_t  _cmXScoreReorderParseGrace(cmXScore_t* p, const cmChar_t* b, unsigned line, cmXsReorder_t* r, unsigned* graceGroupIdRef )
2705
+cmXsRC_t  _cmXScoreReorderParseGrace(cmXScore_t* p, const cmChar_t* b, unsigned line, char** s0, cmXsReorder_t* r, unsigned* graceGroupIdRef )
2457
 {
2706
 {
2458
-  cmXsRC_t        rc = kOkXsRC;
2459
-  const cmChar_t* s;
2707
+  cmXsRC_t  rc = kOkXsRC;
2708
+  cmChar_t* s;
2460
 
2709
 
2461
   if((s = strchr(b,'%')) == NULL )
2710
   if((s = strchr(b,'%')) == NULL )
2462
     return rc;
2711
     return rc;
2463
 
2712
 
2713
+  if( *s0==NULL || s<*s0 )
2714
+    *s0 = s;
2715
+  
2464
   ++s;
2716
   ++s;
2465
 
2717
 
2466
   r->graceGroupId = *graceGroupIdRef;
2718
   r->graceGroupId = *graceGroupIdRef;
2502
   
2754
   
2503
 }
2755
 }
2504
 
2756
 
2505
-cmXsRC_t  _cmXScoreReorderParsePitch(cmXScore_t* p, const cmChar_t* b, unsigned line, unsigned* pitchRef )
2757
+cmXsRC_t  _cmXScoreReorderParsePitch(cmXScore_t* p, const cmChar_t* b, unsigned line, char** s0, unsigned* pitchRef )
2506
 {
2758
 {
2507
-  cmXsRC_t rc = kOkXsRC;
2759
+  cmXsRC_t  rc = kOkXsRC;
2508
   cmChar_t* s;
2760
   cmChar_t* s;
2509
-  cmChar_t buf[4];
2510
-  unsigned i,j;
2761
+  cmChar_t  buf[4];
2762
+  unsigned  i,j;
2511
   memset(buf,0,sizeof(buf));
2763
   memset(buf,0,sizeof(buf));
2512
 
2764
 
2513
   *pitchRef = 0;
2765
   *pitchRef = 0;
2515
   if((s = strchr(b,'$')) == NULL )
2767
   if((s = strchr(b,'$')) == NULL )
2516
     return rc;
2768
     return rc;
2517
 
2769
 
2770
+  if( *s0==NULL || s<*s0)
2771
+    *s0 = s;
2772
+  
2518
   ++s;
2773
   ++s;
2519
 
2774
 
2520
   j=2;
2775
   j=2;
2546
   return rc;  
2801
   return rc;  
2547
 }
2802
 }
2548
 
2803
 
2804
+cmXsRC_t _cmXsReadEditFile( cmXScore_t* p, const cmChar_t* fn, unsigned* graceGroupIdPtr, cmXsReorderFile_t* rfp )
2805
+{
2806
+  typedef enum { kFindMeasStId, kFindEventStId, kReadEventStId } stateId_t;
2807
+
2808
+  cmXsRC_t           rc           = kOkXsRC;
2809
+  cmFileH_t          fH           = cmFileNullHandle;
2810
+  cmChar_t*          b            = NULL;
2811
+  unsigned           bN           = 0;
2812
+  unsigned           ln           = 0;
2813
+  stateId_t          stateId      = kFindMeasStId;
2814
+  cmXsReorderMeas_t* curMeas      = NULL;
2815
+  
2816
+  *graceGroupIdPtr = 1;
2817
+  
2818
+  if( cmFileOpen(&fH,fn,kReadFileFl,p->err.rpt) != kOkFileRC )
2819
+  {
2820
+    rc = cmErrMsg(&p->err,kFileFailXsRC,"The reordering file '%s' could not be opened.",cmStringNullGuard(fn));
2821
+    return rc;
2822
+  }
2823
+
2824
+  for(; cmFileGetLineAuto(fH,&b,&bN) == kOkFileRC; ++ln)
2825
+  {
2826
+    switch( stateId )
2827
+    {
2828
+      case kFindEventStId:      // scanning past labels to an event line
2829
+        {
2830
+          unsigned voice,loc;
2831
+          if( sscanf(b,"%i %i",&voice,&loc) != 2 )
2832
+            continue;
2833
+
2834
+          stateId = kReadEventStId;
2835
+        }
2836
+        // fall through
2837
+
2838
+      case kReadEventStId:
2839
+        {
2840
+          cmXsReorder_t* r = _cmXsReorderMeasAllocEvent(p, curMeas );
2841
+          char           pitchStr[4];
2842
+          char*          s0 = NULL;
2843
+
2844
+          // parse an event line
2845
+          if( sscanf(b,"%i %i %i %i %i %f",&r->idx,&r->voice,&r->locIdx,&r->tick,&r->durtn,&r->rval) == 6 )
2846
+          {
2847
+            assert( strlen(b)>=52);
2848
+            int PC = 39; // text file column where first pitch char occurs
2849
+            
2850
+            if( b[PC] == ' ')
2851
+              r->midi = kInvalidMidiPitch;
2852
+            else
2853
+            {
2854
+              pitchStr[0] = b[PC+0];
2855
+              pitchStr[1] = b[PC+1];
2856
+              pitchStr[2] = b[PC+2];              
2857
+              pitchStr[3] = 0;
2858
+              
2859
+              if( !isdigit(pitchStr[2]) )
2860
+                r->midi = kInvalidMidiPitch;
2861
+              else
2862
+              {
2863
+                if( pitchStr[1] == ' ')
2864
+                {
2865
+                  pitchStr[1] = pitchStr[2];
2866
+                  pitchStr[2] = 0;
2867
+                }
2868
+
2869
+                r->midi = cmSciPitchToMidi(pitchStr);
2870
+
2871
+                //printf("%i %i %s %s\n",curMeas->measNumb,r->midi,pitchStr,fn);
2872
+              }
2873
+            }
2874
+            
2875
+            // parse the flag edits following a '~'
2876
+            if((rc = _cmXScoreReorderParseFlags(p,b,ln+1, &s0, &r->newFlags)) != kOkXsRC )
2877
+              goto errLabel;
2878
+
2879
+            // parse the dynamic marking following a '!'
2880
+            if((rc = _cmXScoreReorderParseDyn(p,b,ln+1, &s0, &r->dynIdx, &r->newFlags, curMeas->measNumb)) != kOkXsRC )
2881
+              goto errLabel;
2882
+                        
2883
+            // parse the @newtick marker
2884
+            if((rc = _cmXScoreReorderParseTick(p, b, ln+1, &s0, &r->newTick)) != kOkXsRC )
2885
+              goto errLabel;
2886
+
2887
+            // parse the %grace note marker
2888
+            if((rc = _cmXScoreReorderParseGrace(p, b, ln+1, &s0, r, graceGroupIdPtr)) != kOkXsRC )
2889
+              goto errLabel;
2890
+
2891
+            // parse the $pitch marker
2892
+            if((rc =  _cmXScoreReorderParsePitch(p, b, ln+1, &s0, &r->pitch )) != kOkXsRC )
2893
+              goto errLabel;
2894
+
2895
+            if( s0 != NULL )
2896
+              r->editStr = cmTextTrimEnd(cmLhAllocStrN( p->lhH, s0, strlen(s0)+1 ));
2897
+            
2898
+            continue;
2899
+          }
2900
+
2901
+          // remove the last reorder record because it was not filled
2902
+          _cmXsReorderMeasPop(curMeas);
2903
+          
2904
+          stateId = kFindMeasStId;
2905
+          // fall through
2906
+        }
2907
+
2908
+      case kFindMeasStId:  // scanning for a bar-line
2909
+        {
2910
+          char     colon;
2911
+          unsigned measNumb = 0;
2912
+
2913
+          if( sscanf(b,"%i %c",&measNumb,&colon) == 2 && colon == ':' )
2914
+          {
2915
+            curMeas = _cmXsReorderFileAllocMeas( p, rfp, measNumb );
2916
+            stateId = kFindEventStId;
2917
+          }
2918
+        }
2919
+        break;
2920
+    }
2921
+
2922
+  }
2923
+ errLabel:
2924
+  cmMemFree(b);
2925
+  cmFileClose(&fH);
2926
+  return rc;  
2927
+}
2928
+
2549
 cmXsRC_t _cmXsApplyEditFile( cmXScore_t* p, const cmChar_t* fn )
2929
 cmXsRC_t _cmXsApplyEditFile( cmXScore_t* p, const cmChar_t* fn )
2550
 {
2930
 {
2931
+  cmXsRC_t           rc           = kOkXsRC;
2932
+  unsigned           graceGroupId = 1;
2933
+  cmXsReorderFile_t  rf;
2934
+  cmXsReorderMeas_t* m;
2935
+  memset(&rf,0,sizeof(rf));
2936
+  
2937
+  if((rc = _cmXsReadEditFile( p, fn, &graceGroupId, &rf )) != kOkXsRC )
2938
+    return rc;
2939
+
2940
+  // reorder each measure
2941
+  for(m=rf.beg; m!=NULL; m=m->link)
2942
+    if((rc =  _cmXScoreReorderMeas(p, m)) != kOkXsRC )
2943
+      goto errLabel;
2944
+  
2945
+  // the ticks may have changed so the 'secs' and 'dsecs' must be updated
2946
+  _cmXScoreSetAbsoluteTime( p );
2947
+
2948
+  // the bar lines should be the first event in the measure
2949
+  _cmXScoreFixBarLines(p);
2950
+
2951
+  // resort to force the links to be correct 
2952
+  _cmXScoreSort(p);
2953
+
2954
+  // process the grace notes.
2955
+  _cmXScoreProcessGraceNotes( p, graceGroupId );
2956
+
2957
+  // inserting grace notes may have left the score unsorted
2958
+  _cmXScoreSort(p);
2959
+  
2960
+  // process the dynamic forks
2961
+  _cmXScoreProcessDynamicForks(p);
2962
+
2963
+  //_cmXScoreReport(p, NULL, true );
2964
+
2965
+ errLabel:
2966
+  return rc;
2967
+}
2968
+
2969
+
2970
+
2971
+cmXsRC_t _cmXsMergeEditFiles( cmXScore_t* p, unsigned measNumb0, const cmChar_t* keyEditFn, unsigned keyMeasNumb, const cmChar_t* outFn )
2972
+{
2973
+  cmXsRC_t           rc            = kOkXsRC;
2974
+  unsigned           graceGroup1Id = 1;
2975
+  unsigned           measNumb1     = keyMeasNumb;
2976
+  cmXsReorderFile_t  rf1;
2977
+  memset(&rf1,0,sizeof(rf1));
2978
+
2979
+  if((rc = _cmXsReadEditFile( p, keyEditFn, &graceGroup1Id, &rf1 )) != kOkXsRC )
2980
+    return rc;
2981
+
2982
+  while(1)
2983
+  {
2984
+    cmXsMeas_t*        m0   = _cmXsFindMeas( p->partL, measNumb0 );
2985
+    cmXsReorderMeas_t* m1   = _cmXsReorderFileFindMeas( &rf1, measNumb1 );
2986
+    cmXsReorder_t*     key  = NULL;
2987
+    unsigned           idx0 = 0;
2988
+    
2989
+    if( m1==NULL )
2990
+    {
2991
+      rc = cmErrMsg(&p->err,kEventNotFoundXsRC,"The measure %i was not found in the key edit file '%s'.",keyMeasNumb,cmStringNullGuard(keyEditFn));
2992
+      break;
2993
+    }
2994
+    
2995
+    key  = m1->beg;
2996
+    
2997
+    for(; key!=NULL; key=key->link)
2998
+    {
2999
+      unsigned    idx1 = cmInvalidIdx;
3000
+      cmXsNote_t* np   = _cmXsFindNote( m0, idx0, key->midi, key->rval, key->durtn, &idx1);
3001
+      
3002
+      if( np==NULL )
3003
+      {
3004
+        if( key->editStr != NULL )
3005
+        {
3006
+          const char* sciPitch = key->midi!=kInvalidMidiPitch ? cmMidiToSciPitch(key->midi,NULL,0) : "<non-pitch>";
3007
+          cmErrWarnMsg(&p->err,kEventNotFoundXsRC,"Sync error: meas: ref:%i key:%i index:%i %s (midi:%i) edit:%s did not match to the reference edit file.", measNumb0,m1->measNumb,key->idx, sciPitch, key->midi, key->editStr);
3008
+        }
3009
+      }
3010
+      else
3011
+      {
3012
+        np->editStr = key->editStr;
3013
+        
3014
+        if( key->editStr != NULL )
3015
+          idx0        = idx1;
3016
+      }
3017
+    }
3018
+    
3019
+    ++measNumb0;
3020
+    ++measNumb1;
3021
+
3022
+  }
3023
+  
3024
+  return rc;
3025
+}
3026
+
3027
+
3028
+
3029
+cmXsRC_t _cmXsApplyEditFile0( cmXScore_t* p, const cmChar_t* fn )
3030
+{
2551
   typedef enum { kFindMeasStId, kFindEventStId, kReadEventStId } stateId_t;
3031
   typedef enum { kFindMeasStId, kFindEventStId, kReadEventStId } stateId_t;
2552
 
3032
 
2553
   cmXsRC_t      rc       = kOkXsRC;
3033
   cmXsRC_t      rc       = kOkXsRC;
2586
         {
3066
         {
2587
           cmXsReorder_t r;
3067
           cmXsReorder_t r;
2588
           char     pitchStr[4];
3068
           char     pitchStr[4];
3069
+          char* s0 = NULL;
2589
 
3070
 
2590
           memset(&r,0,sizeof(r));
3071
           memset(&r,0,sizeof(r));
2591
           
3072
           
2596
             int PC = 39; // text file column where first pitch char occurs
3077
             int PC = 39; // text file column where first pitch char occurs
2597
             
3078
             
2598
             if( b[PC] == ' ')
3079
             if( b[PC] == ' ')
2599
-              r.midi = 0;
3080
+              r.midi = kInvalidMidiPitch;
2600
             else
3081
             else
2601
             {
3082
             {
2602
               pitchStr[0] = b[PC+0];
3083
               pitchStr[0] = b[PC+0];
2605
               pitchStr[3] = 0;
3086
               pitchStr[3] = 0;
2606
               
3087
               
2607
               if( !isdigit(pitchStr[2]) )
3088
               if( !isdigit(pitchStr[2]) )
2608
-                r.midi = 0;
3089
+                r.midi = kInvalidMidiPitch;
2609
               else
3090
               else
2610
               {
3091
               {
2611
                 if( pitchStr[1] == ' ')
3092
                 if( pitchStr[1] == ' ')
2621
 
3102
 
2622
             
3103
             
2623
             // parse the flag edits following a '~'
3104
             // parse the flag edits following a '~'
2624
-            if((rc = _cmXScoreReorderParseFlags(p,b,ln+1, &r.newFlags)) != kOkXsRC )
3105
+            if((rc = _cmXScoreReorderParseFlags(p,b,ln+1, &s0, &r.newFlags)) != kOkXsRC )
2625
               goto errLabel;
3106
               goto errLabel;
2626
 
3107
 
2627
             // parse the dynamic marking following a '!'
3108
             // parse the dynamic marking following a '!'
2628
-            if((rc = _cmXScoreReorderParseDyn(p,b,ln+1,&r.dynIdx, &r.newFlags, measNumb)) != kOkXsRC )
3109
+            if((rc = _cmXScoreReorderParseDyn(p,b,ln+1,&s0, &r.dynIdx, &r.newFlags, measNumb)) != kOkXsRC )
2629
               goto errLabel;
3110
               goto errLabel;
2630
                         
3111
                         
2631
             // parse the @newtick marker
3112
             // parse the @newtick marker
2632
-            if((rc = _cmXScoreReorderParseTick(p, b, ln+1, &r.newTick)) != kOkXsRC )
3113
+            if((rc = _cmXScoreReorderParseTick(p, b, ln+1, &s0, &r.newTick)) != kOkXsRC )
2633
               goto errLabel;
3114
               goto errLabel;
2634
 
3115
 
2635
             // parse the %grace note marker
3116
             // parse the %grace note marker
2636
-            if((rc = _cmXScoreReorderParseGrace(p, b, ln+1, &r, &graceGroupId)) != kOkXsRC )
3117
+            if((rc = _cmXScoreReorderParseGrace(p, b, ln+1, &s0, &r, &graceGroupId)) != kOkXsRC )
2637
               goto errLabel;
3118
               goto errLabel;
2638
 
3119
 
2639
             // parse the $pitch marker
3120
             // parse the $pitch marker
2640
-            if((rc =  _cmXScoreReorderParsePitch(p, b, ln+1, &r.pitch )) != kOkXsRC )
3121
+            if((rc =  _cmXScoreReorderParsePitch(p, b, ln+1, &s0, &r.pitch )) != kOkXsRC )
2641
               goto errLabel;
3122
               goto errLabel;
2642
-
2643
-            // process grace notes - these need to be processed separate from
2644
-            // the _cmXScoreReorderMeas() because grace notes may cross measure boundaries.
2645
-            /*
2646
-            if( r.graceType != 0 )
2647
-            {
2648
-              r.graceGroupId = graceGroupId;
2649
-
2650
-              // if this is an end of a grace note group
2651
-              if( r.graceType != 'g' && r.graceType != 'b' )
2652
-              {
2653
-                graceGroupId += 1;
2654
-              }
2655
-              
2656
-            }
2657
-            */
2658
             
3123
             
2659
             // store the record
3124
             // store the record
2660
             assert( ri < rN );
3125
             assert( ri < rN );
2666
 
3131
 
2667
           // the end of the measure was encountered -
3132
           // the end of the measure was encountered -
2668
           // reorder the measure based on the cmXsReorder_t in rV[ri]
3133
           // reorder the measure based on the cmXsReorder_t in rV[ri]
2669
-          if((rc =  _cmXScoreReorderMeas(p, measNumb, rV, ri )) != kOkXsRC )
3134
+          if((rc =  _cmXScoreReorderMeas0(p, measNumb, rV, ri )) != kOkXsRC )
2670
             goto errLabel;
3135
             goto errLabel;
2671
 
3136
 
2672
           ri = 0;
3137
           ri = 0;
2692
 
3157
 
2693
   // If reorder records remain to be processed
3158
   // If reorder records remain to be processed
2694
   if( ri > 0 )
3159
   if( ri > 0 )
2695
-    if((rc =  _cmXScoreReorderMeas(p, measNumb, rV, ri )) != kOkXsRC )
3160
+    if((rc =  _cmXScoreReorderMeas0(p, measNumb, rV, ri )) != kOkXsRC )
2696
       goto errLabel;
3161
       goto errLabel;
2697
     
3162
     
2698
   
3163
   
2724
 }
3189
 }
2725
 
3190
 
2726
 
3191
 
2727
-
2728
-cmXsRC_t cmXScoreInitialize( cmCtx_t* ctx, cmXsH_t* hp, const cmChar_t* xmlFn, const cmChar_t* editFn, bool damperRptFl )
3192
+cmXsRC_t cmXScoreAlloc( cmCtx_t* ctx, cmXsH_t* hp )
2729
 {
3193
 {
2730
   cmXsRC_t rc = kOkXsRC;
3194
   cmXsRC_t rc = kOkXsRC;
2731
 
3195
 
2740
   if( cmLHeapIsValid( p->lhH = cmLHeapCreate(8196,ctx)) == false )
3204
   if( cmLHeapIsValid( p->lhH = cmLHeapCreate(8196,ctx)) == false )
2741
     return cmErrMsg(&p->err,kLHeapFailXsRC,"Lheap create failed.");
3205
     return cmErrMsg(&p->err,kLHeapFailXsRC,"Lheap create failed.");
2742
 
3206
 
3207
+  hp->h = p;
3208
+  
3209
+  return rc;
3210
+}
3211
+
3212
+cmXsRC_t cmXScoreInitialize( cmCtx_t* ctx, cmXsH_t* hp, const cmChar_t* xmlFn, const cmChar_t* editFn, bool damperRptFl )
3213
+{
3214
+  cmXsRC_t rc;
3215
+  cmXScore_t* p = NULL;
3216
+  
3217
+  if((rc = cmXScoreAlloc(ctx,hp)) != kOkXsRC )
3218
+    goto errLabel;
3219
+
3220
+  p  = _cmXScoreHandleToPtr(*hp);
3221
+    
2743
   // open the music xml file
3222
   // open the music xml file
2744
   if( cmXmlAlloc(ctx, &p->xmlH, xmlFn) != kOkXmlRC )
3223
   if( cmXmlAlloc(ctx, &p->xmlH, xmlFn) != kOkXmlRC )
2745
   {
3224
   {
2798
   
3277
   
2799
  errLabel:
3278
  errLabel:
2800
   if( rc != kOkXsRC )
3279
   if( rc != kOkXsRC )
2801
-    _cmXScoreFinalize(p);
2802
-  else
2803
-    hp->h = p;
3280
+    cmXScoreFinalize(hp);
3281
+  
2804
 
3282
 
2805
   return rc;
3283
   return rc;
2806
 }
3284
 }
3321
 
3799
 
3322
   if( note->dynamics != 0)
3800
   if( note->dynamics != 0)
3323
     cmRptPrintf(rpt," dyn=%i %i",note->dynamics,note->vel);
3801
     cmRptPrintf(rpt," dyn=%i %i",note->dynamics,note->vel);
3802
+
3803
+  if( note->editStr != NULL )
3804
+    cmRptPrintf(rpt, " %s", note->editStr );
3324
   
3805
   
3325
   /*
3806
   /*
3326
   if( cmIsFlag(note->flags,kBegGraceXsFl) )
3807
   if( cmIsFlag(note->flags,kBegGraceXsFl) )
3371
 
3852
 
3372
           t1 = note->slink==NULL ? note->tick : note->slink->tick;
3853
           t1 = note->slink==NULL ? note->tick : note->slink->tick;
3373
 
3854
 
3855
+          // check that this note is in tick order
3374
           if( !(t0 <= note->tick && note->tick <= t1) )
3856
           if( !(t0 <= note->tick && note->tick <= t1) )
3375
           {
3857
           {
3376
             cmRptPrintf(rpt," +");
3858
             cmRptPrintf(rpt," +");
3427
   }
3909
   }
3428
 }
3910
 }
3429
 
3911
 
3430
-cmXsRC_t cmXScoreGenEditFile( cmCtx_t* ctx, const cmChar_t* xmlFn, const cmChar_t* outFn, bool damperRptFl )
3912
+cmXsRC_t _cmXScoreEditFileRpt( cmCtx_t* ctx, cmXScore_t* p, const cmChar_t* outFn, bool damperRptFl )
3431
 {
3913
 {
3432
-  cmXsH_t   xsH = cmXsNullHandle;
3433
-  cmFileH_t fH  = cmFileNullHandle;
3434
   cmXsRC_t  rc  = kOkXsRC;
3914
   cmXsRC_t  rc  = kOkXsRC;
3435
   cmErr_t   err;
3915
   cmErr_t   err;
3436
   cmRpt_t   rpt;
3916
   cmRpt_t   rpt;
3917
+  cmFileH_t fH  = cmFileNullHandle;
3437
 
3918
 
3438
   cmErrSetup(&err,&ctx->rpt,"cmXScoreGenEditFile");
3919
   cmErrSetup(&err,&ctx->rpt,"cmXScoreGenEditFile");
3439
   cmRptSetup(&rpt,_cmXScoreGenEditFileWrite,_cmXScoreGenEditFileWrite,&fH);
3920
   cmRptSetup(&rpt,_cmXScoreGenEditFileWrite,_cmXScoreGenEditFileWrite,&fH);
3440
-
3441
-  if((rc = cmXScoreInitialize(ctx,&xsH,xmlFn,NULL,damperRptFl)) != kOkXsRC )
3442
-    return rc;
3443
-
3921
+  
3444
   if( cmFileOpen(&fH,outFn,kWriteFileFl,&ctx->rpt) != kOkFileRC )
3922
   if( cmFileOpen(&fH,outFn,kWriteFileFl,&ctx->rpt) != kOkFileRC )
3445
   {
3923
   {
3446
     cmErrMsg(&err,kFileFailXsRC,"Unable to open the output file '%s'.",cmStringNullGuard(outFn));
3924
     cmErrMsg(&err,kFileFailXsRC,"Unable to open the output file '%s'.",cmStringNullGuard(outFn));
3447
     goto errLabel;
3925
     goto errLabel;
3448
   }
3926
   }
3449
   
3927
   
3450
-  cmXScoreReport(xsH,&rpt,true);
3928
+  _cmXScoreReport(p,&rpt,true);
3451
   
3929
   
3452
  errLabel:
3930
  errLabel:
3453
   
3931
   
3454
   if( cmFileClose(&fH) != kOkFileRC )
3932
   if( cmFileClose(&fH) != kOkFileRC )
3455
     rc = cmErrMsg(&err,kFileFailXsRC,"File close failed on '%s'.",cmStringNullGuard(outFn));
3933
     rc = cmErrMsg(&err,kFileFailXsRC,"File close failed on '%s'.",cmStringNullGuard(outFn));
3934
+
3935
+  return rc;
3936
+}
3937
+
3938
+cmXsRC_t cmXScoreGenEditFile( cmCtx_t* ctx, const cmChar_t* xmlFn, const cmChar_t* outFn, bool damperRptFl )
3939
+{
3940
+  cmXsH_t   xsH = cmXsNullHandle;
3941
+  cmXsRC_t  rc  = kOkXsRC;
3942
+
3943
+  if((rc = cmXScoreInitialize(ctx,&xsH,xmlFn,NULL,damperRptFl)) != kOkXsRC )
3944
+    return rc;
3945
+
3946
+  rc = _cmXScoreEditFileRpt( ctx, _cmXScoreHandleToPtr(xsH), outFn, damperRptFl );
3456
   
3947
   
3457
   cmXScoreFinalize(&xsH);
3948
   cmXScoreFinalize(&xsH);
3458
 
3949
 
4148
   return cmXScoreFinalize(&h);
4639
   return cmXScoreFinalize(&h);
4149
 
4640
 
4150
 }
4641
 }
4642
+
4643
+
4644
+cmXsRC_t cmXScoreMergeEditFiles( cmCtx_t* ctx, const cmChar_t* xmlFn, const cmChar_t* refEditFn,  unsigned refBegMeasNumb, const cmChar_t* editFn, unsigned keyMeasNumb, const cmChar_t* outFn )
4645
+{
4646
+  cmXsH_t  h           = cmXsNullHandle;
4647
+  cmXsRC_t rc;
4648
+  bool     damperRptFl = false;
4649
+  
4650
+  if((rc = cmXScoreInitialize(ctx, &h, xmlFn, refEditFn, damperRptFl )) == kOkXsRC )
4651
+  {
4652
+    cmXScore_t* p  = _cmXScoreHandleToPtr(h);
4653
+    
4654
+    if((rc = _cmXsMergeEditFiles(p, refBegMeasNumb, editFn, keyMeasNumb, outFn )) == kOkXsRC )
4655
+      rc = _cmXScoreEditFileRpt( ctx, p, outFn, damperRptFl );
4656
+    
4657
+
4658
+    cmXScoreFinalize(&h);
4659
+  }
4660
+
4661
+  return rc;
4662
+}

+ 4
- 1
src/app/cmXScore.h View File

20
     kFileFailXsRC,
20
     kFileFailXsRC,
21
     kSvgFailXsRC,
21
     kSvgFailXsRC,
22
     kOverlapWarnXsRC,
22
     kOverlapWarnXsRC,
23
-    kZeroLengthEventXsRC
23
+    kZeroLengthEventXsRC,
24
+    kEventNotFoundXsRC
24
   };
25
   };
25
 
26
 
26
   typedef cmRC_t     cmXsRC_t;
27
   typedef cmRC_t     cmXsRC_t;
73
   // Set begMeasNumb to the first measure the to be written to the output csv, MIDI and SVG files.
74
   // Set begMeasNumb to the first measure the to be written to the output csv, MIDI and SVG files.
74
   // Set begBPM to 0 to use the tempo from the score otherwise set it to the tempo at begMeasNumb.
75
   // Set begBPM to 0 to use the tempo from the score otherwise set it to the tempo at begMeasNumb.
75
   cmXsRC_t cmXScoreTest( cmCtx_t* ctx, const cmChar_t* xmlFn, const cmChar_t* reorderFn, const cmChar_t* csvOutFn, const cmChar_t* midiOutFn, const cmChar_t* svgOutFn, bool reportFl, int begMeasNumb, int begBPM, bool svgStandAloneFl, bool svgPanZoomFl, bool damperRptFl );
76
   cmXsRC_t cmXScoreTest( cmCtx_t* ctx, const cmChar_t* xmlFn, const cmChar_t* reorderFn, const cmChar_t* csvOutFn, const cmChar_t* midiOutFn, const cmChar_t* svgOutFn, bool reportFl, int begMeasNumb, int begBPM, bool svgStandAloneFl, bool svgPanZoomFl, bool damperRptFl );
77
+
78
+  cmXsRC_t cmXScoreMergeEditFiles( cmCtx_t* ctx, const cmChar_t* xmlFn, const cmChar_t* refEditFn,  unsigned refBegMeasNumb, const cmChar_t* editFn, unsigned keyMeasNumb, const cmChar_t* outFn );
76
   
79
   
77
 #ifdef __cplusplus
80
 #ifdef __cplusplus
78
 }
81
 }

Loading…
Cancel
Save