Inhaltlich sinnvollere Aufteilung der include Skripte

This commit is contained in:
Christoph Wagner 2023-07-22 19:37:17 +02:00
parent 3c8c23a638
commit 5113539951
17 changed files with 767 additions and 736 deletions

View File

@ -1,3 +1,3 @@
# lilypond-common-includes
Lilypondskripte zur Erstellung eines Liederbuches
Lilypondskripte zur Erstellung eines Liederbuches

63
arrows_in_scores.ly Normal file
View File

@ -0,0 +1,63 @@
%%%%%%%%%%%%%%%%% Pfeilezeugs
% http://lilypond.org/doc/v2.19/Documentation/snippets/vocal-music
#(define-markup-command (arrow-at-angle layout props angle-deg length fill)
(number? number? boolean?)
(let* (
(PI-OVER-180 (/ (atan 1 1) 34))
(degrees->radians (lambda (degrees) (* degrees PI-OVER-180)))
(angle-rad (degrees->radians angle-deg))
(target-x (* length (cos angle-rad)))
(target-y (* length (sin angle-rad))))
(interpret-markup layout props
(markup
#:translate (cons (/ target-x 2) (/ target-y 2))
#:rotate angle-deg
#:translate (cons (/ length -2) 0)
#:concat (#:draw-line (cons length 0)
#:arrow-head X RIGHT fill)))))
splitStaffBarLineMarkup = \markup \with-dimensions #'(0 . 0) #'(0 . 0) {
\combine
\arrow-at-angle #45 #(sqrt 8) ##t
\arrow-at-angle #-45 #(sqrt 8) ##t
}
splitStaffBarLine = {
\once \override Staff.BarLine.stencil =
#(lambda (grob)
(ly:stencil-combine-at-edge
(ly:bar-line::print grob)
X RIGHT
(grob-interpret-markup grob splitStaffBarLineMarkup)
0))
\break
}
convDownStaffBarLine = {
\once \override Staff.BarLine.stencil =
#(lambda (grob)
(ly:stencil-combine-at-edge
(ly:bar-line::print grob)
X RIGHT
(grob-interpret-markup grob #{
\markup\with-dimensions #'(0 . 0) #'(0 . 0) {
\translate #'(0 . -.13)\arrow-at-angle #-45 #(sqrt 8) ##t
}#})
0))
\break
}
convUpStaffBarLine = {
\once \override Staff.BarLine.stencil =
#(lambda (grob)
(ly:stencil-combine-at-edge
(ly:bar-line::print grob)
X RIGHT
(grob-interpret-markup grob #{
\markup\with-dimensions #'(0 . 0) #'(0 . 0) {
\translate #'(0 . .14)\arrow-at-angle #45 #(sqrt 8) ##t
}#})
0))
\break
}

86
auto_rest_merging.ly Normal file
View File

