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