%% 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 '()))))))