1 /*
2   MusicXML Library
3   Copyright (C) Grame 2006-2013
4 
5   This Source Code Form is subject to the terms of the Mozilla Public
6   License, v. 2.0. If a copy of the MPL was not distributed with this
7   file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9   Grame Research Laboratory, 11, cours de Verdun Gensoul 69002 Lyon - France
10   research@grame.fr
11 */
12 
13 #include <iostream>
14 #include <sstream>
15 
16 #include <climits>      // INT_MIN, INT_MAX
17 
18 #include "utilities.h"
19 
20 #include "msrBasicTypes.h"
21 #include "lpsrBasicTypes.h"
22 
23 #include "setTraceOahIfDesired.h"
24 #ifdef TRACE_OAH
25   #include "traceOah.h"
26 #endif
27 
28 #include "generalOah.h"
29 #include "lpsrOah.h"
30 
31 #include "messagesHandling.h"
32 
33 
34 using namespace std;
35 
36 namespace MusicXML2
37 {
38 
39 //_______________________________________________________________________________
lpsrDurationBinaryLogarithm(int duration)40 int lpsrDurationBinaryLogarithm (int duration)
41 {
42   int result = INT_MIN;
43 
44 /*
45 with LilyPond's limitation to 128th of a whole note,
46 valid denominators binary logarithms, i.e. their exponent, are:
47 */
48 
49   switch (duration) {
50     case 1:
51       result = 0;
52       break;
53     case 2:
54       result = 1;
55       break;
56     case 4:
57       result = 2;
58       break;
59     case 8:
60       result = 3;
61       break;
62     case 16:
63       result = 4;
64       break;
65     case 32:
66       result = 5;
67       break;
68     case 64:
69       result = 6;
70       break;
71     case 128:
72       result = 7;
73       break;
74     case 256: // JMI
75       result = 8;
76       break;
77 
78     default:
79       ;
80   } // switch
81 
82   return result;
83 }
84 
85 //_______________________________________________________________________________
lpsrNumberOfDots(int n)86 int lpsrNumberOfDots (int n)
87 {
88   int  result = INT_MIN;
89 
90    switch (n) {
91     case 1:
92       result = 0;
93       break;
94     case 3:
95       result = 1;
96       break;
97     case 7:
98       result = 2;
99       break;
100     case 15:
101       result = 3;
102       break;
103     case 31:
104       result = 4;
105       break;
106     case 63:
107       result = 5;
108       break;
109     case 127:
110       result = 6;
111       break;
112 
113     default:
114       ;
115     } // switch
116 
117   return result;
118 }
119 
120 //_______________________________________________________________________________
wholeNotesAsLilypondString(int inputLineNumber,rational wholeNotes,int & dotsNumber)121 string wholeNotesAsLilypondString (
122   int      inputLineNumber,
123   rational wholeNotes,
124   int&     dotsNumber)
125 {
126   // this algorithm is inspired by musicxml2ly
127 
128 #ifdef TRACE_OAH
129   if (gTraceOah->fTraceWholeNotes) {
130     gLogOstream <<
131       "--> wholeNotesAsLilypondString() 1 -------------------------------------" <<
132       ", wholeNotes: " << wholeNotes <<
133       ", line " << inputLineNumber <<
134       endl;
135   }
136 #endif
137 
138   int
139     numerator    = wholeNotes.getNumerator (),
140     denominator  = wholeNotes.getDenominator ();
141 
142 #ifdef TRACE_OAH
143   if (gTraceOah->fTraceWholeNotes) {
144     gLogOstream <<
145       "--> numerator:   " << numerator <<
146       endl <<
147       "--> denominator: " << denominator <<
148       endl <<
149       endl;
150   }
151 #endif
152 
153 /* JMI
154   if (false && numerator <= 0) { // JMI
155     stringstream s;
156 
157     s <<
158      "%{ZERO_LENGTH: " <<
159      wholeNotes << // JMI
160      ", line " <<
161      inputLineNumber <<
162      " %}";
163 
164     return s.str ();
165   }
166 */
167 
168   // sanity check
169   if (numerator <= 0) {
170     stringstream s;
171 
172     s <<
173       "numerator is not positive in wholeNotesAsLilypondString()" <<
174       ", wholeNotes = " << wholeNotes;
175 
176  //   msrMusicXMLError ( JMI
177     msrMusicXMLWarning (
178       gOahOah->fInputSourceName,
179       inputLineNumber,
180   //    __FILE__, __LINE__,
181       s.str ());
182 abort (); // JMI
183     return "???";
184   }
185 
186   wholeNotes.rationalise ();
187 
188 #ifdef TRACE_OAH
189   if (gTraceOah->fTraceWholeNotesDetails) {
190     gLogOstream <<
191       "--> wholeNotes rationalised: " << wholeNotes <<
192       endl;
193   }
194 #endif
195 
196   bool
197     rationalHasBeenSimplified =
198       wholeNotes.getNumerator () != numerator; // denominators could be used too
199 
200   if (rationalHasBeenSimplified) {
201     numerator    = wholeNotes.getNumerator (),
202     denominator  = wholeNotes.getDenominator ();
203   }
204 
205   bool
206     integralNumberOfWholeNotes = denominator == 1;
207 
208 #ifdef TRACE_OAH
209   if (gTraceOah->fTraceWholeNotesDetails) {
210     gLogOstream <<
211       "--> rationalHasBeenSimplified: " <<
212       booleanAsString (
213         rationalHasBeenSimplified) <<
214       endl <<
215       "--> integralNumberOfWholeNotes: " <<
216       booleanAsString (
217         integralNumberOfWholeNotes) <<
218       endl <<
219       endl;
220   }
221 #endif
222 
223   /*
224     augmentation dots add half the preceding increment to the duration:
225     they constitue a series of frations or the form '(2^n-1) / 2^n',
226     starting with 3/2, 7/4, 15/8,
227     that tends towards 2 while always remaining less than two.
228 
229     with MusicXML's limitation to 1024th of a whole note,
230     with LilyPond's limitation to 128th of a whole note,
231     valid numerators are:
232   */
233 
234   int  numeratorDots = lpsrNumberOfDots (numerator);
235 
236 #ifdef TRACE_OAH
237   if (gTraceOah->fTraceWholeNotesDetails) {
238     gLogOstream <<
239       "--> numeratorDots " << " : " << numeratorDots <<
240       endl <<
241       endl;
242   }
243 #endif
244 
245 /*
246     default:
247       if (! integralNumberOfWholeNotes) {
248   //      multiplyingFactorIsToBeUsed = true;
249       }
250       else {
251         // there can be integral numbers of whole notes up to 15,
252         // corresponding to a \maxima...
253           stringstream s;
254 
255           s <<
256             "numerator " << numerator <<
257             " is not one of 1, 3, 7, 15, 31, 63 or 127" <<
258        //     " is not one of 1, 3, 7, 15, 31, 63, 127, 255, 511 or 1023" <<
259             ", whole notes duration " <<
260             numerator << "/" << denominator;
261 
262           if (rationalHasBeenSimplified) {
263             s <<
264               " (" << numerator << "/" << denominator << ")" <<
265             endl;
266           }
267 
268           s <<
269             " it will be represented using a multiplying factor";
270 
271           msrMusicXMLWarning (
272             gOahOah->fInputSourceName,
273             inputLineNumber,
274             s.str ());
275 
276   //      multiplyingFactorIsToBeUsed = true;
277       }
278   } // switch
279     */
280 
281   /*
282     valid denominators are powers of 2
283 
284     the rational representing a dotted duration has to be brought
285     to a value less than two, as explained above
286 
287     this is done by changing it denominator in the resulting string:
288 
289      whole notes        string
290          3/1              \breve.
291          3/2              1.
292          3/4              2.
293          3/8              4.
294 
295          7/1              \longa..
296          7/2              \breve..
297          7/4              1..
298          7/8              2..
299 
300     since such resulting denominators can be fractions of wholes notes
301     as well as multiple thereof,
302     we'll be better of using binary logarithms for the computations
303   */
304 
305   int denominatorDurationLog =
306     lpsrDurationBinaryLogarithm (denominator);
307 
308   if (denominatorDurationLog == INT_MIN) {
309      string result;
310 
311     {
312       stringstream s;
313 
314       s <<
315         1 <<
316         "*" <<
317         numerator <<
318         "/" <<
319         denominator;
320 
321       result = s.str ();
322     }
323 
324 #ifdef TRACE_OAH
325     if (gTraceOah->fTraceWholeNotesDetails) {
326       stringstream s;
327 
328       s <<
329         "denominator " << denominator <<
330         " is no power of two between 1 and 128" <<
331    //     " is no power of 2 between 1 and 1024" <<
332         ", whole notes duration " <<
333         numerator << "/" << denominator;
334 
335       if (rationalHasBeenSimplified) {
336         s <<
337           " (" << numerator << "/" << denominator << ")" <<
338         endl;
339       }
340 
341       s <<
342         " cannot be represented as a dotted power of 2" <<
343         ", " <<
344         result <<
345         " will be used";
346 
347    //   msrMusicXMLError ( JMI
348       msrMusicXMLWarning (
349         gOahOah->fInputSourceName,
350         inputLineNumber,
351     //    __FILE__, __LINE__,
352         s.str ());
353     }
354 #endif
355 
356     return result;
357   }
358 
359 #ifdef TRACE_OAH
360   if (gTraceOah->fTraceWholeNotesDetails) {
361     gLogOstream <<
362       "--> denominatorDurationLog" << " : " <<
363       denominatorDurationLog <<
364       endl <<
365       endl;
366   }
367 #endif
368 
369   // bring the resulting fraction to be less that two if needed
370   if (integralNumberOfWholeNotes) {
371     // adapt the duration to avoid even numerators if can be,
372     // since dotted durations cannot be recognized otherwise
373     // 6/1 thus becomes 3\breve, hence \longa.
374 #ifdef TRACE_OAH
375     if (gTraceOah->fTraceWholeNotesDetails) {
376       gLogOstream <<
377         "--> integralNumberOfWholeNotes,"
378         " bringing the faction to be less that 2" <<
379         endl;
380     }
381 #endif
382 
383     while (numerator % 2 == 0) {
384       numerator /= 2;
385       denominatorDurationLog -= 1;
386 
387 #ifdef TRACE_OAH
388       if (gTraceOah->fTraceWholeNotesDetails) {
389         gLogOstream <<
390           "--> numerator" << " : " <<
391           numerator <<
392           endl <<
393           "--> denominatorDurationLog " << " : " <<
394           denominatorDurationLog <<
395           endl <<
396           endl;
397       }
398 #endif
399     } // while
400 
401     // update the number of dots
402     numeratorDots = lpsrNumberOfDots (numerator);
403   }
404 
405 #ifdef TRACE_OAH
406   if (gTraceOah->fTraceWholeNotesDetails) {
407     gLogOstream <<
408       "--> numerator" << " : " <<
409       numerator <<
410       endl <<
411       "--> denominatorDurationLog" << " : " <<
412       denominatorDurationLog <<
413       endl <<
414       "--> numeratorDots " << " : " <<
415       numeratorDots <<
416       endl <<
417       endl;
418   }
419 #endif
420 
421   // take care of the dots
422   int multiplyingFactor = 1;
423 
424   if (numeratorDots >= 0 && denominatorDurationLog >= numeratorDots) {
425     // take the dots into account
426     denominatorDurationLog -= numeratorDots;
427 
428 #ifdef TRACE_OAH
429     if (gTraceOah->fTraceWholeNotesDetails) {
430       gLogOstream <<
431         "--> denominatorDurationLog" << " : " <<
432         denominatorDurationLog <<
433         endl <<
434         "--> multiplyingFactor " << " : " <<
435         multiplyingFactor <<
436         endl <<
437         endl;
438     }
439 #endif
440   }
441   else {
442     // set the multiplying factor
443 #ifdef TRACE_OAH
444     if (gTraceOah->fTraceWholeNotesDetails) {
445       gLogOstream <<
446         "--> setting the multiplying factor" <<
447         endl;
448     }
449 #endif
450 
451     // 5/8 becomes 8*5
452 
453     multiplyingFactor = numerator;
454     numerator = 1;
455 
456     /* JMI
457     multiplyingFactor = numerator;
458 
459 #ifdef TRACE_OAH
460     if (gTraceOah->fTraceWholeNotesDetails) {
461       gLogOstream <<
462         "--> denominatorDurationLog" << " : " <<
463         denominatorDurationLog <<
464         endl <<
465         "--> multiplyingFactor " << " : " <<
466         multiplyingFactor <<
467         endl <<
468         endl;
469     }
470 #endif
471 
472     while (multiplyingFactor >= 2) {
473       // double duration
474       denominatorDurationLog--;
475 
476       // adapt multiplying factor
477       multiplyingFactor /= 2;
478 
479 #ifdef TRACE_OAH
480       if (gTraceOah->fTraceWholeNotesDetails) {
481         gLogOstream <<
482           "--> denominatorDurationLog" << " : " <<
483           denominatorDurationLog <<
484           endl <<
485           "--> multiplyingFactor " << " : " <<
486           multiplyingFactor <<
487           endl <<
488           endl;
489       }
490 #endif
491     } // while
492     */
493   }
494 
495 #ifdef TRACE_OAH
496   if (gTraceOah->fTraceWholeNotesDetails) {
497     gLogOstream <<
498       "--> numerator " << " : " <<
499       numerator <<
500       endl <<
501       "--> numeratorDots " << " : " <<
502       numeratorDots <<
503       endl <<
504       "--> denominatorDurationLog" << " : " <<
505       denominatorDurationLog <<
506       endl <<
507       "--> multiplyingFactor " << " : " <<
508       multiplyingFactor <<
509       endl <<
510       endl;
511   }
512 #endif
513 
514   // generate the code for the duration
515   stringstream s;
516 
517   switch (denominatorDurationLog) {
518     case -3:
519       s << "\\maxima";
520       break;
521     case -2:
522       s << "\\longa";
523       break;
524     case -1:
525       s << "\\breve";
526       break;
527 
528     default:
529       s << (1 << denominatorDurationLog);
530   } // switch
531 
532   // append the dots if any
533   if (numeratorDots > 0) {
534     for (int i = 0; i < numeratorDots; i++) {
535       s << ".";
536     } // for
537   }
538 
539   if (multiplyingFactor != 1) {
540     // append the multiplying factor
541     s <<
542       "*" << multiplyingFactor;
543 
544     /* JMI
545     if (integralNumberOfWholeNotes) {
546       s <<
547         "*" << multiplyingFactor;
548     }
549     else {
550       s <<
551         "*" << multiplyingFactor << "/" << 1; // ??? denominator;
552     }
553     */
554   }
555 
556   string result = s.str ();
557 
558 #ifdef TRACE_OAH
559   if (gTraceOah->fTraceWholeNotes) {
560     gLogOstream <<
561       "--> wholeNotesAsLilypondString() 2 -------------------------------------" <<
562      ", result: \"" << result << "\"" <<
563       ", numeratorDots" << " : " << numeratorDots <<
564       endl;
565   }
566 #endif
567 
568   // return the result
569   dotsNumber = numeratorDots;
570 
571   return result;
572 }
573 
wholeNotesAsLilypondString(int inputLineNumber,rational wholeNotes)574 string wholeNotesAsLilypondString (
575   int      inputLineNumber,
576   rational wholeNotes)
577 {
578   int dotsNumber; // not used
579 
580   return
581     wholeNotesAsLilypondString (
582       inputLineNumber,
583       wholeNotes,
584       dotsNumber);
585 }
586 
587 //_______________________________________________________________________________
dottedDurationAsLilypondString(int inputLineNumber,msrDottedDuration dottedDuration)588 string dottedDurationAsLilypondString (
589   int               inputLineNumber,
590   msrDottedDuration dottedDuration)
591 {
592   return
593     wholeNotesAsLilypondString (
594       inputLineNumber,
595       dottedDuration.dottedDurationAsWholeNotes (
596         inputLineNumber));
597 }
598 
dottedDurationAsLilypondStringWithoutBackSlash(int inputLineNumber,msrDottedDuration dottedDuration)599 string dottedDurationAsLilypondStringWithoutBackSlash (
600   int               inputLineNumber,
601   msrDottedDuration dottedDuration)
602 {
603   string result =
604     wholeNotesAsLilypondString (
605       inputLineNumber,
606       dottedDuration.dottedDurationAsWholeNotes (
607         inputLineNumber));
608 
609   if (result [0] == '\\') {
610     result = result.substr (1);
611   }
612 
613   return result;
614 }
615 
616 //_______________________________________________________________________________
restMeasuresWholeNoteAsLilypondString(int inputLineNumber,rational wholeNotes)617 string restMeasuresWholeNoteAsLilypondString (
618   int      inputLineNumber,
619   rational wholeNotes)
620 {
621   stringstream s;
622 
623   rational
624     denominatorAsFraction =
625       rational (
626         1,
627         wholeNotes.getDenominator ());
628 
629   int numberOfWholeNotes =
630     wholeNotes.getNumerator ();
631 
632   s <<
633     wholeNotesAsLilypondString (
634       inputLineNumber,
635       denominatorAsFraction);
636 
637   if (numberOfWholeNotes != 1) {
638     s <<
639       "*" << numberOfWholeNotes;
640   }
641 
642   return s.str ();
643 }
644 
645 //_______________________________________________________________________________
writeTextsListAsLilypondString(const list<string> & textsList,ostream & os)646 void writeTextsListAsLilypondString (
647   const list<string>& textsList,
648   ostream&            os)
649 {
650   string contents;
651 
652   if (textsList.size ()) {
653     list<string>::const_iterator
654       iBegin = textsList.begin (),
655       iEnd   = textsList.end (),
656       i      = iBegin;
657 
658     for ( ; ; ) {
659       contents += (*i);
660       if (++i == iEnd) break;
661   // JMI    os << ", ";
662     } // for
663   }
664 
665   size_t found = contents.find("\"");
666   if (found != std::string::npos) {
667     os << doubleQuoteString (contents);
668   }
669   else {
670     os << doubleQuoteStringIfNonAlpha (contents); // JMI
671   }
672 }
673 
674 // score output kinds
675 //______________________________________________________________________________
676 
677 map<string, lpsrScoreOutputKind>
678   gLpsrScoreOutputKindsMap;
679 
lpsrScoreOutputKindAsString(lpsrScoreOutputKind scoreOutputKind)680 string lpsrScoreOutputKindAsString (
681   lpsrScoreOutputKind scoreOutputKind)
682 {
683   string result;
684 
685   // no CamelCase here, these strings are used in the command line options
686 
687   switch (scoreOutputKind) {
688     case kScoreOnly: // default value
689       result = "score-only";
690       break;
691     case kScoreAndParts:
692       result = "score-and-parts";
693       break;
694     case kPartsAndScore:
695       result = "parts-and-score";
696       break;
697     case kPartsOnly:
698       result = "parts-only";
699       break;
700     case kScoreAndPartsOneFile:
701       result = "score-and-parts-one-file";
702       break;
703     case kPartsAndScoreOneFile:
704       result = "parts-and-score-one-file";
705       break;
706     case kPartsOnlyOneFile:
707       result = "parts-only-one-file";
708       break;
709   } // switch
710 
711   return result;
712 }
713 
initializeLpsrScoreOutputKindsMap()714 void initializeLpsrScoreOutputKindsMap ()
715 {
716   // register the LilyPond score output kinds
717   // --------------------------------------
718 
719   // no CamelCase here, these strings are used in the command line options
720 
721   gLpsrScoreOutputKindsMap ["score-only"] = kScoreOnly;
722   gLpsrScoreOutputKindsMap ["score-and-parts"] = kScoreAndParts;
723   gLpsrScoreOutputKindsMap ["parts-and-score"] = kPartsAndScore;
724   gLpsrScoreOutputKindsMap ["parts-only"] = kPartsOnly;
725   gLpsrScoreOutputKindsMap ["score-and-parts-one-file"] = kScoreAndPartsOneFile;
726   gLpsrScoreOutputKindsMap ["parts-and-score-one-file"] = kPartsAndScoreOneFile;
727   gLpsrScoreOutputKindsMap ["parts-only-one-file"] = kPartsOnlyOneFile;
728 }
729 
existingLpsrScoreOutputKinds(int namesListMaxLength)730 string existingLpsrScoreOutputKinds (int namesListMaxLength)
731 {
732   stringstream s;
733 
734   if (gLpsrScoreOutputKindsMap.size ()) {
735     map<string, lpsrScoreOutputKind>::const_iterator
736       iBegin = gLpsrScoreOutputKindsMap.begin (),
737       iEnd   = gLpsrScoreOutputKindsMap.end (),
738       i      = iBegin;
739 
740     int cumulatedLength = 0;
741 
742     for ( ; ; ) {
743       string theString = (*i).first;
744 
745       s << theString;
746 
747       cumulatedLength += theString.size ();
748       if (cumulatedLength >= K_NAMES_LIST_MAX_LENGTH) break;
749 
750       if (++i == iEnd) break;
751 
752       if (next (i) == iEnd) {
753         s << " and ";
754       }
755       else {
756         s << ", ";
757       }
758     } // for
759 
760   /* JMI BUG IN MAP ITERATORS...???
761 {
762     list<string> lpsrScoreOutputKindsList;
763     for (
764       map<string, lpsrScoreOutputKind>::const_iterator i = gLpsrScoreOutputKindsMap.begin ();
765       i != gLpsrScoreOutputKindsMap.end ();
766       ++i
767     ) {
768       lpsrScoreOutputKindsList.push_back ((*i).first);
769     } // for
770 
771     list<string>::const_iterator
772       iBegin = lpsrScoreOutputKindsList.begin (),
773       iEnd   = lpsrScoreOutputKindsList.end (),
774       i      = iBegin;
775 
776     int cumulatedLength = 0;
777 
778     for ( ; ; ) {
779       string theString = (*i);
780 
781       s << theString;
782 
783       cumulatedLength += theString.size ();
784       if (cumulatedLength >= K_NAMES_LIST_MAX_LENGTH) break;
785 
786       if (++i == iEnd) break;
787       if (next (i) == iEnd) {
788         s << " and ";
789       }
790       else {
791         s << ", ";
792       }
793     } // for
794 }
795 */
796   }
797 
798   return s.str ();
799 }
800 
801 // octave entry kinds
802 //______________________________________________________________________________
803 
804 map<string, lpsrOctaveEntryKind>
805   gLpsrOctaveEntryKindsMap;
806 
lpsrOctaveEntryKindAsString(lpsrOctaveEntryKind octaveEntryKind)807 string lpsrOctaveEntryKindAsString (
808   lpsrOctaveEntryKind octaveEntryKind)
809 {
810   string result;
811 
812   // no CamelCase here, these strings are used in the command line options
813 
814   switch (octaveEntryKind) {
815     case kOctaveEntryRelative: // default value
816       result = "relative";
817       break;
818     case kOctaveEntryAbsolute:
819       result = "absolute";
820       break;
821     case kOctaveEntryFixed:
822       result = "fixed";
823       break;
824   } // switch
825 
826   return result;
827 }
828 
initializeLpsrOctaveEntryKindsMap()829 void initializeLpsrOctaveEntryKindsMap ()
830 {
831   // register the LilyPond score output kinds
832   // --------------------------------------
833 
834   // no CamelCase here, these strings are used in the command line options
835 
836   gLpsrOctaveEntryKindsMap ["relative"] = kOctaveEntryRelative;
837   gLpsrOctaveEntryKindsMap ["absolute"] = kOctaveEntryAbsolute;
838   gLpsrOctaveEntryKindsMap ["fixed"] = kOctaveEntryFixed;
839 }
840 
existingLpsrOctaveEntryKinds(int namesListMaxLength)841 string existingLpsrOctaveEntryKinds (int namesListMaxLength)
842 {
843   stringstream s;
844 
845   if (gLpsrOctaveEntryKindsMap.size ()) {
846     map<string, lpsrOctaveEntryKind>::const_iterator
847       iBegin = gLpsrOctaveEntryKindsMap.begin (),
848       iEnd   = gLpsrOctaveEntryKindsMap.end (),
849       i      = iBegin;
850 
851     int cumulatedLength = 0;
852 
853     for ( ; ; ) {
854       string theString = (*i).first;
855 
856       s << theString;
857 
858       cumulatedLength += theString.size ();
859       if (cumulatedLength >= K_NAMES_LIST_MAX_LENGTH) break;
860 
861       if (++i == iEnd) break;
862       if (next (i) == iEnd) {
863         s << " and ";
864       }
865       else {
866         s << ", ";
867       }
868     } // for
869   }
870 
871   return s.str ();
872 }
873 
874 // accidental styles
875 //______________________________________________________________________________
876 
877 map<string, lpsrAccidentalStyleKind>
878   gLpsrAccidentalStyleKindsMap;
879 
lpsrAccidentalStyleKindAsString(lpsrAccidentalStyleKind accidentalStyleKind)880 string lpsrAccidentalStyleKindAsString (
881   lpsrAccidentalStyleKind accidentalStyleKind)
882 {
883   string result;
884 
885   switch (accidentalStyleKind) {
886     case kDefault: // default value
887       result = "default";
888       break;
889     case kVoice:
890       result = "voice";
891       break;
892     case kModern:
893       result = "modern";
894       break;
895     case kModernCautionary:
896       result = "modernCautionary";
897       break;
898     case kModernVoice:
899       result = "modernVoice";
900       break;
901     case kModernVoiceCautionary:
902       result = "modernVoiceCautionary";
903       break;
904     case kPiano:
905       result = "piano";
906       break;
907     case kPianoCautionary:
908       result = "pianoCautionary";
909       break;
910     case kNeoModern:
911       result = "neoModern";
912       break;
913     case kNeoModernCautionary:
914       result = "neoModernCautionary";
915       break;
916     case kNeoModernVoice:
917       result = "neoModernVoice";
918       break;
919     case kNeoModernVoiceCautionary:
920       result = "neoModernVoiceCautionary";
921       break;
922     case kDodecaphonic:
923       result = "dodecaphonic";
924       break;
925     case kDodecaphonicNoRepeat:
926       result = "dodecaphonicNoRepeat";
927       break;
928     case kDodecaphonicFirst:
929       result = "dodecaphonicFirst";
930       break;
931     case kTeaching:
932       result = "teaching";
933       break;
934     case kNoReset:
935       result = "noReset";
936       break;
937     case kForget:
938       result = "Forget";
939       break;
940   } // switch
941 
942   return result;
943 }
944 
lpsrAccidentalStyleKindAsLilypondString(lpsrAccidentalStyleKind accidentalStyleKind)945 string lpsrAccidentalStyleKindAsLilypondString (
946   lpsrAccidentalStyleKind accidentalStyleKind)
947 {
948   string result;
949 
950   switch (accidentalStyleKind) {
951     case kDefault: // default value
952       result = "default";
953       break;
954     case kVoice:
955       result = "voice";
956       break;
957     case kModern:
958       result = "modern";
959       break;
960     case kModernCautionary:
961       result = "modern-cautionary";
962       break;
963     case kModernVoice:
964       result = "modern-voice";
965       break;
966     case kModernVoiceCautionary:
967       result = "modern-voice-cautionary";
968       break;
969     case kPiano:
970       result = "piano";
971       break;
972     case kPianoCautionary:
973       result = "piano-cautionary";
974       break;
975     case kNeoModern:
976       result = "neo-modern";
977       break;
978     case kNeoModernCautionary:
979       result = "neo-modern-cautionary";
980       break;
981     case kNeoModernVoice:
982       result = "neo-modern-voice";
983       break;
984     case kNeoModernVoiceCautionary:
985       result = "neo-modern--voice-cautionary";
986       break;
987     case kDodecaphonic:
988       result = "dodecaphonic";
989       break;
990     case kDodecaphonicNoRepeat:
991       result = "dodecaphonic-no-repeat";
992       break;
993     case kDodecaphonicFirst:
994       result = "dodecaphonic-first";
995       break;
996     case kTeaching:
997       result = "teaching";
998       break;
999     case kNoReset:
1000       result = "no-reset";
1001       break;
1002     case kForget:
1003       result = "forget";
1004       break;
1005   } // switch
1006 
1007   return result;
1008 }
1009 
initializeLpsrAccidentalStyleKindsMap()1010 void initializeLpsrAccidentalStyleKindsMap ()
1011 {
1012   // register the LilyPond accidental styles
1013   // --------------------------------------
1014 
1015   gLpsrAccidentalStyleKindsMap ["default"] = kDefault;
1016   gLpsrAccidentalStyleKindsMap ["voice"] = kVoice;
1017   gLpsrAccidentalStyleKindsMap ["modern"] = kModern;
1018   gLpsrAccidentalStyleKindsMap ["modern-cautionary"] = kModernCautionary;
1019   gLpsrAccidentalStyleKindsMap ["modern-voice"] = kModernVoice;
1020   gLpsrAccidentalStyleKindsMap ["modern-voice-cautionary"] = kModernVoiceCautionary;
1021   gLpsrAccidentalStyleKindsMap ["piano"] = kPiano;
1022   gLpsrAccidentalStyleKindsMap ["piano-cautionary"] = kPianoCautionary;
1023   gLpsrAccidentalStyleKindsMap ["neo-modern"] = kNeoModern;
1024   gLpsrAccidentalStyleKindsMap ["neo-modern-cautionary"] = kNeoModernCautionary;
1025   gLpsrAccidentalStyleKindsMap ["neo-modern-voice"] = kNeoModernVoice;
1026   gLpsrAccidentalStyleKindsMap ["neo-modern-voice-cautionary"] = kNeoModernVoiceCautionary;
1027   gLpsrAccidentalStyleKindsMap ["dodecaphonic"] = kDodecaphonic;
1028   gLpsrAccidentalStyleKindsMap ["dodecaphonic-no-repeat"] = kDodecaphonicNoRepeat;
1029   gLpsrAccidentalStyleKindsMap ["dodecaphonic-first"] = kDodecaphonicFirst;
1030   gLpsrAccidentalStyleKindsMap ["teaching"] = kTeaching;
1031   gLpsrAccidentalStyleKindsMap ["no-reset"] = kNoReset;
1032   gLpsrAccidentalStyleKindsMap ["forget"] = kForget;
1033 }
1034 
existingLpsrAccidentalStyleKinds(int namesListMaxLength)1035 string existingLpsrAccidentalStyleKinds (int namesListMaxLength)
1036 {
1037   stringstream s;
1038 
1039   if (gLpsrAccidentalStyleKindsMap.size ()) {
1040     map<string, lpsrAccidentalStyleKind>::const_iterator
1041       iBegin = gLpsrAccidentalStyleKindsMap.begin (),
1042       iEnd   = gLpsrAccidentalStyleKindsMap.end (),
1043       i      = iBegin;
1044 
1045     int cumulatedLength = 0;
1046 
1047     for ( ; ; ) {
1048       string theString = (*i).first;
1049 
1050       s << theString;
1051 
1052       cumulatedLength += theString.size ();
1053       if (cumulatedLength >= K_NAMES_LIST_MAX_LENGTH) break;
1054 
1055       if (++i == iEnd) break;
1056 
1057       if (next (i) == iEnd) {
1058         s << " and ";
1059       }
1060       else {
1061         s << ", ";
1062       }
1063     } // for
1064   }
1065 
1066   return s.str ();
1067 }
1068 
1069 // chords languages
1070 //______________________________________________________________________________
1071 
1072 map<string, lpsrChordsLanguageKind>
1073   gLpsrChordsLanguageKindsMap;
1074 
initializeLpsrChordsLanguageKindsMap()1075 void initializeLpsrChordsLanguageKindsMap ()
1076 {
1077   gLpsrChordsLanguageKindsMap ["ignatzek"]   = k_IgnatzekChords; // default
1078   gLpsrChordsLanguageKindsMap ["german"]     = k_GermanChords;
1079   gLpsrChordsLanguageKindsMap ["semiGerman"] = k_SemiGermanChords;
1080   gLpsrChordsLanguageKindsMap ["italian"]    = k_ItalianChords;
1081   gLpsrChordsLanguageKindsMap ["french"]     = k_FrenchChords;
1082 }
1083 
lpsrChordsLanguageKindAsString(lpsrChordsLanguageKind languageKind)1084 string lpsrChordsLanguageKindAsString (
1085   lpsrChordsLanguageKind languageKind)
1086 {
1087   string result;
1088 
1089   switch (languageKind) {
1090     case k_IgnatzekChords: // default value
1091       result = "ignatzek";
1092       break;
1093     case k_GermanChords:
1094       result = "german";
1095       break;
1096     case k_SemiGermanChords:
1097       result = "semiGerman";
1098       break;
1099     case k_ItalianChords:
1100       result = "italian";
1101       break;
1102     case k_FrenchChords:
1103       result = "french";
1104       break;
1105   } // switch
1106 
1107   return result;
1108 }
1109 
existingLpsrChordsLanguageKinds(int namesListMaxLength)1110 string existingLpsrChordsLanguageKinds (int namesListMaxLength)
1111 {
1112   stringstream s;
1113 
1114   if (gLpsrChordsLanguageKindsMap.size ()) {
1115     map<string, lpsrChordsLanguageKind>::const_iterator
1116       iBegin = gLpsrChordsLanguageKindsMap.begin (),
1117       iEnd   = gLpsrChordsLanguageKindsMap.end (),
1118       i      = iBegin;
1119 
1120     int cumulatedLength = 0;
1121 
1122     for ( ; ; ) {
1123       string theString = (*i).first;
1124 
1125       s << theString;
1126 
1127       cumulatedLength += theString.size ();
1128       if (cumulatedLength >= K_NAMES_LIST_MAX_LENGTH) break;
1129 
1130       if (next (i) == iEnd) {
1131         s << " and ";
1132       }
1133       else {
1134         s << ", ";
1135       }
1136     } // for
1137   }
1138 
1139   return s.str ();
1140 }
1141 
1142 //______________________________________________________________________________
msrSemiTonesPitchAndOctaveAsLilypondString(msrQuarterTonesPitchesLanguageKind languageKind,S_msrSemiTonesPitchAndOctave semiTonesPitchAndOctave)1143 string msrSemiTonesPitchAndOctaveAsLilypondString (
1144   msrQuarterTonesPitchesLanguageKind languageKind,
1145   S_msrSemiTonesPitchAndOctave       semiTonesPitchAndOctave)
1146 {
1147   stringstream s;
1148 
1149   msrQuarterTonesPitchKind
1150     quarterTonesPitchKind =
1151       quarterTonesPitchKindFromSemiTonesPitchKind (
1152         semiTonesPitchAndOctave->getSemiTonesPitchKind ());
1153 
1154   map<msrQuarterTonesPitchKind, string>
1155     *pitchNamesMapPTR =
1156       &gNederlandsPitchNamesMap; // default LilyPond value
1157 
1158   // is quarterTonesPitchName in the part renaming map?
1159   switch (languageKind) {
1160     case kNederlands:
1161       pitchNamesMapPTR = &gNederlandsPitchNamesMap;
1162       break;
1163     case kCatalan:
1164       pitchNamesMapPTR = &gCatalanPitchNamesMap;
1165       break;
1166     case kDeutsch:
1167       pitchNamesMapPTR = &gDeutschPitchNamesMap;
1168       break;
1169     case kEnglish:
1170       pitchNamesMapPTR = &gEnglishPitchNamesMap;
1171       break;
1172     case kEspanol:
1173       pitchNamesMapPTR = &gEspanolPitchNamesMap;
1174       break;
1175     case kFrancais:
1176       pitchNamesMapPTR = &gFrancaisPitchNamesMap;
1177       break;
1178     case kItaliano:
1179       pitchNamesMapPTR = &gItalianoPitchNamesMap;
1180       break;
1181     case kNorsk:
1182       pitchNamesMapPTR = &gNorskPitchNamesMap;
1183       break;
1184     case kPortugues:
1185       pitchNamesMapPTR = &gPortuguesPitchNamesMap;
1186       break;
1187     case kSuomi:
1188       pitchNamesMapPTR = &gSuomiPitchNamesMap;
1189       break;
1190     case kSvenska:
1191       pitchNamesMapPTR = &gSvenskaPitchNamesMap;
1192       break;
1193     case kVlaams:
1194       pitchNamesMapPTR = &gVlaamsPitchNamesMap;
1195       break;
1196   } // switch
1197 
1198   s << (*pitchNamesMapPTR) [quarterTonesPitchKind];
1199 
1200   switch (semiTonesPitchAndOctave->getOctave ()) {
1201     case -7:
1202       s << ",,,,,,,,,,";
1203       break;
1204     case -6:
1205       s << ",,,,,,,,,,";
1206       break;
1207     case -5:
1208       s << ",,,,,,,,,";
1209       break;
1210     case -4:
1211       s << ",,,,,,,";
1212       break;
1213     case -3:
1214       s << ",,,,,,";
1215       break;
1216     case -2:
1217       s << ",,,,,";
1218       break;
1219     case -1:
1220       s << ",,,,";
1221       break;
1222     case 0:
1223       s << ",,,";
1224       break;
1225     case 1:
1226       s << ",,";
1227       break;
1228     case 2:
1229       s << ",";
1230       break;
1231     case 3:
1232       s << "";
1233       break;
1234     case 4:
1235       s << "'";
1236       break;
1237     case 5:
1238       s << "''";
1239       break;
1240     case 6:
1241       s << "'''";
1242       break;
1243     case 7:
1244       s << "''''";
1245       break;
1246     case 8:
1247       s << "'''''";
1248       break;
1249     case 9:
1250       s << "''''''";
1251       break;
1252     case 10:
1253       s << "'''''''";
1254       break;
1255     case 11:
1256       s << "''''''''";
1257       break;
1258     case 12:
1259       s << "'''''''''";
1260       break;
1261     case 13:
1262       s << "''''''''''";
1263       break;
1264     case 14:
1265       s << "'''''''''''";
1266       break;
1267     case 15:
1268       s << "''''''''''''";
1269       break;
1270     case 16:
1271       s << "'''''''''''''";
1272       break;
1273     default:
1274       s << "!!!";
1275   } // switch
1276 
1277 #ifdef TRACE_OAH
1278   if (gTraceOah->fTraceNotesOctaveEntry) {
1279     s <<
1280       " %{ " <<
1281       semiTonesPitchAndOctave->asString () <<
1282       " %}";
1283   }
1284 #endif
1285 
1286   return s.str ();
1287 }
1288 
1289 /* JMI
1290 string msrSemiTonesPitchAndOctaveAsLilypondString (
1291   msrQuarterTonesPitchesLanguageKind languageKind,
1292   S_msrSemiTonesPitchAndOctave       semiTonesPitchAndOctave)
1293 {
1294   msrQuarterTonesPitchKind
1295     quarterTonesPitchKind =
1296       quarterTonesPitchKindFromSemiTonesPitchKind (
1297         semiTonesPitchKind);
1298 
1299   return
1300     msrQuarterTonesPitchAndOctaveAsLilypondString (
1301       languageKind,
1302       quarterTonesPitchKind);
1303 
1304   return "??????";
1305 }
1306 */
1307 
1308 // lyrics durations
1309 //______________________________________________________________________________
1310 
1311 map<string, lpsrLyricsDurationsKind>
1312   gLpsrLyricsDurationsKindsMap;
1313 
lpsrLyricsDurationsKindAsString(lpsrLyricsDurationsKind lyricsDurationsKind)1314 string lpsrLyricsDurationsKindAsString (
1315   lpsrLyricsDurationsKind lyricsDurationsKind)
1316 {
1317   string result;
1318 
1319   // no CamelCase here, these strings are used in the command line options
1320 
1321   switch (lyricsDurationsKind) {
1322     case kLyricsDurationsImplicit:
1323       result = "lyricsDurationsImplicit";
1324       break;
1325     case kLyricsDurationsExplicit:
1326       result = "lyricsDurationsExplicit";
1327       break;
1328   } // switch
1329 
1330   return result;
1331 }
1332 
initializeLpsrLyricsDurationsKindsMap()1333 void initializeLpsrLyricsDurationsKindsMap ()
1334 {
1335   // register the LilyPond score output kinds
1336   // --------------------------------------
1337 
1338   // no CamelCase here, these strings are used in the command line options
1339 
1340   gLpsrLyricsDurationsKindsMap ["implicit"] = kLyricsDurationsImplicit;
1341   gLpsrLyricsDurationsKindsMap ["explicit"] = kLyricsDurationsExplicit;
1342 }
1343 
existingLpsrLyricsDurationsKinds(int namesListMaxLength)1344 string existingLpsrLyricsDurationsKinds (int namesListMaxLength)
1345 {
1346   stringstream s;
1347 
1348   if (gLpsrLyricsDurationsKindsMap.size ()) {
1349     map<string, lpsrLyricsDurationsKind>::const_iterator
1350       iBegin = gLpsrLyricsDurationsKindsMap.begin (),
1351       iEnd   = gLpsrLyricsDurationsKindsMap.end (),
1352       i      = iBegin;
1353 
1354     int cumulatedLength = 0;
1355 
1356     for ( ; ; ) {
1357       string theString = (*i).first;
1358 
1359       s << theString;
1360 
1361       cumulatedLength += theString.size ();
1362       if (cumulatedLength >= K_NAMES_LIST_MAX_LENGTH) break;
1363 
1364       if (++i == iEnd) break;
1365       if (next (i) == iEnd) {
1366         s << " and ";
1367       }
1368       else {
1369         s << ", ";
1370       }
1371     } // for
1372   }
1373 
1374   return s.str ();
1375 }
1376 
1377 //______________________________________________________________________________
initializeLPSRBasicTypes()1378 void initializeLPSRBasicTypes ()
1379 {
1380 #ifdef TRACE_OAH
1381   if (gTraceOah->fTraceOah && ! gGeneralOah->fQuiet) {
1382     gLogOstream <<
1383       "Initializing LPSR basic types handling" <<
1384       endl;
1385   }
1386 #endif
1387 
1388   // LPSR score output handling
1389   // ------------------------------------------------------
1390 
1391   initializeLpsrScoreOutputKindsMap ();
1392 
1393   // LPSR octave entry handling
1394   // ------------------------------------------------------
1395 
1396   initializeLpsrOctaveEntryKindsMap ();
1397 
1398   // LPSR accidental styles handling
1399   // ------------------------------------------------------
1400 
1401   initializeLpsrAccidentalStyleKindsMap ();
1402 
1403   // LPSR chords languages handling
1404   // ------------------------------------------------------
1405 
1406   initializeLpsrChordsLanguageKindsMap ();
1407 
1408 
1409   // LPSR lyrics durations kinds handling
1410   // ------------------------------------------------------
1411 
1412   initializeLpsrLyricsDurationsKindsMap ();
1413 }
1414 
1415 
1416 }
1417