\version "2.19.82" \pointAndClickOff %% relies on: %% %% VerticalAxisGroup.details.catch-me %% VerticalAxisGroup.details.combined %% VerticalAxisGroup.details.geediness %% %% see inline comments below %% %% %% Limitations/TODOs: %% Staves can't be started/ended mid-line. %% For divisi of two instrument one divisi-Staff needs to be initiated. %% For divisi of three instrument three divisi-Staves need to be initiated. #(define (divisis divisi-groups) ;; Kill selected other Staffs, if divisi-Staffs are alive. ;; Do it separatly for every instrument-group specified by `divisi-groups`. (lambda (grob) ;; `grob` is supposed to be `VerticalAlignment`, per default living in ;; Score-context ;; ;; Apply the procedure to every element of `divisi-groups`, ;; p.e. '("flutes" "trumpets") (for-each (lambda (group) (let* ( ;; Get all `VerticalAxisGroup`s from `VerticalAlignment` ;; Those are the relevant grobs to look at to make others dead ;; or not (vags-array (ly:grob-object grob 'elements)) (vags-list (if (null? vags-array) '() (ly:grob-array->list vags-array))) ;; Select only those `VerticalAxisGroup`s related to current ;; `group` ;; Done by comparing the property `details.catch-me` with `group` (splitted-vags-list (call-with-values (lambda () (partition (lambda (vag) (equal? group (assoc-get 'catch-me (ly:grob-property vag 'details)))) vags-list)) (lambda (x y) (list x y)))) ;; Split them into those supposed to contain combinations and ;; others. ;; Done by reading the property `details.combined`. Which is ;; supposed to be a boolean, if set. ;; ;; The resulting list contains two sublists, each ordered ;; after increasing `details.greediness`. ;; ;; `greediness` should be set like: ;; single: ;; flute-I greediness 1 ;; flute-II greediness 2 ;; flute-III greediness 3 ;; combined ;; flute-1+2+3 greediness 1 ;; flute-1+2 greediness 2 ;; flute-2+3 greediness 3 ;; or similar increasing numerical values. (splitted (call-with-values (lambda () (partition (lambda (vag) (assoc-get 'combined (ly:grob-property vag 'details) #f)) (car splitted-vags-list))) (lambda (x y) (let ( (greediness-sorting-proc (lambda (p q) (< (assoc-get 'greediness (ly:grob-property p 'details) 0) (assoc-get 'greediness (ly:grob-property q 'details) 0))))) (list (sort x greediness-sorting-proc) (sort y greediness-sorting-proc))))))) ;; (length (cadr splitted)) is the amount of instruments which may ;; be combined in divisi staves (case (length (cadr splitted)) ;; Two instruments ((2) ;; Kill all other, if "1+2", i.e. (list-ref (car splitted) 0)), ;; is alive (for-each (lambda (x) (ly:pointer-group-interface::add-grob x 'make-dead-when (list-ref (car splitted) 0))) (remove (lambda (x) (equal? (list-ref (car splitted) 0) x)) (car splitted-vags-list)))) ;; Three instruments ((3) ;; Kill all other, if "1+2+3", i.e. (list-ref (car splitted) 0)), ;; is alive (for-each (lambda (x) (ly:pointer-group-interface::add-grob x 'make-dead-when (list-ref (car splitted) 0))) (remove (lambda (x) (equal? (list-ref (car splitted) 0) x)) (car splitted-vags-list))) ;; Additionally: ;; Kill all but "3", if "1+2", i.e. (list-ref (car splitted) 1)), ;; is alive (for-each (lambda (x) (ly:pointer-group-interface::add-grob x 'make-dead-when (list-ref (car splitted) 1))) ;; all but "3": (take (cadr splitted) 2)) ;; Additionally: ;; Kill all but "1", if "2+3", i.e. (list-ref (car splitted) 2)), ;; is alive (for-each (lambda (x) (ly:pointer-group-interface::add-grob x 'make-dead-when (list-ref (car splitted) 2))) ;; all but "1": (drop (cadr splitted) 1))) ;; divisi for 4 instruments is not yet coded (else '())))) divisi-groups))) %% Short-cuts to switch on/off Staves %% They should be inserted at line-breaks. switchOff = \set Staff.keepAliveInterfaces = #'() switchOn = \unset Staff.keepAliveInterfaces %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% EXAMPLE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #(set-default-paper-size "a3") #(set-global-staff-size 15) \paper { indent = 20 short-indent = 20 } %% %% the actual music %% fluteI = \repeat unfold 12 c''2 fluteII = \repeat unfold 12 e'2 trumpetI = \repeat unfold 6 { g'4 c'' e'' c'' } trumpetII = \repeat unfold 6 { e'4 g' c'' g' } trumpetIII = \repeat unfold 6 { c'4 e' g' e' } %% %% controlling divisis (colors only for better viewing) %% %% divisi-Staffs are switched off per default, they may be switched on as wished %% %% flutes combined-flutes-I-II = { %% 1 \switchOff s1 \break %% 2 \switchOn \override NoteHead.color = #green s1 \break %% 3 s1 \break %% 4 \revert NoteHead.color \switchOff s1 \break %% 5 \switchOn \override NoteHead.color = #green s1 \break %% 6 s1 \break \revert NoteHead.color } %% trumpets combined-trumpets-I-II-III = { %% 1 \switchOff s1 \break %% 2 s1 \break %% 3 \switchOn \override NoteHead.color = #red s1 \break %% 4 \revert NoteHead.color \switchOff s1 \break %% 5 s1 \break %% 6 s1 \break } combined-trumpets-I-II = { %% 1 \switchOff s1 \break %% 2 s1 \break %% 3 s1 \break %% 4 \switchOn \override NoteHead.color = #(x11-color 'orange) s1 \break %% 5 \revert NoteHead.color \switchOff s1 \break %% 6 s1 \break } combined-trumpets-II-III = { %% 1 \switchOff s1 \break %% 2 s1 \break %% 3 s1 \break %% 4 s1 \break %% 5 s1 \break %% 6 \switchOn \override NoteHead.color = #yellow s1 \break } %% For divisi instruments initiate Staff-contexts for every single instrument. %% Set `VerticalAxisGroup.details.catch-me` and %% `VerticalAxisGroup.details.greediness` appropiate. The latter may left unset, %% if only two instruments participate. %% Initiate every desired divisi-Staff. %% Staves meant for divisi should be labed with %% `VerticalAxisGroup.details.combined = ##t`, appropriate `catch-me` and %% `greediness'. %% Again, the latter may left unset, if only two instruments participate. %% Apply \RemoveAllEmptyStaves to every divisi-Staff. \score { << %% A Staff which should not become part of any divisi \new Staff = "0" \with { instrumentName = "Picc" shortInstrumentName = "picc" } { \repeat unfold 48 c''8 } %% FLUTES \new StaffGroup \with { \override SystemStartBracket.collapse-height = 1 instrumentName = \markup { \rotate #90 "FLUTES" \hspace #12 } shortInstrumentName = \markup { \rotate #90 "FLUTES" \hspace #12 } } << \new Staff = "fl1" \with { instrumentName = "Fl 1" shortInstrumentName = "Fl 1" \override VerticalAxisGroup.details.catch-me = "flutes" } \fluteI \new Staff = "fl2" \with { instrumentName = "Fl 2" shortInstrumentName = "Fl 2" \override VerticalAxisGroup.details.catch-me = "flutes" } \fluteII \new Staff = "fl1+2" \with { instrumentName = "Fl 1+2" shortInstrumentName = "Fl 1+2" \RemoveAllEmptyStaves \override VerticalAxisGroup.details.catch-me = "flutes" \override VerticalAxisGroup.details.combined = ##t %\override VerticalAxisGroup.details.greediness = 1 } \new Voice << \combined-flutes-I-II \fluteI \fluteII >> >> %% TRUMPETS \new StaffGroup \with { \override SystemStartBracket.collapse-height = 1 instrumentName = \markup { \rotate #90 "TUMPETS" \hspace #12 } shortInstrumentName = \markup { \rotate #90 "TRUMPETS" \hspace #12 } } << \new Staff = "tr1" \with { instrumentName = "Tr 1" shortInstrumentName = "Tr 1" \override VerticalAxisGroup.details.catch-me = "trumpets" \override VerticalAxisGroup.details.greediness = 1 } \trumpetI \new Staff = "tr2" \with { instrumentName = "Tr 2" shortInstrumentName = "Tr 2" \override VerticalAxisGroup.details.catch-me = "trumpets" \override VerticalAxisGroup.details.greediness = 2 } \trumpetII \new Staff = "tr3" \with { instrumentName = "Tr 3" shortInstrumentName = "Tr 3" \override VerticalAxisGroup.details.catch-me = "trumpets" \override VerticalAxisGroup.details.greediness = 3 } \trumpetIII \new Staff = "tr1+2+3" \with { instrumentName = "Tr 1+2+3" shortInstrumentName = "Tr 1+2+3" \RemoveAllEmptyStaves \override VerticalAxisGroup.details.combined = ##t \override VerticalAxisGroup.details.catch-me = "trumpets" \override VerticalAxisGroup.details.greediness = 1 } \new Voice << \combined-trumpets-I-II-III \trumpetI \trumpetII \trumpetIII >> \new Staff = "tr1+2" \with { instrumentName = "Tr 1+2" shortInstrumentName = "Tr 1+2" \RemoveAllEmptyStaves \override VerticalAxisGroup.details.catch-me = "trumpets" \override VerticalAxisGroup.details.combined = ##t \override VerticalAxisGroup.details.greediness = 2 alignAboveContext = "tr3" } \new Voice << \combined-trumpets-I-II \trumpetI \trumpetII >> \new Staff = "tr2+3" \with { instrumentName = "Tr 2+3" shortInstrumentName = "Tr 2+3" \RemoveAllEmptyStaves \override VerticalAxisGroup.details.catch-me = "trumpets" \override VerticalAxisGroup.details.combined = ##t \override VerticalAxisGroup.details.greediness = 3 alignBelowContext = "tr1+2" } \new Voice << \combined-trumpets-II-III \trumpetII \trumpetIII >> >> %% A Staff which should not become part of any divisi \new Staff = "7" \with { instrumentName = "Bass" shortInstrumentName = "Bass" } { \clef bass \repeat unfold 6 c1 } >> \layout { \context { \Score \override VerticalAlignment.before-line-breaking = #(divisis '("flutes" "trumpets")) } } }