Initial clef change: Difference between revisions
Add "See also" Tags: Reverted Visual edit |
No edit summary |
||
| (One intermediate revision by the same user not shown) | |||
| Line 1: | Line 1: | ||
This snippet handles initial clef changes with a custom engraver. This engraver checks whether there is a difference between the initial clef (as given by <code>\with { \clef ... }</code> and the clef at the first timestep. If any difference is encountered a new clef (spaced like a cue clef) is created, while the original clef and any key signatures are modified to look like the initial clef values. See also [[Clef change at the beginning of a piece]] and [[Clef change at the beginning of a piece (alternative)]]. | This snippet handles initial clef changes with a custom engraver. This engraver checks whether there is a difference between the initial clef (as given by <code>\with { \clef ... }</code> and the clef at the first timestep. If any difference is encountered a new clef (spaced like a cue clef) is created, while the original clef and any key signatures are modified to look like the initial clef values. See also the snippets [[Clef change at the beginning of a piece]] and [[Clef change at the beginning of a piece (alternative)]]. | ||
< | <lilypond version="2.24"> | ||
%%% This engraver records the initial clef properties (e.g. what is set by \with { \clef ... }) | |||
%%% If in the first timestep these changed, engrave the original clef, and change formatting and break | |||
%%% alignment of the actual clef to mimic a clef change clef. Duplicates some procedure from clef engraver | |||
%%% and could easily be integrated. | |||
#(define (initial-clef-change-engraver context) | |||
(let ((initial-clef-properties #f) (cclef #f) (keysigs '())) | |||
; macro for checking if any clef property has changed | |||
(define (clef-changed) | |||
(> | |||
(length initial-clef-properties) | |||
(length | |||
(filter | |||
(lambda (x) (equal? (cdr x) (ly:context-property context (car x)))) | |||
initial-clef-properties)))) | |||
(make-engraver | |||
; Record initials propertis | |||
((initialize engraver) | |||
(set! | |||
initial-clef-properties | |||
`((clefGlyph . ,(ly:context-property context 'clefGlyph)) | |||
(clefPosition . ,(ly:context-property context 'clefPosition)) | |||
(middleCClefPosition . ,(ly:context-property context 'middleCClefPosition)) | |||
(clefTransposition . ,(ly:context-property context 'clefTransposition))))) | |||
; Record the actual clef to adjust. Use details.muted to not acknowledge clef created by this engraver. | |||
(acknowledgers | |||
((clef-interface engraver grob source-engraver) | |||
(if (not (assoc-get 'muted (ly:grob-property grob 'details) #f)) | |||
(set! cclef grob))) | |||
((key-signature-interface engraver grob source-engraver) | |||
(set! keysigs (cons grob keysigs)))) | |||
; Create a clef if necessary | |||
((process-music engraver) | |||
(if (and initial-clef-properties (clef-changed)) | |||
(let ((clef (ly:engraver-make-grob engraver 'Clef '()))) | |||
(ly:grob-set-property! clef 'staff-position (assoc-get 'clefPosition initial-clef-properties)) | |||
(ly:grob-set-property! clef 'glyph (assoc-get 'clefGlyph initial-clef-properties)) | |||
(ly:grob-set-nested-property! clef '(details muted) #t) | |||
(if ((lambda (x) (and (number? x) (not (= 0 x)))) | |||
(assoc-get 'clefTransposition initial-clef-properties 0)) | |||
(let ((mod (ly:engraver-make-grob engraver 'ClefModifier '())) | |||
(formatter (ly:context-property context 'clefTranspositionFormatter)) | |||
(style (ly:context-property context 'clefTranspositionStyle)) | |||
(dir (sign (assoc-get 'clefTransposition initial-clef-properties 0))) | |||
(abs_trans (1+ (abs (assoc-get 'clefTransposition initial-clef-properties 0))))) | |||
(if (procedure? formatter) | |||
(ly:grob-set-property! mod 'text (formatter (number->string abs_trans) style))) | |||
(ly:grob-set-object! mod 'side-support-elements (ly:grob-list->grob-array (list clef))) | |||
(ly:grob-set-parent! mod X clef) | |||
(ly:grob-set-parent! mod Y clef) | |||
(ly:grob-set-property! mod 'direction dir)))))) | |||
; Adjust the actual clef and key signatures | |||
((process-acknowledged engraver) | |||
(if (and cclef initial-clef-properties (clef-changed)) | |||
(begin | |||
; Key signatures need to be handled if they appear before the cue-clef | |||
; This requires the break alignment information, so this only sets a | |||
; hook which will be processed during `before-line-breaking` of the | |||
; BreakAlignGroups | |||
(for-each | |||
(lambda (keysig) | |||
(let ((det (ly:grob-property keysig 'details)) | |||
(initial-clef-properties initial-clef-properties)) | |||
(ly:grob-set-property! | |||
keysig | |||
'details | |||
(acons | |||
'break-alignment-handler | |||
(lambda (grob break-alignment) | |||
(let ((start-of-line | |||
(vector-ref | |||
(ly:grob-property break-alignment 'break-align-orders) | |||
2))) | |||
(if (member 'cue-clef (or (member 'key-signature start-of-line) '())) | |||
(ly:grob-set-property! | |||
grob 'c0-position | |||
(assoc-get 'middleCClefPosition initial-clef-properties))))) | |||
det)))) | |||
keysigs) | |||
(ly:grob-set-property! cclef 'non-default #t) | |||
(ly:grob-set-property! cclef 'break-align-symbol 'cue-clef) | |||
(if (not (eq? #t (ly:grob-property cclef 'full-size-change))) | |||
(ly:grob-set-property! cclef 'glyph-name | |||
(format #f "~a_change" (ly:grob-property cclef 'glyph))))))) | |||
; Unset parameters | |||
((stop-translation-timestep engraver) | |||
(set! initial-clef-properties #f) | |||
(set! clef #f) | |||
(set! keysigs '()))))) | |||
\layout { | |||
\context { | |||
\Staff | |||
\consists #initial-clef-change-engraver | |||
} | |||
\context { | |||
\Score | |||
\override BreakAlignGroup.before-line-breaking = | |||
#(lambda (grob) | |||
(let ((grobs (ly:grob-object grob 'elements)) | |||
(break-alignment (ly:grob-parent grob X))) | |||
(if (not (null? grobs)) | |||
(set! grobs (ly:grob-array->list grobs))) | |||
(for-each | |||
(lambda (grob) | |||
(let* ((det (ly:grob-property grob 'details)) | |||
(handler (assoc-get 'break-alignment-handler det))) | |||
(if (procedure? handler) | |||
(handler grob break-alignment)))) | |||
grobs))) | |||
} | |||
} | |||
\new Staff \with { \clef "bass^15" } { | |||
\key bes\major | |||
\clef "treble_8" | |||
c'1 c'1 | |||
\clef bass | |||
c'1 | |||
} | |||
\score { | |||
\layout { | |||
\context { | |||
\Score | |||
\override BreakAlignment.break-align-orders = | |||
##((staff-ellipsis | |||
left-edge | |||
cue-end-clef | |||
ambitus | |||
breathing-sign | |||
optional-material-end-bracket | |||
signum-repetitionis | |||
clef | |||
cue-clef | |||
staff-bar | |||
key-cancellation | |||
key-signature | |||
time-signature | |||
optional-material-start-bracket | |||
custos) | |||
(staff-ellipsis | |||
left-edge | |||
optional-material-end-bracket | |||
cue-end-clef | |||
ambitus | |||
breathing-sign | |||
signum-repetitionis | |||
clef | |||
cue-clef | |||
staff-bar | |||
key-cancellation | |||
key-signature | |||
time-signature | |||
optional-material-start-bracket | |||
custos) | |||
(staff-ellipsis | |||
left-edge | |||
optional-material-end-bracket | |||
ambitus | |||
breathing-sign | |||
signum-repetitionis | |||
clef | |||
cue-clef | |||
key-cancellation | |||
key-signature | |||
time-signature | |||
staff-bar | |||
optional-material-start-bracket | |||
custos)) | |||
} | |||
} | |||
\new Staff \with { \clef "bass^15" } { | |||
\key bes\major | |||
\clef "treble_8" | |||
c'1 c'1 | |||
\clef bass | |||
c'1 | |||
} | |||
} | |||
% Basic usage: | |||
\score { | |||
<< | |||
% Just the treble clef | |||
\new Staff { | |||
\key bes \major | |||
c''1 | |||
} | |||
% Just the bass clef | |||
\new Staff \with { \clef bass } { | |||
\key bes \major | |||
c1 | |||
} | |||
% Initial treble clef, then bass clef | |||
\new Staff { | |||
\key bes \major | |||
\clef bass | |||
c1 | |||
} | |||
% Initial bass clef, then treble clef | |||
\new Staff \with { \clef bass } { | |||
\key bes \major | |||
\clef treble | |||
c''1 | |||
} | |||
>> | |||
\layout { | |||
\context { | |||
\Staff | |||
\consists #initial-clef-change-engraver | |||
} | |||
} | |||
} | |||
</lilypond> | |||
[[Category:Contexts and engravers]] | [[Category:Contexts and engravers]] | ||