Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0338f1329b |
No files matched your search
+1
-1
@@ -1,8 +1,8 @@
|
||||
# ---> Lilypond
|
||||
*.pdf
|
||||
*.cho
|
||||
*.ps
|
||||
*.midi
|
||||
*.mid
|
||||
*.log
|
||||
*~
|
||||
|
||||
@@ -21,28 +21,15 @@
|
||||
)))))
|
||||
(scm-load "resolve_inherits.scm")
|
||||
(scm-load "yaml_parser.scm")))
|
||||
#(define AUTHOR_DATA (if (defined? 'AUTHOR_DATA) AUTHOR_DATA (parse-yml-file "../../lilypond-song-includes/data/authors.yml")))
|
||||
#(define SONG_DATA (if (defined? 'SONG_DATA) SONG_DATA (parse-yml-file "../../lilypond-song-includes/data/songs.yml")))
|
||||
|
||||
#(define (song-includes-data-path filename)
|
||||
(string-join
|
||||
(list
|
||||
(dirname (dirname (dirname (dirname (current-filename)))))
|
||||
"lilypond-song-includes"
|
||||
"data"
|
||||
filename)
|
||||
file-name-separator-string))
|
||||
#(define AUTHOR_DATA (if (defined? 'AUTHOR_DATA) AUTHOR_DATA (parse-yml-file (song-includes-data-path "authors.yml"))))
|
||||
#(define SONG_DATA (if (defined? 'SONG_DATA) SONG_DATA (parse-yml-file (song-includes-data-path "songs.yml"))))
|
||||
|
||||
\include #(if (ly:version? < '(2 27 0)) "compat_lilypond_2_26.ily" "../void.ily")
|
||||
\include "merge_rests_engraver_override.ily"
|
||||
\include "basic_format_and_style_settings.ily"
|
||||
\include "eps_file_from_song_dir.ily"
|
||||
\include "embedded_songs.ily"
|
||||
\include "title_with_category_images.ily"
|
||||
\include "chord_settings.ily"
|
||||
\include "chordpro.ily"
|
||||
\include "transposition.ily"
|
||||
\include "markup_tag_groups_hack.ily"
|
||||
\include "verses_with_chords.ily"
|
||||
\include "arrows_in_scores.ily"
|
||||
\include "swing_style.ily"
|
||||
@@ -56,10 +43,7 @@ HEADER = {}
|
||||
MUSIC = {}
|
||||
TEXT = \markuplist {}
|
||||
TEXT_PAGES = #f
|
||||
EMBEDDED_SONGS = #'()
|
||||
|
||||
verseChords = {}
|
||||
firstVoice = {}
|
||||
global = {}
|
||||
|
||||
\resetTagGroups
|
||||
@@ -29,11 +29,6 @@
|
||||
(if (null? stanzanumbers)
|
||||
refString
|
||||
(ly:format refStringWithNumbers (string-join (map (lambda (stanzanumber) (ly:format "~a" stanzanumber)) stanzanumbers) ", ")))))
|
||||
bridgeMarkupFormatter = #(lambda (layout props stanzanumbers)
|
||||
(interpret-markup layout props
|
||||
(if (null? stanzanumbers)
|
||||
bridgeString
|
||||
(ly:format bridgeStringWithNumbers (string-join (map (lambda (stanzanumber) (ly:format "~a" stanzanumber)) stanzanumbers) ", ")))))
|
||||
}
|
||||
|
||||
generalLayout = \layout {
|
||||
@@ -54,11 +49,8 @@ generalLayout = \layout {
|
||||
\context {
|
||||
\Score
|
||||
\remove "Bar_number_engraver"
|
||||
\remove "Metronome_mark_engraver"
|
||||
\RemoveEmptyStaves
|
||||
\override VerticalAxisGroup.remove-first = ##t
|
||||
\numericTimeSignature
|
||||
rehearsalMarkFormatter = #format-mark-box-alphabet
|
||||
\overrideTimeSignatureSettings
|
||||
4/4 % timeSignatureFraction
|
||||
1/4 % baseMomentFraction
|
||||
@@ -86,27 +78,6 @@ generalLayout = \layout {
|
||||
}
|
||||
}
|
||||
|
||||
#(define (customized-layout base-layout)
|
||||
(let
|
||||
((custom-size (ly:output-def-lookup base-layout 'size #f)))
|
||||
(if custom-size (layout-set-staff-size custom-size))))
|
||||
|
||||
% Scores in Markups (z.B. inline-score) kopieren ihr \layout schon beim Parsen,
|
||||
% also bevor customized-layout greift. Deshalb nachträglich anpassen.
|
||||
#(define (customize-embedded-score-layouts! obj)
|
||||
(cond
|
||||
((ly:score? obj)
|
||||
(for-each
|
||||
(lambda (def)
|
||||
(let ((custom-size (ly:output-def-lookup def 'size #f))
|
||||
(scope (ly:output-def-scope def)))
|
||||
(if custom-size
|
||||
(layout-set-absolute-staff-size-in-module scope (* custom-size (eval 'pt scope))))))
|
||||
(ly:score-output-defs obj)))
|
||||
((pair? obj)
|
||||
(customize-embedded-score-layouts! (car obj))
|
||||
(customize-embedded-score-layouts! (cdr obj)))))
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%% kleine Helferlein:
|
||||
|
||||
@@ -155,129 +126,74 @@ romanStanza =
|
||||
#(define-music-function (parser location) ()
|
||||
#{ \override StanzaNumber.style = #'roman #})
|
||||
|
||||
#(define (number-or-number-list? x) (or (number? x) (number-list? x)))
|
||||
|
||||
% "1,4" -> (1 4); Einträge, die keine Zahl sind, bleiben Strings ("1b,2b" -> ("1b" "2b"))
|
||||
#(define (stanza-numbers-from-string str)
|
||||
(map (lambda (s) (or (string->number s) s))
|
||||
(remove string-null? (map string-trim-both (string-split str #\,)))))
|
||||
|
||||
% Kein number? hier, sonst kann der Parser 1,4 nicht mehr als Liste lesen
|
||||
#(define (stanza-numbers? x) (or (number-list? x) (string? x)))
|
||||
|
||||
override-stanza =
|
||||
#(define-music-function (stanzanumbers) (number-or-number-list?)
|
||||
#(define-music-function (parser location stanzanumbers) (number-list?)
|
||||
#{
|
||||
\once \override StanzaNumber.details.custom-stanzanumber-override = #(if (number? stanzanumbers) (list stanzanumbers) stanzanumbers)
|
||||
\once \override StanzaNumber.details.custom-stanzanumber-override = #stanzanumbers
|
||||
#}
|
||||
)
|
||||
|
||||
#(define (romanize-stanza-numbers numbers style)
|
||||
(if (eq? style 'roman)
|
||||
(map (lambda (n) (if (number? n) (format #f "~@r" n) n)) numbers)
|
||||
numbers))
|
||||
|
||||
#(define (format-stanza-numbers numbers style)
|
||||
(string-join
|
||||
(map (lambda (n) (format #f stanzaFormat n)) (romanize-stanza-numbers numbers style))
|
||||
", "))
|
||||
|
||||
% Strophennummer, die erst beim Setzen aus den Eigenschaften des StanzaNumber-Grobs gebaut wird
|
||||
% (details.custom-stanza-type, details.custom-stanza-numbers, style, details.custom-inline-text).
|
||||
% So können \fstanza, \ref, \bridge und \repStartWithTag im selben Zeitschritt kombiniert werden.
|
||||
#(define-markup-command (formatted-stanza layout props) ()
|
||||
#:properties ((details '()) (style #f))
|
||||
(let* ((realstanza (ly:assoc-get 'custom-realstanza details #f))
|
||||
(type (ly:assoc-get 'custom-stanza-type details 'verse))
|
||||
(numbers (ly:assoc-get 'custom-stanzanumber-override details
|
||||
(ly:assoc-get 'custom-stanza-numbers details '())))
|
||||
(inline-text (ly:assoc-get 'custom-inline-text details #f))
|
||||
(inline-direction (ly:assoc-get 'custom-inline-direction details CENTER))
|
||||
(rep-start (and inline-text (eqv? inline-direction LEFT)))
|
||||
(roman-numbers (romanize-stanza-numbers numbers style))
|
||||
(stanza-stencil
|
||||
(and realstanza
|
||||
(case type
|
||||
((ref) ((ly:output-def-lookup layout 'refMarkupFormatter) layout props roman-numbers))
|
||||
((bridge) ((ly:output-def-lookup layout 'bridgeMarkupFormatter) layout props roman-numbers))
|
||||
(else (interpret-markup layout props (format-stanza-numbers numbers style))))))
|
||||
(padded-stanza-stencil
|
||||
(and stanza-stencil
|
||||
(interpret-markup layout props (make-pad-left-markup 1 (make-stencil-markup stanza-stencil))))))
|
||||
(if rep-start
|
||||
(interpret-markup layout props
|
||||
(make-concat-markup
|
||||
(append
|
||||
(if padded-stanza-stencil (list (make-stencil-markup padded-stanza-stencil) (make-hspace-markup 1)) '())
|
||||
(list (make-override-markup '(font-series . normal) inline-text)))))
|
||||
(or padded-stanza-stencil empty-stencil))))
|
||||
|
||||
#(define (formatted-stanza-music type stanzanumbers)
|
||||
#(define (stanza . stanzanumbers)
|
||||
#{
|
||||
\once \override StanzaNumber.details.custom-realstanza = ##t % set this to signal that there is a real stanza and no repeat signs
|
||||
\once \override StanzaNumber.details.custom-stanza-type = #type
|
||||
\once \override StanzaNumber.details.custom-stanza-numbers = #stanzanumbers
|
||||
\stanza \markup \formatted-stanza
|
||||
#})
|
||||
|
||||
% \fstanza 1 -> "1."
|
||||
% \fstanza 1,4 -> "1., 4." (nur im Notenmodus, z.B. \chordverse { \fstanza 1,4 } ...)
|
||||
% \fstanza "1,4" -> "1., 4." (auch im \lyricmode, dort versteht LilyPond 1,4 nicht als Liste)
|
||||
fstanza =
|
||||
#(define-music-function (stanzanumbers) (stanza-numbers?)
|
||||
(formatted-stanza-music 'verse
|
||||
(if (string? stanzanumbers) (stanza-numbers-from-string stanzanumbers) stanzanumbers)))
|
||||
\applyContext
|
||||
#(lambda (context)
|
||||
(let* ((stanzanumbers-override (ly:assoc-get 'custom-stanzanumber-override (ly:assoc-get 'details (ly:context-grob-definition context 'StanzaNumber) '()) #f))
|
||||
(stanza-style (ly:assoc-get 'style (ly:context-grob-definition context 'StanzaNumber)))
|
||||
(stanza-format (lambda (stanzanumber) (format #f (if (eq? stanza-style 'roman) romanStanzaFormat stanzaFormat) stanzanumber))))
|
||||
(ly:context-set-property! context 'stanza
|
||||
(string-join (map stanza-format
|
||||
(if stanzanumbers-override stanzanumbers-override stanzanumbers))
|
||||
", "))))
|
||||
#}
|
||||
)
|
||||
|
||||
ref =
|
||||
#(define-music-function (stanzanumbers lyrics) ((number-list? (list)) ly:music?)
|
||||
#{ \lyricmode {
|
||||
#(formatted-stanza-music 'ref stanzanumbers)
|
||||
#lyrics
|
||||
}
|
||||
#}
|
||||
)
|
||||
|
||||
bridge =
|
||||
#(define-music-function (stanzanumbers lyrics) ((number-list? (list)) ly:music?)
|
||||
#{ \lyricmode {
|
||||
#(formatted-stanza-music 'bridge stanzanumbers)
|
||||
\once \override StanzaNumber.details.custom-realstanza = ##t % set this to signal that there is a real stanza and no repeat signs
|
||||
\set stanza = #(make-on-the-fly-markup (lambda (layout props m) ((ly:output-def-lookup layout 'refMarkupFormatter) layout props stanzanumbers)) (make-null-markup))
|
||||
#lyrics
|
||||
}
|
||||
#}
|
||||
)
|
||||
|
||||
% prints a repStart Sign as stanza if the tag 'repeats is kept.
|
||||
% if there is a stanza set by \fstanza in the same moment, \formatted-stanza prints both.
|
||||
% Sets custom-inline-text for ChordPro export so it can collect the repeat sign separately
|
||||
repStartWithTag =
|
||||
#(define-music-function () ()
|
||||
#{ \lyricmode {
|
||||
% if there was a stanza already set by the stanza function with StanzaNumber.details.custom-realstanza = ##t we set that also as stanza.
|
||||
repStartWithTag = \lyricmode {
|
||||
\tag #'repeats {
|
||||
\once \override StanzaNumber.details.custom-inline-text = \repStart
|
||||
\once \override StanzaNumber.details.custom-inline-direction = #LEFT
|
||||
\stanza \markup \formatted-stanza
|
||||
\applyContext
|
||||
#(lambda (context)
|
||||
(let ((lastStanza (ly:context-property context 'stanza))
|
||||
(printLastStanza (ly:assoc-get 'custom-realstanza (ly:assoc-get 'details (ly:context-grob-definition context 'StanzaNumber) '()) #f))
|
||||
(stanzaFontSeries (ly:assoc-get 'font-series (ly:context-grob-definition context 'StanzaNumber) 'normal)))
|
||||
(ly:context-set-property! context 'stanza
|
||||
(make-concat-markup
|
||||
(if printLastStanza
|
||||
(list (make-override-markup `(font-series . ,stanzaFontSeries) lastStanza) (make-hspace-markup 1) repStart)
|
||||
(list repStart)
|
||||
)))))
|
||||
\once \override StanzaNumber.font-series = #'normal
|
||||
}
|
||||
} #})
|
||||
}
|
||||
|
||||
repStopWithTag = \lyricmode {
|
||||
\tag #'repeats {
|
||||
\once \override StanzaNumber.details.custom-inline-text = \repStop
|
||||
\once \override StanzaNumber.details.custom-inline-direction = #RIGHT
|
||||
\once \override StanzaNumber.font-series = #'normal
|
||||
\once \override StanzaNumber.direction = 1
|
||||
\stanza \markup { \pad-x-right #1 \repStop }
|
||||
\set stanza = \markup { \repStop }
|
||||
}
|
||||
}
|
||||
|
||||
rightHyphen = \lyricmode {
|
||||
\once \override StanzaNumber.font-series = #'normal
|
||||
\once \override StanzaNumber.direction = 1
|
||||
\stanza "-"
|
||||
\set stanza = "-"
|
||||
}
|
||||
|
||||
leftHyphen = \lyricmode {
|
||||
\once \override StanzaNumber.font-series = #'normal
|
||||
\stanza "-"
|
||||
\set stanza = "-"
|
||||
}
|
||||
|
||||
multiVerseSkips =
|
||||
@@ -343,23 +259,9 @@ rufWithMarkup =
|
||||
\lyricmode {
|
||||
\once \override StanzaNumber.font-series = #'normal
|
||||
\once \override StanzaNumber.direction = 1
|
||||
\stanza #text
|
||||
\set stanza = #text
|
||||
}
|
||||
#})
|
||||
ruf =
|
||||
#(define-music-function (text) (string?)
|
||||
(rufWithMarkup (make-ruf-style-markup text)))
|
||||
|
||||
underlineOn =
|
||||
#(define-music-function () ()
|
||||
#{
|
||||
\override LyricText.stencil =
|
||||
#(lambda (grob)
|
||||
(grob-interpret-markup grob (make-underline-markup (ly:grob-property grob 'text))))
|
||||
#})
|
||||
|
||||
underlineOff =
|
||||
#(define-music-function () ()
|
||||
#{
|
||||
\revert LyricText.stencil
|
||||
#})
|
||||
(rufWithMarkup (make-ruf-style-markup text)))
|
||||
@@ -40,19 +40,34 @@ shiftChords = #(define-music-function (parser location xshift chords) (number? l
|
||||
|
||||
altChord =
|
||||
#(define-music-function (parser location mainchord altchord) (ly:music? ly:music?)
|
||||
(let* ((chord-name (lambda (in-pitches bass inversion context)
|
||||
(make-line-markup (list
|
||||
(ignatzek-chord-names in-pitches bass inversion context)
|
||||
(make-hspace-markup 0.3)
|
||||
(parenthesis-ignatzek-chord-names (music-pitches (transposable (cons (car (music-pitches mainchord)) (car in-pitches)) (music-clone altchord))) '() '() context)
|
||||
))
|
||||
)))
|
||||
(let* ((remove-point-and-click
|
||||
(lambda (grob)
|
||||
(ly:grob-set-property! grob 'cause #f)
|
||||
(ly:text-interface::print grob)))
|
||||
(chord-name (lambda (in-pitches bass inversion context) #{
|
||||
\markup {
|
||||
\translate #'(-0.5 . 0)
|
||||
\score {
|
||||
\chords { \transposable #(cons (car (music-pitches mainchord)) (car in-pitches)) { #(music-clone mainchord) \klamm #(music-clone altchord) } }
|
||||
\layout {
|
||||
\LAYOUT
|
||||
\context {
|
||||
\ChordNames
|
||||
\override ChordName.extra-spacing-width = #'(0 . 0.3)
|
||||
\override ChordName.stencil = #remove-point-and-click
|
||||
}
|
||||
\context {
|
||||
\Score
|
||||
\override SpacingSpanner.spacing-increment = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}#})))
|
||||
#{
|
||||
\once \set chordNameFunction = #chord-name
|
||||
#mainchord
|
||||
#}))
|
||||
|
||||
|
||||
% Akkorde werden so transponiert, dass sie passen, wenn man mit Kapo im angegebenen Bund spielt
|
||||
capoTranspose =
|
||||
#(define-music-function (fret chords) (number? ly:music?)
|
||||
@@ -65,8 +80,41 @@ capoTranspose =
|
||||
(ly:make-pitch 0 0)
|
||||
chords))
|
||||
|
||||
% kleine Mollakkorde und Alteration ausgeschrieben
|
||||
#(define (note-name->german-markup-nosym pitch lowercase?)
|
||||
(define (pitch-alteration-semitones pitch) (inexact->exact (round (* (ly:pitch-alteration pitch) 2))))
|
||||
(define (accidental->markup alteration name)
|
||||
(if (= alteration 0)
|
||||
(make-line-markup (list empty-markup))
|
||||
(if (= alteration FLAT)
|
||||
(if (equal? name "B")
|
||||
""
|
||||
; (make-line-markup (list (make-hspace-markup 0.2)
|
||||
; (make-tiny-markup (make-raise-markup 1.2
|
||||
; (make-musicglyph-markup (assoc-get alteration standard-alteration-glyph-name-alist ""))))
|
||||
; ))
|
||||
(if (or (equal? name "E") (equal? name "A")) "s" "es"))
|
||||
"is")
|
||||
))
|
||||
(define (conditional-string-downcase str condition)
|
||||
(if condition (string-downcase str) str))
|
||||
|
||||
(let* ((name (ly:pitch-notename pitch))
|
||||
(alt-semitones (pitch-alteration-semitones pitch))
|
||||
(n-a (if (member (cons name alt-semitones) `((6 . -1) (6 . -2)))
|
||||
(cons 7 (+ 0 alt-semitones))
|
||||
(cons name alt-semitones))))
|
||||
(make-line-markup
|
||||
(list
|
||||
(make-simple-markup
|
||||
(conditional-string-downcase
|
||||
(vector-ref #("C" "D" "E" "F" "G" "A" "H" "B") (car n-a))
|
||||
lowercase?))
|
||||
(accidental->markup (/ (cdr n-a) 2) (vector-ref #("C" "D" "E" "F" "G" "A" "H" "B") (car n-a)) ))))
|
||||
)
|
||||
|
||||
% additional bass notes should get uppercased
|
||||
#(define (bassnote-name->german-markup-nosym pitch lowercase?)((chord-name:name-markup 'deutsch) pitch #f))
|
||||
#(define (bassnote-name->german-markup-nosym pitch lowercase?)(note-name->german-markup-nosym pitch #f))
|
||||
|
||||
defaultChordPrintings = {
|
||||
<c g>-\markup { \super "5" }
|
||||
@@ -109,15 +157,15 @@ generalLayout = \layout {
|
||||
\generalLayout
|
||||
\context {
|
||||
\ChordNames
|
||||
\semiGermanChords
|
||||
\override ChordName.font-size = \songScoreChordFontSize
|
||||
\override ChordName.font-series = \songChordFontSeries
|
||||
\override ChordName.font-family = #'serif
|
||||
chordNameLowercaseMinor = ##t
|
||||
chordChanges = ##t
|
||||
chordRootNamer = #(chord-name:name-markup 'deutsch)
|
||||
% eigenen chordRootNamer damit F# = Fis und Gb = Ges (also alteration ausgeschrieben)
|
||||
chordRootNamer = #note-name->german-markup-nosym
|
||||
chordNoteNamer = #bassnote-name->german-markup-nosym
|
||||
additionalPitchPrefix = ""
|
||||
|
||||
majorSevenSymbol = "maj7"
|
||||
chordNameExceptions = \chordNameExceptions
|
||||
}
|
||||
@@ -155,7 +203,7 @@ Ensure_first_chord_after_line_break_printed_engraver =
|
||||
; the current chord handling implementation in lilypond uses 'begin-of-line-visible to mark repeated chords
|
||||
(ly:grob-set-property! grob 'begin-of-line-visible #f))
|
||||
(set! last-system-column-rank current-system-column-rank)
|
||||
(item::enforce-musical-break-visibility grob)
|
||||
(ly:chord-name::after-line-breaking grob)
|
||||
)))))))
|
||||
|
||||
% If you add this engraver to ChordNames Context chords get only printed on chordchanges and not at newline.
|
||||
@@ -166,4 +214,4 @@ Ignoring_newline_chord_changes_engraver =
|
||||
((chord-name-interface this-engraver grob source-engraver)
|
||||
(when (and (ly:context-property ctx 'chordChanges #f) (ly:grob-property grob 'begin-of-line-visible #f))
|
||||
(ly:grob-suicide! grob)
|
||||
)))))
|
||||
)))))
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,11 +0,0 @@
|
||||
% Abwärtskompatibilität zu LilyPond 2.26.
|
||||
% Wird von all.ily nur eingebunden, wenn die laufende LilyPond-Version älter als 2.27 ist.
|
||||
% Alles andere ist für die aktuelle 2.27 geschrieben.
|
||||
|
||||
% Ab 2.27 gibt es \stanza als Musikfunktion (StanzaEvent), in 2.26 nur die Kontext-Property stanza.
|
||||
stanza =
|
||||
#(define-music-function (text) (markup?)
|
||||
(context-spec-music (make-property-set 'stanza text) 'Bottom))
|
||||
|
||||
% Ab 2.27 heißt ly:chord-name::after-line-breaking item::enforce-musical-break-visibility.
|
||||
#(define item::enforce-musical-break-visibility ly:chord-name::after-line-breaking)
|
||||
@@ -2,18 +2,16 @@
|
||||
poetPrefix = "Worte:"
|
||||
composerPrefix = "Weise:"
|
||||
compositionPrefix = "Satz:"
|
||||
adaptionTextPrefix = "Bearbeitung:"
|
||||
adaptionMusicPrefix = "Bearbeitung:"
|
||||
adaptionTextPrefix = "Bearbeitung Text:"
|
||||
adaptionMusicPrefix = "Bearbeitung Musik:"
|
||||
poetAndComposerEqualPrefix = "Worte und Weise:"
|
||||
voicePrefix = "Stimme:"
|
||||
versePrefix = "Strophe:"
|
||||
refPrefix = "Refrain:"
|
||||
translationAuthorPrefix = "Übersetzung:"
|
||||
translationPrefix = "Übersetzung:"
|
||||
pronunciationPrefix = "Aussprache:"
|
||||
interludePrefix = "Zwischenspiel:"
|
||||
bridgePrefix = "Bridge:"
|
||||
author-joiner = #(lambda (author-list) (string-join author-list ", "))
|
||||
|
||||
authorFormat =
|
||||
#(lambda (noDetails name trail_name birth_year death_year organization)
|
||||
@@ -33,114 +31,6 @@
|
||||
""
|
||||
)))
|
||||
|
||||
authorContributionFormat =
|
||||
#(lambda* (render-contribution-group render-partial-contribution-group #:key
|
||||
(poetIds '())
|
||||
(translatorIds '())
|
||||
(versePoetData '())
|
||||
(composerIds '())
|
||||
(verseComposerData '())
|
||||
(refComposerIds '())
|
||||
(voiceComposerData '())
|
||||
(compositionIds '())
|
||||
(adaptionTextIds '())
|
||||
(adaptionMusicIds '())
|
||||
(bridgeIds '())
|
||||
(interludeIds '())
|
||||
(year_text #f)
|
||||
(year_translation #f)
|
||||
(year_melody #f)
|
||||
(year_melody_meloref #f)
|
||||
(year_composition #f)
|
||||
(year_adaption_text #f)
|
||||
(year_adaption_music #f)
|
||||
(poetAndComposerEqualPrefix "")
|
||||
(poetPrefix "")
|
||||
(composerPrefix "")
|
||||
(translationAuthorPrefix "")
|
||||
(pronunciationPrefix "")
|
||||
(compositionPrefix "")
|
||||
(adaptionTextPrefix "")
|
||||
(adaptionMusicPrefix "")
|
||||
(bridgePrefix "")
|
||||
(interludePrefix "")
|
||||
(refPrefix ""))
|
||||
(if (and
|
||||
(equal? poetIds composerIds)
|
||||
(null? translatorIds)
|
||||
(null? versePoetData)
|
||||
(null? verseComposerData)
|
||||
(null? refComposerIds)
|
||||
(null? voiceComposerData)
|
||||
(null? compositionIds)
|
||||
(null? adaptionTextIds)
|
||||
(null? adaptionMusicIds)
|
||||
(null? bridgeIds)
|
||||
(null? interludeIds))
|
||||
(list
|
||||
(join-present (list
|
||||
(render-contribution-group poetAndComposerEqualPrefix poetIds)
|
||||
(if (equal? year_text year_melody) year_text (join-present (list year_text year_melody) "/"))
|
||||
) ", ")
|
||||
#f)
|
||||
(list
|
||||
(if (and (null? poetIds) (null? versePoetData) (null? translatorIds)) #f
|
||||
(string-append
|
||||
poetPrefix
|
||||
" "
|
||||
(join-present (list
|
||||
(join-present (list
|
||||
(render-contribution-group "" poetIds)
|
||||
year_text
|
||||
) ", ")
|
||||
(render-partial-contribution-group 'versePrefix versePoetData)
|
||||
(join-present (list
|
||||
(render-contribution-group adaptionTextPrefix adaptionTextIds)
|
||||
year_adaption_text
|
||||
) ", ")
|
||||
(join-present (list
|
||||
(render-contribution-group translationAuthorPrefix translatorIds)
|
||||
year_translation
|
||||
) ", ")
|
||||
) "; ")
|
||||
))
|
||||
(if (and
|
||||
(null? composerIds)
|
||||
(null? compositionIds)
|
||||
(null? adaptionMusicIds)
|
||||
(null? verseComposerData)
|
||||
(null? refComposerIds)
|
||||
(null? voiceComposerData)
|
||||
(null? bridgeIds)
|
||||
(null? interludeIds)) #f
|
||||
(string-append
|
||||
composerPrefix
|
||||
" "
|
||||
(join-present (list
|
||||
(join-present (list
|
||||
(render-contribution-group "" composerIds)
|
||||
year_melody
|
||||
) ", ")
|
||||
(render-partial-contribution-group 'versePrefix verseComposerData)
|
||||
(join-present (list
|
||||
(render-contribution-group refPrefix refComposerIds)
|
||||
year_melody_meloref
|
||||
) ", ")
|
||||
(render-partial-contribution-group 'voicePrefix voiceComposerData)
|
||||
(join-present (list
|
||||
(render-contribution-group compositionPrefix compositionIds)
|
||||
year_composition
|
||||
) ", ")
|
||||
(join-present (list
|
||||
(render-contribution-group adaptionMusicPrefix adaptionMusicIds)
|
||||
year_adaption_music
|
||||
) ", ")
|
||||
(render-contribution-group bridgePrefix bridgeIds)
|
||||
(render-contribution-group interludePrefix interludeIds)
|
||||
) "; ")
|
||||
)))))
|
||||
|
||||
|
||||
songinfoMarkup =
|
||||
#(make-on-the-fly-markup
|
||||
(lambda (layout props m)
|
||||
@@ -155,15 +45,13 @@
|
||||
(year_melody (chain-assoc-get 'songinfo:year_melody props #f))
|
||||
(poet-with-year (if (and poet-maybe-with-composer year_text) (string-append poet-maybe-with-composer ", " year_text) poet-maybe-with-composer))
|
||||
(composer-with-year (if (and composer year_melody) (string-append composer ", " year_melody) composer))
|
||||
(concat-markupped-strings (lambda (text)
|
||||
(ly:regex-replace (ly:make-regex "(\\S+)(\\\\\\w+(?:\\s+\\[^\\{\\s]*|\\s*\\{[^\\}]*\\}))(\\S*)") text "\\concat {" 1 "\\line {" 2 "}" 3 "}")))
|
||||
(string-with-paragraphs->markuplist (lambda (prefix text)
|
||||
(if text
|
||||
(apply append
|
||||
(map
|
||||
(lambda (paragraph)
|
||||
(make-wordwrap-internal-markup-list #t
|
||||
#{ \markuplist { $(ly:parser-include-string (concat-markupped-strings paragraph)) } #}))
|
||||
#{ \markuplist { $(ly:parser-include-string paragraph) } #}))
|
||||
(ly:regex-split (ly:make-regex "\r?\n[ \t\r\n]*\n[ \t\r\n]*") (string-append prefix text))))
|
||||
'())))
|
||||
(poet-and-composer-markup-list
|
||||
@@ -187,4 +75,4 @@
|
||||
)))))
|
||||
(make-null-markup)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -16,10 +16,9 @@ songTocColumns = 3
|
||||
globalSize = 15
|
||||
lyricSize = 1.6
|
||||
stanzaFormat = "~a."
|
||||
romanStanzaFormat = "~@r."
|
||||
refString = "Ref.:"
|
||||
refStringWithNumbers = "Ref. ~a:"
|
||||
bridgeString = "Bridge:"
|
||||
bridgeStringWithNumbers = "Bridge ~a:"
|
||||
% hübsche Wiederholungszeichen für den Liedtext
|
||||
repStart = "𝄆"
|
||||
repStop = "𝄇"
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
%% Mehrere Lieder in einer Liederdatei (z.B. zwei Lieder auf einer Seite)
|
||||
%%
|
||||
%% Das erste Lied ist das Hauptlied (HEADER), alle weiteren werden als
|
||||
%% eingebettete Lieder angemeldet. Eingebettete Lieder bekommen eigene
|
||||
%% Eintraege im Inhaltsverzeichnis, in den Kategorie-, Autoren- und
|
||||
%% Kapitelverzeichnissen, im PDF-Inhaltsverzeichnis, in der toc.csv und
|
||||
%% eine eigene Liednummer. Im Footer steht die Songinfo des letzten
|
||||
%% eingebetteten Lieds (abschaltbar mit footersong = ##f im HEADER bzw. mit
|
||||
%% footersong = \andereslied umstellbar), die Songinfo des Hauptlieds wird
|
||||
%% mit \songinfo-of selbst platziert.
|
||||
%%
|
||||
%% Beispiel:
|
||||
%%
|
||||
%% \include "../../lilypond-song-includes/liedbausteine/lied_a.ly"
|
||||
%% liedA = \captureSong
|
||||
%% \include "../../lilypond-song-includes/liedbausteine/lied_b.ly"
|
||||
%% liedB = \captureSong
|
||||
%%
|
||||
%% TEXT = \markuplist {
|
||||
%% \songinfo-of \liedA
|
||||
%% \vspace #2
|
||||
%% \embedded-song-title \liedB
|
||||
%% \vspace #.5
|
||||
%% \score { \songMusic \liedB \layout { \LAYOUT } }
|
||||
%% \with-song \liedB {
|
||||
%% \chordlyrics \secondVerse
|
||||
%% }
|
||||
%% }
|
||||
%%
|
||||
%% \restoreSong \liedA
|
||||
%% \embedSong \liedB
|
||||
%% \include "public_includes/layout_bottom.ily"
|
||||
%%
|
||||
%% \captureSong sichert den Header (basicSongInfo) und die Variablen aus
|
||||
%% captured-song-variable-names, damit das naechste \include sie nicht
|
||||
%% ueberschreibt. Das Ergebnis ist ein normales Header-Modul, es kann also
|
||||
%% auch in \header { \liedA } verwendet werden.
|
||||
%%
|
||||
%% \restoreSong setzt basicSongInfo, HEADER und diese Variablen zurueck,
|
||||
%% TEXT aber nicht. TEXT also vor \restoreSong schreiben, solange darin noch
|
||||
%% Variablen des zuletzt eingebundenen Lieds (\secondVerse usw.) stehen.
|
||||
%%
|
||||
%% Ohne \with-song beziehen sich Strophen mit Akkorden auf das Hauptlied.
|
||||
%%
|
||||
%% Alle Verzeichniseintraege zeigen auf die erste Seite des Hauptlieds.
|
||||
|
||||
#(define captured-song-variable-names '(MUSIC global firstVoice verseChords))
|
||||
|
||||
#(define (song-variable song name)
|
||||
(assq-ref (module-ref song 'captured-song-variables '()) name))
|
||||
|
||||
#(define (extract-and-check-vars-from-module headermodule varlist)
|
||||
(let* ((headervars (if (module? headermodule) (hash-map->list cons (struct-ref headermodule 0)) '()))
|
||||
(extract-var-and-check (lambda (headervar)
|
||||
(let* ((variableref (assoc-ref headervars headervar))
|
||||
(extracted (if variableref (variable-ref variableref) #f)))
|
||||
(if (and extracted (not (and (string? extracted) (string-null? extracted)))) extracted #f)))))
|
||||
(map (lambda (varsymbol)
|
||||
(cons varsymbol (extract-var-and-check varsymbol))
|
||||
) varlist)))
|
||||
|
||||
% Text des PDF-Lesezeichens eines Lieds, #f wenn es keins bekommt.
|
||||
% Gleiche Regel wie in build-full-title.
|
||||
#(define (song-pdf-bookmark-title headermodule)
|
||||
(let* ((vars (extract-and-check-vars-from-module headermodule '(title starttext)))
|
||||
(title (assq-ref vars 'title))
|
||||
(starttext (assq-ref vars 'starttext))
|
||||
(as-string (lambda (m) (if (markup? m) (markup->string m) ""))))
|
||||
(cond ((and title starttext) (string-append (as-string starttext) " | " (as-string title)))
|
||||
(title (as-string title))
|
||||
(starttext (string-append (as-string starttext) " | "))
|
||||
(else #f))))
|
||||
|
||||
#(define (embedded-song-list songs)
|
||||
(if (list? songs) (filter module? songs) '()))
|
||||
|
||||
#(define (embedded-songs-of-header headermodule)
|
||||
(if (module? headermodule)
|
||||
(embedded-song-list (module-ref headermodule 'embeddedsongs '()))
|
||||
'()))
|
||||
|
||||
% Ersetzt alle header:*-Properties durch die Felder aus headermodule, damit
|
||||
% keine Felder des Hauptlieds in das andere Lied durchsickern.
|
||||
#(define (header-module->props headermodule props)
|
||||
(let ((header-key? (lambda (entry)
|
||||
(and (pair? entry) (symbol? (car entry))
|
||||
(string-prefix? "header:" (symbol->string (car entry)))))))
|
||||
(cons
|
||||
(map (lambda (kv) (cons (symbol-append 'header: (car kv)) (cdr kv)))
|
||||
(ly:module->alist headermodule))
|
||||
(map (lambda (alist) (remove header-key? alist)) props))))
|
||||
|
||||
captureSong =
|
||||
#(define-scheme-function () ()
|
||||
(let ((song (make-module)))
|
||||
(ly:module-copy song basicSongInfo)
|
||||
(module-define! song 'captured-song-variables
|
||||
(filter-map
|
||||
(lambda (name)
|
||||
(let ((value (ly:parser-lookup name)))
|
||||
(and (not (null? value)) (cons name value))))
|
||||
captured-song-variable-names))
|
||||
song))
|
||||
|
||||
% Stellt basicSongInfo, HEADER und die gesicherten Variablen eines Lieds
|
||||
% wieder her, als waere es das zuletzt eingebundene.
|
||||
restoreSong =
|
||||
#(define-void-function (song) (module?)
|
||||
(for-each
|
||||
(lambda (kv) (ly:parser-define! (car kv) (cdr kv)))
|
||||
(module-ref song 'captured-song-variables '()))
|
||||
(ly:parser-define! 'basicSongInfo song)
|
||||
(ly:parser-define! 'HEADER #{ \bookpart { \header { $song } } #}))
|
||||
|
||||
embedSong =
|
||||
#(define-void-function (song) (module?)
|
||||
(set! EMBEDDED_SONGS (append EMBEDDED_SONGS (list song))))
|
||||
|
||||
songMusic =
|
||||
#(define-music-function (song) (module?)
|
||||
(let ((music (song-variable song 'MUSIC)))
|
||||
(if (ly:music? music) music (make-music 'SequentialMusic))))
|
||||
|
||||
% Strophen, \fromproperty #'header:... usw. beziehen sich innerhalb auf das
|
||||
% angegebene Lied. Die Transposition des Hauptlieds wird nicht uebernommen.
|
||||
#(define-markup-list-command (with-song layout props song args) (module? markup-list?)
|
||||
(let* ((music-or-empty (lambda (name)
|
||||
(let ((music (song-variable song name)))
|
||||
(if (ly:music? music) music (make-music 'SequentialMusic)))))
|
||||
(verseChords (music-or-empty 'verseChords))
|
||||
(global (music-or-empty 'global))
|
||||
(firstVoice (music-or-empty 'firstVoice)))
|
||||
(interpret-markup-list layout
|
||||
(prepend-alist-chain 'verse-chords #{ \chords { $verseChords } #}
|
||||
(prepend-alist-chain 'verse-reference-voice #{ $global $firstVoice #}
|
||||
(prepend-alist-chain 'transposition (cons #f #f)
|
||||
(header-module->props song props))))
|
||||
args)))
|
||||
|
||||
#(define-markup-command (songinfo-of layout props song) (module?)
|
||||
(interpret-markup layout (header-module->props song props)
|
||||
(make-fractional-line-width-markup (make-songinfo-content-markup))))
|
||||
|
||||
#(define-markup-command (embedded-song-title layout props song) (module?)
|
||||
(interpret-markup layout (header-module->props song props)
|
||||
(make-fill-line-markup (list (ly:output-def-lookup layout 'defaultTitleMarkup)))))
|
||||
|
||||
% PDF-Lesezeichen der eingebetteten Lieder, wird von build-full-title direkt
|
||||
% nach dem Lesezeichen des Hauptlieds ausgegeben.
|
||||
#(define-markup-command (embedded-songs-to-pdf-toc layout props) ()
|
||||
(apply ly:stencil-add
|
||||
(cons empty-stencil
|
||||
(filter-map
|
||||
(lambda (song)
|
||||
(let ((bookmark (song-pdf-bookmark-title song)))
|
||||
(and bookmark (make-pdf-toc-stencil bookmark 0))))
|
||||
(embedded-song-list (chain-assoc-get 'header:embeddedsongs props '()))))))
|
||||
@@ -6,20 +6,10 @@
|
||||
#(define-markup-command (customEps layout props ysize filename)(number? string?)
|
||||
#:properties ((songfilename ""))
|
||||
(interpret-markup layout props
|
||||
(let* ((defaulttitlemarkup (ly:output-def-lookup layout 'defaultTitleMarkup))
|
||||
;; Determine the song directory to resolve the EPS relative to.
|
||||
;; In TEXT the name arrives via the markup props (\setsongfilename),
|
||||
;; but inside MUSIC (e.g. \mark) the props do not carry it, so we
|
||||
;; fall back to the value stored in the score's \layout block.
|
||||
(layout-songfilename (ly:output-def-lookup layout 'songfilename #f))
|
||||
(songdir (cond ((not (string-null? songfilename)) songfilename)
|
||||
((and (string? layout-songfilename)
|
||||
(not (string-null? layout-songfilename)))
|
||||
layout-songfilename)
|
||||
(else #f)))
|
||||
(filepath (if songdir
|
||||
(ly:format "~a/~a/~a" songPath songdir filename)
|
||||
filename)))
|
||||
(let ((defaulttitlemarkup (ly:output-def-lookup layout 'defaultTitleMarkup))
|
||||
(filepath (if (string-null? songfilename)
|
||||
filename
|
||||
(ly:format "~a/~a/~a" songPath songfilename filename))))
|
||||
(if (file-exists? filepath)
|
||||
(make-epsfile-markup Y ysize filepath)
|
||||
(if defaulttitlemarkup
|
||||
|
||||
@@ -30,11 +30,7 @@
|
||||
(lambda (a b) (< (cadr a) (cadr b))))
|
||||
(list)))
|
||||
|
||||
#(define (join-present items joiner)
|
||||
(string-join (filter (lambda (item) (and (string? item) (not (string-null? (string-trim-both item))))) items) joiner))
|
||||
|
||||
% Songinfo aus den header:*-Properties, ohne Pruefung auf die letzte Seite.
|
||||
#(define-markup-command (songinfo-content layout props) ()
|
||||
#(define-markup-command (print-songinfo layout props) ()
|
||||
(define (songinfo-from songId key)
|
||||
(let ((song (if (defined? 'SONG_DATA) (assoc-ref SONG_DATA songId) #f)))
|
||||
(if song
|
||||
@@ -78,7 +74,11 @@
|
||||
(define (render-contribution-group contributionPrefix authorIds)
|
||||
(if (null? authorIds)
|
||||
""
|
||||
(string-append contributionPrefix " " ((ly:output-def-lookup layout 'author-joiner) (format-authors authorIds))))
|
||||
(string-append contributionPrefix " " (string-join (format-authors authorIds) ", ")))
|
||||
)
|
||||
|
||||
(define (join-present items joiner)
|
||||
(string-join (filter (lambda (item) (and (string? item) (not (string-null? (string-trim-both item))))) items) joiner)
|
||||
)
|
||||
|
||||
(define (render-partial-contribution-group prefixLookup authorData)
|
||||
@@ -94,44 +94,99 @@
|
||||
|
||||
(define (poet-and-composer-from-authors authors)
|
||||
(if authors
|
||||
((ly:output-def-lookup layout 'authorContributionFormat)
|
||||
render-contribution-group
|
||||
render-partial-contribution-group
|
||||
#:poetIds (find-author-ids-by 'text authors)
|
||||
#:translatorIds (find-author-ids-by 'translation authors)
|
||||
#:versePoetData (find-author-id-with-part-numbers 'verse authors)
|
||||
#:composerIds (find-author-ids-by 'melody authors)
|
||||
#:verseComposerData (find-author-id-with-part-numbers 'meloverse authors)
|
||||
#:refComposerIds (find-author-ids-by 'meloref authors)
|
||||
#:voiceComposerData (find-author-id-with-part-numbers 'voice authors)
|
||||
#:compositionIds (find-author-ids-by 'composition authors)
|
||||
#:adaptionTextIds (find-author-ids-by 'adaption_text authors)
|
||||
#:adaptionMusicIds (find-author-ids-by 'adaption_music authors)
|
||||
#:bridgeIds (find-author-ids-by 'bridge authors)
|
||||
#:interludeIds (find-author-ids-by 'interlude authors)
|
||||
#:year_text (chain-assoc-get 'header:year_text props #f)
|
||||
#:year_translation (chain-assoc-get 'header:year_translation props #f)
|
||||
#:year_melody (chain-assoc-get 'header:year_melody props #f)
|
||||
#:year_melody_meloref (chain-assoc-get 'header:year_melody_meloref props #f)
|
||||
#:year_composition (chain-assoc-get 'header:year_composition props #f)
|
||||
#:year_adaption_text (chain-assoc-get 'header:year_adaption_text props #f)
|
||||
#:year_adaption_music (chain-assoc-get 'header:year_adaption_music props #f)
|
||||
#:poetAndComposerEqualPrefix (ly:output-def-lookup layout 'poetAndComposerEqualPrefix)
|
||||
#:poetPrefix (ly:output-def-lookup layout 'poetPrefix)
|
||||
#:composerPrefix (ly:output-def-lookup layout 'composerPrefix)
|
||||
#:translationAuthorPrefix (ly:output-def-lookup layout 'translationAuthorPrefix)
|
||||
#:pronunciationPrefix (ly:output-def-lookup layout 'pronunciationPrefix)
|
||||
#:compositionPrefix (ly:output-def-lookup layout 'compositionPrefix)
|
||||
#:adaptionTextPrefix (ly:output-def-lookup layout 'adaptionTextPrefix)
|
||||
#:adaptionMusicPrefix (ly:output-def-lookup layout 'adaptionMusicPrefix)
|
||||
#:bridgePrefix (ly:output-def-lookup layout 'bridgePrefix)
|
||||
#:interludePrefix (ly:output-def-lookup layout 'interludePrefix)
|
||||
#:refPrefix (ly:output-def-lookup layout 'refPrefix))
|
||||
(let (
|
||||
(poetIds (find-author-ids-by 'text authors))
|
||||
(translatorIds (find-author-ids-by 'translation authors))
|
||||
(versePoetData (find-author-id-with-part-numbers 'verse authors))
|
||||
(composerIds (find-author-ids-by 'melody authors))
|
||||
(verseComposerData (find-author-id-with-part-numbers 'meloverse authors))
|
||||
(voiceComposerData (find-author-id-with-part-numbers 'voice authors))
|
||||
(compositionIds (find-author-ids-by 'composition authors))
|
||||
(adaptionTextIds (find-author-ids-by 'adaption_text authors))
|
||||
(adaptionMusicIds (find-author-ids-by 'adaption_music authors))
|
||||
(bridgeIds (find-author-ids-by 'bridge authors))
|
||||
(interludeIds (find-author-ids-by 'interlude authors))
|
||||
(year_text (chain-assoc-get 'header:year_text props #f))
|
||||
(year_translation (chain-assoc-get 'header:year_translation props #f))
|
||||
(year_melody (chain-assoc-get 'header:year_melody props #f))
|
||||
(year_composition (chain-assoc-get 'header:year_composition props #f))
|
||||
(year_adaption_text (chain-assoc-get 'header:year_adaption_text props #f))
|
||||
(year_adaption_music (chain-assoc-get 'header:year_adaption_music props #f))
|
||||
)
|
||||
(if (and
|
||||
(equal? poetIds composerIds)
|
||||
(null? translatorIds)
|
||||
(null? versePoetData)
|
||||
(null? verseComposerData)
|
||||
(null? voiceComposerData)
|
||||
(null? compositionIds)
|
||||
(null? adaptionTextIds)
|
||||
(null? adaptionMusicIds)
|
||||
(null? bridgeIds)
|
||||
(null? interludeIds))
|
||||
(list
|
||||
(join-present (list
|
||||
(render-contribution-group (ly:output-def-lookup layout 'poetAndComposerEqualPrefix) poetIds)
|
||||
(if (equal? year_text year_melody) year_text (join-present (list year_text year_melody) "/"))
|
||||
) ", ")
|
||||
#f)
|
||||
(list
|
||||
(if (and (null? poetIds) (null? versePoetData) (null? translatorIds)) #f
|
||||
(string-append
|
||||
(ly:output-def-lookup layout 'poetPrefix)
|
||||
" "
|
||||
(join-present (list
|
||||
(join-present (list
|
||||
(render-contribution-group "" poetIds)
|
||||
year_text
|
||||
) ", ")
|
||||
(render-partial-contribution-group 'versePrefix versePoetData)
|
||||
(join-present (list
|
||||
(render-contribution-group (ly:output-def-lookup layout 'translationAuthorPrefix) translatorIds)
|
||||
year_translation
|
||||
) ", ")
|
||||
(join-present (list
|
||||
(render-contribution-group (ly:output-def-lookup layout 'adaptionTextPrefix) adaptionTextIds)
|
||||
year_adaption_text
|
||||
) ", ")
|
||||
) "; ")
|
||||
))
|
||||
(if (and
|
||||
(null? composerIds)
|
||||
(null? compositionIds)
|
||||
(null? adaptionMusicIds)
|
||||
(null? verseComposerData)
|
||||
(null? voiceComposerData)
|
||||
(null? bridgeIds)
|
||||
(null? interludeIds)) #f
|
||||
(string-append
|
||||
(ly:output-def-lookup layout 'composerPrefix)
|
||||
" "
|
||||
(join-present (list
|
||||
(join-present (list
|
||||
(render-contribution-group "" composerIds)
|
||||
year_melody
|
||||
) ", ")
|
||||
(render-partial-contribution-group 'versePrefix verseComposerData)
|
||||
(render-partial-contribution-group 'voicePrefix voiceComposerData)
|
||||
(join-present (list
|
||||
(render-contribution-group (ly:output-def-lookup layout 'compositionPrefix) compositionIds)
|
||||
year_composition
|
||||
) ", ")
|
||||
(join-present (list
|
||||
(render-contribution-group (ly:output-def-lookup layout 'adaptionMusicPrefix) adaptionMusicIds)
|
||||
year_adaption_music
|
||||
) ", ")
|
||||
(render-contribution-group (ly:output-def-lookup layout 'bridgePrefix) bridgeIds)
|
||||
(render-contribution-group (ly:output-def-lookup layout 'interludePrefix) interludeIds)
|
||||
) "; ")
|
||||
)))))
|
||||
(list #f #f)
|
||||
)
|
||||
)
|
||||
|
||||
(interpret-markup layout props
|
||||
(if (chain-assoc-get 'page:is-bookpart-last-page props #f)
|
||||
(let* ((authors (chain-assoc-get 'header:authors props #f))
|
||||
(poet-and-composers (poet-and-composer-from-authors authors))
|
||||
(songId (chain-assoc-get 'header:songId props #f))
|
||||
@@ -145,7 +200,7 @@
|
||||
(translation (chain-assoc-get 'header:translation props #f))
|
||||
(pronunciation (chain-assoc-get 'header:pronunciation props #f))
|
||||
(year_text (if (string? (car poet-and-composers)) #f (chain-assoc-get 'header:year_text props #f)))
|
||||
(year_melody (if (string? (cadr poet-and-composers)) #f (chain-assoc-get 'header:year_melody props #f))))
|
||||
(year_melody (if (string? (car poet-and-composers)) #f (chain-assoc-get 'header:year_melody props #f))))
|
||||
(markup
|
||||
#:override (cons 'songinfo:poet-maybe-with-composer
|
||||
(if (and poet-maybe-with-composer (not (and (string? poet-maybe-with-composer) (string-null? poet-maybe-with-composer)))) poet-maybe-with-composer #f))
|
||||
@@ -167,25 +222,10 @@
|
||||
#:fontsize songInfoFontSize
|
||||
#:sans
|
||||
(ly:output-def-lookup layout 'songinfoMarkup)
|
||||
))))
|
||||
)))
|
||||
(make-null-markup)))
|
||||
)
|
||||
|
||||
% Songinfo im Footer, nur auf der letzten Seite des Bookparts. Gibt es
|
||||
% eingebettete Lieder (siehe embedded_songs.ily), steht hier die Songinfo des
|
||||
% letzten eingebetteten Lieds, ausser im Header ist footersong gesetzt
|
||||
% (##f = Hauptlied, oder ein mit \captureSong gesichertes Lied).
|
||||
#(define-markup-command (print-songinfo layout props) ()
|
||||
(if (chain-assoc-get 'page:is-bookpart-last-page props #f)
|
||||
(let* ((footersong (chain-assoc-get 'header:footersong props 'auto))
|
||||
(embedded (embedded-song-list (chain-assoc-get 'header:embeddedsongs props '())))
|
||||
(song (if (eq? footersong 'auto)
|
||||
(and (pair? embedded) (last embedded))
|
||||
footersong)))
|
||||
(interpret-markup layout
|
||||
(if (module? song) (header-module->props song props) props)
|
||||
(make-songinfo-content-markup)))
|
||||
(interpret-markup layout props (make-null-markup))))
|
||||
|
||||
#(define-markup-command (print-pagenumber layout props)()
|
||||
(let ((label (chain-assoc-get 'header:myindexlabel props #f)))
|
||||
(interpret-markup layout props
|
||||
@@ -230,4 +270,4 @@
|
||||
\line { \page-number-to-pdf-label \null }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
% We have to record the tag groups for markup, so we use the right tag groups during markup interpretiton.
|
||||
recordedTagGroups = #'()
|
||||
|
||||
tagGroup =
|
||||
#(define-void-function (tags) (symbol-list?)
|
||||
(let ((err (define-tag-group tags)))
|
||||
(if err (ly:parser-error err (*location*))
|
||||
(set! recordedTagGroups (cons tags recordedTagGroups)))))
|
||||
|
||||
#(define-markup-command (handle-tag-groups layout props recorded-groups m) (list? markup?)
|
||||
(resetTagGroups)
|
||||
(for-each
|
||||
(lambda (group)
|
||||
(define-tag-group group))
|
||||
recorded-groups)
|
||||
(interpret-markup layout props m))
|
||||
@@ -1,4 +1,4 @@
|
||||
swing = \textMark \markup {
|
||||
swing = \mark \markup {
|
||||
\line \general-align #Y #DOWN {
|
||||
\score {
|
||||
\new Staff \with {
|
||||
@@ -47,7 +47,7 @@ swing = \textMark \markup {
|
||||
}
|
||||
}
|
||||
|
||||
swingOff = \textMark \markup {
|
||||
swingOff = \mark \markup {
|
||||
\line \general-align #Y #DOWN {
|
||||
\score {
|
||||
\new Staff \with {
|
||||
@@ -99,7 +99,7 @@ swingOff = \textMark \markup {
|
||||
\include "swing.ly"
|
||||
|
||||
swingMusic =
|
||||
#(define-music-function (music) (ly:music?)
|
||||
#(define-music-function (parser location music) (ly:music?)
|
||||
(define (partial-duration-length m)
|
||||
(let ((name (ly:music-property m 'name))
|
||||
(es (ly:music-property m 'elements))
|
||||
@@ -118,4 +118,4 @@ swingMusic =
|
||||
#{
|
||||
\swing
|
||||
\applySwingWithOffset 8 #'(2 1) #(partial-duration-length music) #music
|
||||
#})
|
||||
#})
|
||||
@@ -1,5 +1,6 @@
|
||||
#(define-markup-command (bookTitleMarkupCustom layout props)()
|
||||
(interpret-markup layout props
|
||||
(interpret-markup layout
|
||||
(prepend-alist-chain 'songfilename (chain-assoc-get 'header:songfilename props "") props)
|
||||
(make-column-markup
|
||||
(list
|
||||
(make-vspace-markup (chain-assoc-get 'header:titletopspace props 0))
|
||||
@@ -26,60 +27,34 @@
|
||||
|
||||
#(define pdf-encode (@@ (lily framework-ps) pdf-encode))
|
||||
% PDF tags
|
||||
% Erzeugt ein PDF-Lesezeichen (Outline-Eintrag) auf der aktuellen Seite.
|
||||
% count = Anzahl der direkten Unterpunkte, die (in Seitenreihenfolge) direkt
|
||||
% nachfolgen. 0 = Blatt-Eintrag (kein /Count), >0 = aufgeklappt,
|
||||
% <0 = zugeklappt (Betrag = Anzahl direkter Kinder).
|
||||
#(define (make-pdf-toc-stencil title count)
|
||||
#(define-markup-command (title-to-pdf-toc layout props title) (string?)
|
||||
(if (string-null? title)
|
||||
empty-stencil
|
||||
(ly:make-stencil
|
||||
(list 'embedded-ps
|
||||
(ly:format
|
||||
"[~a/Action /GoTo /View [/XYZ -4 currentpagedevice /PageSize get 1 get 4 add null] /Title (~a) /OUT pdfmark"
|
||||
(if (= count 0) "" (ly:format "/Count ~a " count))
|
||||
(pdf-encode title)))
|
||||
"[/Action /GoTo /View [/XYZ -4 currentpagedevice /PageSize get 1 get 4 add null] /Title (~a) /OUT pdfmark" (pdf-encode title)))
|
||||
empty-interval empty-interval
|
||||
;'(0 . 0) '(0 . 0)
|
||||
)))
|
||||
|
||||
% Einzelner (Blatt-)Eintrag im PDF-Inhaltsverzeichnis.
|
||||
#(define-markup-command (title-to-pdf-toc layout props title) (string?)
|
||||
(make-pdf-toc-stencil title 0))
|
||||
|
||||
% Kapitel-Eintrag mit verschachtelten Unterpunkten.
|
||||
% count = Anzahl der direkt nachfolgenden Einträge, die diesem Kapitel
|
||||
% untergeordnet werden sollen (positiv = aufgeklappt, negativ = zugeklappt).
|
||||
#(define-markup-command (chapter-to-pdf-toc layout props count title) (integer? string?)
|
||||
(make-pdf-toc-stencil title count))
|
||||
|
||||
#(define-markup-command (build-full-title layout props right)(boolean?)
|
||||
(interpret-markup layout (prepend-alist-chain 'songfilename (chain-assoc-get 'header:songfilename props "") props)
|
||||
#(define-markup-command (title-with-category-images layout props right)(boolean?)
|
||||
(interpret-markup layout props
|
||||
(let* ((title (chain-assoc-get 'header:title props ""))
|
||||
(starttext (chain-assoc-get 'header:starttext props #f))
|
||||
(pdfbookmark (if starttext (string-append starttext " | " title) title))
|
||||
(chaptertitle (chain-assoc-get 'header:chaptertitle props #f))
|
||||
(chaptercount (chain-assoc-get 'header:chaptercount props 0))
|
||||
(title-markup (ly:output-def-lookup layout (if right 'oddTitleLineMarkup 'evenTitleLineMarkup))))
|
||||
(pdfbookmark (if starttext (string-append starttext " | " title) title)))
|
||||
(if title
|
||||
;; Ist dieses Lied das erste eines Kapitels, wird der Kapitel-Eintrag
|
||||
;; unmittelbar vor dem Lied-Eintrag ausgegeben, damit die pdfmark-/OUT-
|
||||
;; Reihenfolge (Elternteil vor Kindern) im PDF-Stream garantiert stimmt.
|
||||
;; Eingebettete Lieder (embedded_songs.ily) folgen direkt nach dem Lied.
|
||||
(if (and (string? chaptertitle) (not (string-null? chaptertitle)))
|
||||
(markup #:chapter-to-pdf-toc chaptercount chaptertitle
|
||||
#:title-to-pdf-toc pdfbookmark #:embedded-songs-to-pdf-toc title-markup)
|
||||
(markup #:title-to-pdf-toc pdfbookmark #:embedded-songs-to-pdf-toc title-markup))
|
||||
make-null-markup)
|
||||
(if right
|
||||
#{\markup { \title-to-pdf-toc #pdfbookmark \fill-line \general-align #Y #UP { \null \bookTitleMarkupCustom \category-images } } #}
|
||||
#{\markup { \title-to-pdf-toc #pdfbookmark \fill-line \general-align #Y #UP { \category-images \bookTitleMarkupCustom \null } } #})
|
||||
#{ \markup { " " } #})
|
||||
)))
|
||||
|
||||
\paper {
|
||||
bookTitleMarkup = \markup \null
|
||||
scoreTitleMarkup = \markup \null
|
||||
oddHeaderMarkup = \markup { \if \on-first-page-of-part \build-full-title ##t }
|
||||
evenHeaderMarkup = \markup { \if \on-first-page-of-part \build-full-title ##f }
|
||||
oddTitleLineMarkup = \markup { \fill-line \general-align #Y #UP { \null \bookTitleMarkupCustom \category-images } }
|
||||
evenTitleLineMarkup = \markup { \fill-line \general-align #Y #UP { \category-images \bookTitleMarkupCustom \null } }
|
||||
oddHeaderMarkup = \markup { \if \on-first-page-of-part \title-with-category-images ##t }
|
||||
evenHeaderMarkup = \markup { \if \on-first-page-of-part \title-with-category-images ##f }
|
||||
defaultTitleMarkup = \markup {
|
||||
\override #'(baseline-skip . 3.5)
|
||||
\center-column {
|
||||
@@ -88,4 +63,4 @@
|
||||
\smaller \bold \fromproperty #'header:subsubtitle
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,7 @@ TRANSPOSITION = #(cons #f #f)
|
||||
|
||||
transposeGlobal =
|
||||
#(define-void-function (from to) (ly:pitch? ly:pitch?)
|
||||
(if (not (car TRANSPOSITION))
|
||||
(set! TRANSPOSITION (cons from to))
|
||||
(let ((current_to (cdr TRANSPOSITION))
|
||||
(interval (ly:pitch-diff to from)))
|
||||
(set! TRANSPOSITION (cons (car TRANSPOSITION)
|
||||
(ly:pitch-transpose current_to interval))))))
|
||||
(set! TRANSPOSITION (cons from to)))
|
||||
|
||||
transposable =
|
||||
#(define-music-function (fromto music) (pair? ly:music?)
|
||||
|
||||
@@ -60,20 +60,19 @@
|
||||
|
||||
% Text über Text mittig darstellen
|
||||
#(define-markup-command (textup layout props text uptext) (markup? markup?)
|
||||
#:properties ((verselayout generalLayout)
|
||||
(verse-text-chord-distance songTextChordDistance))
|
||||
"Markup über Text mittig darstellen."
|
||||
(let ((verselayout (chain-assoc-get 'verselayout props generalLayout)))
|
||||
(interpret-markup layout props
|
||||
#{\markup {
|
||||
\size-box-to-box-style-dependent ##t ##f
|
||||
\general-align #X #LEFT \override #`(direction . ,UP) \override #'(baseline-skip . 1) \dir-column \chord-alignment-style-dependent {
|
||||
\pad-to-box #'(0 . 0) #`(0 . ,(- verse-text-chord-distance 0.8)) { #text }
|
||||
\size-box-to-box ##f ##t #uptext \score { \chords { g4:m a } \layout { $verselayout #(customized-layout verselayout) } }
|
||||
\general-align #X #LEFT \override #`(direction . ,UP) \override #'(baseline-skip . 1.0) \dir-column \chord-alignment-style-dependent {
|
||||
\pad-to-box #'(0 . 0) #'(0 . 2.0) { #text }
|
||||
\size-box-to-box ##f ##t #uptext \score { \chords { g4:m a } \layout { \verselayout } }
|
||||
}
|
||||
#text
|
||||
}
|
||||
#}
|
||||
))
|
||||
)))
|
||||
|
||||
#(define-markup-command (anchor-x-between layout props arga argb)
|
||||
(markup? markup?)
|
||||
@@ -83,15 +82,16 @@
|
||||
(ly:stencil-aligned-to m X (- (/ (* la 2) l) 1))
|
||||
))
|
||||
|
||||
#(define-markup-command (stanza-raw layout props arg) (string-or-music?)
|
||||
#:properties ((verselayout generalLayout))
|
||||
#(define-markup-command (stanza-raw layout props arg)
|
||||
(string-or-music?)
|
||||
(let ((verselayout (chain-assoc-get 'verselayout props generalLayout)))
|
||||
(interpret-markup layout props
|
||||
(if (and (string? arg) (string-null? arg))
|
||||
" "
|
||||
#{\markup
|
||||
\score { \new Lyrics { \lyricmode { #(if (ly:music? arg) arg #{ \stanza #arg #}) "" } } \layout { $verselayout #(customized-layout verselayout) } }
|
||||
\score { \new Lyrics { \lyricmode { #(if (ly:music? arg) arg #{ \set stanza = #arg #}) "" } } \layout { \verselayout } }
|
||||
#}
|
||||
)))
|
||||
))))
|
||||
|
||||
#(define-markup-command (stanza layout props arg)
|
||||
(string-or-music?)
|
||||
@@ -141,7 +141,7 @@
|
||||
(make-wrap-newline-markup
|
||||
(ly:regex-replace (ly:make-regex "\\(( *)([^,()]*)( *),([^)]*)\\)")
|
||||
(ly:regex-replace (ly:make-regex "(([^ \n]*\\([^()]*,[^()]+\\)[^ \n(]*)+)") (handle-custom-newlines custom-verse-breaks verse) " \\concat { " 1 " } ")
|
||||
"\\textup \\line { \"" 1 "\" " 2 " \"" 3 "\" } \\score { " transp " \\chords { s4 " 4 " } \\layout { $verselayout #(customized-layout verselayout) } }")
|
||||
"\\textup \\line { \"" 1 "\" " 2 " \"" 3 "\" } \\score { " transp " \\chords { s4 " 4 " } \\layout { \\verselayout } }")
|
||||
)
|
||||
))))
|
||||
|
||||
@@ -203,9 +203,23 @@
|
||||
|
||||
#(define-markup-command (pad-left layout props amount arg)
|
||||
(number? markup?)
|
||||
(let* ((m (interpret-markup layout props arg))
|
||||
(x (ly:stencil-extent m X))
|
||||
(y (ly:stencil-extent m Y)))
|
||||
(ly:stencil-translate
|
||||
(interpret-markup layout props (make-pad-x-left-markup amount arg))
|
||||
`(,amount . 0)))
|
||||
(ly:make-stencil (ly:stencil-expr m)
|
||||
(cons (- (car x) amount) (cdr x))
|
||||
y)
|
||||
`(,amount . 0))))
|
||||
|
||||
#(define-markup-command (pad-right layout props amount arg)
|
||||
(number? markup?)
|
||||
(let* ((m (interpret-markup layout props arg))
|
||||
(x (ly:stencil-extent m X))
|
||||
(y (ly:stencil-extent m Y)))
|
||||
(ly:make-stencil (ly:stencil-expr m)
|
||||
(cons (car x) (+ (cdr x) amount))
|
||||
y)))
|
||||
|
||||
#(define-markup-command (score-equal-height-with-indents layout props lines)
|
||||
(markup-list?)
|
||||
@@ -236,144 +250,115 @@
|
||||
(let ((text (ly:grob-property grob 'text)))
|
||||
|
||||
(grob-interpret-markup grob (if (string? text)
|
||||
(make-pad-x-right-markup -0.1 (make-tied-lyric-markup text))
|
||||
(make-pad-right-markup -0.1 (make-tied-lyric-markup text))
|
||||
text))))
|
||||
|
||||
Chord_lyrics_spacing_engraver =
|
||||
#(lambda (ctx)
|
||||
(let ((last-lyric-syllable #f)
|
||||
(let ((last-note-head #f)
|
||||
(note-head-extended #f)
|
||||
(last-lyric-syllable-width 0)
|
||||
(lyric-width-since-last-chord 0)
|
||||
(music-columns-for-last-syllable 0)
|
||||
(last-printed-chord #f)
|
||||
(chord-width-since-last-lyric 0)
|
||||
(lyrics-seen-since-break #f)
|
||||
(have-a-rest #f)
|
||||
(stanza #f)
|
||||
; Akkord auf einer Skip-Silbe "_" nach Wortende soll über die folgende Silbe
|
||||
(word-continues #f)
|
||||
(continuation-this-step #f)
|
||||
(lyric-skip-this-step #f)
|
||||
(syllable-this-step #f)
|
||||
(chord-this-step #f)
|
||||
(chord-on-lyric-skip #f)
|
||||
(place-at-right-edge
|
||||
(lambda (grob anchor padding)
|
||||
(let ((anchor-width (interval-length (ly:grob-extent anchor anchor X))))
|
||||
(ly:grob-set-parent! grob X anchor)
|
||||
(ly:grob-set-property! grob 'X-offset (+ padding anchor-width))
|
||||
))))
|
||||
(notes-on-syllable-count 0)
|
||||
(last-chord-name #f)
|
||||
(remaining-chord-width 0)
|
||||
(last-rest #f)
|
||||
(rest-count 0)
|
||||
(multi-measure-rest-count 0)
|
||||
(stanza-shift 0))
|
||||
(make-engraver
|
||||
((start-translation-timestep engraver)
|
||||
(set! continuation-this-step #f)
|
||||
(set! lyric-skip-this-step #f)
|
||||
(set! syllable-this-step #f)
|
||||
(set! chord-this-step #f)
|
||||
)
|
||||
((stop-translation-timestep engraver)
|
||||
(if (and chord-on-lyric-skip (not (eq? chord-on-lyric-skip chord-this-step)))
|
||||
(begin
|
||||
(if (and syllable-this-step (not chord-this-step))
|
||||
(begin
|
||||
(ly:grob-set-parent! chord-on-lyric-skip X syllable-this-step)
|
||||
(ly:grob-set-property! chord-on-lyric-skip 'X-offset 0)
|
||||
(ly:grob-set-property! chord-on-lyric-skip 'extra-spacing-width '(+inf.0 . -inf.0))
|
||||
(set! lyric-width-since-last-chord (interval-length (ly:grob-extent syllable-this-step syllable-this-step X)))))
|
||||
(set! chord-on-lyric-skip #f)))
|
||||
(if syllable-this-step
|
||||
(set! word-continues continuation-this-step))
|
||||
)
|
||||
(listeners
|
||||
((multi-measure-rest-event engraver event)
|
||||
(set! have-a-rest #t)
|
||||
)
|
||||
((rest-event engraver event)
|
||||
(set! have-a-rest #t)
|
||||
)
|
||||
((hyphen-event engraver event)
|
||||
(set! continuation-this-step #t)
|
||||
)
|
||||
((extender-event engraver event)
|
||||
(set! continuation-this-step #t)
|
||||
)
|
||||
((lyric-event engraver event)
|
||||
(set! have-a-rest #f)
|
||||
; "_" wird zu " " und erzeugt keine LyricText
|
||||
(if (equal? (ly:event-property event 'text) " ")
|
||||
(begin
|
||||
(set! lyric-skip-this-step #t)
|
||||
(set! chord-on-lyric-skip #f)))
|
||||
(set! music-columns-for-last-syllable 0)
|
||||
(set! multi-measure-rest-count (+ multi-measure-rest-count 1))
|
||||
)
|
||||
((break-event engraver event)
|
||||
(set! last-lyric-syllable #f)
|
||||
(set! last-note-head #f)
|
||||
(set! note-head-extended #f)
|
||||
(set! last-lyric-syllable-width 0)
|
||||
(set! lyric-width-since-last-chord 0)
|
||||
(set! music-columns-for-last-syllable 0)
|
||||
(set! last-printed-chord #f)
|
||||
(set! chord-width-since-last-lyric 0)
|
||||
(set! lyrics-seen-since-break #f)
|
||||
(set! chord-on-lyric-skip #f)
|
||||
(set! notes-on-syllable-count 0)
|
||||
(set! last-chord-name #f)
|
||||
(set! remaining-chord-width 0)
|
||||
(set! last-rest #f)
|
||||
(set! rest-count 0)
|
||||
(set! multi-measure-rest-count 0)
|
||||
(set! stanza-shift 0)
|
||||
))
|
||||
(acknowledgers
|
||||
((musical-paper-column-interface this-engraver grob source-engraver)
|
||||
(set! music-columns-for-last-syllable (+ 1 music-columns-for-last-syllable))
|
||||
((note-head-interface this-engraver grob source-engraver)
|
||||
(if (and (> rest-count 0) (not last-note-head))
|
||||
(let ((rest-spacing-on-line-start 1.2))
|
||||
(ly:grob-set-property! grob 'minimum-X-extent (cons (- rest-spacing-on-line-start) 0))
|
||||
(set! stanza-shift rest-spacing-on-line-start)
|
||||
))
|
||||
(set! notes-on-syllable-count (+ 1 notes-on-syllable-count))
|
||||
(set! last-note-head grob)
|
||||
(set! note-head-extended #f)
|
||||
(set! last-rest #f)
|
||||
(set! rest-count 0)
|
||||
(set! multi-measure-rest-count 0)
|
||||
)
|
||||
((lyric-syllable-interface this-engraver grob source-engraver)
|
||||
(let ((syllable-width (interval-length (ly:grob-extent grob grob X))))
|
||||
(set! lyric-width-since-last-chord (+ lyric-width-since-last-chord syllable-width))
|
||||
)
|
||||
(if (> chord-width-since-last-lyric 0)
|
||||
(if lyrics-seen-since-break
|
||||
(ly:grob-set-property! grob 'extra-spacing-width
|
||||
(cons (- chord-width-since-last-lyric) (cdr (ly:grob-property grob 'extra-spacing-width '(0 . 0)))))
|
||||
(if last-printed-chord
|
||||
(let ((gap-for-starting-rest 2.0))
|
||||
(if stanza (ly:grob-set-property! stanza 'padding (+ 1 gap-for-starting-rest)))
|
||||
(ly:grob-set-parent! grob X last-printed-chord)
|
||||
(ly:grob-set-property! grob 'X-offset gap-for-starting-rest)
|
||||
)))
|
||||
)
|
||||
(set! syllable-this-step grob)
|
||||
(set! last-lyric-syllable grob)
|
||||
(set! chord-width-since-last-lyric 0)
|
||||
(set! lyrics-seen-since-break #t)
|
||||
(set! remaining-chord-width (max 0 (- remaining-chord-width lyric-width-since-last-chord)))
|
||||
(set! last-lyric-syllable-width (- (cdr (ly:grob-extent grob grob X)) 0.2))
|
||||
(set! lyric-width-since-last-chord (+ lyric-width-since-last-chord last-lyric-syllable-width))
|
||||
(if last-note-head (set! notes-on-syllable-count 1))
|
||||
)
|
||||
((chord-name-interface this-engraver grob source-engraver)
|
||||
(if (not (and
|
||||
(boolean? (ly:grob-property grob 'begin-of-line-visible))
|
||||
(ly:grob-property grob 'begin-of-line-visible)
|
||||
lyrics-seen-since-break))
|
||||
(let* ((last-printed-chord-width (if last-printed-chord (interval-length (ly:grob-extent last-printed-chord last-printed-chord X)) 0))
|
||||
(chord-overwidth (- last-printed-chord-width lyric-width-since-last-chord))
|
||||
(chord-gap 0.5))
|
||||
(if have-a-rest
|
||||
(let ((chord-width (interval-length (ly:grob-extent grob grob X))))
|
||||
(if last-lyric-syllable
|
||||
(if (and last-printed-chord (> chord-overwidth 0))
|
||||
(place-at-right-edge grob last-printed-chord chord-gap)
|
||||
(place-at-right-edge grob last-lyric-syllable 0))
|
||||
(if last-printed-chord
|
||||
(place-at-right-edge grob last-printed-chord chord-gap)))
|
||||
(set! chord-width-since-last-lyric (+ chord-width-since-last-lyric chord-width chord-gap))
|
||||
))
|
||||
(if (and last-lyric-syllable last-printed-chord (> chord-overwidth 0))
|
||||
(ly:grob-set-property! last-lyric-syllable 'extra-spacing-width
|
||||
(cons (car (ly:grob-property last-lyric-syllable 'extra-spacing-width '(0 . 0))) (+ chord-gap chord-overwidth)))
|
||||
)
|
||||
(set! lyric-width-since-last-chord (* (if last-lyric-syllable (interval-length (ly:grob-extent last-lyric-syllable last-lyric-syllable X)) 0) (- 1 (/ 1.0 music-columns-for-last-syllable))))
|
||||
(set! chord-this-step grob)
|
||||
(if (and lyric-skip-this-step (not have-a-rest) (not word-continues))
|
||||
(set! chord-on-lyric-skip grob))
|
||||
(set! last-printed-chord grob)
|
||||
(set! last-lyric-syllable #f)
|
||||
)
|
||||
(ly:grob-set-property! grob 'X-extent '(+inf.0 . -inf.0))
|
||||
)
|
||||
(ly:grob-property grob 'begin-of-line-visible)))
|
||||
(let ((on-a-rest (> rest-count 0)))
|
||||
(if (not on-a-rest)
|
||||
(set! notes-on-syllable-count (- notes-on-syllable-count 1)))
|
||||
(if (and last-chord-name (= multi-measure-rest-count 1) (> lyric-width-since-last-chord remaining-chord-width))
|
||||
(ly:grob-set-property! last-chord-name 'extra-spacing-width (cons -0.1 (+ 0.1 (- lyric-width-since-last-chord remaining-chord-width)))))
|
||||
(if last-note-head
|
||||
(let* ((last-note-min-x-extent (ly:grob-property last-note-head 'minimum-X-extent))
|
||||
(last-note-min-x-lower (if (pair? last-note-min-x-extent) (car last-note-min-x-extent) 0))
|
||||
(last-note-min-x-upper (if (pair? last-note-min-x-extent) (cdr last-note-min-x-extent) 0)))
|
||||
(if on-a-rest
|
||||
(begin
|
||||
(if (not note-head-extended)
|
||||
(begin
|
||||
(ly:grob-set-property! last-note-head 'minimum-X-extent
|
||||
(cons last-note-min-x-lower (- last-lyric-syllable-width -2 (* 2.2 rest-count))))
|
||||
(set! note-head-extended #t)
|
||||
))
|
||||
(ly:grob-set-property! last-rest 'minimum-X-extent (cons 0 2))
|
||||
)
|
||||
(if (and (> lyric-width-since-last-chord 0)
|
||||
(> remaining-chord-width lyric-width-since-last-chord))
|
||||
(ly:grob-set-property! last-note-head 'minimum-X-extent
|
||||
(cons (- -1.2 (- remaining-chord-width lyric-width-since-last-chord)) last-note-min-x-upper))
|
||||
(let* ((width-per-note-head 0.5)
|
||||
(note-width-since-last-chord (* width-per-note-head notes-on-syllable-count)))
|
||||
(if (> remaining-chord-width note-width-since-last-chord)
|
||||
(ly:grob-set-property! last-note-head 'minimum-X-extent
|
||||
(cons (- note-width-since-last-chord remaining-chord-width) last-note-min-x-upper))
|
||||
)
|
||||
)
|
||||
)
|
||||
)))
|
||||
(set! last-chord-name grob)
|
||||
(set! remaining-chord-width
|
||||
(if (and on-a-rest (equal? (ly:prob-property (ly:grob-property grob 'cause) 'duration) (ly:prob-property (ly:grob-property last-rest 'cause) 'duration)))
|
||||
0
|
||||
(cdr (ly:grob-extent grob grob X))))
|
||||
(set! lyric-width-since-last-chord 0)
|
||||
(set! notes-on-syllable-count (if on-a-rest 0 1))
|
||||
))
|
||||
)
|
||||
((stanza-number-interface this-engraver grob source-engraver)
|
||||
(set! stanza grob)
|
||||
)
|
||||
)
|
||||
)))
|
||||
((rest-interface this-engraver grob source-engraver)
|
||||
(set! rest-count (+ 1 rest-count))
|
||||
(set! last-rest grob)
|
||||
(set! multi-measure-rest-count 0)
|
||||
)
|
||||
((stanza-number-interface this-engraver grob source-engraver)
|
||||
(ly:grob-set-property! grob 'padding (+ 1 stanza-shift)))
|
||||
))))
|
||||
|
||||
%#(ly:set-option 'debug-skylines #t)
|
||||
|
||||
#(define-markup-command (chordlyrics layout props lyrics) (ly:music?)
|
||||
#:properties ((verse-chords #{#})
|
||||
@@ -394,8 +379,10 @@ Chord_lyrics_spacing_engraver =
|
||||
\new Lyrics \lyricsto "dummyvoice" { #lyrics }
|
||||
>>
|
||||
\layout {
|
||||
$verselayout
|
||||
#(customized-layout verselayout)
|
||||
\verselayout
|
||||
#(let
|
||||
((custom-size (ly:output-def-lookup verselayout 'size #f)))
|
||||
(if custom-size (layout-set-staff-size custom-size)))
|
||||
ragged-right = ##t
|
||||
\context {
|
||||
\Lyrics
|
||||
@@ -416,20 +403,17 @@ Chord_lyrics_spacing_engraver =
|
||||
\context {
|
||||
\Score
|
||||
\override PaperColumn.keep-inside-line = ##f
|
||||
% \override SpacingSpanner.strict-note-spacing = ##t
|
||||
% \override SpacingSpanner.strict-note-spacing = ##t
|
||||
\override SpacingSpanner.uniform-stretching = ##t
|
||||
\override SpacingSpanner.spacing-increment = 0
|
||||
% \override SpacingSpanner.packed-spacing = ##t
|
||||
%\override SpacingSpanner.packed-spacing = ##t
|
||||
\consists \Chord_lyrics_spacing_engraver
|
||||
% ChordPro engraver in Score context to collect all data
|
||||
\consists \ChordPro_score_collector
|
||||
\remove Bar_number_engraver
|
||||
\remove Mark_engraver
|
||||
\remove Jump_engraver
|
||||
\remove Volta_engraver
|
||||
\remove Parenthesis_engraver
|
||||
\remove Metronome_mark_engraver
|
||||
\remove Text_mark_engraver
|
||||
}
|
||||
\context {
|
||||
\Staff
|
||||
@@ -453,6 +437,15 @@ Chord_lyrics_spacing_engraver =
|
||||
\remove Note_heads_engraver
|
||||
\remove Script_engraver
|
||||
}
|
||||
\context {
|
||||
\NullVoice
|
||||
\consists Rest_engraver
|
||||
\omit Rest
|
||||
\override Rest.X-extent = #'(0 . 0)
|
||||
\undo \omit NoteHead
|
||||
\hide NoteHead
|
||||
\override NoteHead.X-extent = #'(0 . 0.5)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ width may require additional tweaking.)"
|
||||
|
||||
|
||||
includeSong =
|
||||
#(define-void-function (filename) (string?)
|
||||
#(define-void-function (parser location filename) (string?)
|
||||
#{
|
||||
\bookOutputName #filename
|
||||
#}
|
||||
@@ -130,47 +130,32 @@ includeSong =
|
||||
(acons label additional-page-numbers additional-page-switch-label-list))
|
||||
(set! song-list
|
||||
(acons (string->symbol filename)
|
||||
`(
|
||||
(label . ,label)
|
||||
(header . ,HEADER)
|
||||
(music . ,MUSIC)
|
||||
(layout . ,LAYOUT)
|
||||
(text-pages . ,(map (lambda (text)
|
||||
(acons 'label label
|
||||
(acons 'header HEADER
|
||||
(acons 'music MUSIC
|
||||
(acons 'layout LAYOUT
|
||||
(acons 'text-pages
|
||||
(map (lambda (text)
|
||||
#{ \markuplist \setsongfilename $filename $text #})
|
||||
TEXT_PAGES))
|
||||
)
|
||||
TEXT_PAGES)
|
||||
'())))))
|
||||
song-list))
|
||||
))
|
||||
|
||||
blankpage =
|
||||
#(define-void-function () ()
|
||||
#(define-void-function (parser location) ()
|
||||
(set! song-list
|
||||
(acons 'emptyPage
|
||||
'()
|
||||
song-list)))
|
||||
|
||||
imagepage =
|
||||
#(define-void-function (xsize filename) (number? string?)
|
||||
#(define-void-function (parser location xsize filename) (number? string?)
|
||||
(set! song-list
|
||||
(acons 'imagePage
|
||||
`((xsize . ,xsize)
|
||||
(filename . ,filename))
|
||||
(acons 'xsize xsize (acons 'filename filename '()))
|
||||
song-list)))
|
||||
|
||||
markuppage =
|
||||
#(define-void-function (mkup) (markup?)
|
||||
(set! song-list
|
||||
(acons 'markupPage
|
||||
`((markup . ,mkup))
|
||||
song-list)))
|
||||
|
||||
#(define chapters '())
|
||||
|
||||
songsChapter =
|
||||
#(define-void-function (title) (string?)
|
||||
(set! chapters
|
||||
(cons (cons title (length song-list)) chapters)))
|
||||
|
||||
#(define-markup-command (pagecenter layout props stuff)(markup?)
|
||||
(interpret-markup layout props
|
||||
(let ((halfpaperheight (/ (ly:output-def-lookup layout 'paper-height) 2))
|
||||
@@ -179,154 +164,53 @@ songsChapter =
|
||||
)))
|
||||
|
||||
songs =
|
||||
#(define-void-function () ()
|
||||
(let* ((ordered (reverse song-list))
|
||||
(total (length ordered))
|
||||
;; Ein Lied erzeugt nur dann einen PDF-Outline-Eintrag (/OUT), wenn
|
||||
;; title oder starttext gesetzt sind (siehe build-full-title). Nur solche
|
||||
;; Lieder duerfen als Kapitel-Kinder gezaehlt werden -- sonst wird die
|
||||
;; /Count zu hoch und der erste Folgeeintrag (z.B. ein spaeteres Kapitel)
|
||||
;; rutscht faelschlich als Kind mit hinein.
|
||||
;; Eingebettete Lieder (embedded_songs.ily) haben jeweils ein eigenes
|
||||
;; Lesezeichen, daher die Anzahl statt eines Booleans.
|
||||
(bookmark-count
|
||||
(lambda (e)
|
||||
(if (or (eq? (car e) 'emptyPage)
|
||||
(eq? (car e) 'imagePage)
|
||||
(eq? (car e) 'markupPage))
|
||||
0
|
||||
(let* ((headermodule (ly:book-header (assq-ref (cdr e) 'header)))
|
||||
(vars (extract-and-check-vars-from-module headermodule '(title starttext))))
|
||||
(+ (if (or (assq-ref vars 'title) (assq-ref vars 'starttext)) 1 0)
|
||||
(count song-pdf-bookmark-title (embedded-songs-of-header headermodule)))))))
|
||||
(count-bookmark-songs
|
||||
(lambda (start end)
|
||||
(let loop ((i 0) (l ordered) (c 0))
|
||||
(cond ((or (null? l) (>= i end)) c)
|
||||
((< i start) (loop (+ i 1) (cdr l) c))
|
||||
(else (loop (+ i 1) (cdr l) (+ c (bookmark-count (car l)))))))))
|
||||
;; chapters: (title . start-index). start-index = Anzahl der song-list-
|
||||
;; Eintraege beim Aufruf von songsChapter = Index in `ordered`, ab dem
|
||||
;; das Kapitel beginnt.
|
||||
(chapters-asc (sort chapters (lambda (a b) (< (cdr a) (cdr b)))))
|
||||
;; pending: aufsteigende Liste von (start title count); count = Anzahl
|
||||
;; der Lesezeichen-Lieder von diesem Kapitel bis zum Beginn des naechsten.
|
||||
(pending
|
||||
(let loop ((chs chapters-asc) (acc '()))
|
||||
(if (null? chs)
|
||||
(reverse acc)
|
||||
(let* ((title (caar chs))
|
||||
(start (cdar chs))
|
||||
(end (if (null? (cdr chs)) total (cdadr chs)))
|
||||
(cnt (count-bookmark-songs start end)))
|
||||
(loop (cdr chs) (cons (list start title cnt) acc))))))
|
||||
;; Aktuell aktives Kapitel (Titel-String) waehrend des Durchlaufs. Wird
|
||||
;; gesetzt, sobald ein Kapitel aktiviert (aus `pending` entfernt) wird --
|
||||
;; egal ob auf einer Seite (chapter-prefixed-markup) oder auf dem ersten
|
||||
;; Song. Jeder danach folgende Song erhaelt dieses Kapitel als
|
||||
;; chapterref-Header-Feld, woraus toc_include.ily den Kapitel-Index baut.
|
||||
(current-chapter #f)
|
||||
;; Stellt einer beliebigen Seite (markup-/image-/emptyPage) den Kapitel-
|
||||
;; Eintrag (chapter-to-pdf-toc) bei, falls an Position `this-index` ein
|
||||
;; Kapitel faellig ist, und entfernt es aus `pending`. So fuehrt die
|
||||
;; Kapitel-Referenz zur ersten Seite nach dem \songsChapter -- egal
|
||||
;; welcher Seitentyp das ist. Der Eintrag wird als unsichtbares Overlay
|
||||
;; (\combine) beigelegt, damit er das Seitenlayout nicht veraendert;
|
||||
;; \with-dimensions gibt dem sonst extent-losen pdfmark einen minimalen
|
||||
;; Extent, damit er auch auf leeren Seiten nicht verworfen wird.
|
||||
(chapter-prefixed-markup
|
||||
(lambda (this-index base-markup)
|
||||
(if (and (pair? pending) (<= (car (car pending)) this-index))
|
||||
(let ((cnt (caddr (car pending)))
|
||||
(title (cadr (car pending))))
|
||||
(set! pending (cdr pending))
|
||||
(set! current-chapter title)
|
||||
(make-combine-markup
|
||||
base-markup
|
||||
(make-with-dimensions-markup '(0 . 0) '(0 . 0.1)
|
||||
(make-chapter-to-pdf-toc-markup cnt title))))
|
||||
base-markup)))
|
||||
(index 0))
|
||||
#(define-void-function (parser location) ()
|
||||
(for-each (lambda (songitems)
|
||||
(let ((this-index index))
|
||||
(set! index (+ index 1))
|
||||
(ly:book-add-bookpart! (ly:parser-lookup '$current-book)
|
||||
(let ((filename (car songitems))
|
||||
(songvars (cdr songitems)))
|
||||
(if (eq? filename 'emptyPage)
|
||||
#{ \bookpart { \markup { $(chapter-prefixed-markup this-index (make-null-markup)) } } #}
|
||||
(if (eq? filename 'markupPage)
|
||||
;; Kapitelanfang auf einer markuppage: Kapitel-Eintrag wird dieser
|
||||
;; Seite beigelegt (siehe chapter-prefixed-markup).
|
||||
#{ \bookpart { \markup { $(chapter-prefixed-markup this-index (assq-ref songvars 'markup)) } } #}
|
||||
(if (eq? filename 'imagePage)
|
||||
(let* ((xsize (assq-ref songvars 'xsize))
|
||||
(filename (ly:format "~a/~a" imagePagePath (assq-ref songvars 'filename)))
|
||||
(img-markup #{ \markup { \pagecenter { \epsfile #X #xsize #filename } } #}))
|
||||
#{ \bookpart {
|
||||
\paper {
|
||||
%{
|
||||
inner-margin = 0
|
||||
outer-margin = 0
|
||||
binding-offset = 0
|
||||
top-margin = 0
|
||||
bottom-margin = 0
|
||||
%}
|
||||
print-page-number = ##f
|
||||
last-bottom-spacing = #'((basic-distance . 0) (minimum-distance . 0) (padding . 0))
|
||||
page-count = 1
|
||||
}
|
||||
\markup { $(chapter-prefixed-markup this-index img-markup) }
|
||||
} #}
|
||||
)
|
||||
;; Ist ein Kapitel faellig (Start <= aktuelle Position) und dies ein
|
||||
;; echtes Lied, wird die Kapitelinfo an dieses Lied gehaengt und aus
|
||||
;; `pending` entfernt.
|
||||
(let* ((newnumber (+ 1 song-number))
|
||||
(chaptertitle (if (and (pair? pending) (<= (car (car pending)) this-index))
|
||||
(cadr (car pending)) #f))
|
||||
(chaptercount (if chaptertitle (caddr (car pending)) 0))
|
||||
;; Startet das Kapitel erst auf diesem Song (nicht schon auf
|
||||
;; einer vorangehenden Seite), wird current-chapter jetzt
|
||||
;; gesetzt und pending entfernt -- vor dem Bau des Headers,
|
||||
;; damit chapterref bereits das neue Kapitel enthaelt.
|
||||
(_ (if chaptertitle
|
||||
(begin (set! current-chapter chaptertitle)
|
||||
(set! pending (cdr pending)))))
|
||||
(header #{ \bookpart { $(assq-ref songvars 'header) \header {
|
||||
songfilename = $(symbol->string filename)
|
||||
myindexlabel = #(assq-ref songvars 'label)
|
||||
songnumber = #(number->string newnumber)
|
||||
chaptertitle = #chaptertitle
|
||||
chaptercount = #chaptercount
|
||||
chapterref = #current-chapter
|
||||
} } #})
|
||||
(music (assq-ref songvars 'music))
|
||||
(layout (assq-ref songvars 'layout))
|
||||
(text-pages (assq-ref songvars 'text-pages))
|
||||
(label (assq-ref songvars 'label))
|
||||
(toc-music (header-module-to-toc! (ly:book-header header) label)))
|
||||
(ly:book-add-bookpart! (ly:parser-lookup '$current-book)
|
||||
(let ((filename (car songitems))
|
||||
(songvars (cdr songitems)))
|
||||
(if (eq? filename 'emptyPage)
|
||||
#{ \bookpart { \markup { \null } } #}
|
||||
(if (eq? filename 'imagePage)
|
||||
(let ((xsize (assq-ref songvars 'xsize))
|
||||
(filename (ly:format "~a/~a" imagePagePath (assq-ref songvars 'filename))))
|
||||
#{ \bookpart {
|
||||
\paper {
|
||||
%{
|
||||
inner-margin = 0
|
||||
outer-margin = 0
|
||||
binding-offset = 0
|
||||
top-margin = 0
|
||||
bottom-margin = 0
|
||||
%}
|
||||
print-page-number = ##f
|
||||
last-bottom-spacing = #'((basic-distance . 0) (minimum-distance . 0) (padding . 0))
|
||||
page-count = 1
|
||||
}
|
||||
\markup { \pagecenter { \epsfile #X #xsize #filename } }
|
||||
} #}
|
||||
)
|
||||
(let* ((newnumber (+ 1 song-number))
|
||||
(header #{ \bookpart { $(assq-ref songvars 'header) \header {
|
||||
songfilename = $(symbol->string filename)
|
||||
myindexlabel = #(assq-ref songvars 'label)
|
||||
songnumber = #(number->string newnumber)
|
||||
} } #})
|
||||
(music (assq-ref songvars 'music))
|
||||
(layout (assq-ref songvars 'layout))
|
||||
(text-pages (assq-ref songvars 'text-pages))
|
||||
(label (assq-ref songvars 'label)))
|
||||
(set! song-number newnumber)
|
||||
;; Eingebettete Lieder: eigene Liednummer, gleiche Seite (label)
|
||||
(for-each
|
||||
(lambda (song)
|
||||
(let ((tocheader (make-module)))
|
||||
(set! song-number (+ 1 song-number))
|
||||
(ly:module-copy tocheader song)
|
||||
(module-define! tocheader 'songnumber (number->string song-number))
|
||||
(module-define! tocheader 'chapterref current-chapter)
|
||||
(header-module-to-toc! tocheader label)))
|
||||
(embedded-songs-of-header (ly:book-header header)))
|
||||
#{
|
||||
\bookpart {
|
||||
$header
|
||||
$toc-music
|
||||
\score { $music \layout { $layout songfilename = $(symbol->string filename) } }
|
||||
\headerToTOC #header #label
|
||||
\score { $music \layout { $layout } }
|
||||
$(add-text-pages text-pages)
|
||||
}
|
||||
#}))))))))
|
||||
ordered
|
||||
)))
|
||||
#}))))))
|
||||
(reverse song-list)
|
||||
))
|
||||
|
||||
#(define (boernel-stats)
|
||||
(let (
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
(for-each (lambda (category)
|
||||
(let* ((catsym (string->symbol category))
|
||||
(catlist (hashq-ref category-index-hash catsym
|
||||
(list (list label 'indexCategoryMarkup `(((combine-with-next . #t) (rawtext . ,category))))))))
|
||||
(list (list label 'indexCategoryMarkup `(((rawtext . ,category))))))))
|
||||
(if (assq catsym category-names)
|
||||
(hashq-set! category-index-hash catsym
|
||||
(cons (list label markup-symbol textoptions) catlist))
|
||||
@@ -114,7 +114,7 @@
|
||||
(for-each (lambda (authorID)
|
||||
(let* ((authorsym (string->symbol authorID))
|
||||
(authorlist (hashq-ref author-index-hash authorsym
|
||||
(list (list label 'indexAuthorMarkup `(((combine-with-next . #t) (rawtext . ,authorID))))))))
|
||||
(list (list label 'indexAuthorMarkup `(((rawtext . ,authorID))))))))
|
||||
(hashq-set! author-index-hash authorsym
|
||||
(cons (list label markup-symbol textoptions) authorlist))
|
||||
))
|
||||
@@ -132,37 +132,6 @@
|
||||
author-index-hash)
|
||||
(lambda (a b) (string-ci<? (car a) (car b))))))))
|
||||
|
||||
% code for chapter index
|
||||
% Anders als bei Kategorien/Autoren ergibt sich die Kapitelzugehoerigkeit nicht
|
||||
% aus dem Song-Header, sondern aus dem \songsChapter, das dem Song vorangeht
|
||||
% (in book_include.ily als Header-Feld chapterref an jeden Song gehaengt).
|
||||
% Die Kapitel behalten hier ihre Auftritts-Reihenfolge (nicht alphabetisch),
|
||||
% ebenso die Songs innerhalb eines Kapitels ihre Song-Reihenfolge.
|
||||
#(define*-public (add-chapter-index-item! chapter markup-symbol textoptions #:optional label) #f)
|
||||
#(define-public (chapter-index-items) #f)
|
||||
|
||||
#(let ((chapter-index-hash (make-hash-table))
|
||||
(chapter-order '()))
|
||||
(set! add-chapter-index-item!
|
||||
(lambda* (chapter markup-symbol textoptions #:optional (label (gensym "index")))
|
||||
(let* ((chaptersym (string->symbol chapter))
|
||||
(existing (hashq-ref chapter-index-hash chaptersym #f))
|
||||
(chapterlist (or existing
|
||||
(begin
|
||||
(set! chapter-order (cons chaptersym chapter-order))
|
||||
(list (list label 'indexChapterMarkup `(((combine-with-next . #t) (rawtext . ,chapter))))))))
|
||||
)
|
||||
(hashq-set! chapter-index-hash chaptersym
|
||||
(cons (list label markup-symbol textoptions) chapterlist)))
|
||||
(make-music 'EventChord
|
||||
'page-marker #t
|
||||
'page-label label
|
||||
'elements (list (make-music 'LabelEvent
|
||||
'page-label label)))))
|
||||
(set! chapter-index-items (lambda ()
|
||||
(append-map (lambda (chaptersym) (reverse (hashq-ref chapter-index-hash chaptersym (list))))
|
||||
(reverse chapter-order)))))
|
||||
|
||||
|
||||
#(define-markup-command (with-link-symbol-ref layout props symbol arg)
|
||||
(symbol? markup?)
|
||||
@@ -246,52 +215,37 @@
|
||||
(make-null-markup))
|
||||
\vspace #.4
|
||||
}
|
||||
indexChapterMarkup = \markup \override #'(baseline-skip . 1.5) \left-column {
|
||||
\vspace #1
|
||||
\sans \bold \fontsize #3 \fromproperty #'index:text
|
||||
\vspace #.4
|
||||
}
|
||||
}
|
||||
|
||||
#(define (prepare-item-markup items layout)
|
||||
(define (single-item-markup index-item)
|
||||
(let* ((label (car index-item))
|
||||
(index-markup (cadr index-item))
|
||||
(textoptions (caddr index-item))
|
||||
(text (chain-assoc-get 'rawtext textoptions))
|
||||
(alternative (chain-assoc-get 'alternative textoptions))
|
||||
(songnumber (chain-assoc-get 'songnumber textoptions)))
|
||||
(markup #:override (cons 'index:label label)
|
||||
#:override (cons 'index:page (markup #:custom-page-number label -1))
|
||||
#:override (cons 'index:text text)
|
||||
#:override (cons 'index:alternative alternative)
|
||||
#:override (cons 'index:songnumber songnumber)
|
||||
(ly:output-def-lookup layout index-markup))))
|
||||
(if (null? items)
|
||||
items
|
||||
(let* ((index-item (car items))
|
||||
(combine-with-next (chain-assoc-get 'combine-with-next (caddr index-item) #f))
|
||||
(restitems (cdr items))
|
||||
(item-markup (single-item-markup index-item)))
|
||||
(if (and combine-with-next (not (null? restitems)))
|
||||
(cons (make-column-markup (list item-markup (single-item-markup (car restitems)))) (prepare-item-markup (cdr restitems) layout))
|
||||
(cons item-markup (prepare-item-markup restitems layout))))
|
||||
))
|
||||
(map (lambda (index-item)
|
||||
(let* ((label (car index-item))
|
||||
(index-markup (cadr index-item))
|
||||
(textoptions (caddr index-item))
|
||||
(text (chain-assoc-get 'rawtext textoptions))
|
||||
(alternative (chain-assoc-get 'alternative textoptions))
|
||||
(songnumber (chain-assoc-get 'songnumber textoptions)))
|
||||
(markup #:override (cons 'index:label label)
|
||||
#:override (cons 'index:page (markup #:custom-page-number label -1))
|
||||
#:override (cons 'index:text text)
|
||||
#:override (cons 'index:alternative alternative)
|
||||
#:override (cons 'index:songnumber songnumber)
|
||||
(ly:output-def-lookup layout index-markup))))
|
||||
(items)))
|
||||
|
||||
#(define-markup-list-command (index-in-columns-with-title layout props index-type title-markup) (symbol? markup?)
|
||||
( _i "Outputs index alphabetical sorted or in categories" )
|
||||
(let ((items (case index-type
|
||||
((alphabetical) index-items)
|
||||
((categories) category-index-items)
|
||||
((authors) author-index-items)
|
||||
((chapters) chapter-index-items)))
|
||||
((authors) author-index-items)))
|
||||
(title (interpret-markup layout props title-markup)))
|
||||
(cons title
|
||||
(interpret-markup-list layout props
|
||||
(make-columnlayout-markup-list songTocColumns 2
|
||||
(let ((h (- (ly:output-def-lookup layout 'paper-height) 12)))
|
||||
(cons (- h (interval-length (ly:stencil-extent title Y))) h))
|
||||
(prepare-item-markup (items) layout))))))
|
||||
(prepare-item-markup items layout))))))
|
||||
|
||||
indexItem =
|
||||
#(define-music-function (parser location sorttext text) (string? markup?)
|
||||
@@ -301,30 +255,36 @@ indexItem =
|
||||
indexSection =
|
||||
#(define-music-function (parser location sorttext text) (string? markup?)
|
||||
"Add a section line to the alphabetical index, using @code{indexSectionMarkup} paper variable markup. This can be used to divide the alphabetical index into different sections, for example one section for each first letter."
|
||||
(add-index-item! 'indexSectionMarkup (prepend-alist-chain 'combine-with-next #t (prepend-alist-chain 'rawtext text '())) sorttext))
|
||||
(add-index-item! 'indexSectionMarkup (prepend-alist-chain 'rawtext text '()) sorttext))
|
||||
|
||||
#(define (extract-and-check-vars-from-header bookheader varlist)
|
||||
(extract-and-check-vars-from-module (ly:book-header bookheader) varlist))
|
||||
(let* ((headervars (hash-map->list cons (struct-ref (ly:book-header bookheader) 0)))
|
||||
(extract-var-and-check (lambda (headervar)
|
||||
(let* ((variableref (assoc-ref headervars headervar))
|
||||
(extracted (if variableref (variable-ref variableref) #f)))
|
||||
(if (and extracted (not (and (string? extracted) (string-null? extracted)))) extracted #f)))))
|
||||
(map (lambda (varsymbol)
|
||||
(cons varsymbol (extract-var-and-check varsymbol))
|
||||
) varlist)))
|
||||
|
||||
#(define (header-module-to-toc! headermodule label)
|
||||
headerToTOC = #(define-music-function (parser location header label) (ly:book? symbol?)
|
||||
(define (all-author-ids authors)
|
||||
(let ((poetIds (find-author-ids-by 'text authors))
|
||||
(translatorIds (find-author-ids-by 'translation authors))
|
||||
(versePoetData (find-author-id-with-part-numbers 'verse authors))
|
||||
(composerIds (find-author-ids-by 'melody authors))
|
||||
(verseComposerData (find-author-id-with-part-numbers 'meloverse authors))
|
||||
(refComposerIds (find-author-ids-by 'meloref authors))
|
||||
(voiceComposerData (find-author-id-with-part-numbers 'voice authors))
|
||||
(compositionIds (find-author-ids-by 'composition authors))
|
||||
(adaptionIds (find-author-ids-by 'adaption authors))
|
||||
(bridgeIds (find-author-ids-by 'bridge authors))
|
||||
(interludeIds (find-author-ids-by 'interlude authors)))
|
||||
(delete-duplicates
|
||||
(append poetIds translatorIds (map car versePoetData) composerIds (map car verseComposerData) refComposerIds (map car voiceComposerData) compositionIds adaptionIds bridgeIds interludeIds))
|
||||
(append poetIds translatorIds (map car versePoetData) composerIds (map car verseComposerData) (map car voiceComposerData) compositionIds adaptionIds bridgeIds interludeIds))
|
||||
))
|
||||
(let*
|
||||
(
|
||||
(extractedheadervars (extract-and-check-vars-from-module headermodule '(title starttext alttitle categorytitle categories authors songnumber chapterref)))
|
||||
(extractedheadervars (extract-and-check-vars-from-header header '(title starttext alttitle categorytitle categories authors songnumber)))
|
||||
(title (assq-ref extractedheadervars 'title))
|
||||
(starttext (assq-ref extractedheadervars 'starttext))
|
||||
(alttitle (assq-ref extractedheadervars 'alttitle))
|
||||
@@ -332,14 +292,12 @@ indexSection =
|
||||
(categories (assq-ref extractedheadervars 'categories))
|
||||
(authors (assq-ref extractedheadervars 'authors))
|
||||
(songnumber (assq-ref extractedheadervars 'songnumber))
|
||||
(chapterref (assq-ref extractedheadervars 'chapterref))
|
||||
(textoptions (lambda (text alternative) `(((rawtext . ,text) (alternative . ,alternative) (songnumber . ,songnumber)))))
|
||||
(add-to-toc! (lambda (toctitle alternative)
|
||||
(add-index-item! 'indexItemMarkup (textoptions toctitle alternative) toctitle label)))
|
||||
)
|
||||
(if categories (add-category-index-item! (string-tokenize categories) 'indexItemMarkup (textoptions (if categorytitle categorytitle title) #f) label))
|
||||
(if authors (add-author-index-item! (all-author-ids authors) 'indexItemMarkup (textoptions (if categorytitle categorytitle title) #f) label))
|
||||
(if chapterref (add-chapter-index-item! chapterref 'indexItemMarkup (textoptions (if categorytitle categorytitle title) #f) label))
|
||||
(if starttext (add-to-toc! starttext #t))
|
||||
(if alttitle
|
||||
(if (list? alttitle)
|
||||
@@ -350,9 +308,6 @@ indexSection =
|
||||
(if title (add-to-toc! title #f) #{ #})
|
||||
))
|
||||
|
||||
headerToTOC = #(define-music-function (parser location header label) (ly:book? symbol?)
|
||||
(header-module-to-toc! (ly:book-header header) label))
|
||||
|
||||
|
||||
%% https://github.com/NalaGinrut/guile-csv/blob/master/csv/csv.scm
|
||||
|
||||
@@ -398,8 +353,11 @@ headerToTOC = #(define-music-function (parser location header label) (ly:book? s
|
||||
(para-lines (map cleanup-whitespaces para-strings)))
|
||||
(string-join para-lines "\n")))
|
||||
(define (generate-toc-csv labelPageTable)
|
||||
(define (song-line filename page-number headermodule)
|
||||
(let* ((extractedheadervars (extract-and-check-vars-from-module headermodule
|
||||
(let ((song-lines (map (lambda (song)
|
||||
(let* ((filename (symbol->string (car song)))
|
||||
(songvars (cdr song))
|
||||
(page-number (number->string (assoc-get (assq-ref songvars 'label) labelPageTable)))
|
||||
(extractedheadervars (extract-and-check-vars-from-header (assq-ref songvars 'header)
|
||||
'(title starttext alttitle categorytitle categories authors year_text year_melody year_translation year_composition year_adaption infotext translation pronunciation copyright source)))
|
||||
(headervar-or-empty (lambda (varsym)
|
||||
(let ((extracted (assq-ref extractedheadervars varsym)))
|
||||
@@ -410,7 +368,6 @@ headerToTOC = #(define-music-function (parser location header label) (ly:book? s
|
||||
(versePoetData (find-author-id-with-part-numbers 'verse authors))
|
||||
(composerIds (find-author-ids-by 'melody authors))
|
||||
(verseComposerData (find-author-id-with-part-numbers 'meloverse authors))
|
||||
(refComposerIds (find-author-ids-by 'meloref authors))
|
||||
(voiceComposerData (find-author-id-with-part-numbers 'voice authors))
|
||||
(compositionIds (find-author-ids-by 'composition authors))
|
||||
(adaptionTextIds (find-author-ids-by 'adaption_text authors))
|
||||
@@ -432,7 +389,7 @@ headerToTOC = #(define-music-function (parser location header label) (ly:book? s
|
||||
(headervar-or-empty 'categories)
|
||||
(format-authors (append poetIds adaptionTextIds (map car versePoetData)))
|
||||
(format-authors translatorIds)
|
||||
(format-authors (append composerIds compositionIds adaptionMusicIds bridgeIds interludeIds (map car voiceComposerData) (map car verseComposerData) refComposerIds))
|
||||
(format-authors (append composerIds compositionIds adaptionMusicIds bridgeIds interludeIds (map car voiceComposerData) (map car verseComposerData)))
|
||||
(headervar-or-empty 'year_text)
|
||||
(headervar-or-empty 'year_melody)
|
||||
(headervar-or-empty 'year_translation)
|
||||
@@ -445,16 +402,7 @@ headerToTOC = #(define-music-function (parser location header label) (ly:book? s
|
||||
(format-info-paragraphs (headervar-or-empty 'translation))
|
||||
(format-info-paragraphs (headervar-or-empty 'pronunciation))
|
||||
))))
|
||||
;; Eingebettete Lieder (embedded_songs.ily) bekommen eigene Zeilen mit
|
||||
;; Dateiname und Seite des Hauptlieds.
|
||||
(let ((song-lines (append-map (lambda (song)
|
||||
(let* ((filename (symbol->string (car song)))
|
||||
(songvars (cdr song))
|
||||
(page-number (assoc-get (assq-ref songvars 'label) labelPageTable))
|
||||
(headermodule (ly:book-header (assq-ref songvars 'header))))
|
||||
(map (lambda (module) (song-line filename page-number module))
|
||||
(cons headermodule (embedded-songs-of-header headermodule)))))
|
||||
(alist-delete 'markupPage (alist-delete 'imagePage (alist-delete 'emptyPage song-list))))))
|
||||
(alist-delete 'imagePage (alist-delete 'emptyPage song-list)))))
|
||||
(call-with-output-file "toc.csv"
|
||||
(lambda (port)
|
||||
(csv-write (cons '(
|
||||
@@ -484,6 +432,6 @@ headerToTOC = #(define-music-function (parser location header label) (ly:book? s
|
||||
; we use a delayed stencil to have all the page references available
|
||||
(ly:make-stencil
|
||||
`(delay-stencil-evaluation
|
||||
,(delay (let* ((table (ly:output-def-lookup layout 'label-page-string-table)))
|
||||
,(delay (let* ((table (ly:output-def-lookup layout 'label-page-table)))
|
||||
(generate-toc-csv (if (list? table) table '()))
|
||||
empty-stencil)))))
|
||||
@@ -1,17 +1,8 @@
|
||||
% set the speed of the midi music
|
||||
#(define midiQuarterNoteSpeed (if (defined? 'midiQuarterNoteSpeed) midiQuarterNoteSpeed 90))
|
||||
|
||||
MUSIC = { \transposable #TRANSPOSITION \MUSIC }
|
||||
|
||||
%% Eingebettete Lieder (siehe embedded_songs.ily) im Header des Hauptlieds
|
||||
%% vermerken, daraus bauen Footer, PDF-Lesezeichen und Verzeichnisse.
|
||||
#(if (and (pair? EMBEDDED_SONGS) (ly:book? HEADER) (ly:book-header HEADER))
|
||||
(module-define! (ly:book-header HEADER) 'embeddedsongs EMBEDDED_SONGS))
|
||||
|
||||
LAYOUT = \layout {
|
||||
\LAYOUT
|
||||
#(customized-layout LAYOUT)
|
||||
}
|
||||
|
||||
#(customize-embedded-score-layouts! (list TEXT TEXT_PAGES))
|
||||
|
||||
verselayout = \layout {
|
||||
\LAYOUT
|
||||
\context {
|
||||
@@ -20,12 +11,18 @@ verselayout = \layout {
|
||||
}
|
||||
}
|
||||
|
||||
LAYOUT = \layout {
|
||||
\LAYOUT
|
||||
#(let
|
||||
((custom-size (ly:output-def-lookup LAYOUT 'size #f)))
|
||||
(if custom-size (layout-set-staff-size custom-size)))
|
||||
}
|
||||
|
||||
TEXT = \markuplist {
|
||||
\override #`(transposition . ,TRANSPOSITION)
|
||||
\override #`(verselayout . ,verselayout)
|
||||
\override #`(verse-chords . ,#{ \chords { \verseChords } #})
|
||||
\override #`(verse-reference-voice . ,#{ \global \firstVoice #})
|
||||
\handle-tag-groups \recordedTagGroups
|
||||
\TEXT
|
||||
}
|
||||
|
||||
@@ -37,7 +34,6 @@ TEXT = \markuplist {
|
||||
\override #`(verselayout . ,verselayout)
|
||||
\override #`(verse-chords . ,#{ \chords { \verseChords } #})
|
||||
\override #`(verse-reference-voice . ,#{ \global \firstVoice #})
|
||||
\handle-tag-groups \recordedTagGroups
|
||||
#text
|
||||
}
|
||||
#})
|
||||
@@ -48,20 +44,6 @@ TEXT = \markuplist {
|
||||
TEXT_PAGES
|
||||
(list TEXT))))
|
||||
|
||||
%% Add invisible ChordPro write trigger to last TEXT_PAGES markuplist
|
||||
#(when (and (defined? 'chordpro-export-enabled) chordpro-export-enabled (pair? TEXT_PAGES))
|
||||
(let* ((last-index (- (length TEXT_PAGES) 1))
|
||||
(last-page (list-ref TEXT_PAGES last-index))
|
||||
(modified-last-page #{
|
||||
\markuplist {
|
||||
#last-page
|
||||
\chordpro-delayed-write
|
||||
}
|
||||
#}))
|
||||
(set! TEXT_PAGES
|
||||
(append (list-head TEXT_PAGES last-index)
|
||||
(list modified-last-page)))))
|
||||
|
||||
#(define (add-text-pages text-pages)
|
||||
(if (pair? text-pages)
|
||||
(begin
|
||||
@@ -78,41 +60,21 @@ TEXT = \markuplist {
|
||||
(if header (set! $defaultheader header))
|
||||
(if paper (set! $defaultpaper paper))
|
||||
)
|
||||
|
||||
;; ChordPro export: Store filename and extract metadata from basicSongInfo FIRST
|
||||
(when (and (defined? 'chordpro-export-enabled) chordpro-export-enabled)
|
||||
;; Use ly:parser-output-name which returns the output basename
|
||||
;; This will write relative to current working directory (same as PDF)
|
||||
(let ((output-name (ly:parser-output-name)))
|
||||
(set! chordpro-current-filename output-name))
|
||||
|
||||
;; Try to extract metadata from the HEADER (falls back to basicSongInfo)
|
||||
(let ((header-module (if (and (ly:book? HEADER) (ly:book-header HEADER))
|
||||
(ly:book-header HEADER)
|
||||
(and (defined? 'basicSongInfo) basicSongInfo))))
|
||||
(when header-module
|
||||
(let* ((header-alist (ly:module->alist header-module))
|
||||
(title (assoc-ref header-alist 'title))
|
||||
(authors (assoc-ref header-alist 'authors)))
|
||||
(when title
|
||||
(set! chordpro-header-title
|
||||
(if (markup? title)
|
||||
(markup->string title)
|
||||
(if (string? title) title "Untitled"))))
|
||||
(when authors
|
||||
(set! chordpro-header-authors authors))))))
|
||||
|
||||
(add-score #{
|
||||
\score {
|
||||
\MUSIC
|
||||
\layout { \LAYOUT }
|
||||
}#})
|
||||
(add-text-pages TEXT_PAGES)
|
||||
|
||||
(add-score #{
|
||||
\score {
|
||||
\unfoldRepeats { \MUSIC \INLINESCOREMUSIC }
|
||||
\midi {
|
||||
\context {
|
||||
\Score
|
||||
% Tempo des midi files
|
||||
tempoWholesPerMinute = #(/ midiQuarterNoteSpeed 4)
|
||||
}
|
||||
\context {
|
||||
\Staff
|
||||
\remove "Staff_performer"
|
||||
@@ -123,4 +85,4 @@ TEXT = \markuplist {
|
||||
}
|
||||
}
|
||||
}#})
|
||||
))
|
||||
))
|
||||
@@ -4,4 +4,4 @@ HEADER = \bookpart {
|
||||
\basicSongInfo
|
||||
}
|
||||
}
|
||||
\include #(if noDefaultOutput "../private_includes/void.ily" "layout_bottom.ily")
|
||||
\include #(if noDefaultOutput "../private_includes/void.ily" "layout_bottom.ily")
|
||||
Reference in new issue
Block a user