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 "lpsrScores.h"
14 
15 #include "version.h"
16 
17 #include "generalOah.h"
18 
19 #include "setTraceOahIfDesired.h"
20 #ifdef TRACE_OAH
21   #include "traceOah.h"
22 #endif
23 
24 
25 using namespace std;
26 
27 namespace MusicXML2
28 {
29 
30 //______________________________________________________________________________
create(int inputLineNumber,S_msrScore mScore)31 S_lpsrScore lpsrScore::create (
32   int        inputLineNumber,
33   S_msrScore mScore)
34 {
35   lpsrScore* o = new lpsrScore (
36     inputLineNumber, mScore);
37   assert(o!=0);
38   return o;
39 }
40 
lpsrScore(int inputLineNumber,S_msrScore mScore)41 lpsrScore::lpsrScore (
42   int        inputLineNumber,
43   S_msrScore mScore)
44     : lpsrElement (inputLineNumber)
45 {
46   fMsrScore = mScore;
47 
48   // create the LilyPond version assoc
49   fLilypondVersion =
50     lpsrVarValAssoc::create (
51       inputLineNumber,
52       lpsrVarValAssoc::kCommentedNo,
53       lpsrVarValAssoc::kWithBackSlashYes,
54       lpsrVarValAssoc::kLibraryVersion,
55       lpsrVarValAssoc::kVarValSeparatorSpace,
56       lpsrVarValAssoc::kQuotesAroundValueYes,
57       gLpsrOah->fLilyPondVersion,
58       lpsrVarValAssoc::g_LilyPondVarValAssocNoUnit,
59       kFontStyleNone,
60       kFontWeightNone,
61       lpsrVarValAssoc::g_LilyPondVarValAssocNoComment,
62       lpsrVarValAssoc::kEndlOnce);
63 
64   // should the initial comments about the executable and the options used
65   // be generated?
66   if (gLilypondOah->fXml2lyInfos) {
67     // create the 'input source name and translation date' comment
68     {
69       stringstream s;
70 
71       s <<
72         "Generated by " <<
73         gOahOah->fHandlerExecutableName <<
74         " " <<
75         currentVersionNumber () <<
76         " from ";
77 
78       if (gOahOah->fInputSourceName == "-") {
79         s << "standard input";
80       }
81       else {
82         s << "\"" << gOahOah->fInputSourceName << "\"";
83       }
84 
85       s <<
86         endl <<
87         "% on " << gGeneralOah->fTranslationDate <<
88         endl;
89 
90       fInputSourceNameComment =
91         lpsrComment::create (
92           inputLineNumber,
93           s.str (),
94           lpsrComment::kNoGapAfterwards);
95     }
96 
97     // create the 'translation command line' comment
98     {
99       stringstream s;
100 
101       s <<
102         "The translation command line was:";
103 
104       fTranslationDateComment =
105         lpsrComment::create (
106           inputLineNumber,
107           s.str (),
108           lpsrComment::kNoGapAfterwards);
109     }
110 
111     // create the 'command line as supplied' comment
112     {
113       stringstream s;
114 
115       s <<
116         gTab <<
117         gOahOah->fCommandLineAsSupplied;
118 
119       fCommandLineAsSuppliedComment =
120         lpsrComment::create (
121           inputLineNumber,
122           s.str (),
123           lpsrComment::kNoGapAfterwards);
124     }
125 
126     // do the command line long and short options differ?
127     bool
128       longAndShortOptionsDiffer =
129         gOahOah->fCommandLineWithShortOptionsNames
130           !=
131         gOahOah->fCommandLineWithLongOptionsNames;
132 
133     // create the 'command line long options' comment
134     {
135       stringstream s;
136 
137       s <<
138         "or, with long option names:" <<
139         endl <<
140         "%" <<
141         gTab <<
142         gOahOah->fCommandLineWithLongOptionsNames;
143 
144       if (longAndShortOptionsDiffer) {
145         s <<
146           endl <<
147           "% or, with short option names:";
148       }
149 
150       fCommandLineLongOptionsComment =
151         lpsrComment::create (
152           inputLineNumber,
153           s.str (),
154           longAndShortOptionsDiffer
155             ? lpsrComment::kNoGapAfterwards
156             : lpsrComment::kGapAfterwards);
157     }
158 
159     if (longAndShortOptionsDiffer) {
160       // create the 'command line short options' comment
161       stringstream s;
162 
163       s <<
164         gTab <<
165         gOahOah->fCommandLineWithShortOptionsNames;
166 
167       fCommandLineShortOptionsComment =
168         lpsrComment::create (
169           inputLineNumber,
170           s.str (),
171           lpsrComment::kGapAfterwards);
172     }
173   }
174 
175   // create the global staff size variable
176   // too early to benefit from gLpsrOah->fGlobalStaffSize... JMI
177   // needs to be updated later in msrScaling::globalStaffSize()
178   fScoreGlobalStaffSizeSchemeVariable =
179     lpsrSchemeVariable::create (
180       inputLineNumber,
181       lpsrSchemeVariable::kCommentedNo,
182       "set-global-staff-size",
183       to_string (gLpsrOah->fGlobalStaffSize),
184       "Comment or adapt next line as needed (default is 20)",
185       lpsrSchemeVariable::kEndlTwice);
186 
187   // initialize Scheme functions informations
188   // ----------------------------------------
189 
190   // files includes
191   fJianpuFileIncludeIsNeeded = false;
192 
193   // Scheme modules
194   fScmAndAccregSchemeModulesAreNeeded = false;
195 
196   // Scheme functions
197   fTongueSchemeFunctionIsNeeded = false;
198   fCustomShortBarlineSchemeFunctionIsNeeded = false;
199   fEditorialAccidentalSchemeFunctionIsNeeded = false;
200   fDynamicsSchemeFunctionIsNeeded = false;
201   fTupletsCurvedBracketsSchemeFunctionIsNeeded = false;
202   fAfterSchemeFunctionIsNeeded = false;
203   fTempoRelationshipSchemeFunctionIsNeeded = false;
204   fGlissandoWithTextSchemeFunctionsIsNeeded = false;
205   fOtherDynamicSchemeFunctionIsNeeded = false;
206 
207   // markups
208   fDampMarkupIsNeeded = false;
209   fDampAllMarkupIsNeeded = false;
210 
211   // white note heads
212   fWhiteNoteHeadsIsNeeded = false;
213 
214     // bar numbers
215   fBoxAroundNextBarNumberIsNeeded = false;
216 
217   // jazz chords display
218   fJazzChordsDisplayIsNeeded = false;
219 
220   // colored ledger lines
221   fColoredLedgerLinesIsNeeded = false;
222 
223   if (gLilypondOah->fLilypondCompileDate) {
224     // create the date and time functions
225     addDateAndTimeSchemeFunctionsToScore ();
226   }
227 
228   if (gLilypondOah->fPointAndClickOff) {
229     // create the pointAndClickOff scheme function
230     addPointAndClickOffSchemeFunctionsToScore ();
231   }
232 
233   if (gLilypondOah->fPointAndClickOff) {
234     // create the glissandoWithText scheme functions
235     addGlissandoWithTextSchemeFunctionsToScore ();
236   }
237 
238   if (gLilypondOah->fJianpu) {
239     // create the Jianpu include command JMI
240   }
241 
242   // create the header
243   fScoreHeader =
244     lpsrHeader::create (
245       inputLineNumber);
246 
247   // create the paper
248   fScorePaper =
249     lpsrPaper::create (
250       inputLineNumber,
251       fMsrScore->getScaling (),
252       fMsrScore->getPageLayout ());
253 
254   // populate the paper
255 /* JMI
256   // populate paper
257   msrLength paperWidth =
258     elt->getPaperWidth ();
259   if (gLpsrOah->fPaperWidth.getLengthValue () > 0.0) {
260     paperWidth = gLpsrOah->fPaperWidth;
261   }
262   paper ->
263     setPaperWidth (paperWidth);
264 
265   msrLength paperHeight =
266     elt->getPaperHeight ();
267   if (gLpsrOah->fPaperHeight.getLengthValue () > 0.0) {
268     paperWidth = gLpsrOah->fPaperHeight;
269   }
270   paper->
271     setPaperHeight (paperHeight);
272 
273   msrLength topMargin =
274     elt->getTopMargin ();
275   if (gLpsrOah->fTopMargin > 0.0) {
276     topMargin = gLpsrOah->fTopMargin;
277   }
278   paper->
279     setTopMargin (topMargin);
280 
281   msrLength bottomMargin =
282     elt->getBottomMargin ();
283   if (gLpsrOah->fBottomMargin > 0.0) {
284     bottomMargin = gLpsrOah->fBottomMargin;
285   }
286   paper->
287     setBottomMargin (bottomMargin);
288 
289   msrLength leftMargin =
290     elt->getLeftMargin ();
291   if (gLpsrOah->fLeftMargin > 0.0) {
292     leftMargin = gLpsrOah->fLeftMargin;
293   }
294   paper->
295     setLeftMargin (leftMargin);
296 
297   msrLength rightMargin =
298     elt->getRightMargin ();
299   if (gLpsrOah->fRightMargin > 0.0) {
300     rightMargin = gLpsrOah->fRightMargin;
301   }
302   paper->
303     setRightMargin (rightMargin);
304 */
305 
306     // indents
307   if (gLpsrOah->fPaperHorizontalShift.getLengthValue () > 0.0) {
308     fScorePaper->
309       setHorizontalShift (
310         msrLength::create (
311           gLpsrOah->fPaperHorizontalShift.getLengthUnitKind (),
312           gLpsrOah->fPaperHorizontalShift.getLengthValue ()));
313   }
314 
315   if (gLpsrOah->fPaperIndent.getLengthValue () > 0.0) {
316     fScorePaper->
317       setIndent (
318         msrLength::create (
319           gLpsrOah->fPaperIndent.getLengthUnitKind (),
320           gLpsrOah->fPaperIndent.getLengthValue ()));
321   }
322 
323   if (gLpsrOah->fPaperShortIndent.getLengthValue () > 0.0) {
324     fScorePaper->
325       setShortIndent (
326         msrLength::create (
327           gLpsrOah->fPaperShortIndent.getLengthUnitKind (),
328           gLpsrOah->fPaperShortIndent.getLengthValue ()));
329   }
330 
331   if (gLilypondOah->fLilypondCompileDate) {
332     // define headers and footers
333 
334     fScorePaper->
335       setOddHeaderMarkup (
336 R"(\markup {
337     \fill-line {
338       \on-the-fly \not-first-page {
339         \fromproperty #'page:page-number-string
340         " "
341         \fromproperty #'header:title
342         " "
343         \fromproperty #'header:subtitle
344       }
345     }
346   }
347 )"
348       );
349 
350     fScorePaper->
351       setEvenHeaderMarkup (
352 R"(\markup {
353     \fill-line {
354       \on-the-fly \not-first-page {
355         \fromproperty #'page:page-number-string
356         " "
357         \fromproperty #'header:title
358         " "
359         \fromproperty #'header:subtitle
360       }
361     }
362   }
363 )"
364       );
365 
366     stringstream s;
367 
368 /* JMI YES???
369       \fill-line {
370         "https://github.com/grame-cncm/libmusicxml/tree/lilypond - http://www.lilypond.org"
371       }
372 */
373     s <<
374 R"(\markup {
375     \tiny
376     \column {
377       \fill-line {
378         #(string-append
379 )"
380       <<
381       "\"Music generated from MusicXML by " <<
382       gOahOah->fHandlerExecutableName <<
383       " " <<
384       currentVersionNumber () <<
385       " and engraved by LilyPond \" (lilypond-version))" <<
386 R"(
387       }
388       \fill-line { \italic { \modTimeAsString }}
389     }
390   }
391 )";
392 
393     fScorePaper->
394       setOddFooterMarkup (
395         s.str ());
396   }
397 
398   // create the score layout // JMI ???
399   fScoreLayout =
400     lpsrLayout::create (
401       inputLineNumber);
402 
403   // create the 'myBreakIsBreak' assoc
404   {
405     lpsrVarValAssoc::lpsrCommentedKind
406       commentedKind =
407         gLilypondOah->fIgnoreMusicXMLLineBreaks
408           ? lpsrVarValAssoc::kCommentedYes
409           : lpsrVarValAssoc::kCommentedNo;
410 
411     fMyBreakIsBreakAssoc =
412       lpsrVarValAssoc::create (
413         inputLineNumber,
414         commentedKind,
415         lpsrVarValAssoc::kWithBackSlashNo,
416         lpsrVarValAssoc::kLilypondMyBreak,
417         lpsrVarValAssoc::kVarValSeparatorEqualSign,
418         lpsrVarValAssoc::kQuotesAroundValueNo,
419         "{ \\break }",
420         lpsrVarValAssoc::g_LilyPondVarValAssocNoUnit,
421         kFontStyleNone,
422         kFontWeightNone,
423         "Pick your choice from the next two lines as needed",
424         lpsrVarValAssoc::kEndlNone);
425   }
426 
427   // create the 'myBreakIsEmpty' assoc
428   {
429     lpsrVarValAssoc::lpsrCommentedKind
430       commentedKind =
431         gLilypondOah->fIgnoreMusicXMLLineBreaks
432           ? lpsrVarValAssoc::kCommentedNo
433           : lpsrVarValAssoc::kCommentedYes;
434 
435     fMyBreakIsEmptyAssoc =
436       lpsrVarValAssoc::create (
437         inputLineNumber,
438         commentedKind,
439         lpsrVarValAssoc::kWithBackSlashNo,
440         lpsrVarValAssoc::kLilypondMyBreak,
441         lpsrVarValAssoc::kVarValSeparatorEqualSign,
442         lpsrVarValAssoc::kQuotesAroundValueNo,
443         "{ }",
444         lpsrVarValAssoc::g_LilyPondVarValAssocNoUnit,
445         kFontStyleNone,
446         kFontWeightNone,
447         lpsrVarValAssoc::g_LilyPondVarValAssocNoComment,
448         lpsrVarValAssoc::kEndlOnce);
449   }
450 
451   // create the 'myPageBreakIsPageBreak' assoc
452   {
453     lpsrVarValAssoc::lpsrCommentedKind
454       commentedKind =
455         gLilypondOah->fIgnoreMusicXMLLineBreaks
456           ? lpsrVarValAssoc::kCommentedYes
457           : lpsrVarValAssoc::kCommentedNo;
458 
459     fMyPageBreakIsPageBreakAssoc =
460       lpsrVarValAssoc::create (
461         inputLineNumber,
462         commentedKind,
463         lpsrVarValAssoc::kWithBackSlashNo,
464         lpsrVarValAssoc::kLilypondMyPageBreak,
465         lpsrVarValAssoc::kVarValSeparatorEqualSign,
466         lpsrVarValAssoc::kQuotesAroundValueNo,
467         "{ \\pageBreak }",
468         lpsrVarValAssoc::g_LilyPondVarValAssocNoUnit,
469         kFontStyleNone,
470         kFontWeightNone,
471         "Pick your choice from the next two lines as needed",
472         lpsrVarValAssoc::kEndlNone);
473   }
474 
475   // create the 'myPageBreakIsEmpty' assoc
476   {
477     lpsrVarValAssoc::lpsrCommentedKind
478       commentedKind =
479         gLilypondOah->fIgnoreMusicXMLLineBreaks
480           ? lpsrVarValAssoc::kCommentedNo
481           : lpsrVarValAssoc::kCommentedYes;
482 
483     fMyPageBreakIsEmptyAssoc =
484       lpsrVarValAssoc::create (
485         inputLineNumber,
486         commentedKind,
487         lpsrVarValAssoc::kWithBackSlashNo,
488         lpsrVarValAssoc::kLilypondMyPageBreak,
489         lpsrVarValAssoc::kVarValSeparatorEqualSign,
490         lpsrVarValAssoc::kQuotesAroundValueNo,
491         "{ }",
492         lpsrVarValAssoc::g_LilyPondVarValAssocNoUnit,
493         kFontStyleNone,
494         kFontWeightNone,
495         lpsrVarValAssoc::g_LilyPondVarValAssocNoComment,
496         lpsrVarValAssoc::kEndlOnce);
497   }
498 
499   if (gLilypondOah->fGlobal) {
500     // create the 'global' assoc
501     fScoreGlobalAssoc =
502       lpsrVarValAssoc::create (
503         inputLineNumber,
504         lpsrVarValAssoc::kCommentedNo,
505         lpsrVarValAssoc::kWithBackSlashNo,
506         lpsrVarValAssoc::kLilypondGlobal,
507         lpsrVarValAssoc::kVarValSeparatorEqualSign,
508         lpsrVarValAssoc::kQuotesAroundValueNo,
509         "{ }",
510         lpsrVarValAssoc::g_LilyPondVarValAssocNoUnit,
511         kFontStyleNone,
512         kFontWeightNone,
513         "Place whatever you need in the 'global' variable",
514         lpsrVarValAssoc::kEndlOnce);
515   }
516 }
517 
~lpsrScore()518 lpsrScore::~lpsrScore ()
519 {}
520 
setScoreGlobalStaffSizeSchemeVariable(float size)521 void lpsrScore::setScoreGlobalStaffSizeSchemeVariable (float size)
522 {
523   stringstream s;
524 
525   s << size;
526 
527 #ifdef TRACE_OAH
528   if (gTraceOah->fTraceGeometry) {
529     gLogOstream <<
530       "Setting score global staff size Scheme variable to '" <<
531       size <<
532       "'" <<
533       endl;
534   }
535 #endif
536 
537   string sizeAsString = s.str ();
538 
539   fScoreGlobalStaffSizeSchemeVariable->
540     setVariableValue (sizeAsString);
541 }
542 
setJianpuFileIncludeIsNeeded()543 void lpsrScore::setJianpuFileIncludeIsNeeded ()
544 {
545   if (! fScmAndAccregSchemeModulesAreNeeded) {
546     addJianpuFileIncludeToScore ();
547 
548     fJianpuFileIncludeIsNeeded = true;
549   }
550 }
551 
setScmAndAccregSchemeModulesAreNeeded()552 void lpsrScore::setScmAndAccregSchemeModulesAreNeeded ()
553 {
554   if (! fScmAndAccregSchemeModulesAreNeeded) {
555     addAccordionRegistrationSchemeModulesToScore ();
556 
557     fScmAndAccregSchemeModulesAreNeeded = true;
558   }
559 }
560 
setCustomShortBarlineSchemeFunctionIsNeeded()561 void lpsrScore::setCustomShortBarlineSchemeFunctionIsNeeded ()
562 {
563   if (! fCustomShortBarlineSchemeFunctionIsNeeded) {
564     addCustomShortBarlineSchemeFunctionToScore ();
565 
566     fCustomShortBarlineSchemeFunctionIsNeeded = true;
567   }
568 }
569 
setTongueSchemeFunctionIsNeeded()570 void lpsrScore::setTongueSchemeFunctionIsNeeded ()
571 {
572   if (! fTongueSchemeFunctionIsNeeded) {
573     addTongueSchemeFunctionToScore ();
574 
575     fTongueSchemeFunctionIsNeeded = true;
576   }
577 }
578 
setEditorialAccidentalSchemeFunctionIsNeeded()579 void lpsrScore::setEditorialAccidentalSchemeFunctionIsNeeded ()
580 {
581   if (! fEditorialAccidentalSchemeFunctionIsNeeded) {
582     addEditorialAccidentalSchemeFunctionToScore ();
583 
584     fEditorialAccidentalSchemeFunctionIsNeeded = true;
585   }
586 }
587 
setDynamicsSchemeFunctionIsNeeded()588 void lpsrScore::setDynamicsSchemeFunctionIsNeeded ()
589 {
590   if (! fDynamicsSchemeFunctionIsNeeded) {
591     addDynamicsSchemeFunctionToScore ();
592 
593     fDynamicsSchemeFunctionIsNeeded = true;
594   }
595 }
596 
setTupletsCurvedBracketsSchemeFunctionIsNeeded()597 void lpsrScore::setTupletsCurvedBracketsSchemeFunctionIsNeeded ()
598 {
599   if (! fTupletsCurvedBracketsSchemeFunctionIsNeeded) {
600     addTupletsCurvedBracketsSchemeFunctionToScore ();
601 
602     fTupletsCurvedBracketsSchemeFunctionIsNeeded = true;
603   }
604 }
605 
setAfterSchemeFunctionIsNeeded()606 void lpsrScore::setAfterSchemeFunctionIsNeeded ()
607 {
608   if (! fAfterSchemeFunctionIsNeeded) {
609     addAfterSchemeFunctionToScore ();
610 
611     fAfterSchemeFunctionIsNeeded = true;
612   }
613 }
614 
setTempoRelationshipSchemeFunctionIsNeeded()615 void lpsrScore::setTempoRelationshipSchemeFunctionIsNeeded ()
616 {
617   if (! fTempoRelationshipSchemeFunctionIsNeeded) {
618     addTempoRelationshipSchemeFunctionToScore ();
619 
620     fTempoRelationshipSchemeFunctionIsNeeded = true;
621   }
622 }
623 
setGlissandoWithTextSchemeFunctionsIsNeeded()624 void lpsrScore::setGlissandoWithTextSchemeFunctionsIsNeeded ()
625 {
626   if (! fGlissandoWithTextSchemeFunctionsIsNeeded) {
627     addGlissandoWithTextSchemeFunctionsToScore ();
628 
629     fGlissandoWithTextSchemeFunctionsIsNeeded = true;
630   }
631 }
632 
setOtherDynamicSchemeFunctionIsNeeded()633 void lpsrScore::setOtherDynamicSchemeFunctionIsNeeded ()
634 {
635   if (! fOtherDynamicSchemeFunctionIsNeeded) {
636     addOtherDynamicSchemeFunctionToScore ();
637 
638     fOtherDynamicSchemeFunctionIsNeeded = true;
639   }
640 }
641 
setDampMarkupIsNeeded()642 void lpsrScore::setDampMarkupIsNeeded ()
643 {
644   if (! fDampMarkupIsNeeded) {
645     addDampMarkupToScore ();
646 
647     fDampMarkupIsNeeded = true;
648   }
649 }
650 
setDampAllMarkupIsNeeded()651 void lpsrScore::setDampAllMarkupIsNeeded ()
652 {
653   if (! fDampAllMarkupIsNeeded) {
654     addDampAllMarkupToScore ();
655 
656     fDampAllMarkupIsNeeded = true;
657   }
658 }
659 
setWhiteNoteHeadsIsNeeded()660 void lpsrScore::setWhiteNoteHeadsIsNeeded ()
661 {
662   if (! fWhiteNoteHeadsIsNeeded) {
663     addWhiteNoteHeadsToScore ();
664 
665     fWhiteNoteHeadsIsNeeded = true;
666   }
667 }
668 
setBoxAroundNextBarNumberIsNeeded()669 void lpsrScore::setBoxAroundNextBarNumberIsNeeded ()
670 {
671   if (! fBoxAroundNextBarNumberIsNeeded) {
672     addBoxAroundNextBarNumberToScore ();
673 
674     fBoxAroundNextBarNumberIsNeeded = true;
675   }
676 }
677 
setJazzChordsDisplayIsNeeded()678 void lpsrScore::setJazzChordsDisplayIsNeeded ()
679 {
680   if (! fJazzChordsDisplayIsNeeded) {
681     addJazzChordsDisplayToScore ();
682 
683     fJazzChordsDisplayIsNeeded = true;
684   }
685 }
686 
setColoredLedgerLinesIsNeeded()687 void lpsrScore::setColoredLedgerLinesIsNeeded ()
688 {
689   if (! fColoredLedgerLinesIsNeeded) {
690     addColoredLedgerLinesToScore ();
691 
692     fColoredLedgerLinesIsNeeded = true;
693   }
694 }
695 
addDateAndTimeSchemeFunctionsToScore()696 void lpsrScore::addDateAndTimeSchemeFunctionsToScore ()
697 {
698   string
699     schemeFunctionName =
700       "date & time",
701 
702     schemeFunctionDescription =
703 R"(
704 % A set of functions to obtain a source file's modification time.
705 )",
706 
707     schemeFunctionCode =
708 R"(
709 #(define comml           (object->string (command-line)))
710 #(define loc             (+ (string-rindex comml #\space ) 2))
711 #(define commllen        (- (string-length comml) 2))
712 #(define filen           (substring comml loc commllen))
713 #(define siz             (object->string (stat:size (stat filen))))
714 #(define ver             (object->string (lilypond-version)))
715 #(define dat             (strftime "%d/%m/%Y" (localtime (current-time))))
716 #(define tim             (strftime "%H:%M:%S" (localtime (current-time))))
717 #(define modTime         (stat:mtime (stat filen)))
718 #(define modTimeAsString (strftime "%d/%m/%Y - %H:%M:%S" (localtime modTime)))
719 )";
720 
721 #ifdef TRACE_OAH
722   if (gLpsrOah->fTraceSchemeFunctions) {
723     gLogOstream <<
724       "Creating Scheme functions for '" << schemeFunctionName << "'" <<
725       endl;
726   }
727 #endif
728 
729   // create the Scheme function
730   S_lpsrSchemeFunction
731     schemeFunction =
732       lpsrSchemeFunction::create (
733         1, // inputLineNumber, JMI ???
734         schemeFunctionName,
735         schemeFunctionDescription,
736         schemeFunctionCode);
737 
738   // register it in the Scheme functions map
739   fScoreSchemeFunctionsMap [schemeFunctionName] =
740     schemeFunction;
741 }
742 
addPointAndClickOffSchemeFunctionsToScore()743 void lpsrScore::addPointAndClickOffSchemeFunctionsToScore ()
744 {
745   string
746     schemeFunctionName =
747       "pointAndClickOff",
748 
749     schemeFunctionDescription =
750 R"(
751 % \pointAndClickOff to reduce the size of the produced PDF file.
752 )",
753 
754     schemeFunctionCode =
755 R"(
756 \pointAndClickOff
757 )";
758 
759 #ifdef TRACE_OAH
760   if (gLpsrOah->fTraceSchemeFunctions) {
761     gLogOstream <<
762       "Creating Scheme functions for '" << schemeFunctionName << "'" <<
763       endl;
764   }
765 #endif
766 
767   // create the Scheme function
768   S_lpsrSchemeFunction
769     schemeFunction =
770       lpsrSchemeFunction::create (
771         1, // inputLineNumber, JMI ???
772         schemeFunctionName,
773         schemeFunctionDescription,
774         schemeFunctionCode);
775 
776   // register it in the Scheme functions map
777   fScoreSchemeFunctionsMap [schemeFunctionName] =
778     schemeFunction;
779 }
780 
addGlissandoWithTextSchemeFunctionsToScore()781 void lpsrScore::addGlissandoWithTextSchemeFunctionsToScore ()
782 {
783   string
784     schemeFunctionName =
785       "glissandoWithText",
786 
787     schemeFunctionDescription =
788 R"(
789 % \\glissandoTextOn/Off to get text along glissandos.
790 )",
791 
792     schemeFunctionCode =
793 R"(
794 % thanks to Thomas Morley for contributing this code
795 
796 %% c/p from lily-library.scm (it is not public)
797 #(define (sign x)
798   (if (= x 0)
799       0
800       (if (< x 0) -1 1)))
801 
802 #(define (radians->degree radians)
803   (/ (* radians 180) PI))
804 
805 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
806 %%%% Glissando with text
807 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
808 %%%% Reads from Glissando.details
809 %%%%   - glissando-text
810 %%%%   - glissando-text-font-size
811 %%%%   - glissando-text-padding
812 
813 #(define* ((gliss-plus-text #:optional always-add-text) grob)
814   (let*  ((orig-grob (ly:grob-original grob))
815           (broken-beams (ly:spanner-broken-into orig-grob))
816           (stil (ly:line-spanner::print grob)))
817     (if (or (null? broken-beams)
818             (and (pair? broken-beams)
819                  (or
820                     always-add-text
821                     (equal? grob (car broken-beams)))))
822         (if (not (ly:stencil? stil))
823             #f
824             (let* ((layout (ly:grob-layout grob))
825                    (line-thickness
826                      (ly:output-def-lookup layout 'line-thickness))
827                    (props
828                      (ly:grob-alist-chain
829                        grob
830                        (ly:output-def-lookup layout 'text-font-defaults)))
831                    (font
832                      (ly:paper-get-font
833                      layout
834                      (cons
835                        '((font-encoding . fetaMusic) (font-name . #f))
836                        props)))
837                    (trill-glyph
838                      (ly:font-get-glyph font "scripts.trill_element"))
839                    (trill-glyph-height
840                      (interval-length (ly:stencil-extent trill-glyph Y)))
841                    (zigzag-width
842                      (ly:grob-property grob 'zigzag-width))
843                    (thickness (ly:grob-property grob 'thickness))
844                    (thick
845                      (if (number? thickness)
846                          (/ thickness 10)
847                          line-thickness))
848                    (style (ly:grob-property grob 'style))
849                    (corr
850                      (cond ((eq? style 'trill)
851                              trill-glyph-height)
852                            ((eq? style 'zigzag)
853                              (+ thick zigzag-width))
854                            (else 0)))
855                    (stil-x-ext (ly:stencil-extent stil X))
856                    (stil-y-ext (ly:stencil-extent stil Y))
857                    (stil-x-length (- (cdr stil-x-ext) (car stil-x-ext)))
858                    (stil-y-length (- (cdr stil-y-ext) (car stil-y-ext)))
859                    (details (ly:grob-property grob 'details))
860                    (gliss-text
861                      (assoc-get 'glissando-text details "gliss."))
862                    (gliss-text-font-size
863                      (assoc-get 'glissando-text-font-size details -5))
864                    (gliss-text-padding
865                      (assoc-get 'glissando-text-padding details 0.5))
866                    (left-bound-info (ly:grob-property grob 'left-bound-info))
867                    (y-left (assoc-get 'Y left-bound-info))
868                    (right-bound-info (ly:grob-property grob 'right-bound-info))
869                    (y-right (assoc-get 'Y right-bound-info))
870                    (slant (sign (- y-right y-left)))
871                    (gradient
872                      (/ (- stil-y-length corr) stil-x-length))
873                    ;; `ly:stencil-rotate' needs an angle in degrees...
874                    ;; TODO use ly:angle ?
875                    (alpha
876                      (radians->degree
877                        (angle
878                          (make-rectangular
879                            stil-x-length
880                            (- stil-y-length corr line-thickness)))))
881                    (text-stencil
882                      (grob-interpret-markup
883                        grob
884                          (make-halign-markup CENTER
885                            (make-fontsize-markup
886                              gliss-text-font-size
887                              gliss-text))))
888                    (text-stencil-height
889                      (interval-length (ly:stencil-extent text-stencil Y)))
890                    (y-move
891                      (+
892                        (/ text-stencil-height 2)
893                        gliss-text-padding))
894                    (rotated-text-stil
895                      (ly:stencil-rotate text-stencil (* slant alpha) 0 0))
896                    (text-center-X
897                      (interval-center (ly:stencil-extent rotated-text-stil X)))
898                    (translated-text-stencil
899                      (ly:stencil-translate
900                        rotated-text-stil
901                        ;; Constuction-helpers
902                        ;text-stencil
903                        ;(make-cross-stencil '(0 . 0)) ;; not included atm
904                        (cons
905                          (+
906                            (car stil-x-ext)
907                            (/ stil-x-length 2)
908                            (* slant -1 y-move gradient))
909                          (+
910                            (car stil-y-ext)
911                            (/ stil-y-length 2)
912                            y-move)))))
913             (ly:stencil-add
914               stil
915               ;; Construction-helpers
916               ;;
917               ;(make-line-stencil
918               ;  0.1
919               ;  (+ (car stil-x-ext)(/ stil-x-length 2))
920               ;  (+ (car stil-y-ext)(/ stil-y-length 2))
921               ;  (+ (car stil-x-ext)(/ stil-x-length 2)(* slant -1 10 gradient))
922               ;  10)
923               ;;
924               ;; (2) colors the text-part
925               ;;
926               ;(stencil-with-color translated-text-stencil red)
927               translated-text-stencil
928               )))
929         stil)))
930 
931 glissandoTextOn =
932   \temporary \override Glissando.stencil =
933     #(gliss-plus-text
934       ;; change to true, if added text is wished for both parts of a broken
935       ;; glissando
936       ;; TODO added text at second parts needs to be improved, vertical
937       ;; positioning is sometimes bad
938       #f)
939 
940 glissandoTextOff = \revert Glissando.stencil
941 )";
942 
943 #ifdef TRACE_OAH
944   if (gLpsrOah->fTraceSchemeFunctions) {
945     gLogOstream <<
946       "Creating Scheme functions for '" << schemeFunctionName << "'" <<
947       endl;
948   }
949 #endif
950 
951   // create the Scheme function
952   S_lpsrSchemeFunction
953     schemeFunction =
954       lpsrSchemeFunction::create (
955         1, // inputLineNumber, JMI ???
956         schemeFunctionName,
957         schemeFunctionDescription,
958         schemeFunctionCode);
959 
960   // register it in the Scheme functions map
961   fScoreSchemeFunctionsMap [schemeFunctionName] =
962     schemeFunction;
963 }
964 
addOtherDynamicSchemeFunctionToScore()965 void lpsrScore::addOtherDynamicSchemeFunctionToScore ()
966 {
967   string
968     schemeFunctionName =
969       "otherDynamic",
970 
971     schemeFunctionDescription =
972 R"(
973 % \\otherDynamic to handle any string as dynamics.
974 )",
975 
976     schemeFunctionCode =
977 R"(
978 #(use-modules (ice-9 regex))
979 
980 otherDynamic =
981 #(define-event-function (parser location text) (markup?)
982    (if (string? text)
983        (let* ((underscores-replaced
984                (string-map
985                 (lambda (x) (if (eq? x #\_) #\space x))
986                 text))
987               (split-text (string-split underscores-replaced #\space))
988               (formatted (map
989                           (lambda (word)
990                             (if (string-match "^[mrzfps]*$" word)
991                                 (markup #:dynamic word)
992                                 (markup #:normal-text #:italic word)))
993                           split-text)))
994          #{
995            #(make-dynamic-script (make-line-markup formatted))
996          #})
997        ;; user provided a full-blown markup, so we don't mess with it:
998        #{
999          #(make-dynamic-script (markup #:normal-text text))
1000        #}))
1001 )";
1002 
1003 #ifdef TRACE_OAH
1004   if (gLpsrOah->fTraceSchemeFunctions) {
1005     gLogOstream <<
1006       "Creating Scheme functions for '" << schemeFunctionName << "'" <<
1007       endl;
1008   }
1009 #endif
1010 
1011   // create the Scheme function
1012   S_lpsrSchemeFunction
1013     schemeFunction =
1014       lpsrSchemeFunction::create (
1015         1, // inputLineNumber, JMI ???
1016         schemeFunctionName,
1017         schemeFunctionDescription,
1018         schemeFunctionCode);
1019 
1020   // register it in the Scheme functions map
1021   fScoreSchemeFunctionsMap [schemeFunctionName] =
1022     schemeFunction;
1023 }
1024 
addCustomShortBarlineSchemeFunctionToScore()1025 void lpsrScore::addCustomShortBarlineSchemeFunctionToScore ()
1026 {
1027   string
1028     schemeModulesName =
1029       "curstom short barline Scheme function",
1030 
1031     schemeModulesDescription =
1032 R"(
1033 % The function needed to produce curstom short barlines.
1034 )",
1035 
1036     schemeModulesCode =
1037 R"(
1038 #(define ((make-custom-short-bar-line x y) grob extent)
1039    "Draw a short bar line."
1040    (let* ((short-staff (* 1/2 (ly:staff-symbol-staff-space grob)))
1041           (staff-line-thickness (ly:staff-symbol-line-thickness grob))
1042           (height (interval-end extent)))
1043      (bar-line::draw-filled-box
1044       (cons 0 (+ x staff-line-thickness))
1045       (cons (- height (* 7 short-staff) x) (- height short-staff x))
1046       staff-line-thickness
1047       extent
1048       grob)))
1049 
1050 #(add-bar-glyph-print-procedure "/" (make-custom-short-bar-line 0.1 0.1))
1051 
1052 #(define-bar-line "/" "/" #f #f)
1053 )";
1054 
1055 
1056 #ifdef TRACE_OAH
1057   if (gLpsrOah->fTraceSchemeFunctions) {
1058     gLogOstream <<
1059       "Including Jianpu definition file '" << schemeModulesName << "'" <<
1060       endl;
1061   }
1062 #endif
1063 
1064   // create the Scheme function
1065   S_lpsrSchemeFunction
1066     schemeFunction =
1067       lpsrSchemeFunction::create (
1068         1, // inputLineNumber, JMI ???
1069         schemeModulesName,
1070         schemeModulesDescription,
1071         schemeModulesCode);
1072 
1073   // register it in the Scheme functions map
1074   fScoreSchemeFunctionsMap [schemeModulesName] =
1075     schemeFunction;
1076 }
1077 
addJianpuFileIncludeToScore()1078 void lpsrScore::addJianpuFileIncludeToScore ()
1079 {
1080   string
1081     schemeModulesName =
1082       "jianpu include file",
1083 
1084     schemeModulesDescription =
1085 R"(
1086 % The definitions needed to produce jianpu scores.
1087 )",
1088 
1089     schemeModulesCode =
1090 R"(
1091 % From https://github.com/nybbs2003/lilypond-Jianpu
1092 \include "jianpu10a.ly"
1093 )";
1094 
1095 #ifdef TRACE_OAH
1096   if (gLpsrOah->fTraceSchemeFunctions) {
1097     gLogOstream <<
1098       "Including Jianpu definition file '" << schemeModulesName << "'" <<
1099       endl;
1100   }
1101 #endif
1102 
1103   // create the Scheme function
1104   S_lpsrSchemeFunction
1105     schemeFunction =
1106       lpsrSchemeFunction::create (
1107         1, // inputLineNumber, JMI ???
1108         schemeModulesName,
1109         schemeModulesDescription,
1110         schemeModulesCode);
1111 
1112   // register it in the Scheme functions map
1113   fScoreSchemeFunctionsMap [schemeModulesName] =
1114     schemeFunction;
1115 }
1116 
addAccordionRegistrationSchemeModulesToScore()1117 void lpsrScore::addAccordionRegistrationSchemeModulesToScore ()
1118 {
1119   string
1120     schemeModulesName =
1121       "scm & accreg",
1122 
1123     schemeModulesDescription =
1124 R"(
1125 % Two modules are to be used in the right order to use accordion registration.
1126 )",
1127 
1128     schemeModulesCode =
1129 R"(
1130 #(use-modules (scm accreg))
1131 )";
1132 
1133 #ifdef TRACE_OAH
1134   if (gLpsrOah->fTraceSchemeFunctions) {
1135     gLogOstream <<
1136       "Using Scheme modules '" << schemeModulesName << "'" <<
1137       endl;
1138   }
1139 #endif
1140 
1141   // create the Scheme function
1142   S_lpsrSchemeFunction
1143     schemeFunction =
1144       lpsrSchemeFunction::create (
1145         1, // inputLineNumber, JMI ???
1146         schemeModulesName,
1147         schemeModulesDescription,
1148         schemeModulesCode);
1149 
1150   // register it in the Scheme functions map
1151   fScoreSchemeFunctionsMap [schemeModulesName] =
1152     schemeFunction;
1153 }
1154 
addTongueSchemeFunctionToScore()1155 void lpsrScore::addTongueSchemeFunctionToScore ()
1156 {
1157   string
1158     schemeFunctionName =
1159       "tongue",
1160 
1161     schemeFunctionDescription =
1162 R"(
1163 % Creates multiple tongue technicals, argument is a number.
1164 % Example: 'c4 -\tongue #3' creates a triple tongue.
1165 )",
1166 
1167     schemeFunctionCode =
1168 R"(
1169 tongue =
1170 #(define-music-function (parser location dots) (integer?)
1171    (let ((script (make-music 'ArticulationEvent
1172                    'articulation-type "staccato")))
1173      (set! (ly:music-property script 'tweaks)
1174            (acons 'stencil
1175              (lambda (grob)
1176                (let ((stil (ly:script-interface::print grob)))
1177                  (let loop ((count (1- dots)) (new-stil stil))
1178                    (if (> count 0)
1179                        (loop (1- count)
1180                          (ly:stencil-combine-at-edge new-stil X RIGHT stil 0.2))
1181                        (ly:stencil-aligned-to new-stil X CENTER)))))
1182              (ly:music-property script 'tweaks)))
1183      script))
1184 )";
1185 
1186 #ifdef TRACE_OAH
1187   if (gLpsrOah->fTraceSchemeFunctions) {
1188     gLogOstream <<
1189       "Creating Scheme function '" << schemeFunctionName << "'" <<
1190       endl;
1191   }
1192 #endif
1193 
1194   // create the Scheme function
1195   S_lpsrSchemeFunction
1196     schemeFunction =
1197       lpsrSchemeFunction::create (
1198         1, // inputLineNumber, JMI ???
1199         schemeFunctionName,
1200         schemeFunctionDescription,
1201         schemeFunctionCode);
1202 
1203   // register it in the Scheme functions map
1204   fScoreSchemeFunctionsMap [schemeFunctionName] =
1205     schemeFunction;
1206 }
1207 
addEditorialAccidentalSchemeFunctionToScore()1208 void lpsrScore::addEditorialAccidentalSchemeFunctionToScore ()
1209 {
1210   string
1211     schemeFunctionName =
1212       "editorialAccidental",
1213 
1214     schemeFunctionDescription =
1215 R"(
1216 % Craetes editorial accidentals as LilyPond musica ficta.
1217 % Example: '\editorialAccidental cis4'.
1218 )",
1219 
1220     schemeFunctionCode =
1221 R"(
1222 editorialAccidental =
1223 #(define-music-function
1224   (note)
1225   (ly:music?)
1226   #{
1227     \once\accidentalStyle forget
1228     \once\set suggestAccidentals = ##t
1229     #note
1230   #})
1231 )";
1232 
1233 #ifdef TRACE_OAH
1234   if (gLpsrOah->fTraceSchemeFunctions) {
1235     gLogOstream <<
1236       "Creating Scheme function '" << schemeFunctionName << "'" <<
1237       endl;
1238   }
1239 #endif
1240 
1241   // create the Scheme function
1242   S_lpsrSchemeFunction
1243     schemeFunction =
1244       lpsrSchemeFunction::create (
1245         1, // inputLineNumber, JMI ???
1246         schemeFunctionName,
1247         schemeFunctionDescription,
1248         schemeFunctionCode);
1249 
1250   // register it in the Scheme functions map
1251   fScoreSchemeFunctionsMap [schemeFunctionName] =
1252     schemeFunction;
1253 }
1254 
addDynamicsSchemeFunctionToScore()1255 void lpsrScore::addDynamicsSchemeFunctionToScore ()
1256 {
1257   string
1258     schemeFunctionName =
1259       "dynamics",
1260 
1261     schemeFunctionDescription =
1262 R"(
1263 % Creates variables define dynamics not native to LilyPond.
1264 )",
1265 
1266     schemeFunctionCode =
1267 R"(
1268 rf = #(make-dynamic-script "rf")
1269 sfpp = #(make-dynamic-script "sfpp")
1270 sffz = #(make-dynamic-script "sffz")
1271 ppppp = #(make-dynamic-script "ppppp")
1272 pppppp = #(make-dynamic-script "pppppp")
1273 fffff = #(make-dynamic-script "fffff")
1274 ffffff = #(make-dynamic-script "ffffff")
1275 )";
1276 
1277 #ifdef TRACE_OAH
1278   if (gLpsrOah->fTraceSchemeFunctions) {
1279     gLogOstream <<
1280       "Creating Scheme function '" << schemeFunctionName << "'" <<
1281       endl;
1282   }
1283 #endif
1284 
1285   // create the Scheme function
1286   S_lpsrSchemeFunction
1287     schemeFunction =
1288       lpsrSchemeFunction::create (
1289         1, // inputLineNumber, JMI ???
1290         schemeFunctionName,
1291         schemeFunctionDescription,
1292         schemeFunctionCode);
1293 
1294   // register it in the Scheme functions map
1295   fScoreSchemeFunctionsMap [schemeFunctionName] =
1296     schemeFunction;
1297 }
1298 
addTupletsCurvedBracketsSchemeFunctionToScore()1299 void lpsrScore::addTupletsCurvedBracketsSchemeFunctionToScore ()
1300 {
1301   string
1302     schemeFunctionName =
1303       "tupletsCurvedBrackets",
1304 
1305     schemeFunctionDescription =
1306 R"(
1307 % A function to draw curved tuplets brackets, not native to LilyPond.
1308 % Thanks to Ben, mailto:soundsfromsound@gmail.com
1309 )",
1310 
1311     schemeFunctionCode =
1312 R"(
1313 tupletsCurvedBrackets = {
1314   % Use slur-stencil
1315   \override TupletBracket.stencil = #ly:slur::print
1316   %% Use 'thickness from Slur
1317   \override TupletBracket.thickness = #1.2
1318   %% 'control-points need to be set
1319   \override TupletBracket.control-points =
1320   #(lambda (grob)
1321      (let* ((x-pos (ly:grob-property grob 'X-positions))
1322             (pos (ly:grob-property grob 'positions))
1323             (x-ln (interval-length x-pos))
1324             (dir (ly:grob-property grob 'direction))
1325             ;; read out the height of the TupletBracket, may be
1326             ;; negative!
1327             (height (- (cdr pos) (car pos)))
1328             ;; height-corr is introduced because sometimes the shape
1329             ;; of the slur needs to be adjusted.
1330             ;; It is used in the 2nd/3rd control-point.
1331             ;; The value of 0.3 is found by trial and error
1332             (height-corr (* 0.3 dir height))
1333             (edge-height (ly:grob-property grob 'edge-height
1334                            '(0.7 . 0.7)))
1335             (pad 1.0))
1336        (list
1337         ;; first cp
1338         (cons
1339          (+ (car x-pos) 0.5)
1340          (- (+ (* dir pad) (+ (car pos) (* -1 dir
1341                                           (car edge-height))))
1342            (if (= dir -1)
1343                (if (> height 3)
1344                    (/ dir 2.0)
1345                    0.0)
1346                (if (< height -3)
1347                    (/ dir 2.0)
1348                    0.0))))
1349         ;; second cp
1350         (cons
1351          (+ (car x-pos) (* x-ln 1/4))
1352          (+ (* dir pad) (+ (car pos) (* dir (+ 0.5 height-corr)))))
1353         ;; third cp
1354         (cons
1355          (+ (car x-pos) (* x-ln 3/4))
1356          (+ (* dir pad) (+ (cdr pos) (* dir (- 0.5 height-corr)))))
1357         ;; fourth cp
1358         (cons
1359          (- (cdr x-pos) 0.5)
1360          (+ (* dir pad) (+ (cdr pos) (* -1 dir (cdr edge-height)))))
1361         )))
1362   \override TupletBracket.staff-padding = #' ()
1363   #(define (invert-direction x) (if (eq? UP
1364                                          (ly:tuplet-bracket::calc-direction x)) DOWN UP))
1365   % \override TupletBracket.direction = #invert-direction
1366 }
1367 )";
1368 
1369 #ifdef TRACE_OAH
1370   if (gLpsrOah->fTraceSchemeFunctions) {
1371     gLogOstream <<
1372       "Creating Scheme function '" << schemeFunctionName << "'" <<
1373       endl;
1374   }
1375 #endif
1376 
1377   // create the Scheme function
1378   S_lpsrSchemeFunction
1379     schemeFunction =
1380       lpsrSchemeFunction::create (
1381         1, // inputLineNumber, JMI ???
1382         schemeFunctionName,
1383         schemeFunctionDescription,
1384         schemeFunctionCode);
1385 
1386   // register it in the Scheme functions map
1387   fScoreSchemeFunctionsMap [schemeFunctionName] =
1388     schemeFunction;
1389 }
1390 
addAfterSchemeFunctionToScore()1391 void lpsrScore::addAfterSchemeFunctionToScore ()
1392 {
1393   string
1394     schemeFunctionName =
1395       "after",
1396 
1397     schemeFunctionDescription =
1398 R"(
1399 % A function to create events after given music.
1400 % Thanks to David Kastrup for the inspiration!
1401 )",
1402 
1403     schemeFunctionCode =
1404 R"(
1405 after =
1406 #(define-music-function (t e m) (ly:duration? ly:music? ly:music?)
1407    #{
1408      \context Bottom <<
1409        #m
1410        { \skip $t <> -\tweak extra-spacing-width #empty-interval $e }
1411      >>
1412    #})
1413 )";
1414 
1415 #ifdef TRACE_OAH
1416   if (gLpsrOah->fTraceSchemeFunctions) {
1417     gLogOstream <<
1418       "Creating Scheme function '" << schemeFunctionName << "'" <<
1419       endl;
1420   }
1421 #endif
1422 
1423   // create the Scheme function
1424   S_lpsrSchemeFunction
1425     schemeFunction =
1426       lpsrSchemeFunction::create (
1427         1, // inputLineNumber, JMI ???
1428         schemeFunctionName,
1429         schemeFunctionDescription,
1430         schemeFunctionCode);
1431 
1432   // register it in the Scheme functions map
1433   fScoreSchemeFunctionsMap [schemeFunctionName] =
1434     schemeFunction;
1435 }
1436 
addTempoRelationshipSchemeFunctionToScore()1437 void lpsrScore::addTempoRelationshipSchemeFunctionToScore ()
1438 {
1439   string
1440     schemeFunctionName =
1441       "tempoRelationship",
1442 
1443     schemeFunctionDescription =
1444 R"(
1445 % A function to create tempo relationships,
1446 % such as 'b8 [ b8 ]' = '\tuplet 3/2 { b4 b8 }' for swing.
1447 % See http://lsr.di.unimi.it/LSR/Item?id=204
1448 )",
1449 
1450     schemeFunctionCode =
1451       // add ! before ( and after ) since the code contains )"
1452 R"!(
1453 tempoRelationshipStaffReduce = #-3
1454 
1455 tempoRelationship =
1456 #(define-music-function (parser location label parenthesized musicI musicII)
1457    (string? boolean? ly:music? ly:music?)
1458    (let* (
1459            (left-paren (if parenthesized "(" ""))
1460            (right-paren (if parenthesized ")" ""))
1461            )
1462      #{
1463        \tempo \markup {
1464          \line \general-align #Y #DOWN {
1465            % 1st column in line
1466            $label
1467 
1468            % 2nd column in line
1469 
1470            $left-paren
1471 
1472            \score {
1473              \new Staff \with {
1474                % reduce the font size a la cue
1475                fontSize = #tempoRelationshipStaffReduce
1476                \override StaffSymbol.staff-space = #(magstep tempoRelationshipStaffReduce)
1477                % hide the staff lines
1478                \override StaffSymbol.line-count = #0
1479                % align horizontally
1480                \override VerticalAxisGroup.Y-extent = #'(-0.85 . 0)
1481              }
1482 
1483              {
1484                % \override Score.SpacingSpanner.common-shortest-duration = #(ly:make-moment 1/2) % super-tight
1485                % \override Score.SpacingSpanner.common-shortest-duration = #(ly:make-moment 1/4) % tight
1486                % \override Score.SpacingSpanner.common-shortest-duration = #(ly:make-moment 3/16) % even
1487                \override Score.SpacingSpanner.common-shortest-duration = #(ly:make-moment 5/32) % even
1488 
1489                % the left music
1490                \relative c' { \stemUp $musicI }
1491 
1492                % the equivalence sign
1493                \once \override Score.TextScript.Y-offset = #-0.4
1494                s4.^\markup{
1495                  \halign #-1 "="
1496                }
1497 
1498                % the right music
1499                \relative c' { \stemUp $musicII }
1500              }
1501 
1502              \layout {
1503                indent = 0
1504                \context {
1505                  \Staff
1506                  \remove "Clef_engraver"
1507                  \remove "Time_signature_engraver"
1508                }
1509              } % layout end
1510            } % score end
1511 
1512            $right-paren
1513 
1514          } % line end
1515        } % markup end
1516      #}))
1517 )!";
1518 
1519 #ifdef TRACE_OAH
1520   if (gLpsrOah->fTraceSchemeFunctions) {
1521     gLogOstream <<
1522       "Creating Scheme function '" << schemeFunctionName << "'" <<
1523       endl;
1524   }
1525 #endif
1526 
1527   // create the Scheme function
1528   S_lpsrSchemeFunction
1529     schemeFunction =
1530       lpsrSchemeFunction::create (
1531         1, // inputLineNumber, JMI ???
1532         schemeFunctionName,
1533         schemeFunctionDescription,
1534         schemeFunctionCode);
1535 
1536   // register it in the Scheme functions map
1537   fScoreSchemeFunctionsMap [schemeFunctionName] =
1538     schemeFunction;
1539 }
1540 
addDampMarkupToScore()1541 void lpsrScore::addDampMarkupToScore ()
1542 {
1543   string
1544     schemeFunctionName =
1545       "dampMarkup",
1546 
1547     schemeFunctionDescription =
1548 R"(
1549 % A function to create damp markups,
1550 )",
1551 
1552     schemeFunctionCode =
1553       // add ! before ( and after ) since the code contains )"
1554 R"!(
1555 damp = \markup {
1556 %  \scale #'(5 . 5)
1557   {
1558     \center-column {
1559       {
1560         \override #'(thickness . 1.8)
1561         \combine \draw-line #'(-1.5 . 0)
1562         \combine \draw-line #'(0 . -1.5)
1563         \combine \draw-line #'(0 . 1.5)
1564         \combine \draw-line #'(1.5 . 0)
1565         \draw-circle #0.8 #0.2 ##f
1566       }
1567     }
1568   }
1569 
1570 }
1571 )!";
1572 
1573 #ifdef TRACE_OAH
1574   if (gLpsrOah->fTraceSchemeFunctions) {
1575     gLogOstream <<
1576       "Creating Scheme function '" << schemeFunctionName << "'" <<
1577       endl;
1578   }
1579 #endif
1580 
1581   // create the Scheme function
1582   S_lpsrSchemeFunction
1583     schemeFunction =
1584       lpsrSchemeFunction::create (
1585         1, // inputLineNumber, JMI ???
1586         schemeFunctionName,
1587         schemeFunctionDescription,
1588         schemeFunctionCode);
1589 
1590   // register it in the Scheme functions map
1591   fScoreSchemeFunctionsMap [schemeFunctionName] =
1592     schemeFunction;
1593 }
1594 
addDampAllMarkupToScore()1595 void lpsrScore::addDampAllMarkupToScore ()
1596 {
1597   string
1598     schemeFunctionName =
1599       "dampAllMarkup",
1600 
1601     schemeFunctionDescription =
1602 R"(
1603 % A function to create damp all markups,
1604 )",
1605 
1606     schemeFunctionCode =
1607       // add ! before ( and after ) since the code contains )"
1608 R"!(
1609 dampAll = \markup
1610 %% do not use 'fontsize
1611 %\scale #'(5 . 5)
1612 {
1613   \combine \bold "O"
1614   \path #0.2
1615   #'((moveto -.4 .8)(lineto 2.2 .8)
1616       (closepath)
1617       (moveto .9 -.5)(lineto .9 2.1))
1618 }
1619 )!";
1620 
1621 #ifdef TRACE_OAH
1622   if (gLpsrOah->fTraceSchemeFunctions) {
1623     gLogOstream <<
1624       "Creating Scheme function '" << schemeFunctionName << "'" <<
1625       endl;
1626   }
1627 #endif
1628 
1629   // create the Scheme function
1630   S_lpsrSchemeFunction
1631     schemeFunction =
1632       lpsrSchemeFunction::create (
1633         1, // inputLineNumber, JMI ???
1634         schemeFunctionName,
1635         schemeFunctionDescription,
1636         schemeFunctionCode);
1637 
1638   // register it in the Scheme functions map
1639   fScoreSchemeFunctionsMap [schemeFunctionName] =
1640     schemeFunction;
1641 }
1642 
addWhiteNoteHeadsToScore()1643 void lpsrScore::addWhiteNoteHeadsToScore ()
1644 {
1645   string
1646     schemeFunctionName =
1647       "whiteNoteHeads",
1648 
1649     schemeFunctionDescription =
1650 R"(
1651 % A function to display note shorter than a quarter with white heads,
1652 % as in some ancient music scores
1653 )",
1654 
1655     schemeFunctionCode =
1656       // add ! before ( and after ) since the code contains )"
1657 R"!(
1658 whiteNoteHeads =
1659 #(define-music-function (music) (ly:music?)
1660    #{
1661      \temporary \override NoteHead.stencil = #ly:text-interface::print
1662      \temporary \override NoteHead.text = \markup {
1663        \musicglyph "noteheads.s1"
1664      }
1665      \omit \time 3/4
1666      \shiftDurations #1 #0 { #music }
1667      \omit \time 3/2
1668      \revert NoteHead.stencil
1669      \revert NoteHead.text
1670    #}
1671    )
1672 )!";
1673 
1674 #ifdef TRACE_OAH
1675   if (gLpsrOah->fTraceSchemeFunctions) {
1676     gLogOstream <<
1677       "Creating Scheme function '" << schemeFunctionName << "'" <<
1678       endl;
1679   }
1680 #endif
1681 
1682   // create the Scheme function
1683   S_lpsrSchemeFunction
1684     schemeFunction =
1685       lpsrSchemeFunction::create (
1686         1, // inputLineNumber, JMI ???
1687         schemeFunctionName,
1688         schemeFunctionDescription,
1689         schemeFunctionCode);
1690 
1691   // register it in the Scheme functions map
1692   fScoreSchemeFunctionsMap [schemeFunctionName] =
1693     schemeFunction;
1694 }
1695 
addBoxAroundNextBarNumberToScore()1696 void lpsrScore::addBoxAroundNextBarNumberToScore ()
1697 {
1698   string
1699     schemeFunctionName =
1700       "boxAroundNextBarNumber",
1701 
1702     schemeFunctionDescription =
1703 R"(
1704 % A macro to draw a box round the next bar number
1705 )",
1706 
1707     schemeFunctionCode =
1708       // add ! before ( and after ) since the code contains )"
1709 R"!(
1710 boxAroundNextBarNumber = {
1711   \once\override Score.BarNumber.font-size = 2
1712   \once\override Score.BarNumber.stencil =
1713   #(make-stencil-boxer 0.25 0.5 ly:text-interface::print)
1714 }
1715 )!";
1716 
1717 #ifdef TRACE_OAH
1718   if (gLpsrOah->fTraceSchemeFunctions) {
1719     gLogOstream <<
1720       "Creating Scheme function '" << schemeFunctionName << "'" <<
1721       endl;
1722   }
1723 #endif
1724 
1725   // create the Scheme function
1726   S_lpsrSchemeFunction
1727     schemeFunction =
1728       lpsrSchemeFunction::create (
1729         1, // inputLineNumber, JMI ???
1730         schemeFunctionName,
1731         schemeFunctionDescription,
1732         schemeFunctionCode);
1733 
1734   // register it in the Scheme functions map
1735   fScoreSchemeFunctionsMap [schemeFunctionName] =
1736     schemeFunction;
1737 }
1738 
addJazzChordsDisplayToScore()1739 void lpsrScore::addJazzChordsDisplayToScore ()
1740 {
1741   stringstream s;
1742 
1743   s <<
1744 R"###(% Exception music is chords with markups
1745 #(define (lower-extension pitch chbass)
1746    "Return lowered markup for pitch note name."
1747    #{
1748      \markup \raise #-1.9 \halign #0.2
1749      #(note-name->markup pitch chbass)
1750    #})
1751 
1752 chExceptionMusic = {)###" <<
1753       endl;
1754 
1755     if (gLilypondOah->fJazzChordsDisplay) {
1756       s <<
1757         gLilypondOah->fJazzChordsDisplayLilypondcode;
1758     }
1759 
1760   list<pair<string, string> >&
1761     chordsDisplayList =
1762       gLilypondOah->fChordsDisplayList;
1763 
1764   if (chordsDisplayList.size ()) {
1765     list<pair<string, string> >::const_iterator
1766       iBegin = chordsDisplayList.begin (),
1767       iEnd   = chordsDisplayList.end (),
1768       i      = iBegin;
1769 
1770     for ( ; ; ) {
1771       s <<
1772         gTab <<
1773         (*i).first <<
1774         "1-\\markup { " <<
1775         (*i).second <<
1776         " }" <<
1777         endl;
1778       if (++i == iEnd) break;
1779   //     s << endl;
1780     } // for
1781   }
1782 
1783   s <<
1784     "}" <<
1785     endl <<
1786     endl <<
1787 R"###(% Convert music to list and prepend to existing exceptions.
1788 chExceptions = #( append
1789                   ( sequential-music-to-chord-exceptions chExceptionMusic #t)
1790                   ignatzekExceptions))###" <<
1791     endl <<
1792     endl;
1793 
1794   string
1795     schemeFunctionName =
1796       "jazzChordsDisplay",
1797 
1798   schemeFunctionDescription =
1799 R"(
1800 % A function to display the chords in a common Jazz way using \chordmode
1801 )",
1802 
1803   schemeFunctionCode = s.str ();
1804 
1805 #ifdef TRACE_OAH
1806   if (gLpsrOah->fTraceSchemeFunctions) {
1807     gLogOstream <<
1808       "Creating Scheme function '" << schemeFunctionName << "'" <<
1809       endl;
1810   }
1811 #endif
1812 
1813   // create the Scheme function
1814   S_lpsrSchemeFunction
1815     schemeFunction =
1816       lpsrSchemeFunction::create (
1817         1, // inputLineNumber, JMI ???
1818         schemeFunctionName,
1819         schemeFunctionDescription,
1820         schemeFunctionCode);
1821 
1822   // register it in the Scheme functions map
1823   fScoreSchemeFunctionsMap [schemeFunctionName] =
1824     schemeFunction;
1825 }
1826 
addColoredLedgerLinesToScore()1827 void lpsrScore::addColoredLedgerLinesToScore ()
1828 {
1829   stringstream s;
1830 
1831   s <<
1832 R"###(% there is ony one ledger line spanner/grob/stencil
1833 % produced for each musical system on the page (!)
1834 % see: ledger-line-spanner.cc for c++ code for ly:ledger-line-spanner::print
1835 
1836 #(define (MyLedgerLineSpannerPrint grob)
1837    (let*
1838     ((stil (ly:ledger-line-spanner::print grob))
1839      ;; (ifaces (ly:grob-interfaces grob))
1840 
1841      (noteheads (ly:grob-object grob 'note-heads))
1842      (new-stil (box-stencil (stencil-with-color stil  (rgb-color )###";
1843 
1844   s <<
1845     gLilypondOah->fLedgerLinesRGBColor.getR () <<
1846     " " <<
1847     gLilypondOah->fLedgerLinesRGBColor.getG () <<
1848     " " <<
1849     gLilypondOah->fLedgerLinesRGBColor.getB ();
1850 
1851   s <<
1852 R"###()) 0.1 1))
1853      )
1854 
1855     (display "noteheads: ")(display noteheads)(newline)(newline)
1856     ;; (display (ly:grob-properties grob))(newline)(newline)
1857     ;; (display ifaces)(newline)(newline)
1858 
1859     new-stil))
1860 )###";
1861 
1862   string
1863     schemeFunctionName =
1864       "coloredLedgerLines",
1865 
1866   schemeFunctionDescription =
1867 R"(
1868 % A function to color the staves ledger lines other that black
1869 )",
1870 
1871   schemeFunctionCode = s.str ();
1872 
1873 #ifdef TRACE_OAH
1874   if (gLpsrOah->fTraceSchemeFunctions) {
1875     gLogOstream <<
1876       "Creating Scheme function '" << schemeFunctionName << "'" <<
1877       endl;
1878   }
1879 #endif
1880 
1881   // create the Scheme function
1882   S_lpsrSchemeFunction
1883     schemeFunction =
1884       lpsrSchemeFunction::create (
1885         1, // inputLineNumber, JMI ???
1886         schemeFunctionName,
1887         schemeFunctionDescription,
1888         schemeFunctionCode);
1889 
1890   // register it in the Scheme functions map
1891   fScoreSchemeFunctionsMap [schemeFunctionName] =
1892     schemeFunction;
1893 }
1894 
1895 /* JMI
1896 void lpsrScore::appendVoiceUseToStoreCommand (S_msrVoice voice)
1897 {
1898   S_lpsrUseVoiceCommand
1899     useVoiceCommand =
1900       lpsrUseVoiceCommand::create (
1901         fInputLineNumber,
1902         voice);
1903 
1904   fScoreBlock->
1905     appendVoiceUseToParallelMusicBLock (useVoiceCommand);
1906 }
1907 
1908 void lpsrScore::appendLyricsUseToStoreCommand (S_msrStanza stanza)
1909 {
1910   S_lpsrNewLyricsBlock
1911     newLyricsCommand =
1912       lpsrNewLyricsBlock::create (
1913         fInputLineNumber,
1914         stanza,
1915         stanza->getStanzaVoiceUpLink ());
1916 
1917   fScoreBlock->
1918     appendLyricsUseToParallelMusicBLock (newLyricsCommand);
1919 }
1920 */
1921 
acceptIn(basevisitor * v)1922 void lpsrScore::acceptIn (basevisitor* v)
1923 {
1924 #ifdef TRACE_OAH
1925   if (gLpsrOah->fTraceLpsrVisitors) {
1926     gLogOstream <<
1927       "% ==> lpsrScore::acceptIn ()" <<
1928       endl;
1929   }
1930 #endif
1931 
1932   if (visitor<S_lpsrScore>*
1933     p =
1934       dynamic_cast<visitor<S_lpsrScore>*> (v)) {
1935         S_lpsrScore elem = this;
1936 
1937 #ifdef TRACE_OAH
1938         if (gLpsrOah->fTraceLpsrVisitors) {
1939           gLogOstream <<
1940             "% ==> Launching lpsrScore::visitStart ()" <<
1941             endl;
1942         }
1943 #endif
1944         p->visitStart (elem);
1945   }
1946 }
1947 
acceptOut(basevisitor * v)1948 void lpsrScore::acceptOut (basevisitor* v)
1949 {
1950 #ifdef TRACE_OAH
1951   if (gLpsrOah->fTraceLpsrVisitors) {
1952     gLogOstream <<
1953       "% ==> lpsrScore::acceptOut ()" <<
1954       endl;
1955   }
1956 #endif
1957 
1958   if (visitor<S_lpsrScore>*
1959     p =
1960       dynamic_cast<visitor<S_lpsrScore>*> (v)) {
1961         S_lpsrScore elem = this;
1962 
1963 #ifdef TRACE_OAH
1964         if (gLpsrOah->fTraceLpsrVisitors) {
1965           gLogOstream <<
1966             "% ==> Launching lpsrScore::visitEnd ()" <<
1967             endl;
1968         }
1969 #endif
1970         p->visitEnd (elem);
1971   }
1972 }
1973 
browseData(basevisitor * v)1974 void lpsrScore::browseData (basevisitor* v)
1975 {
1976 #ifdef TRACE_OAH
1977   if (gLpsrOah->fTraceLpsrVisitors) {
1978     gLogOstream <<
1979       "% ==> lpsrScore::browseData ()" <<
1980       endl;
1981   }
1982 #endif
1983 
1984   {
1985     // browse the score LilyPond version
1986     msrBrowser<lpsrVarValAssoc> browser (v);
1987     browser.browse (*fLilypondVersion);
1988   }
1989 
1990   if (fInputSourceNameComment) {
1991     // browse the input source name comment
1992     msrBrowser<lpsrComment> browser (v);
1993     browser.browse (*fInputSourceNameComment);
1994   }
1995 
1996   if (fTranslationDateComment) {
1997     // browse the translation date comment
1998     msrBrowser<lpsrComment> browser (v);
1999     browser.browse (*fTranslationDateComment);
2000   }
2001 
2002   if (fCommandLineAsSuppliedComment) {
2003     // browse the command line as supplied comment
2004     msrBrowser<lpsrComment> browser (v);
2005     browser.browse (*fCommandLineAsSuppliedComment);
2006   }
2007 
2008   if (fCommandLineLongOptionsComment) {
2009     // browse the command line long options comment
2010     msrBrowser<lpsrComment> browser (v);
2011     browser.browse (*fCommandLineLongOptionsComment);
2012   }
2013 
2014   if (fCommandLineShortOptionsComment) {
2015     // browse the command line short options comment
2016     msrBrowser<lpsrComment> browser (v);
2017     browser.browse (*fCommandLineShortOptionsComment);
2018   }
2019 
2020   {
2021     // browse the score global staff size
2022     msrBrowser<lpsrSchemeVariable> browser (v);
2023     browser.browse (*fScoreGlobalStaffSizeSchemeVariable);
2024   }
2025 
2026   {
2027     // browse the Scheme function map
2028     for (
2029       map<string, S_lpsrSchemeFunction>::const_iterator i =
2030         fScoreSchemeFunctionsMap.begin ();
2031       i != fScoreSchemeFunctionsMap.end ();
2032       i++
2033   ) {
2034       // browse the Scheme function
2035       msrBrowser<lpsrSchemeFunction> browser (v);
2036       browser.browse (*(*i).second);
2037     } // for
2038   }
2039 
2040   {
2041     // browse the score header
2042     msrBrowser<lpsrHeader> browser (v);
2043     browser.browse (*fScoreHeader);
2044   }
2045 
2046   {
2047     // browse the score paper
2048     msrBrowser<lpsrPaper> browser (v);
2049     browser.browse (*fScorePaper);
2050   }
2051 
2052   if (fScoreLayout) { // JMI
2053     // browse the score layout
2054     msrBrowser<lpsrLayout> browser (v);
2055     browser.browse (*fScoreLayout);
2056   }
2057 
2058   {
2059     // browse the myBreakIsBreak assoc
2060     msrBrowser<lpsrVarValAssoc> browser (v);
2061     browser.browse (*fMyBreakIsBreakAssoc);
2062   }
2063   {
2064     // browse the myBreakIsEmpty assoc
2065     msrBrowser<lpsrVarValAssoc> browser (v);
2066     browser.browse (*fMyBreakIsEmptyAssoc);
2067   }
2068 
2069   {
2070     // browse the myPageBreakIsPageBreak assoc
2071     msrBrowser<lpsrVarValAssoc> browser (v);
2072     browser.browse (*fMyPageBreakIsPageBreakAssoc);
2073   }
2074   {
2075     // browse the myPageBreakIsEmpty assoc
2076     msrBrowser<lpsrVarValAssoc> browser (v);
2077     browser.browse (*fMyPageBreakIsEmptyAssoc);
2078   }
2079 
2080   if (fScoreGlobalAssoc) {
2081     // browse the 'global' assoc
2082     msrBrowser<lpsrVarValAssoc> browser (v);
2083     browser.browse (*fScoreGlobalAssoc);
2084   }
2085 
2086   {
2087     // browse the voices and stanzas list
2088     for (
2089       list<S_msrElement>::const_iterator i = fScoreElementsList.begin ();
2090       i != fScoreElementsList.end ();
2091       i++
2092     ) {
2093       // browse the element
2094       msrBrowser<msrElement> browser (v);
2095       browser.browse (*(*i));
2096     } // for
2097   }
2098 
2099   {
2100     // browse the score blocks list
2101     for (
2102       list<S_lpsrBookBlock>::const_iterator i = fScoreBookBlocksList.begin ();
2103       i != fScoreBookBlocksList.end ();
2104       i++
2105     ) {
2106       // browse the element
2107       msrBrowser<lpsrBookBlock> browser (v);
2108       browser.browse (*(*i));
2109     } // for
2110   }
2111 
2112 #ifdef TRACE_OAH
2113   if (gLpsrOah->fTraceLpsrVisitors) {
2114     gLogOstream <<
2115       "% <== lpsrScore::browseData ()" <<
2116       endl;
2117   }
2118 #endif
2119 }
2120 
print(ostream & os) const2121 void lpsrScore::print (ostream& os) const
2122 {
2123   os <<
2124     "LPSR Score" <<
2125     endl <<
2126     endl;
2127 
2128   gIndenter++;
2129 
2130   // print the MSR structure (without the voices)
2131   fMsrScore->
2132     printSummary (os);
2133   os << endl;
2134 
2135   // are some Scheme functions needed?
2136   const int fieldWidth = 42;
2137 
2138   os << left <<
2139     setw (fieldWidth) <<
2140     "TongueSchemeFunctionIsNeeded" << " : " <<
2141     booleanAsString (
2142       fTongueSchemeFunctionIsNeeded) <<
2143     endl <<
2144     setw (fieldWidth) <<
2145     "EditorialAccidentalSchemeFunctionIsNeeded" << " : " <<
2146     booleanAsString (
2147       fEditorialAccidentalSchemeFunctionIsNeeded) <<
2148     endl <<
2149     endl;
2150 
2151   // print LPSR basic information
2152   os <<
2153     fLilypondVersion <<
2154     endl <<
2155 
2156     fScoreGlobalStaffSizeSchemeVariable <<
2157     endl <<
2158 
2159     fScoreHeader <<
2160     // no endl here
2161 
2162     fScorePaper <<
2163     endl <<
2164 
2165     fScoreLayout <<
2166     endl;
2167 
2168 // myBreakAssoc,myPageBreakAssoc globalAssoc? JMI
2169 
2170   // print the voices and stanzas
2171   if (fScoreElementsList.size ()) {
2172     list<S_msrElement>::const_iterator
2173       iBegin = fScoreElementsList.begin (),
2174       iEnd   = fScoreElementsList.end (),
2175       i      = iBegin;
2176     for ( ; ; ) {
2177       os << (*i);
2178       if (++i == iEnd) break;
2179       os << endl;
2180     } // for
2181 
2182     os << endl;
2183   }
2184 
2185   // print the book blocks
2186   if (fScoreBookBlocksList.size ()) {
2187     list<S_lpsrBookBlock>::const_iterator
2188       iBegin = fScoreBookBlocksList.begin (),
2189       iEnd   = fScoreBookBlocksList.end (),
2190       i      = iBegin;
2191     for ( ; ; ) {
2192       os << (*i);
2193       if (++i == iEnd) break;
2194       os << endl;
2195     } // for
2196 
2197     os << endl;
2198   }
2199 
2200   gIndenter--;
2201 }
2202 
operator <<(ostream & os,const S_lpsrScore & scr)2203 ostream& operator<< (ostream& os, const S_lpsrScore& scr)
2204 {
2205   scr->print (os);
2206   return os;
2207 }
2208 
2209 
2210 }
2211