Hi,
ich möchte mehrere bookparts in einer Ausgabe zusammenfassen, nachfolgend ein (nicht funktionierendes) Beispiel:
\version "2.19.83"
test =
#(define-music-function (p)
(ly:pitch?)
#{
\new Staff \transpose c $p \relative c'' { c e g }
#}
)
xtest =
#(define-void-function (p q) (ly:pitch? ly:pitch?)
(add-score
(scorify-music #{ { \test $p } #}))
(add-score
(scorify-music #{ { \test $q } #}))
)
mybook =
#(define-void-function (p) (ly:pitch?)
#{
\bookpart {
\xtest $p $p
}
\bookpart {
\xtest $p $p
}
#}
)
\book {
\mybook c
}
Wenn ich in die Funktion mybook nur einen bookpart einfüge, erhalte ich zwar keine Fehlermeldung, aber auch keine Ausgabe.
Lilypond bricht mit einer Fehlermeldung unexpected \bookpart, expecting end of input ab.
Kann man das Programm so ändern, dass es funktioniert?
\version "2.19.83"
test =
#(define-music-function (p)
(ly:pitch?)
#{
\new Staff \transpose c $p \relative c'' { cis e g }
#})
xtest =
#(define-scheme-function (p q) (ly:pitch? ly:pitch?)
(scorify-music (test p)))
mybook =
#(define-void-function (p) (ly:pitch?)
(let* ((bk (ly:make-book $defaultpaper $defaultheader '()))
(bk-parts
(list
(ly:make-book-part (list (xtest p p)))
(ly:make-book-part (list (xtest p p))))))
(for-each
(lambda (bookpart) (ly:book-add-bookpart! bk bookpart))
bk-parts)
(ly:book-process
bk
$defaultpaper
$defaultlayout
(ly:parser-output-name))))
\mybook c
Sollte Dich in die richtige Richtung bringen.
Auch wenn der Beispiel-Code arg abgespeckt ist, Z.B. xtest hat zwei Variablen, verwendet aber nur eine.
Gruß,
Harm
Danke Harm. Das ist sehr hilfreich für mich :)
Der Beispielcode ist natürlich grober Unfug, mein tatsächlicher Code ist ein wenig sinnvoller ;-)
Hallo Harm,
leider klappt es nicht wie gewünscht. Z.B. ist nicht jeder bookpart auf einer eigenen Seite.
Wahrscheinlich ist mein Code wieder mal zu kompliziert. :( :-[
Ich habe rausgefunden, woran es liegt. Sobald in der define-scheme-function addscore 2x auftaucht, tuscht es. Hier ein Beispiel:
\version "2.19.83"
test =
#(define-music-function (p)
(ly:pitch?)
#{
\new Staff \transpose c $p \relative c'' { cis e g }
#})
xtest =
#(define-scheme-function (p q) (ly:pitch? ly:pitch?)
(add-score
(scorify-music (test p)))
(add-score
(scorify-music (test q)))
)
mybook =
#(define-void-function (p q) (ly:pitch? ly:pitch?)
(let* ((bk (ly:make-book $defaultpaper $defaultheader '()))
(bk-parts
(list
(ly:make-book-part (list (xtest p q)))
(ly:make-book-part (list (xtest q p))))))
(for-each
(lambda (bookpart) (ly:book-add-bookpart! bk bookpart))
bk-parts)
(ly:book-process
bk
$defaultpaper
$defaultlayout
(ly:parser-output-name))))
\mybook c d
ZitatIch habe rausgefunden, woran es liegt. Sobald in der define-scheme-function addscore 2x auftaucht, tuscht es
Nun, warum überhaupt add-score?
In meinem Beipiel hatte ich es gestrichen, sodaß xtest einen score zurückgibt! Wozu mehr?
Gruß,
Harm
Danke für deine Antworten, Harm.
Weil ich eine Überschrift als markup habe, und das markup kriege ich in keine define-music-function hinein.
\version "2.19.83"
test =
#(define-music-function (p)
(ly:pitch?)
#{
\new Staff \transpose c $p \relative c'' { cis e g }
#})
xtest =
#(define-scheme-function (p q) (ly:pitch? ly:pitch?)
(add-score
(list #{ \markup \fill-line \override #'(font-features . ("smcp")) \override #'(box-padding . 1)
\override #'(thickness . 2) \override #'(font-size . 4)
{ \null \rounded-box \concat { "Meine Überschrift" } \null }
#}))
(add-score
(scorify-music (test q)))
)
mybook =
#(define-void-function (p q) (ly:pitch? ly:pitch?)
(let* ((bk (ly:make-book $defaultpaper $defaultheader '()))
(bk-parts
(list
(ly:make-book-part (list (xtest p q)))
(ly:make-book-part (list (xtest q p))))))
(for-each
(lambda (bookpart) (ly:book-add-bookpart! bk bookpart))
bk-parts)
(ly:book-process
bk
$defaultpaper
$defaultlayout
(ly:parser-output-name))))
\mybook c d
Wenn sich das anders lösen lässt, würde es mich freuen :-)
ZitatWeil ich eine Überschrift als markup habe, und das markup kriege ich in keine define-music-function hinein.
Eigentlich soll das markup ja in den
bookpart hinein ;)
Möglicherweise könnte man etwas mit einem bookpart-header versuchen. Aber book und boopart sind sone Geschichte...
Ich habs jetzt nur für natives markup gemacht:
\version "2.19.83"
test =
#(define-music-function (p)
(ly:pitch?)
#{
\new Staff \transpose c $p \relative c'' { cis e g }
#})
xtest =
#(define-scheme-function (p q) (ly:pitch? ly:pitch?)
(scorify-music (test p)))
#(define (make-book-parts-with-top-markup markup scores)
(let ((bp (ly:make-book-part '())))
(for-each
(lambda (score) (ly:book-add-score! bp score))
(cons (list markup) scores))
bp))
myMarkup =
\markup
\fill-line
\override #'(font-features . ("smcp"))
\override #'(box-padding . 1)
\override #'(thickness . 2)
\override #'(font-size . 4)
{ \null \rounded-box \concat { "Meine Überschrift" } \null }
mybook =
#(define-void-function (fall-back p) ((string? "top-markup-missing?") ly:pitch?)
(let* ((bk (ly:make-book $defaultpaper $defaultheader '()))
(top-markup (if (defined? 'myMarkup) myMarkup fall-back))
(bk-parts
(list
(make-book-parts-with-top-markup
top-markup
(list (xtest p p)))
(make-book-parts-with-top-markup top-markup
(list (xtest p p) (xtest #{ d #} p) )))))
(for-each
(lambda (bookpart) (ly:book-add-bookpart! bk bookpart))
bk-parts)
(ly:book-process
bk
$defaultpaper
$defaultlayout
(ly:parser-output-name))))
\mybook c
HTH,
Harm
Danke Harm, das hilft mir erst mal weiter.
Jetzt muss ich das Markup zu einer Funktion umbauen, wo als Parameter ebenfalls die Tonhöhe vorkommt. Mal sehen, ob ich das gebacken kriege...
Danke Harm, du hast mir sehr geholfen.
Ein Problem ist jetzt aufgetaucht. Wenn ich die Funktion 2x ausführe, kommt nur der letzte Teil heraus. Wahrscheinlich nur eine Kleinigkeit.
Und noch eine Frage: wenn ich in den verschiedenen bookparts unterschiedliche \paper-Einstellungen haben will, z.B. top-markup-spacing.minimum-distance etc, wie kann ich das machen?
\version "2.19.83"
test =
#(define-music-function (p)
(ly:pitch?)
#{
\new Staff \transpose c $p \relative c'' { cis e g }
#})
xtest =
#(define-scheme-function (p q) (ly:pitch? ly:pitch?)
(scorify-music (test p)))
#(define (make-book-parts-with-top-markup markup scores)
(let ((bp (ly:make-book-part '())))
(for-each
(lambda (score) (ly:book-add-score! bp score))
(cons (list markup) scores))
bp))
#(define (pitch-alteration-semitones pitch)
(inexact->exact (round (* (ly:pitch-alteration pitch) 2))))
#(define (conditional-string-downcase str condition)
(if condition
(string-downcase str)
str))
%% Notenname als Markup mit deutschen Notennamen
#(define (note-name->my-markup pitch lowercase?)
(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 (+ 1 alt-semitones))
(cons name alt-semitones))))
(make-line-markup
;(make-simple-markup
(list
(string-append
(conditional-string-downcase
(list-ref '("C" "D" "E" "F" "G" "A" "H" "B") (car n-a))
lowercase?)
(if (or (equal? (car n-a) 2) (equal? (car n-a) 5))
(list-ref '( "ses" "s" "" "is" "isis") (+ 2 (cdr n-a)))
(list-ref '("eses" "es" "" "is" "isis") (+ 2 (cdr n-a)))))))))
#(define-markup-command (my-header layout props p text1 text2) (ly:pitch? string? string?)
(interpret-markup layout props
#{ \markup \fill-line \override #'(font-features . ("smcp"))
\override #'(box-padding . 1)
\override #'(thickness . 2) \override #'(font-size . 4)
{ \null \rounded-box \concat { $text1 #(note-name->my-markup p #f) $text2 } \null }
#}))
mybook =
#(define-void-function (p) (ly:pitch?)
(let* ((bk (ly:make-book $defaultpaper $defaultheader '()))
(my-kadenzen #{ \markup \my-header ##{ $p #} "Kadenzen " "-Dur" #} )
(my-dreiklang #{ \markup \my-header ##{ $p #} "Leitereigene Dreiklänge " "-Dur" #} )
(my-vierklang #{ \markup \my-header ##{ $p #} "Leitereigene Vierklänge " "-Dur" #} )
(bk-parts
(list
(make-book-parts-with-top-markup
my-kadenzen
(list (xtest p p)))
(make-book-parts-with-top-markup
my-dreiklang
(list (xtest p p) (xtest #{ d #} p)))
(make-book-parts-with-top-markup
my-vierklang
(list (xtest p p) (xtest #{ d #} p)))
)))
(for-each
(lambda (bookpart) (ly:book-add-bookpart! bk bookpart))
bk-parts)
(ly:book-process
bk
$defaultpaper
$defaultlayout
(ly:parser-output-name))))
\mybook ##{ des #}
\mybook ##{ as #}
ZitatEin Problem ist jetzt aufgetaucht. Wenn ich die Funktion 2x ausführe, kommt nur der letzte Teil heraus. Wahrscheinlich nur eine Kleinigkeit.
Wir machen die books ja jetzt selber, d.h. auch die Namen. Bis jetzt haben die books alle denselben Namen, somit überschreibt ein book das andere.
Du könntest z.B. so vorgehen:
(ly:parser-output-name)
=>
(format #f "~a-~a"
(ly:parser-output-name)
(markup->string (note-name->my-markup p #f)))
Zitat
Und noch eine Frage: wenn ich in den verschiedenen bookparts unterschiedliche \paper-Einstellungen haben will, z.B. top-markup-spacing.minimum-distance etc, wie kann ich das machen?
Das ist schwieriger.
Es gibt keine programmatische Funktion, die das macht. Das liegt auch an der meines Erachtens unvollkommenen Umsetzung von book und bookpart.
Man könnte auch sagen, das Ganze ist buggy ... lol
Aber man kann ja erforschen, ob man tricksen kann.
Heut abend aber nicht mehr, ist zu spät.
Gruß,
Harm
Danke für deine Mühe, Harm!
Das book und bookpart buggy ist, hast du schon mehrmals geschrieben.
Der Clou an der Sache für mich wäre gewesen, ein einziges Ausgabefile für mehrere Funktionsaufrufe zu erzeugen. Es ist ziemlich umständlich, die Ausgabedateien nachträglich zu einem PDF zusammen zu fügen.
Gibt es eine Möglichkeit, die einzelnen Ausgabendateien zu einer Datei zusammen zu hängen? Vll eine Pitchliste erzeugen und diese mappen? Wenn ich nur besser Scheme könnte...
ZitatDer Clou an der Sache für mich wäre gewesen, ein einziges Ausgabefile für mehrere Funktionsaufrufe zu erzeugen.
Ich würd jetzt nicht so schnell die Flinte ins Korn werfen. ;)
ZitatEs ist ziemlich umständlich, die Ausgabedateien nachträglich zu einem PDF zusammen zu fügen.
Hmm, mag sein, daß ein Mißverständnis auf meiner Seite besteht.
Ich hatte mich von Deinem anfänglichen Beispiel leiten lassen, in dem Du explizit ein book schaffst.
Du willst vielmehr ein
einziges book?
(Falls ja, dann darf die void-function kein book erzeugen.)
Gruß,
Harm
Wenn die Lösung mit einer Ausgabedatei für jeden Aufruf (=pitch) nur auf einem Missverständnis beruht, bin ich froh ;)
Ich hätte gerne alle Ausgaben in einer Datei, egal wie oft die Funktion aufgerufen wird (mybook ist daher ein irreführende Name, sollte eher mybookpart heißen)
Ok, ich komm' aber frühestens heute abend dazu, hier weiterzumachen.
Kein Problem, danke für deine Hilfe!
Vielleicht:
\version "2.19.83"
test =
#(define-music-function (p)
(ly:pitch?)
#{
\new Staff \transpose c $p \relative c'' { cis e g }
#})
xtest =
#(define-scheme-function (p q) (ly:pitch? ly:pitch?)
(scorify-music (test p)))
foo = \paper { ragged-right = ##f }
#(define (make-book-parts-with-top-markup markup scores)
(let* ((output-def (ly:make-output-def))
(raw-paper
(begin
(ly:output-def-set-variable! output-def 'is-paper #t)
output-def))
(bp #{ \bookpart { $raw-paper } #}))
(for-each
(lambda (score) (ly:book-add-score! bp score))
(cons (list markup) scores))
bp))
#(define (fill-book-part-paper! bookpart key-value-alist)
(for-each
(lambda (key-value)
(ly:output-def-set-variable!
(ly:book-paper bookpart) (car key-value) (cdr key-value)))
key-value-alist))
#(define (pitch-alteration-semitones pitch)
(inexact->exact (round (* (ly:pitch-alteration pitch) 2))))
#(define (conditional-string-downcase str condition)
(if condition
(string-downcase str)
str))
%% Notenname als Markup mit deutschen Notennamen
#(define (note-name->my-markup pitch lowercase?)
(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 (+ 1 alt-semitones))
(cons name alt-semitones))))
(make-line-markup
;(make-simple-markup
(list
(string-append
(conditional-string-downcase
(list-ref '("C" "D" "E" "F" "G" "A" "H" "B") (car n-a))
lowercase?)
(if (or (equal? (car n-a) 2) (equal? (car n-a) 5))
(list-ref '( "ses" "s" "" "is" "isis") (+ 2 (cdr n-a)))
(list-ref '("eses" "es" "" "is" "isis") (+ 2 (cdr n-a)))))))))
#(define-markup-command (my-header layout props p text1 text2)
(ly:pitch? string? string?)
(interpret-markup layout props
#{
\markup
\fill-line
\override #'(font-features . ("smcp"))
\override #'(box-padding . 1)
\override #'(thickness . 2)
\override #'(font-size . 4)
{
\null
\rounded-box \concat { $text1 #(note-name->my-markup p #f) $text2 }
\null
}
#}))
#(define (add-bookparts-to-toplevel-bookparts pitch)
(let* ((bk (ly:make-book $defaultpaper $defaultheader '()))
(my-kadenzen
#{ \markup \my-header ##{ $pitch #} "Kadenzen " "-Dur" #})
(my-dreiklang
#{
\markup \my-header ##{ $pitch #} "Leitereigene Dreiklänge " "-Dur"
#})
(my-vierklang
#{
\markup \my-header ##{ $pitch #} "Leitereigene Vierklänge " "-Dur"
#})
(paper-kadenzen #{ \paper { line-width = 120 ragged-right = ##f } #})
(paper-dreiklang #{ \paper { top-markup-spacing.padding = 40 } #})
(paper-vierklang #{ \paper { top-markup-spacing.padding = 20 } #})
(bk-parts
(list
(make-book-parts-with-top-markup
my-kadenzen
(list (xtest pitch pitch)))
(make-book-parts-with-top-markup
my-dreiklang
(list (xtest pitch pitch) (xtest #{ d #} pitch)))
(make-book-parts-with-top-markup
my-vierklang
(list (xtest pitch pitch) (xtest #{ d #} pitch))))))
(for-each
(lambda (book-part key-values)
(fill-book-part-paper! book-part key-values))
bk-parts
(map
(lambda (paper)
(ly:module->alist (ly:output-def-scope paper)))
(list paper-kadenzen paper-dreiklang paper-vierklang)))
(for-each
(lambda (book-part)
(ly:parser-define! 'toplevel-bookparts
(cons book-part (ly:parser-lookup 'toplevel-bookparts))))
bk-parts)))
myBookparts =
#(define-void-function (mus) (ly:music?)
(let ((pitches (music-pitches mus)))
(for-each
(lambda (pitch) (add-bookparts-to-toplevel-bookparts pitch))
pitches)))
\myBookparts < des aes >
HTH,
Harm
Danke Harm für die viele Mühe, die du dir für gemacht hast.
Das klappt alles ganz wunderbar :) :) :)