So, jetzt meine aktualiserite Version:
\version "2.18.2"
#(define (string-or-markup? x) (or (string? x) (markup? x)))
pmpStartRepeat = #(define-music-function (parser location) () (make-music 'MarkEvent
'label "<parallel-music-results-postprocess:start repeat volta 2>"))
pmpStartRepeatEx = #(define-music-function (parser location count) (integer?) (make-music 'MarkEvent
'label (string-append "<parallel-music-results-postprocess:start repeat volta " (number->string count) ">")
'extra-int count))
pmpEndRepeat = #(define-music-function (parser location) () (make-music 'MarkEvent
'label "<parallel-music-results-postprocess:end repeat>"))
pmpStartAlternative = #(define-music-function (parser location) () (make-music 'MarkEvent
'label "<parallel-music-results-postprocess:start alternative>"))
pmpStartAlternativeEx = #(define-music-function (parser location s) (string-or-markup?) (make-music 'MarkEvent
'label (string-append "<parallel-music-results-postprocess:start named alternative:" (if (markup? s) "(markup)" s) ">")
'extra-text s))
#(define (pmpMark mus)
(if (ly:music? mus)
(let
((eventtype (ly:music-property mus 'name))
(labeltext (ly:music-property mus 'label))
)
(if (and (eq? eventtype 'MarkEvent) (string? labeltext))
(let*
((head "<parallel-music-results-postprocess:")
(headlen (string-length head))
(labellen (string-length labeltext)))
(if (<= labellen headlen) 0
(let*
((labelhead (string-copy labeltext 0 headlen))
(labelpost (string-copy labeltext headlen))
(postlen (string-length labelpost))
(labelshortpost (string-copy labelpost 0 (min postlen 19)))
)
(if (string=? labelhead head)
(if (string=? labelshortpost "start repeat volta ") 1
(if (string=? labelpost "end repeat>") 2
(if (string=? labelpost "start alternative>") 3
(if (string=? labelshortpost "start named alterna") 4
0))))
0))))
0))
0))
#(define (pmpMarkRepeatCount mus)
(if (ly:music? mus)
(let
((eventtype (ly:music-property mus 'name))
(labeltext (ly:music-property mus 'label)))
(if (and (eq? eventtype 'MarkEvent) (string? labeltext))
(let*
((head "<parallel-music-results-postprocess:")
(headlen (+ (string-length head) 19))
(labellen (string-length labeltext)))
(if (<= labellen headlen) 2
(let*
((labelhead (string-copy labeltext 0 headlen))
(labelpost (string-copy labeltext headlen (- labellen 1)))
(labelterm (string-copy labeltext (- labellen 1))))
(if (string=? labelterm ">") (string->number labelpost)
2))))
2))
2))
#(define (parallel-music-results-postprocess mus)
(let ((eventtype (ly:music-property mus 'name)))
(if (eq? eventtype 'SequentialMusic)
(let
((es (ly:music-property mus 'elements))
(new-es '())
(active-dest 0)
(rep-collect '())
(alt-collect '())
(alt-list-collect '())
(rep-count 2)
)
(for-each (lambda (ese)
(let ((etype (pmpMark ese)))
(if (eq? etype 2) ;; end repeat ;;
(begin
(if (eq? active-dest 3)
(set! alt-list-collect (append alt-list-collect (cons (make-music 'SequentialMusic 'elements alt-collect) '()))))
(set! new-es (append new-es (cons
(make-music 'VoltaRepeatedMusic 'repeat-count (max rep-count (length alt-list-collect))
'element (make-music 'SequentialMusic 'elements rep-collect) 'elements alt-list-collect) '())))
(set! active-dest 0)
(set! rep-collect '())
(set! alt-collect '())
(set! alt-list-collect '())))
(if (eq? etype 1) ;; start repeat ;;
(begin
(if (eq? active-dest 3)
(set! alt-list-collect (append alt-list-collect (cons (make-music 'SequentialMusic 'elements alt-collect) '()))))
(if (>= active-dest 1) ;; terminate existing repeat and start new repeat block
(set! new-es (append new-es (cons
(make-music 'VoltaRepeatedMusic 'repeat-count (max rep-count (length alt-list-collect))
'element (make-music 'SequentialMusic 'elements rep-collect) 'elements alt-list-collect) '()))))
(set! active-dest 1)
(set! rep-collect '())
(set! alt-collect '())
(set! rep-count (ly:music-property ese 'extra-int 2))
(set! alt-list-collect '())))
(if (and (eq? etype 3) (>= active-dest 1)) ;; start alternative (only when repeat allready started) ;;
(if (eq? active-dest 3) ;; next alternative ;;
(begin
(set! alt-list-collect (append alt-list-collect (cons (make-music 'SequentialMusic 'elements alt-collect) '())))
(set! alt-collect '()))
(set! active-dest 3)))
(if (and (eq? etype 4) (>= active-dest 1)) ;; start named alternative (only when repeat allready started) ;;
(begin
(if (eq? active-dest 3) ;; next alternative ;;
(set! alt-list-collect (append alt-list-collect (cons (make-music 'SequentialMusic 'elements alt-collect) '())))
(set! active-dest 3))
(set! alt-collect (cons
(make-music 'ApplyContext
'procedure (lambda (ctx)
(let ((score-ctx (ly:context-find ctx 'Score)))
(if (ly:context? score-ctx)
(let* ((old-rc (ly:context-property score-ctx 'repeatCommands '())) ; (boolean? (cadr v))
(filtered-rc (filter (lambda (v)
(or (not (pair? v)) (not (eq? (car v) 'volta)) (boolean? (cadr v)) )) old-rc)))
(ly:context-set-property! score-ctx 'repeatCommands
(cons (list 'volta (ly:music-property ese 'extra-text "?")) filtered-rc)))))))
'()))))
(if (eq? etype 0)
(begin
(if (eq? active-dest 0)
(set! new-es (append new-es (cons ese '()))))
(if (eq? active-dest 1)
(set! rep-collect (append rep-collect (cons ese '()))))
(if (eq? active-dest 3)
(set! alt-collect (append alt-collect (cons ese '()))))))))
es)
(if (eq? active-dest 1) ;; start repeat is open ;;
(set! new-es (append new-es (cons
(make-music 'VoltaRepeatedMusic 'repeat-count (max rep-count (length alt-list-collect))
'element (make-music 'SequentialMusic 'elements rep-collect) 'elements alt-list-collect) '()))))
(if (eq? active-dest 3) ;; start alternative is open ;;
(begin
(set! alt-list-collect (append alt-list-collect (cons (make-music 'SequentialMusic 'elements alt-collect) '())))
(set! new-es (append new-es (cons
(make-music 'VoltaRepeatedMusic 'repeat-count (max rep-count (length alt-list-collect))
'element (make-music 'SequentialMusic 'elements rep-collect) 'elements alt-list-collect) '())))))
(ly:music-set-property! mus 'elements new-es)
mus)
mus)))
LinearToVoltaRepeats =
#(define-music-function (parser location m) (ly:music?)
(parallel-music-results-postprocess m))
setVoltaText =
#(define-music-function (parser location on-ctx str) ((symbol? 'Score) string-or-markup?)
(make-music 'ApplyContext
'procedure (lambda (ctx)
(let ((this-ctx (ly:context-find ctx on-ctx)))
(if (ly:context? this-ctx)
(let* ((old-rc (ly:context-property this-ctx 'repeatCommands '())) ; (boolean? (cadr v))
(filtered-rc (filter (lambda (v)
(or (not (pair? v)) (not (eq? (car v) 'volta)) (boolean? (cadr v)) )) old-rc)))
(ly:context-set-property! this-ctx 'repeatCommands
(cons (list 'volta str) filtered-rc))))))))
setVoltaEndInContext =
#(define-music-function (parser location on-ctx) (symbol?)
(for-each display (list "\n on-ctx = " on-ctx " "))
(make-music 'ApplyContext
'procedure (lambda (ctx)
(let ((this-ctx (ly:context-find ctx on-ctx)))
(if (ly:context? this-ctx)
(let* ((old-rc (ly:context-property this-ctx 'repeatCommands '())) ; (boolean? (cadr v))
(already-in-rc (filter (lambda (v)
(and (pair? v) (eq? (car v) 'volta) (boolean? (cadr v)) (not (cadr v)) )) old-rc)))
(if (null? already-in-rc)
(ly:context-set-property! this-ctx 'repeatCommands
(cons (list 'volta #f) old-rc)))))))))
setVoltaEnd =
#(define-music-function (parser location) ()
(make-music 'ApplyContext
'procedure (lambda (ctx)
(let ((this-ctx (ly:context-find ctx 'Score)))
(if (ly:context? this-ctx)
(let* ((old-rc (ly:context-property this-ctx 'repeatCommands '())) ; (boolean? (cadr v))
(already-in-rc (filter (lambda (v)
(and (pair? v) (eq? (car v) 'volta) (boolean? (cadr v)) (not (cadr v)) )) old-rc)))
(if (null? already-in-rc)
(ly:context-set-property! this-ctx 'repeatCommands
(cons (list 'volta #f) old-rc)))))))))
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\LinearToVoltaRepeats {
c'1
\pmpStartRepeat
d'
\pmpStartAlternative
e'
\pmpStartAlternative
f'
\pmpStartRepeatEx #3 % impizit wird die zuletzt gestartete Wiederholung
g'
\pmpStartAlternative
a'
\pmpStartAlternativeEx #(make-text-markup (make-bold-markup (make-fontsize-markup 2 "Fine")))
b'
\bar "|."
\pmpStartAlternativeEx #"2."
c''
\pmpStartRepeatEx #5
d''
\pmpStartAlternativeEx #"1., 3."
e''
\pmpStartAlternativeEx #"2., 4."
f''
\pmpStartAlternative
g''
\pmpEndRepeat
a''
\bar "|."
\once \override Score.RehearsalMark.direction = #DOWN
\once \override Score.RehearsalMark.self-alignment-X = #RIGHT
\once \override Score.RehearsalMark.break-visibility = #begin-of-line-invisible
\mark \markup \fontsize #-2 "D.C. al Fine"
}
\LinearToVoltaRepeats {
g1
\pmpStartRepeat
a
\pmpStartRepeat
b
\pmpEndRepeat
c'
\pmpStartRepeatEx #3
d'
\pmpStartAlternative
e'
\pmpStartAlternative
f'
\pmpStartRepeat
g'
\pmpStartAlternative
a'
\pmpStartAlternative
b'
\pmpStartRepeat
c''
\pmpStartAlternative
d''
\pmpStartAlternative
e''
\pmpStartAlternative
f''
\pmpEndRepeat
\bar "|."
}
RM = {
\repeat volta 2 {
c'1 cis'
} \alternative { {
\setVoltaText #"7."
d' dis'1
} {
\setVoltaText #"3."
e'2 e' es'1
} }
}
RMx = {
\repeat volta 2 {
c'1 cis'
} \alternative { {
\setVoltaText #'Staff #"777."
d' dis'
} {
\setVoltaText #'Staff #"333."
e' es'
} }
}
RMxu = {
\repeat volta 2 {
c'1 cis'
} \alternative { {
\setVoltaText #'Staff #"777."
d' \unset Staff.repeatCommands dis'
} {
\setVoltaText #'Staff #"333."
<< { e' } { s2 \unset Staff.repeatCommands } >> es'1
} }
}
\score {
<<
\new Staff { \RM \bar "|." }
\new Staff \with {
\consists Volta_engraver
} { \RM \bar "|." }
>>
\header {
piece = \markup \justify {
Mit \bold "\\setVoltaText" kann man den Starttext
der Volte überschreiben, ohne die anderen \bold repeatCommands
zu überschreiben. Implizit bedeutet das immer auch einen Start
der Volta.
}
}
}
\defineBarLine "|-V" #'("|" "" "|")
\allowVoltaHook "|-V"
LM = {
c'1 \bar ".|:"
d'
\setVoltaText "7."
e'
\bar ":|."
\setVoltaEnd
\setVoltaText "3."
f'
\setVoltaEnd
g'
\setVoltaText #(make-text-markup (make-bold-markup (make-fontsize-markup 2 "bis")))
a' b'
\setVoltaEnd \bar "|-V"
c''
\bar "|."
}
\score {
<<
\new Staff { \LM \bar "|." }
\new Staff \with {
\consists Volta_engraver
} { \LM \bar "|." }
>>
\header {
piece = \markup \column { \justify {
Mit \bold "\\setVoltaEnd" kann man das Ende der Voltenklammer
festlegen. Legt man außderdem die Wiederholungszeichen über \bold "\\bar"
fest, so kann man damit alle (zu druckenden) Wiederholungen ohne Nutzung von
\bold "\\repeat volta" beschreiben. Folglich werden diese auch nicht
durch \bold "\\unfoldRepeats" aufgelöst.
}
\vspace #0.3
\justify {
Übrigens, \bold »bis« ist eine alte Bezeichnung, diesen (kurzen) Abschnitt
zwei Mal zu spielen. Damit die benutzte »Voltenklammer« am Schluß an dem
einfachen Taktstrich auch heruntergezogen wird, in den anderen Fällen aber
nicht, wurde eine »neuer Taktstrich-Satz« mittels \bold "\\defineBarLine"
definiert und an diesem per \bold "\\allowVoltaHook" der Schlußstrich der
Voltenklammer aktiviert.
}
}}
}
\score {
<<
\new Staff { \RM \RM \RM \bar "|." }
\new Staff \with {
\consists Volta_engraver
} { \RM \RMx \RM \bar "|." }
>>
\header {
piece = \markup \justify {
Im Prizip kann man auch in jeder Notenzeile
(d. h. in jedem Staff-Kontext)
einen anderen Text setzen, wäre da nicht noch
das eine oder andere kleine, störende Problemchen.
}
}
}
\score {
<<
\new Staff { \RM \RM \RM \bar "|." }
\new Staff \with {
\consists Volta_engraver
} { \RM \RMxu \RM \bar "|." }
>>
\header {
piece = \markup \justify {
Ein \bold "\\unset Staff.repeatCommands" kurz nach
\bold "\\setVoltaText" hilft erst einmal. Aber dieses
\italic { kurz danach } muß auch die Zeitschritte der anderen
Stimmen mit einschließen, und die Score-weit gesetzte
Bezeichnung geht auch noch verloren!
}
}
}
Dabei mußte ich feststellen, daß ich mit \setVoltaText zwar unterschiedliche Bezeichner in die Voltaklammern auf jeder Notenzeile (Staff) setzen kann, aber mit \consists Volta_engraver allein im Staff-Kontext dann doch noch eingies durcheinander kommt.
Arnold