From eba0cc537551d407307b6896ff72fd495d8dd113 Mon Sep 17 00:00:00 2001 From: tux Date: Sat, 22 Jul 2023 22:07:57 +0200 Subject: [PATCH] Inhaltlich sinnvollere Aufteilung der include Skripte --- README.md | 2 +- arrows_in_scores.ly | 63 +++ auto_rest_merging.ly | 86 ++++ basic_format_and_style_settings.ly | 101 ++++ book_include.ly | 27 +- chord_settings.ly | 97 ++++ enable_custom_chord_settings.ly | 15 + eps_file_from_song_dir.ly | 18 + footer_with_songinfo.ly | 61 +++ general_include.ly | 730 +---------------------------- standalone_output.ly | 37 ++ styles/bock.ly | 5 +- styles/börnel.ly | 3 + styles/{büddel.ly => büdel.ly} | 5 +- title_with_category_images.ly | 78 +++ verses_with_chords.ly | 170 +++++++ void.ly | 5 + 17 files changed, 767 insertions(+), 736 deletions(-) create mode 100644 arrows_in_scores.ly create mode 100644 auto_rest_merging.ly create mode 100644 basic_format_and_style_settings.ly create mode 100644 chord_settings.ly create mode 100644 enable_custom_chord_settings.ly create mode 100644 eps_file_from_song_dir.ly create mode 100644 footer_with_songinfo.ly create mode 100644 standalone_output.ly rename styles/{büddel.ly => büdel.ly} (73%) create mode 100644 title_with_category_images.ly create mode 100644 verses_with_chords.ly create mode 100644 void.ly diff --git a/README.md b/README.md index 10f2677..b34caa6 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # lilypond-common-includes -Lilypondskripte zur Erstellung eines Liederbuches \ No newline at end of file +Lilypondskripte zur Erstellung eines Liederbuches diff --git a/arrows_in_scores.ly b/arrows_in_scores.ly new file mode 100644 index 0000000..2e06265 --- /dev/null +++ b/arrows_in_scores.ly @@ -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 +} \ No newline at end of file diff --git a/auto_rest_merging.ly b/auto_rest_merging.ly new file mode 100644 index 0000000..aa0fd4b --- /dev/null +++ b/auto_rest_merging.ly @@ -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 + } +} \ No newline at end of file diff --git a/basic_format_and_style_settings.ly b/basic_format_and_style_settings.ly new file mode 100644 index 0000000..f5e6858 --- /dev/null +++ b/basic_format_and_style_settings.ly @@ -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 = "𝄇" \ No newline at end of file diff --git a/book_include.ly b/book_include.ly index b405667..1c5a1ce 100644 --- a/book_include.ly +++ b/book_include.ly @@ -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) stringgerman-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 + } + } + } + #})) diff --git a/enable_custom_chord_settings.ly b/enable_custom_chord_settings.ly new file mode 100644 index 0000000..c7ba858 --- /dev/null +++ b/enable_custom_chord_settings.ly @@ -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) + } +} \ No newline at end of file diff --git a/eps_file_from_song_dir.ly b/eps_file_from_song_dir.ly new file mode 100644 index 0000000..9419160 --- /dev/null +++ b/eps_file_from_song_dir.ly @@ -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)) +)))) diff --git a/footer_with_songinfo.ly b/footer_with_songinfo.ly new file mode 100644 index 0000000..ed71c2a --- /dev/null +++ b/footer_with_songinfo.ly @@ -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 } + } + } +} \ No newline at end of file diff --git a/general_include.ly b/general_include.ly index 091f0b1..8ae3718 100644 --- a/general_include.ly +++ b/general_include.ly @@ -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 -} \ No newline at end of file +HEADER = {} +MUSIC = {} +TEXT = \markuplist {""} diff --git a/standalone_output.ly b/standalone_output.ly new file mode 100644 index 0000000..a79359f --- /dev/null +++ b/standalone_output.ly @@ -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 } +} \ No newline at end of file diff --git a/styles/bock.ly b/styles/bock.ly index 35f28a3..2a06db6 100644 --- a/styles/bock.ly +++ b/styles/bock.ly @@ -8,4 +8,7 @@ songChordFontSeries = #'normal songTextChordAlignment = #'left songScoreChordFontSize = 3 songTextChordFontSize = 2 -songTextLineHeigth = 5.5 \ No newline at end of file +songTextLineHeigth = 5.5 +songInfoPoetAndComposerStacked = ##f +globalSize = 15 +lyricSize = 1.6 \ No newline at end of file diff --git a/styles/börnel.ly b/styles/börnel.ly index 96811a7..e9cbbb8 100644 --- a/styles/börnel.ly +++ b/styles/börnel.ly @@ -9,3 +9,6 @@ songTextChordAlignment = #'center songScoreChordFontSize = 0 songTextChordFontSize = \songScoreChordFontSize songTextLineHeigth = 5 +songInfoPoetAndComposerStacked = ##f +globalSize = 15 +lyricSize = 1.6 \ No newline at end of file diff --git a/styles/büddel.ly b/styles/büdel.ly similarity index 73% rename from styles/büddel.ly rename to styles/büdel.ly index f06a8fb..8fd6456 100644 --- a/styles/büddel.ly +++ b/styles/büdel.ly @@ -8,4 +8,7 @@ songChordFontSeries = #'bold songTextChordAlignment = #'left songScoreChordFontSize = 2 songTextChordFontSize = 2 -songTextLineHeigth = 5 \ No newline at end of file +songTextLineHeigth = 5 +songInfoPoetAndComposerStacked = ##t +globalSize = 15 +lyricSize = 1.6 \ No newline at end of file diff --git a/title_with_category_images.ly b/title_with_category_images.ly new file mode 100644 index 0000000..68f9973 --- /dev/null +++ b/title_with_category_images.ly @@ -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 } +} \ No newline at end of file diff --git a/verses_with_chords.ly b/verses_with_chords.ly new file mode 100644 index 0000000..6a35a4d --- /dev/null +++ b/verses_with_chords.ly @@ -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)))))) \ No newline at end of file diff --git a/void.ly b/void.ly new file mode 100644 index 0000000..d3fb142 --- /dev/null +++ b/void.ly @@ -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\"")) \ No newline at end of file