@ -0,0 +1,86 @@
%% http://lsr.dsi.unimi.it/LSR/Item?id=336
%% see also http://code.google.com/p/lilypond/issues/detail?id=1228
%% Usage:
%% \new Staff \with {
%% \override RestCollision.positioning-done = #merge-rests-on-positioning
%% } << \somevoice \\ \othervoice >>
%% or (globally):
%% \layout {
%% \context {
%% \Staff
%% \override RestCollision.positioning-done = #merge-rests-on-positioning
%% }
%% }
%%
%% Limitations:
%% - only handles two voices
%% - does not handle multi-measure/whole-measure rests
#(define (rest-score r)
(let ((score 0)
(yoff (ly:grob-property-data r 'Y-offset))
(sp (ly:grob-property-data r 'staff-position)))
(if (number? yoff)
(set! score (+ score 2))
(if (eq? yoff 'calculation-in-progress)
(set! score (- score 3))))
(and (number? sp)
(<= 0 2 sp)
(set! score (+ score 2))
(set! score (- score (abs (- 1 sp)))))
score))
#(define (merge-rests-on-positioning grob)
(let* ((can-merge #f)
(elts (ly:grob-object grob 'elements))
(num-elts (and (ly:grob-array? elts)
(ly:grob-array-length elts)))
(two-voice? (= num-elts 2)))
(if two-voice?
(let* ((v1-grob (ly:grob-array-ref elts 0))
(v2-grob (ly:grob-array-ref elts 1))
(v1-rest (ly:grob-object v1-grob 'rest))
(v2-rest (ly:grob-object v2-grob 'rest)))
(and
(ly:grob? v1-rest)
(ly:grob? v2-rest)
(let* ((v1-duration-log (ly:grob-property v1-rest 'duration-log))
(v2-duration-log (ly:grob-property v2-rest 'duration-log))
(v1-dot (ly:grob-object v1-rest 'dot))
(v2-dot (ly:grob-object v2-rest 'dot))
(v1-dot-count (and (ly:grob? v1-dot)
(ly:grob-property v1-dot 'dot-count -1)))
(v2-dot-count (and (ly:grob? v2-dot)
(ly:grob-property v2-dot 'dot-count -1))))
(set! can-merge
(and
(number? v1-duration-log)
(number? v2-duration-log)
(= v1-duration-log v2-duration-log)
(eq? v1-dot-count v2-dot-count)))
(if can-merge
;; keep the rest that looks best:
(let* ((keep-v1? (>= (rest-score v1-rest)
(rest-score v2-rest)))
(rest-to-keep (if keep-v1? v1-rest v2-rest))
(dot-to-kill (if keep-v1? v2-dot v1-dot)))
;; uncomment if you're curious of which rest was chosen:
;;(ly:grob-set-property! v1-rest 'color green)
;;(ly:grob-set-property! v2-rest 'color blue)
(ly:grob-suicide! (if keep-v1? v2-rest v1-rest))
(if (ly:grob? dot-to-kill)
(ly:grob-suicide! dot-to-kill))
(ly:grob-set-property! rest-to-keep 'direction 0)
(ly:rest::y-offset-callback rest-to-keep)))))))
(if can-merge
#t
(ly:rest-collision::calc-positioning-done grob))))
generalLayout = \layout {
\generalLayout
\context {
\Staff
\override RestCollision.positioning-done = #merge-rests-on-positioning
}
}

View File

@ -0,0 +1,101 @@
\language "deutsch"
\include "styles.ly"
\include #(ly:format "styles/~a.ly" songStyle)
#(set-default-paper-size songFormatAndSize)
#(set-global-staff-size globalSize)
#(define (default-pango size)
(make-pango-font-tree
songChordFont
songLyricFont
"Luxi Mono"
(/ size 20)))
\paper {
#(define fonts (default-pango globalSize))
%annotate-spacing = ##t
% spacing stuff
lyric-size = #lyricSize
two-sided = ##t
inner-margin = 1.5\cm
outer-margin = \songMargin
binding-offset = 0\cm
top-margin = \songMargin
bottom-margin = \songMargin
system-system-spacing = #'((basic-distance . 10) (padding . 1.5))
markup-system-spacing = #'((basic-distance . 1))
score-markup-spacing = #'((padding . 2))
top-markup-spacing = #'((basic-distance . 0) (minimum-distance . 0) (padding . 0))
}
generalLayout = \layout {
indent = #0
\context {
\Lyrics
\override LyricText.font-size = #lyricSize
\override StanzaNumber.font-size = #lyricSize
\override StanzaNumber.font-family = #'sans
\override LyricText.font-family = #'sans
\override LyricExtender.minimum-length = 0
}
\context {
\Staff
\accidentalStyle modern
}
\context {
\Score
\remove "Bar_number_engraver"
\RemoveEmptyStaves
\override VerticalAxisGroup.remove-first = ##t
\overrideTimeSignatureSettings
4/4 % timeSignatureFraction
1/4 % baseMomentFraction
#'(1 1 1 1) % beatStructure
#'() % beamExceptions
\overrideTimeSignatureSettings
3/4 % timeSignatureFraction
1/4 % baseMomentFraction
#'(1 1 1 1) % beatStructure
#'() % beamExceptions
}
\context {
\Voice
% ich will lines breaken wie ich will!
\remove "Forbid_line_break_engraver"
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% kleine Helferlein:
textp = \lyricmode { \markup { \raise #1 \musicglyph #"rests.3" } }
% zweite Stimme alles grau
secondVoiceStyle = {
\override NoteHead.color = #grey
\override Stem.color = #grey
\override Flag.color = #grey
\override Beam.color = #grey
}
firstVoiceStyle = {
\override NoteHead.color = #black
\override Stem.color = #black
\override Flag.color = #black
\override Beam.color = #black
}
% einzelne Noten innerhalb von \secondVoiceStyle mit schwarzem statt grauem Kopf
schwarzkopf =
#(define-music-function (parser location noten) (ly:music?)
#{
\revert NoteHead.color
$noten
\override NoteHead.color = #grey
#})
% hübsche Wiederholungszeichen für den Liedtext
repStart = "𝄆"
repStop = "𝄇"

View File

@ -121,11 +121,7 @@ includeSong =
\bookOutputName #filename
#}
(ly:parser-parse-string (if (< (list-ref (ly:version) 1) 19) (ly:parser-clone parser) (ly:parser-clone))
(string-concatenate
(list
"HEADER = {} \nMUSIC = {}\nTEXT = \\markuplist {""}\nlyricSize = #1.6\n"
;"\\header { songfilename = \"" filename "\" }\n"
"\\include \"" "../../lieder/" filename "/" filename ".ly" "\"")))
(ly:format "\\include \"../../~a/~a/~a.ly\"" songPath filename filename))
(let ((label (gensym "index")))
(set! additional-page-switch-label-list
(acons label additional-page-numbers additional-page-switch-label-list))
@ -149,6 +145,13 @@ imagepage =
(acons 'xsize xsize (acons 'filename filename '()))
song-list)))
#(define-markup-command (pagecenter layout props stuff)(markup?)
(interpret-markup layout props
(let ((halfpaperheight (/ (ly:output-def-lookup layout 'paper-height) 2))
(halfstuffheight (/ (interval-length (ly:stencil-extent (interpret-markup layout props stuff) Y)) 2)))
(make-fill-line-markup (list (make-pad-to-box-markup '(0 . 0) (cons (- (- halfpaperheight halfstuffheight)) (+ halfpaperheight halfstuffheight)) stuff)))
)))
songs =
#(define-void-function (parser location) ()
(for-each (lambda (songitems)
@ -159,7 +162,7 @@ songs =
#{ \bookpart { \markup { \null } } #}
(if (eq? filename 'imagePage)
(let ((xsize (assq-ref songvars 'xsize))
(filename (ly:format "boernel_images/~a" (assq-ref songvars 'filename))))
(filename (ly:format "~a/~a" imagePagePath (assq-ref songvars 'filename))))
#{ \bookpart {
\paper {
%{
@ -196,16 +199,6 @@ songs =
(reverse song-list)
))
includeOnce =
#(define-void-function (parser location filename) (string?)
(if
(not (defined? (string->symbol filename)))
(begin
(ly:parser-include-string parser
(string-concatenate
(list "\\include \"" filename "\"")))
(primitive-eval (list 'define (string->symbol filename) #t)))))
#(define (boernel-stats)
(let (
(songs (map (lambda (song) (symbol->string (car song))) (alist-delete 'emptyPage song-list)))
@ -216,7 +209,7 @@ includeOnce =
;(string-join songs "\n")
"Nicht inkludiert:"
opticalline
(string-join (sort-list (lset-difference string=? (files-in-directory "../../lieder") songs) string<?) "\n")
(string-join (sort-list (lset-difference string=? (files-in-directory (ly:format "../../~a" songPath)) songs) string<?) "\n")
opticalline
) "\n" )
)))

97
chord_settings.ly Normal file
View File

@ -0,0 +1,97 @@
% Akkorde können auch geklammert sein
#(define (parenthesis-ignatzek-chord-names in-pitches bass inversion context)
(markup #:line ( "(" (ignatzek-chord-names in-pitches bass inversion context) ")" )))
klamm = #(define-music-function (parser location chords) (ly:music?)
#{
\set chordNameFunction = #parenthesis-ignatzek-chord-names
$chords
\set chordNameFunction = #ignatzek-chord-names
#})
bchord =
#(define-music-function (parser location chords) (ly:music?)
#{
\override ChordName.font-series = #'bold
$chords
\revert ChordName.font-series
#})
% 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?)(note-name->german-markup-nosym pitch #f))
generalLayout = \layout {
\generalLayout
\context {
\ChordNames
\semiGermanChords
\override ChordName.font-size = \songScoreChordFontSize
\override ChordName.font-series = \songChordFontSeries
\override ChordName.font-family = #'roman
chordNameLowercaseMinor = ##t
chordChanges = ##t
% eigenen chordRootNamer damit F# = Fis und Gb = Ges (also alteration ausgeschrieben)
chordRootNamer = #note-name->german-markup-nosym
chordNoteNamer = #bassnote-name->german-markup-nosym
majorSevenSymbol = "maj7"
% der baseline-skip der Akkorde beeinflusst, wie hoch die Hochstellung ist
\override ChordName.baseline-skip = #1.0
}
}
verseChordLayout = \layout {
\generalLayout
\context {
\ChordNames
\override ChordName.font-size = \songTextChordFontSize
}
}
% Akkord mit Bunddiagramm anzeigen
#(define-markup-command (fret-chord layout props fret chord) (string? string?)
(interpret-markup layout props
#{ \markup { \override #'(baseline-skip . 2)
\center-column {
\score { \new ChordNames { #(if (< (list-ref (ly:version) 1) 19)
(ly:parser-include-string parser (string-append "\\chordmode { s4 " chord " }"))
(ly:parser-include-string (string-append "\\chordmode { s4 " chord " }"))
) } \layout { \generalLayout } }
\override #'(fret-diagram-details . (
(barre-type . straight))) {
\fret-diagram-terse #fret
}
}
}
#}))

View File

@ -0,0 +1,15 @@
generalLayout = \layout {
\generalLayout
\context {
\ChordNames
chordNameExceptions = #(sequential-music-to-chord-exceptions customChordPrintings #t)
}
}
verseChordLayout = \layout {
\verseChordLayout
\context {
\ChordNames
chordNameExceptions = #(sequential-music-to-chord-exceptions customChordPrintings #t)
}
}

18
eps_file_from_song_dir.ly Normal file
View File

@ -0,0 +1,18 @@
% songfilename auch im Markup verfügbar machen
#(define-markup-list-command (setsongfilename layout props songfilename markuplist)
(string? markup-list?)
(interpret-markup-list layout (prepend-alist-chain 'songfilename songfilename props) markuplist))
#(define-markup-command (customEps layout props ysize filename)(number? string?)
#:properties ((songfilename "")
(defaultmarkup #f))
(interpret-markup layout props
(let ((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 defaultmarkup
defaultmarkup
(ly:format "file does not exist ~a" filepath))
))))

61
footer_with_songinfo.ly Normal file
View File

@ -0,0 +1,61 @@
#(define-markup-command (print-songinfo layout props) ()
(interpret-markup layout props
(let (
(blockwidth (* (chain-assoc-get 'header:songinfo-size-factor props 0.9) (ly:output-def-lookup layout 'line-width)))
(infotext (chain-assoc-get 'header:songinfo props #f))
(poet (chain-assoc-get 'header:poet props #f))
(composer (chain-assoc-get 'header:composer props #f))
(poet-and-composer-stacked (chain-assoc-get 'header:poet-and-composer-stacked props songInfoPoetAndComposerStacked))
(between-poet-and-composer-markup (chain-assoc-get 'header:between-poet-and-composer-markup props (make-hspace-markup 3)))
(copyright (chain-assoc-get 'header:copyright props #f)))
(if (chain-assoc-get 'page:is-bookpart-last-page props #f)
(markup #:override '(baseline-skip . 3.0) (
make-fontsize-markup songInfoFontSize
(make-sans-markup
;%\override #'(line-width . 92) \wordwrap-field #symbol
(make-column-markup (list
(make-line-markup
(list
(if (and poet (not (and (string? poet) (string-null? poet)))) (markup poet between-poet-and-composer-markup) "")
(if (and composer (not poet-and-composer-stacked)) composer ""))
)
(if (and composer poet-and-composer-stacked) (make-line-markup (list composer)) "")
(make-override-markup `(line-width . ,blockwidth) (make-justify-string-markup (string-append
(if (and copyright (not (and (string? copyright) (string-null? copyright)))) (ly:format "© ~a\n\n" copyright) "")
(if infotext infotext "")
)))
)))
)
)
(make-null-markup))))
)
#(define-markup-command (print-pagenumber layout props)()
(let ((label (chain-assoc-get 'header:myindexlabel props #f)))
(interpret-markup layout props
(markup #:large #:bold
(if label
(make-custom-page-number-markup label (chain-assoc-get 'page:page-number props 0))
(make-fromproperty-markup 'page:page-number-string)
)
))))
\paper {
print-first-page-number = ##t
first-page-number = #0
oddFooterMarkup = \markup {
\fill-line {
\line { \null }
\line { \general-align #Y #DOWN \print-songinfo }
\line { \if \should-print-page-number \print-pagenumber }
}
}
evenFooterMarkup = \markup {
\fill-line {
\line { \if \should-print-page-number \print-pagenumber }
\line { \general-align #Y #DOWN \print-songinfo }
\line { \null }
}
}
}

View File

@ -1,724 +1,22 @@
\version "2.18"
\language "deutsch"
#(ly:set-option 'relative-includes #t)
compatibilityMode =
#(define-void-function (parser location) ()
(if (< (list-ref (ly:version) 1) 24)
(ly:parser-parse-string (if (< (list-ref (ly:version) 1) 19) (ly:parser-clone parser) (ly:parser-clone))
(string-concatenate
(list "\\include \"" "../../lilypond-common-includes/legacy-lilypond-compatibility.ly" "\"")))))
\compatibilityMode
\include #(if (< (list-ref (ly:version) 1) 24) "legacy-lilypond-compatibility.ly" "void.ly")
\include "./styles.ly"
\include #(ly:format "styles/~a.ly" songStyle)
#(define noStandaloneOutput (if (defined? 'noStandaloneOutput) noStandaloneOutput #f))
#(define (lookup-var varsym default)
(let ((value (assoc-ref (hash-map->list cons (struct-ref (current-module) 0)) varsym)))
(if value (variable-ref value) default)))
globalSize = #(lookup-var 'globalSize 15)
lyricSize = #(lookup-var 'lyricSize 1.6)
showCategoryImages = #(lookup-var 'showCategoryImages #t)
% check if we have a StandAlone compile or if variable noStandaloneOutput is set
#(define isStandAlone (not (lookup-var 'noStandaloneOutput #f)))
#(set-default-paper-size songFormatAndSize)
#(set-global-staff-size globalSize)
#(define-markup-command (print-songinfo layout props) ()
(interpret-markup layout props
(let (
(blockwidth (* (chain-assoc-get 'header:songinfo-size-factor props 0.9) (ly:output-def-lookup layout 'line-width)))
(infotext (chain-assoc-get 'header:songinfo props #f))
(poet (chain-assoc-get 'header:poet props #f))
(composer (chain-assoc-get 'header:composer props #f))
(poet-and-composer-stacked (chain-assoc-get 'header:poet-and-composer-stacked props #f))
(between-poet-and-composer-markup (chain-assoc-get 'header:between-poet-and-composer-markup props (make-hspace-markup 3)))
(copyright (chain-assoc-get 'header:copyright props #f)))
(if (chain-assoc-get 'page:is-bookpart-last-page props #f)
(markup #:override '(baseline-skip . 3.0) (
make-fontsize-markup songInfoFontSize
(make-sans-markup
;%\override #'(line-width . 92) \wordwrap-field #symbol
(make-column-markup (list
(make-line-markup
(list
(if (and poet (not (and (string? poet) (string-null? poet)))) (markup poet between-poet-and-composer-markup) "")
(if (and composer (not poet-and-composer-stacked)) composer ""))
)
(if (and composer poet-and-composer-stacked) (make-line-markup (list composer)) "")
(make-override-markup `(line-width . ,blockwidth) (make-justify-string-markup (string-append
(if (and copyright (not (and (string? copyright) (string-null? copyright)))) (ly:format "© ~a\n\n" copyright) "")
(if infotext infotext "")
)))
)))
)
)
(make-null-markup))))
)
% songfilename verfügbar machen
#(define-markup-list-command (setsongfilename layout props songfilename markuplist)
(string? markup-list?)
(interpret-markup-list layout (prepend-alist-chain 'songfilename songfilename props) markuplist))
#(define-markup-command (customEps layout props ysize filename)(number? string?)
#:properties ((songfilename "")
(defaultmarkup #f))
(interpret-markup layout props
(let ((filepath (if (string-null? songfilename)
filename
(ly:format "../../lieder/~a/~a" songfilename filename))))
(if (file-exists? filepath)
(make-epsfile-markup Y ysize filepath)
(if defaultmarkup
defaultmarkup
(ly:format "file does not exist ~a" filepath))
))))
#(define-markup-command (bookTitleMarkupCustom layout props)()
(interpret-markup layout
(prepend-alist-chain 'defaultmarkup #{
\markup {
\override #'(baseline-skip . 3.5)
\center-column {
\override #`(font-name . ,songTitleFont) { \fontsize #6 \fromproperty #'header:title }
\large \bold \fromproperty #'header:subtitle
\smaller \bold \fromproperty #'header:subsubtitle
}
}
#}
(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))
(make-customEps-markup (chain-assoc-get 'header:titlesize props 3.5) "titel.eps")
))
))
#(define-markup-command (category-image layout props size category)(number? string?)
(interpret-markup layout props
(if isStandAlone
(make-epsfile-markup Y size
(category-image-path category))
(make-epsfileref-markup Y size
(category-image-path category)))))
#(define-markup-command (category-images layout props)()
(interpret-markup layout props
(if showCategoryImages
(make-line-markup (map (lambda (category) (make-category-image-markup 5 category))
(string-tokenize (chain-assoc-get 'header:categories props ""))))
(make-null-markup))))
#(define-markup-command (pagecenter layout props stuff)(markup?)
(interpret-markup layout props
(let ((halfpaperheight (/ (ly:output-def-lookup layout 'paper-height) 2))
(halfstuffheight (/ (interval-length (ly:stencil-extent (interpret-markup layout props stuff) Y)) 2)))
(make-fill-line-markup (list (make-pad-to-box-markup '(0 . 0) (cons (- (- halfpaperheight halfstuffheight)) (+ halfpaperheight halfstuffheight)) stuff)))
)))
#(define-markup-command (print-pagenumber layout props)()
(let ((label (chain-assoc-get 'header:myindexlabel props #f)))
(interpret-markup layout props
(markup #:large #:bold
(if label
(make-custom-page-number-markup label (chain-assoc-get 'page:page-number props 0))
(make-fromproperty-markup 'page:page-number-string)
)
))))
#(define pdf-encode
(if (< (list-ref (ly:version) 1) 24)
ly:encode-string-for-pdf
(@@ (lily framework-ps) pdf-encode)))
% PDF tags
#(define-markup-command (title-to-pdf-toc layout props title) (string?)
(ly:make-stencil
(list 'embedded-ps
(ly:format
"[/Action /GoTo /View [/Fit] /Title <~a> /OUT pdfmark"
(fold
(lambda (ch hexout)
(string-append hexout
(format #f "~2,'0x" (char->integer ch))))
""
(string->list
(pdf-encode title)))))
empty-interval empty-interval
;'(0 . 0) '(0 . 0)
))
#(define-markup-command (title-with-category-images layout props right)(boolean?)
(interpret-markup layout props
(let* ((title (chain-assoc-get 'header:title props #f))
(pdfbookmark (chain-assoc-get 'header:songfilename props title)))
(if title
;(if (chain-assoc-get 'header:categories props #f)
(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 \fill-line \general-align #Y #UP { \null \bookTitleMarkupCustom \null } #})
;(make-null-markup))
#{ \markup { " " } #})
)))
#(define (default-pango size)
(make-pango-font-tree
songChordFont
songLyricFont
"Luxi Mono"
(/ size 20)))
\paper {
#(define fonts (default-pango globalSize))
%annotate-spacing = ##t
% spacing stuff
lyric-size = #lyricSize
two-sided = ##t
inner-margin = 1.5\cm
outer-margin = \songMargin
binding-offset = 0\cm
top-margin = \songMargin
bottom-margin = \songMargin
system-system-spacing = #'((basic-distance . 10) (padding . 1.5))
markup-system-spacing = #'((basic-distance . 1))
score-markup-spacing = #'((padding . 2))
top-markup-spacing = #'((basic-distance . 0) (minimum-distance . 0) (padding . 0))
% top-system-spacing = #'((basic-distance . 0) (minimum-distance . 0) (padding . -3))
%top-system-spacing #'stretchability = #30
% last-bottom-spacing #'stretchability = #0
print-first-page-number = ##t
first-page-number = #0
bookTitleMarkup = \markup \null
scoreTitleMarkup = \markup \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 }
oddFooterMarkup = \markup {
\fill-line {
\line { \null }
\line { \general-align #Y #DOWN \print-songinfo }
\line { \if \should-print-page-number \print-pagenumber }
}
}
evenFooterMarkup = \markup {
\fill-line {
\line { \if \should-print-page-number \print-pagenumber }
\line { \general-align #Y #DOWN \print-songinfo }
\line { \null }
}
}
}
% Akkorde können auch geklammert sein
#(define (parenthesis-ignatzek-chord-names in-pitches bass inversion context)
(markup #:line ( "(" (ignatzek-chord-names in-pitches bass inversion context) ")" )))
klamm = #(define-music-function (parser location chords) (ly:music?)
#{
\set chordNameFunction = #parenthesis-ignatzek-chord-names
$chords
\set chordNameFunction = #ignatzek-chord-names
#})
bchord =
#(define-music-function (parser location chords) (ly:music?)
#{
\override ChordName.font-series = #'bold
$chords
\revert ChordName.font-series
#})
% 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?)(note-name->german-markup-nosym pitch #f))
%% http://lsr.dsi.unimi.it/LSR/Item?id=336
%% see also http://code.google.com/p/lilypond/issues/detail?id=1228
%% Usage:
%% \new Staff \with {
%% \override RestCollision.positioning-done = #merge-rests-on-positioning
%% } << \somevoice \\ \othervoice >>
%% or (globally):
%% \layout {
%% \context {
%% \Staff
%% \override RestCollision.positioning-done = #merge-rests-on-positioning
%% }
%% }
%%
%% Limitations:
%% - only handles two voices
%% - does not handle multi-measure/whole-measure rests
#(define (rest-score r)
(let ((score 0)
(yoff (ly:grob-property-data r 'Y-offset))
(sp (ly:grob-property-data r 'staff-position)))
(if (number? yoff)
(set! score (+ score 2))
(if (eq? yoff 'calculation-in-progress)
(set! score (- score 3))))
(and (number? sp)
(<= 0 2 sp)
(set! score (+ score 2))
(set! score (- score (abs (- 1 sp)))))
score))
#(define (merge-rests-on-positioning grob)
(let* ((can-merge #f)
(elts (ly:grob-object grob 'elements))
(num-elts (and (ly:grob-array? elts)
(ly:grob-array-length elts)))
(two-voice? (= num-elts 2)))
(if two-voice?
(let* ((v1-grob (ly:grob-array-ref elts 0))
(v2-grob (ly:grob-array-ref elts 1))
(v1-rest (ly:grob-object v1-grob 'rest))
(v2-rest (ly:grob-object v2-grob 'rest)))
(and
(ly:grob? v1-rest)
(ly:grob? v2-rest)
(let* ((v1-duration-log (ly:grob-property v1-rest 'duration-log))
(v2-duration-log (ly:grob-property v2-rest 'duration-log))
(v1-dot (ly:grob-object v1-rest 'dot))
(v2-dot (ly:grob-object v2-rest 'dot))
(v1-dot-count (and (ly:grob? v1-dot)
(ly:grob-property v1-dot 'dot-count -1)))
(v2-dot-count (and (ly:grob? v2-dot)
(ly:grob-property v2-dot 'dot-count -1))))
(set! can-merge
(and
(number? v1-duration-log)
(number? v2-duration-log)
(= v1-duration-log v2-duration-log)
(eq? v1-dot-count v2-dot-count)))
(if can-merge
;; keep the rest that looks best:
(let* ((keep-v1? (>= (rest-score v1-rest)
(rest-score v2-rest)))
(rest-to-keep (if keep-v1? v1-rest v2-rest))
(dot-to-kill (if keep-v1? v2-dot v1-dot)))
;; uncomment if you're curious of which rest was chosen:
;;(ly:grob-set-property! v1-rest 'color green)
;;(ly:grob-set-property! v2-rest 'color blue)
(ly:grob-suicide! (if keep-v1? v2-rest v1-rest))
(if (ly:grob? dot-to-kill)
(ly:grob-suicide! dot-to-kill))
(ly:grob-set-property! rest-to-keep 'direction 0)
(ly:rest::y-offset-callback rest-to-keep)))))))
(if can-merge
#t
(ly:rest-collision::calc-positioning-done grob))))
generalLayout = \layout {
indent = #0
% Akkordeinstellungen
\context {
\ChordNames
\semiGermanChords
\override ChordName.font-size = \songScoreChordFontSize
\override ChordName.font-series = \songChordFontSeries
\override ChordName.font-family = #'roman
chordNameLowercaseMinor = ##t
chordChanges = ##t
% eigenen chordRootNamer damit F# = Fis und Gb = Ges (also alteration ausgeschrieben)
chordRootNamer = #note-name->german-markup-nosym
chordNoteNamer = #bassnote-name->german-markup-nosym
majorSevenSymbol = "maj7"
% der baseline-skip der Akkorde beeinflusst, wie hoch die Hochstellung ist
\override ChordName.baseline-skip = #1.0
}
\context {
\Lyrics
\override LyricText.font-size = #lyricSize
\override StanzaNumber.font-size = #lyricSize
\override StanzaNumber.font-family = #'sans
\override LyricText.font-family = #'sans
\override LyricExtender.minimum-length = 0
}
\context {
\Staff
\override RestCollision.positioning-done = #merge-rests-on-positioning
\accidentalStyle modern
}
\context {
\Score
\remove "Bar_number_engraver"
\RemoveEmptyStaves
\override VerticalAxisGroup.remove-first = ##t
\overrideTimeSignatureSettings
4/4 % timeSignatureFraction
1/4 % baseMomentFraction
#'(1 1 1 1) % beatStructure
#'() % beamExceptions
\overrideTimeSignatureSettings
3/4 % timeSignatureFraction
1/4 % baseMomentFraction
#'(1 1 1 1) % beatStructure
#'() % beamExceptions
}
\context {
\Voice
% ich will lines breaken wie ich will!
\remove "Forbid_line_break_engraver"
}
}
verseChordLayout = \layout {
\generalLayout
\context {
\ChordNames
\override ChordName.font-size = \songTextChordFontSize
}
}
\include "basic_format_and_style_settings.ly"
\include "eps_file_from_song_dir.ly"
\include "title_with_category_images.ly"
\include "footer_with_songinfo.ly"
\include "auto_rest_merging.ly"
\include "chord_settings.ly"
\include "verses_with_chords.ly"
\include "arrows_in_scores.ly"
% reset important variables
LAYOUT = \layout { \generalLayout }
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% kleine Helferlein:
textp = \lyricmode { \markup { \raise #1 \musicglyph #"rests.3" } }
% zweite Stimme alles grau
secondVoiceStyle = {
\override NoteHead.color = #grey
\override Stem.color = #grey
\override Flag.color = #grey
\override Beam.color = #grey
}
firstVoiceStyle = {
\override NoteHead.color = #black
\override Stem.color = #black
\override Flag.color = #black
\override Beam.color = #black
}
% einzelne Noten innerhalb von \secondVoiceStyle mit schwarzem statt grauem Kopf
schwarzkopf =
#(define-music-function (parser location noten) (ly:music?)
#{
\revert NoteHead.color
$noten
\override NoteHead.color = #grey
#})
% guile regular expressions aktivieren:
#(use-modules (ice-9 regex))
%{
% parsing line by line
#(define-markup-command (wrap-newline layout props text) (string?)
"Text Zeile für Zeile parsen"
(interpret-markup layout props
(ly:parse-string-expression (if (< (list-ref (ly:version) 1) 19) (ly:parser-clone parser) (ly:parser-clone)) (string-append "\\markup { \\column { \\line {"
(regexp-substitute/global #f "\n"
text
'pre "} \\line {" 'post )
"} } }" ))
)
)
%}
% parsing line by line
#(define-markup-command (wrap-newline layout props text) (string?)
"Text Zeile für Zeile parsen"
(interpret-markup layout props
#{ \markup { \column {
$(let ((verse-markup-string (string-append "\\line { "
(regexp-substitute/global #f "\n"
text
'pre " } \\line { " 'post )
" \\size-box-to-box ##f ##t \"\" \"Agj\" }" )))
;(ly:parse-string-expression (if (< (list-ref (ly:version) 1) 19) (ly:parser-clone parser) (ly:parser-clone)) verse-markup-string))
(if (< (list-ref (ly:version) 1) 19) (ly:parser-include-string parser verse-markup-string) (ly:parser-include-string verse-markup-string)))
}}#}
)
)
#(define-markup-command (size-box-to-box layout props use-x use-y abox bbox)
(boolean? boolean? markup? markup?)
(let* ((ma (interpret-markup layout props abox))
(mb (interpret-markup layout props bbox))
(ax (ly:stencil-extent ma X))
(ay (ly:stencil-extent ma Y))
(bx (ly:stencil-extent mb X))
(by (ly:stencil-extent mb Y))
(halfdiffabx (* (- (interval-length bx) (interval-length ax)) 0.5)))
(ly:stencil-translate (ly:make-stencil (ly:stencil-expr ma)
(if use-x
(if (< halfdiffabx 0)
(cons
(- (interval-bound ax DOWN) halfdiffabx)
(+ (interval-bound ax UP) halfdiffabx))
bx)
ax)
(if use-y by ay))
(cons (if (and use-x (< halfdiffabx 0)) halfdiffabx 0) 0) )))
#(define-markup-command (size-box-to-box-left-aligned layout props use-x use-y abox bbox)
(boolean? boolean? markup? markup?)
(let* ((ma (interpret-markup layout props abox))
(mb (interpret-markup layout props bbox))
(ax (ly:stencil-extent ma X))
(ay (ly:stencil-extent ma Y))
(bx (ly:stencil-extent mb X))
(by (ly:stencil-extent mb Y)))
(ly:make-stencil (ly:stencil-expr ma)
(if use-x bx ax)
(if use-y by ay))
))
#(define-markup-command (size-box-to-box-style-dependent layout props use-x use-y abox bbox)
(boolean? boolean? markup? markup?)
(interpret-markup layout props
(case songTextChordAlignment
((center) (make-size-box-to-box-markup use-x use-y abox bbox))
((left) (make-size-box-to-box-left-aligned-markup use-x use-y abox bbox)))))
% Akkord mit Bunddiagramm anzeigen
#(define-markup-command (fret-chord layout props fret chord) (string? string?)
(interpret-markup layout props
#{ \markup { \override #'(baseline-skip . 2)
\center-column {
\score { \new ChordNames { #(if (< (list-ref (ly:version) 1) 19)
(ly:parser-include-string parser (string-append "\\chordmode { s4 " chord " }"))
(ly:parser-include-string (string-append "\\chordmode { s4 " chord " }"))
) } \layout { \generalLayout } }
\override #'(fret-diagram-details . (
(barre-type . straight))) {
\fret-diagram-terse #fret
}
}
}
#}))
% Akkorde in Strophen transponieren
#(define-markup-list-command (transpose layout props from to markuplist)
(markup? markup? markup-list?)
(interpret-markup-list layout (prepend-alist-chain 'transposition (cons from to) props) markuplist))
#(define-markup-command (chord-alignment-style-dependent layout props chord-with-text) (markup?)
(interpret-markup layout props
(case songTextChordAlignment
((center) (make-center-align-markup chord-with-text))
((left) (make-left-align-markup chord-with-text)))))
% Text über Text mittig darstellen
#(define-markup-command (textup layout props text uptext) (markup? markup?)
"Markup über Text mittig darstellen."
(interpret-markup layout props
#{\markup {
\size-box-to-box-style-dependent ##t ##f
\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 { \generalLayout } }
}
#text
}
#}
))
#(define-markup-command (anchor-x-between layout props arga argb)
(markup? markup?)
(let* ((la (interval-length (ly:stencil-extent (interpret-markup layout props arga) X)))
(m (interpret-markup layout props (markup #:general-align Y DOWN arga argb (make-size-box-to-box-markup #t #t (markup #:null) arga))))
(l (interval-length (ly:stencil-extent m X))))
(ly:stencil-aligned-to m X (- (/ (* la 2) l) 1))
))
#(define-markup-command (stanza-raw layout props arg)
(markup?)
(interpret-markup layout props
(if (and (string? arg) (string-null? arg))
" "
#{\markup
\score { \new Lyrics { \lyricmode { \set stanza = #arg "" } } \layout { \generalLayout } }
#}
)))
#(define-markup-command (stanza layout props arg)
(markup?)
(interpret-markup layout props
(make-size-box-to-box-markup #f #t (make-stanza-raw-markup arg) (make-stanza-raw-markup "x"))))
% Kompletten Vers mit Akkorden
#(define-markup-command (chordverse layout props stanza verse) (markup? string?)
"Vers mit Akkorden"
(let* ((fromto (chain-assoc-get 'transposition props #f))
(transp (if fromto
(string-append "\\transpose " (car fromto) " " (cdr fromto))
"")))
(interpret-markup layout props
(markup #:override `(baseline-skip . ,songTextLineHeigth) #:anchor-x-between #:stanza stanza
(make-wrap-newline-markup
(regexp-substitute/global #f "\\(( *)([^,()]*)( *),([^)]*)\\)"
(regexp-substitute/global #f "(([^ \n]*\\([^()]*\\)[^ \n]*)+)" verse
'pre " \\concat { " 1 " } " 'post)
'pre "\\textup \\line { \"" 1 "\" " 2 " \"" 3 "\" } \\score { " transp " \\chords { s4 " 4 " } \\layout { \\verseChordLayout } }" 'post))
))))
% Kompletter Vers aus dem Akkorde entfernt werden
#(define-markup-command (nochordverse layout props stanza verse) (markup? string?)
"Vers ohne Akkorde"
(interpret-markup layout props
(markup #:override '(baseline-skip . 3.0) #:anchor-x-between #:stanza stanza
#:wrap-newline (regexp-substitute/global #f "\\(([^,]*),([^)]*)\\)" verse 'pre 1 'post )
)
)
)
% hübsche Wiederholungszeichen für den Liedtext
repStart = "𝄆"
repStop = "𝄇"
%{
repStart = \markup { \raise #0.75 \override #'(word-space . 0.2) {
\wordwrap { \vcenter { \override #'(word-space . 0.2) { \wordwrap {
\filled-box #'(0 . 0.3) #'(0 . 2.5) #0 \filled-box #'(0 . 0.15) #'(0 . 2.5) #0 } }
%\override #'(baseline-skip . 1.3) \fontsize #-5 \column { "•" "•" }
\override #'(baseline-skip . 1.0) \column { \draw-circle #0.2 #0 ##t \draw-circle #0.2 #0 ##t }
} } } }
repStop = \markup { \rotate #180 \repStart }
%}
#(define-markup-command (verseformat layout props verse) (markup?)
"Textformatierung für Strophen"
(interpret-markup layout props
(make-sans-markup (make-fontsize-markup (ly:output-def-lookup layout 'lyric-size) verse))
)
)
#(define-markup-command (group-verses layout props versegroup) (markup-list?)
#:properties ((verse-cols 1)
(verse-vspace 1)
(verse-hspace 1)
(verse-ordering-horizontal #f))
"Gruppiere Strophen in einem Markup auf Wunsch spaltenweise"
(let ((h (make-hash-table verse-cols))
(index 0)
(column-item-count (ceiling (/ (length versegroup) verse-cols))))
(for-each (lambda (el)
(let ((i (if verse-ordering-horizontal
(modulo index verse-cols)
(floor (/ index column-item-count)))))
(hashv-set! h i (cons el (hashv-ref h i (list)))) (set! index (+ index 1))))
versegroup)
(interpret-markup layout props
(make-fill-line-markup (cons (make-verseformat-markup (make-line-markup
(reverse (hash-fold (lambda (key value l)
(cons (make-column-markup
(fold (lambda (v verses)
(cons v (if (null? verses)
verses
(cons (make-vspace-markup verse-vspace) verses))))
(list) value))
(if (null-list? l)
l
(cons (make-hspace-markup verse-hspace) l))))
(list) h))))
(list))))))
%%%%%%%%%%%%%%%%% Pfeilezeugs
% http://lilypond.org/doc/v2.19/Documentation/snippets/vocal-music
#(define-markup-command (arrow-at-angle layout props angle-deg length fill)
(number? number? boolean?)
(let* (
(PI-OVER-180 (/ (atan 1 1) 34))
(degrees->radians (lambda (degrees) (* degrees PI-OVER-180)))
(angle-rad (degrees->radians angle-deg))
(target-x (* length (cos angle-rad)))
(target-y (* length (sin angle-rad))))
(interpret-markup layout props
(markup
#:translate (cons (/ target-x 2) (/ target-y 2))
#:rotate angle-deg
#:translate (cons (/ length -2) 0)
#:concat (#:draw-line (cons length 0)
#:arrow-head X RIGHT fill)))))
splitStaffBarLineMarkup = \markup \with-dimensions #'(0 . 0) #'(0 . 0) {
\combine
\arrow-at-angle #45 #(sqrt 8) ##t
\arrow-at-angle #-45 #(sqrt 8) ##t
}
splitStaffBarLine = {
\once \override Staff.BarLine.stencil =
#(lambda (grob)
(ly:stencil-combine-at-edge
(ly:bar-line::print grob)
X RIGHT
(grob-interpret-markup grob splitStaffBarLineMarkup)
0))
\break
}
convDownStaffBarLine = {
\once \override Staff.BarLine.stencil =
#(lambda (grob)
(ly:stencil-combine-at-edge
(ly:bar-line::print grob)
X RIGHT
(grob-interpret-markup grob #{
\markup\with-dimensions #'(0 . 0) #'(0 . 0) {
\translate #'(0 . -.13)\arrow-at-angle #-45 #(sqrt 8) ##t
}#})
0))
\break
}
convUpStaffBarLine = {
\once \override Staff.BarLine.stencil =
#(lambda (grob)
(ly:stencil-combine-at-edge
(ly:bar-line::print grob)
X RIGHT
(grob-interpret-markup grob #{
\markup\with-dimensions #'(0 . 0) #'(0 . 0) {
\translate #'(0 . .14)\arrow-at-angle #45 #(sqrt 8) ##t
}#})
0))
\break
}
HEADER = {}
MUSIC = {}
TEXT = \markuplist {""}

37
standalone_output.ly Normal file
View File

@ -0,0 +1,37 @@
% set the speed of the midi music
#(define midiQuarterNoteSpeed (if (defined? 'midiQuarterNoteSpeed) midiQuarterNoteSpeed 90))
% nur Output wenn noStandaloneOutput auf false steht
output = #(if (not noStandaloneOutput)
#{
\bookpart {
\HEADER
\score {
\MUSIC
\layout { \LAYOUT }
}
\TEXT
\score {
\unfoldRepeats \MUSIC
\midi {
\context {
\Score
% Tempo des midi files
tempoWholesPerMinute = #(ly:make-moment midiQuarterNoteSpeed 4)
}
}
}
}
#}
)
% if we don't want a standalone output, cause we compile a book, we just have an empty output here,
% so lilypond does not generate output for this song
\book {
\bookpart { \output }
}

View File

@ -8,4 +8,7 @@ songChordFontSeries = #'normal
songTextChordAlignment = #'left
songScoreChordFontSize = 3
songTextChordFontSize = 2
songTextLineHeigth = 5.5
songTextLineHeigth = 5.5
songInfoPoetAndComposerStacked = ##f
globalSize = 15
lyricSize = 1.6

View File

@ -9,3 +9,6 @@ songTextChordAlignment = #'center
songScoreChordFontSize = 0
songTextChordFontSize = \songScoreChordFontSize
songTextLineHeigth = 5
songInfoPoetAndComposerStacked = ##f
globalSize = 15
lyricSize = 1.6

View File

@ -8,4 +8,7 @@ songChordFontSeries = #'bold
songTextChordAlignment = #'left
songScoreChordFontSize = 2
songTextChordFontSize = 2
songTextLineHeigth = 5
songTextLineHeigth = 5
songInfoPoetAndComposerStacked = ##t
globalSize = 15
lyricSize = 1.6

View File

@ -0,0 +1,78 @@
#(define-markup-command (bookTitleMarkupCustom layout props)()
(interpret-markup layout
(prepend-alist-chain 'defaultmarkup #{
\markup {
\override #'(baseline-skip . 3.5)
\center-column {
\override #`(font-name . ,songTitleFont) { \fontsize #6 \fromproperty #'header:title }
\large \bold \fromproperty #'header:subtitle
\smaller \bold \fromproperty #'header:subsubtitle
}
}
#}
(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))
(make-customEps-markup (chain-assoc-get 'header:titlesize props 3.5) "titel.eps")
))
))
#(define-markup-command (category-image layout props size category)(number? string?)
(interpret-markup layout props
(if noStandaloneOutput
(make-epsfileref-markup Y size
(category-image-path category))
(make-epsfile-markup Y size
(category-image-path category)))))
#(define showCategoryImages (if (defined? 'showCategoryImages) showCategoryImages #t))
#(define-markup-command (category-images layout props)()
(interpret-markup layout props
(if showCategoryImages
(make-line-markup (map (lambda (category) (make-category-image-markup 5 category))
(string-tokenize (chain-assoc-get 'header:categories props ""))))
(make-null-markup))))
#(define pdf-encode
(if (< (list-ref (ly:version) 1) 24)
ly:encode-string-for-pdf
(@@ (lily framework-ps) pdf-encode)))
% PDF tags
#(define-markup-command (title-to-pdf-toc layout props title) (string?)
(ly:make-stencil
(list 'embedded-ps
(ly:format
"[/Action /GoTo /View [/Fit] /Title <~a> /OUT pdfmark"
(fold
(lambda (ch hexout)
(string-append hexout
(format #f "~2,'0x" (char->integer ch))))
""
(string->list
(pdf-encode title)))))
empty-interval empty-interval
;'(0 . 0) '(0 . 0)
))
#(define-markup-command (title-with-category-images layout props right)(boolean?)
(interpret-markup layout props
(let* ((title (chain-assoc-get 'header:title props #f))
(pdfbookmark (chain-assoc-get 'header:songfilename props title)))
(if title
;(if (chain-assoc-get 'header:categories props #f)
(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 \fill-line \general-align #Y #UP { \null \bookTitleMarkupCustom \null } #})
;(make-null-markup))
#{ \markup { " " } #})
)))
\paper {
bookTitleMarkup = \markup \null
scoreTitleMarkup = \markup \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 }
}

170
verses_with_chords.ly Normal file
View File

@ -0,0 +1,170 @@
% guile regular expressions aktivieren:
#(use-modules (ice-9 regex))
% parsing line by line
#(define-markup-command (wrap-newline layout props text) (string?)
"Text Zeile für Zeile parsen"
(interpret-markup layout props
#{ \markup { \column {
$(let ((verse-markup-string (string-append "\\line { "
(regexp-substitute/global #f "\n"
text
'pre " } \\line { " 'post )
" \\size-box-to-box ##f ##t \"\" \"Agj\" }" )))
;(ly:parse-string-expression (if (< (list-ref (ly:version) 1) 19) (ly:parser-clone parser) (ly:parser-clone)) verse-markup-string))
(if (< (list-ref (ly:version) 1) 19) (ly:parser-include-string parser verse-markup-string) (ly:parser-include-string verse-markup-string)))
}}#}
)
)
#(define-markup-command (size-box-to-box layout props use-x use-y abox bbox)
(boolean? boolean? markup? markup?)
(let* ((ma (interpret-markup layout props abox))
(mb (interpret-markup layout props bbox))
(ax (ly:stencil-extent ma X))
(ay (ly:stencil-extent ma Y))
(bx (ly:stencil-extent mb X))
(by (ly:stencil-extent mb Y))
(halfdiffabx (* (- (interval-length bx) (interval-length ax)) 0.5)))
(ly:stencil-translate (ly:make-stencil (ly:stencil-expr ma)
(if use-x
(if (< halfdiffabx 0)
(cons
(- (interval-bound ax DOWN) halfdiffabx)
(+ (interval-bound ax UP) halfdiffabx))
bx)
ax)
(if use-y by ay))
(cons (if (and use-x (< halfdiffabx 0)) halfdiffabx 0) 0) )))
#(define-markup-command (size-box-to-box-left-aligned layout props use-x use-y abox bbox)
(boolean? boolean? markup? markup?)
(let* ((ma (interpret-markup layout props abox))
(mb (interpret-markup layout props bbox))
(ax (ly:stencil-extent ma X))
(ay (ly:stencil-extent ma Y))
(bx (ly:stencil-extent mb X))
(by (ly:stencil-extent mb Y)))
(ly:make-stencil (ly:stencil-expr ma)
(if use-x bx ax)
(if use-y by ay))
))
#(define-markup-command (size-box-to-box-style-dependent layout props use-x use-y abox bbox)
(boolean? boolean? markup? markup?)
(interpret-markup layout props
(case songTextChordAlignment
((center) (make-size-box-to-box-markup use-x use-y abox bbox))
((left) (make-size-box-to-box-left-aligned-markup use-x use-y abox bbox)))))
% Akkorde in Strophen transponieren
#(define-markup-list-command (transpose layout props from to markuplist)
(markup? markup? markup-list?)
(interpret-markup-list layout (prepend-alist-chain 'transposition (cons from to) props) markuplist))
#(define-markup-command (chord-alignment-style-dependent layout props chord-with-text) (markup?)
(interpret-markup layout props
(case songTextChordAlignment
((center) (make-center-align-markup chord-with-text))
((left) (make-left-align-markup chord-with-text)))))
% Text über Text mittig darstellen
#(define-markup-command (textup layout props text uptext) (markup? markup?)
"Markup über Text mittig darstellen."
(interpret-markup layout props
#{\markup {
\size-box-to-box-style-dependent ##t ##f
\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 { \generalLayout } }
}
#text
}
#}
))
#(define-markup-command (anchor-x-between layout props arga argb)
(markup? markup?)
(let* ((la (interval-length (ly:stencil-extent (interpret-markup layout props arga) X)))
(m (interpret-markup layout props (markup #:general-align Y DOWN arga argb (make-size-box-to-box-markup #t #t (markup #:null) arga))))
(l (interval-length (ly:stencil-extent m X))))
(ly:stencil-aligned-to m X (- (/ (* la 2) l) 1))
))
#(define-markup-command (stanza-raw layout props arg)
(markup?)
(interpret-markup layout props
(if (and (string? arg) (string-null? arg))
" "
#{\markup
\score { \new Lyrics { \lyricmode { \set stanza = #arg "" } } \layout { \generalLayout } }
#}
)))
#(define-markup-command (stanza layout props arg)
(markup?)
(interpret-markup layout props
(make-size-box-to-box-markup #f #t (make-stanza-raw-markup arg) (make-stanza-raw-markup "x"))))
% Kompletten Vers mit Akkorden
#(define-markup-command (chordverse layout props stanza verse) (markup? string?)
"Vers mit Akkorden"
(let* ((fromto (chain-assoc-get 'transposition props #f))
(transp (if fromto
(string-append "\\transpose " (car fromto) " " (cdr fromto))
"")))
(interpret-markup layout props
(markup #:override `(baseline-skip . ,songTextLineHeigth) #:anchor-x-between #:stanza stanza
(make-wrap-newline-markup
(regexp-substitute/global #f "\\(( *)([^,()]*)( *),([^)]*)\\)"
(regexp-substitute/global #f "(([^ \n]*\\([^()]*\\)[^ \n]*)+)" verse
'pre " \\concat { " 1 " } " 'post)
'pre "\\textup \\line { \"" 1 "\" " 2 " \"" 3 "\" } \\score { " transp " \\chords { s4 " 4 " } \\layout { \\verseChordLayout } }" 'post))
))))
% Kompletter Vers aus dem Akkorde entfernt werden
#(define-markup-command (nochordverse layout props stanza verse) (markup? string?)
"Vers ohne Akkorde"
(interpret-markup layout props
(markup #:override '(baseline-skip . 3.0) #:anchor-x-between #:stanza stanza
#:wrap-newline (regexp-substitute/global #f "\\(([^,]*),([^)]*)\\)" verse 'pre 1 'post )
)
)
)
#(define-markup-command (verseformat layout props verse) (markup?)
"Textformatierung für Strophen"
(interpret-markup layout props
(make-sans-markup (make-fontsize-markup (ly:output-def-lookup layout 'lyric-size) verse))
)
)
#(define-markup-command (group-verses layout props versegroup) (markup-list?)
#:properties ((verse-cols 1)
(verse-vspace 1)
(verse-hspace 1)
(verse-ordering-horizontal #f))
"Gruppiere Strophen in einem Markup auf Wunsch spaltenweise"
(let ((h (make-hash-table verse-cols))
(index 0)
(column-item-count (ceiling (/ (length versegroup) verse-cols))))
(for-each (lambda (el)
(let ((i (if verse-ordering-horizontal
(modulo index verse-cols)
(floor (/ index column-item-count)))))
(hashv-set! h i (cons el (hashv-ref h i (list)))) (set! index (+ index 1))))
versegroup)
(interpret-markup layout props
(make-fill-line-markup (cons (make-verseformat-markup (make-line-markup
(reverse (hash-fold (lambda (key value l)
(cons (make-column-markup
(fold (lambda (v verses)
(cons v (if (null? verses)
verses
(cons (make-vspace-markup verse-vspace) verses))))
(list) value))
(if (null-list? l)
l
(cons (make-hspace-markup verse-hspace) l))))
(list) h))))
(list))))))

5
void.ly Normal file
View File

@ -0,0 +1,5 @@
% this is just an empty dummy file to make conditional includes work so that relative pathes could be used
% this is working if #(ly:set-option 'relative-includes #t) was set:
% \include #(if condition relative/path/to/file.ly void.ly)
% but this does not work:
% #(if condition (ly:parser-include-string "\\include \"relative/path/to/file.ly\""))