Re: New snippet: remove staff if another is alive (for wind divisi)
Thomas Morley writes: > Or with other words, the rhythm is wrong in the line labeled with %% <== > > controlDivisi = { > \switchOn > s4 s s s > \switchOff > s %% <== > \switchOn > s1 > } > > And I'm blind ... at least today. It's more like that I'm better at answering "how would this look to a computer" kind of questions than "how would this look to a human" ones, having spent so much more time in my life with the former. -- David Kastrup ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: New snippet: remove staff if another is alive (for wind divisi)
2018-08-09 0:09 GMT+02:00 David Kastrup : > Thomas Morley writes: > >> 2018-08-08 22:21 GMT+02:00 Thomas Morley : >> >>> >>> Well, this whole post was meant to explain my thoughts while coding >>> the example from my previous mail. >>> I expected the code to fail like my previous. >>> It doesn't. >>> Though, even after your hints above, what's the essential difference? >>> >>> I'll investigate. >> >> >> The essential difference is the rhythm of the control-voice. >> The code below never prints single instrument staves. >> But changing in controlDivisi >> s4 s s s -> s1 >> works. >> >> Changing >> s4 s s s -> $#{ s4 s s s #} >> works as well. >> >> WTF? > > Bit of a red herring here. Those two sequences produce the same music > but the first one sets the default duration to 4 while the second one > leaves it unchanged at the previous value of 1, and the next skip then, > lacking a duration of its own, gets a duration of 4 and 1, respectively. > > Same with s4 s s s -> s1 . That's one reason why it is a good idea to > use an explicit duration for the first note of each line, making the > line's meaning independent from how the last line ended (at least > regarding the duration). > > -- > David Kastrup Or with other words, the rhythm is wrong in the line labeled with %% <== controlDivisi = { \switchOn s4 s s s \switchOff s %% <== \switchOn s1 } And I'm blind ... at least today. Thanks, Harm ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: New snippet: remove staff if another is alive (for wind divisi)
Thomas Morley writes: > 2018-08-08 22:21 GMT+02:00 Thomas Morley : > >> >> Well, this whole post was meant to explain my thoughts while coding >> the example from my previous mail. >> I expected the code to fail like my previous. >> It doesn't. >> Though, even after your hints above, what's the essential difference? >> >> I'll investigate. > > > The essential difference is the rhythm of the control-voice. > The code below never prints single instrument staves. > But changing in controlDivisi > s4 s s s -> s1 > works. > > Changing > s4 s s s -> $#{ s4 s s s #} > works as well. > > WTF? Bit of a red herring here. Those two sequences produce the same music but the first one sets the default duration to 4 while the second one leaves it unchanged at the previous value of 1, and the next skip then, lacking a duration of its own, gets a duration of 4 and 1, respectively. Same with s4 s s s -> s1 . That's one reason why it is a good idea to use an explicit duration for the first note of each line, making the line's meaning independent from how the last line ended (at least regarding the duration). -- David Kastrup ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: New snippet: remove staff if another is alive (for wind divisi)
2018-08-08 22:21 GMT+02:00 Thomas Morley : > > Well, this whole post was meant to explain my thoughts while coding > the example from my previous mail. > I expected the code to fail like my previous. > It doesn't. > Though, even after your hints above, what's the essential difference? > > I'll investigate. The essential difference is the rhythm of the control-voice. The code below never prints single instrument staves. But changing in controlDivisi s4 s s s -> s1 works. Changing s4 s s s -> $#{ s4 s s s #} works as well. WTF? \version "2.19.82" one = { e'1 f'4 g' a' f' g'1 } two = { c'1 d'1 e'1 } breaks = { s1 \break s1 \break s1 } switchOff = \set Staff.keepAliveInterfaces = #'() switchOn = \unset Staff.keepAliveInterfaces controlDivisi = { \switchOn % s1 % s4 s s s $#{ s4 s s s #} \switchOff s \switchOn s1 } \new StaffGroup \with { \consists "Keep_alive_together_engraver" } << \new Staff = "single1" \with { \override VerticalAxisGroup.remove-layer = 2 } << \breaks \one >> \new Staff = "single2" \with { \override VerticalAxisGroup.remove-layer = 2 } << \breaks \two >> \new Staff = "divisi" \with { \RemoveAllEmptyStaves \override VerticalAxisGroup.remove-layer = 1 } << \controlDivisi \new Voice { \voiceOne \one } \new Voice { \voiceTwo \two } >> >> Cheers, Harm ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: New snippet: remove staff if another is alive (for wind divisi)
2018-08-08 15:25 GMT+02:00 David Kastrup : > Thomas Morley writes: > >> 2018-08-07 21:42 GMT+02:00 David Kastrup : >>> Thomas Morley writes: >>> 2018-08-07 20:28 GMT+02:00 David Kastrup : > Thomas Morley writes: >>> Ok, let me chime in: I've basically developed some of the low-level >>> mechanisms for divisi staves. >> >> You mean that 'make-dead-when stuff? > > Well, that's the internal part of the low end. But it's usually driven > by the remove-layer property. You are not actually using it? Nope. I'll have a closer look at it, though. >>> >>> Maybe it's a failure. It may well have problems scaling since it >>> creates a single hierarchy. I know that one tenet or inspiration for >>> that kind of numerical hierarchy was that it was reasonably certain to >>> avoid creating strange loops. >> >> >> I've started trying to understand 'remove-layer by reading the IR, >> doc-strings and playing with /input/regression/divisi-staves.ly >> Afaik no further documentation exists. >> >> As mentioned earlier in this thread I think divisi-Staffs should be >> controled from inside themselves, not from the content for the single >> voices. > > What does "from inside themselves" even mean? You need three different > versions: what should appear in the non-divided staves, what should > appear in the upper staff of a division, what should appear in the lower > staff of a division. All of these need to be present in source, likely > employing the help of tags. > > I think one problem here may be what we consider "divisi staves": > I suspect that your approach considers two voices to be identical > outside of a divisi stave passage. However, divisi passages rarely > require divisi staves unless the division becomes too complex to be > representable in a single staff. > > So for me the principal division is not as much one of unison > vs. divided rather than monophonic vs polyphonic (the former usually > lends itself to single-staff notation reasonably well). Which means > that the content in "does not need divisi staves" passages still > fundamentally contains three different versions to work with rather than > a single one. > >> Thus I changed the regtest like below. >> While it works starting with single Staffs, switching to divisi and >> back later, from a divisiVoice >> It fails the other way round, i.e. single Staffs are never printed. >> >> switchOff = \set Staff.keepAliveInterfaces = #'() >> switchOn = \unset Staff.keepAliveInterfaces >> >> violI=\relative d' { >> \repeat unfold 44 d4 >> 2 >> \repeat unfold 58 d4 >> \bar "|." >> } >> >> violII=\relative g { >> \repeat unfold 44 g4 >> 2 >> \repeat unfold 58 g4 >> \bar "|." >> } >> >> %% start with single Staffs, switch to divisi and back later >> tstI = { >> \switchOff >> \repeat unfold 44 s4 >> \switchOn >> s2 >> \switchOff >> \repeat unfold 58 s4 >> } >> >> %% start with divisi, switch to single Staffs and back later >> tstII = { >> \switchOn >> \repeat unfold 44 s4 >> \switchOff >> s2 >> \switchOn >> \repeat unfold 58 s4 >> } >> >> divisiVoiceI = >> \new Voice << \tstI \violII \violI >> >> >> divisiVoiceII = >> \new Voice << \tstII \violII \violI >> >> >> \score { >> \new StaffGroup \with { \consists "Keep_alive_together_engraver" } >> << >> \new Staff \with { instrumentName = "Violin I" >>shortInstrumentName = "V I" >>\RemoveAllEmptyStaves >>\override VerticalAxisGroup.remove-layer = 2 >> } >> \violI >> \new Staff \with { instrumentName = "Violin II" >>shortInstrumentName = "V II" >>\RemoveAllEmptyStaves >>\override VerticalAxisGroup.remove-layer = 2 >> } >> \violII >> \new Staff \with { instrumentName = "Violins" >>shortInstrumentName = "V I" >>\override VerticalAxisGroup.remove-layer = 1 >>\RemoveAllEmptyStaves >> } >> %% control divisi: >> %\divisiVoiceI >> \divisiVoiceII > > This is a total mess. The point of remove-layers is that lower layer > numbers override higher layer numbers, so your divisi control has to be > applied to the lower layer number only, making the higher layer number > appear as fallback when the lower layer number has no motivation to do > so. > > But you switched around the layer numbering, making the divisi staves > the _higher_ numbers (which only appear when the non-divisi staff > suicides). And then instead of applying the divisi controls to a > selected group, you just apply it to everything, meaning that when you > use "\switchOff", none of the contexts retain a reason to appear. > >> >> >> \layout { >> short-indent = 2\cm >> indent = 3\cm >> } >> } >> >> Am I doing something wrong? > > Definitely. First start with the given example. Then put your divisi > controls _only_ in the divisi staff.
Re: New snippet: remove staff if another is alive (for wind divisi)
Thomas Morley writes: > 2018-08-07 21:42 GMT+02:00 David Kastrup : >> Thomas Morley writes: >> >>> 2018-08-07 20:28 GMT+02:00 David Kastrup : Thomas Morley writes: >>> >> Ok, let me chime in: I've basically developed some of the low-level >> mechanisms for divisi staves. > > You mean that 'make-dead-when stuff? Well, that's the internal part of the low end. But it's usually driven by the remove-layer property. You are not actually using it? >>> >>> Nope. >>> I'll have a closer look at it, though. >> >> Maybe it's a failure. It may well have problems scaling since it >> creates a single hierarchy. I know that one tenet or inspiration for >> that kind of numerical hierarchy was that it was reasonably certain to >> avoid creating strange loops. > > > I've started trying to understand 'remove-layer by reading the IR, > doc-strings and playing with /input/regression/divisi-staves.ly > Afaik no further documentation exists. > > As mentioned earlier in this thread I think divisi-Staffs should be > controled from inside themselves, not from the content for the single > voices. What does "from inside themselves" even mean? You need three different versions: what should appear in the non-divided staves, what should appear in the upper staff of a division, what should appear in the lower staff of a division. All of these need to be present in source, likely employing the help of tags. I think one problem here may be what we consider "divisi staves": I suspect that your approach considers two voices to be identical outside of a divisi stave passage. However, divisi passages rarely require divisi staves unless the division becomes too complex to be representable in a single staff. So for me the principal division is not as much one of unison vs. divided rather than monophonic vs polyphonic (the former usually lends itself to single-staff notation reasonably well). Which means that the content in "does not need divisi staves" passages still fundamentally contains three different versions to work with rather than a single one. > Thus I changed the regtest like below. > While it works starting with single Staffs, switching to divisi and > back later, from a divisiVoice > It fails the other way round, i.e. single Staffs are never printed. > > switchOff = \set Staff.keepAliveInterfaces = #'() > switchOn = \unset Staff.keepAliveInterfaces > > violI=\relative d' { > \repeat unfold 44 d4 > 2 > \repeat unfold 58 d4 > \bar "|." > } > > violII=\relative g { > \repeat unfold 44 g4 > 2 > \repeat unfold 58 g4 > \bar "|." > } > > %% start with single Staffs, switch to divisi and back later > tstI = { > \switchOff > \repeat unfold 44 s4 > \switchOn > s2 > \switchOff > \repeat unfold 58 s4 > } > > %% start with divisi, switch to single Staffs and back later > tstII = { > \switchOn > \repeat unfold 44 s4 > \switchOff > s2 > \switchOn > \repeat unfold 58 s4 > } > > divisiVoiceI = > \new Voice << \tstI \violII \violI >> > > divisiVoiceII = > \new Voice << \tstII \violII \violI >> > > \score { > \new StaffGroup \with { \consists "Keep_alive_together_engraver" } > << > \new Staff \with { instrumentName = "Violin I" >shortInstrumentName = "V I" >\RemoveAllEmptyStaves >\override VerticalAxisGroup.remove-layer = 2 > } > \violI > \new Staff \with { instrumentName = "Violin II" >shortInstrumentName = "V II" >\RemoveAllEmptyStaves >\override VerticalAxisGroup.remove-layer = 2 > } > \violII > \new Staff \with { instrumentName = "Violins" >shortInstrumentName = "V I" >\override VerticalAxisGroup.remove-layer = 1 >\RemoveAllEmptyStaves > } > %% control divisi: > %\divisiVoiceI > \divisiVoiceII This is a total mess. The point of remove-layers is that lower layer numbers override higher layer numbers, so your divisi control has to be applied to the lower layer number only, making the higher layer number appear as fallback when the lower layer number has no motivation to do so. But you switched around the layer numbering, making the divisi staves the _higher_ numbers (which only appear when the non-divisi staff suicides). And then instead of applying the divisi controls to a selected group, you just apply it to everything, meaning that when you use "\switchOff", none of the contexts retain a reason to appear. > >> > \layout { > short-indent = 2\cm > indent = 3\cm > } > } > > Am I doing something wrong? Definitely. First start with the given example. Then put your divisi controls _only_ in the divisi staff. That's the one that is interested in forcing its appearance. If you really want to have the same source without tags, you could override DivisiStaff.keepAliveInterfaces and distribute context aliases in a manner
Re: New snippet: remove staff if another is alive (for wind divisi)
2018-08-07 21:42 GMT+02:00 David Kastrup : > Thomas Morley writes: > >> 2018-08-07 20:28 GMT+02:00 David Kastrup : >>> Thomas Morley writes: >> > Ok, let me chime in: I've basically developed some of the low-level > mechanisms for divisi staves. You mean that 'make-dead-when stuff? >>> >>> Well, that's the internal part of the low end. But it's usually driven >>> by the remove-layer property. You are not actually using it? >> >> Nope. >> I'll have a closer look at it, though. > > Maybe it's a failure. It may well have problems scaling since it > creates a single hierarchy. I know that one tenet or inspiration for > that kind of numerical hierarchy was that it was reasonably certain to > avoid creating strange loops. I've started trying to understand 'remove-layer by reading the IR, doc-strings and playing with /input/regression/divisi-staves.ly Afaik no further documentation exists. As mentioned earlier in this thread I think divisi-Staffs should be controled from inside themselves, not from the content for the single voices. Thus I changed the regtest like below. While it works starting with single Staffs, switching to divisi and back later, from a divisiVoice It fails the other way round, i.e. single Staffs are never printed. switchOff = \set Staff.keepAliveInterfaces = #'() switchOn = \unset Staff.keepAliveInterfaces violI=\relative d' { \repeat unfold 44 d4 2 \repeat unfold 58 d4 \bar "|." } violII=\relative g { \repeat unfold 44 g4 2 \repeat unfold 58 g4 \bar "|." } %% start with single Staffs, switch to divisi and back later tstI = { \switchOff \repeat unfold 44 s4 \switchOn s2 \switchOff \repeat unfold 58 s4 } %% start with divisi, switch to single Staffs and back later tstII = { \switchOn \repeat unfold 44 s4 \switchOff s2 \switchOn \repeat unfold 58 s4 } divisiVoiceI = \new Voice << \tstI \violII \violI >> divisiVoiceII = \new Voice << \tstII \violII \violI >> \score { \new StaffGroup \with { \consists "Keep_alive_together_engraver" } << \new Staff \with { instrumentName = "Violin I" shortInstrumentName = "V I" \RemoveAllEmptyStaves \override VerticalAxisGroup.remove-layer = 2 } \violI \new Staff \with { instrumentName = "Violin II" shortInstrumentName = "V II" \RemoveAllEmptyStaves \override VerticalAxisGroup.remove-layer = 2 } \violII \new Staff \with { instrumentName = "Violins" shortInstrumentName = "V I" \override VerticalAxisGroup.remove-layer = 1 \RemoveAllEmptyStaves } %% control divisi: %\divisiVoiceI \divisiVoiceII >> \layout { short-indent = 2\cm indent = 3\cm } } Am I doing something wrong? Cheers, Harm ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: New snippet: remove staff if another is alive (for wind divisi)
Super glad to see this conversation happening! David I'm so glad you've been working on the backend for divisi. Divisi staves have long been my biggest headache. Thomas, thanks for writing the improved version. I haven't had a chance to look at the code deeply yet — I will play around with it this weekend. One observation about the user interface: logically, if the combined 1+2 staff is hidden, both the staff for 1 and the staff for 2 should be printed. IMO one of the design goals for a divisi user interface should be to manage this automatically without the need to write separate simultaneous commands to hide or unhide each staff. There are only two possible states for a two-part divisi: combined or separate staves. Only a single command should be needed to toggle that state. Extrapolate for 3, 4 way divisi etc. As an aside, for what it's worth, from my perspective as a composer who uses a lot of divisi staves, I want to minimize separation of divisi commands from musical content, because the choice to divide or not depends on the musical content, which I may revise frequently. I recognize that many other Lilypond users prefer the style you used in your example, but I just thought I'd mention it, since if this is moving towards an officially supported interface, IMO it needs to support both styles. Saul On Tue, Aug 7, 2018 at 12:42 PM David Kastrup wrote: > Thomas Morley writes: > > > 2018-08-07 20:28 GMT+02:00 David Kastrup : > >> Thomas Morley writes: > > > Ok, let me chime in: I've basically developed some of the low-level > mechanisms for divisi staves. > >>> > >>> You mean that 'make-dead-when stuff? > >> > >> Well, that's the internal part of the low end. But it's usually driven > >> by the remove-layer property. You are not actually using it? > > > > Nope. > > I'll have a closer look at it, though. > > Maybe it's a failure. It may well have problems scaling since it > creates a single hierarchy. I know that one tenet or inspiration for > that kind of numerical hierarchy was that it was reasonably certain to > avoid creating strange loops. > > -- > David Kastrup > > ___ > lilypond-user mailing list > lilypond-user@gnu.org > https://lists.gnu.org/mailman/listinfo/lilypond-user > ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: New snippet: remove staff if another is alive (for wind divisi)
Thomas Morley writes: > 2018-08-07 20:28 GMT+02:00 David Kastrup : >> Thomas Morley writes: > Ok, let me chime in: I've basically developed some of the low-level mechanisms for divisi staves. >>> >>> You mean that 'make-dead-when stuff? >> >> Well, that's the internal part of the low end. But it's usually driven >> by the remove-layer property. You are not actually using it? > > Nope. > I'll have a closer look at it, though. Maybe it's a failure. It may well have problems scaling since it creates a single hierarchy. I know that one tenet or inspiration for that kind of numerical hierarchy was that it was reasonably certain to avoid creating strange loops. -- David Kastrup ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: New snippet: remove staff if another is alive (for wind divisi)
2018-08-07 20:28 GMT+02:00 David Kastrup : > Thomas Morley writes: >>> Ok, let me chime in: I've basically developed some of the low-level >>> mechanisms for divisi staves. >> >> You mean that 'make-dead-when stuff? > > Well, that's the internal part of the low end. But it's usually driven > by the remove-layer property. You are not actually using it? Nope. I'll have a closer look at it, though. Cheers, Harm ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: New snippet: remove staff if another is alive (for wind divisi)
Thomas Morley writes: > 2018-08-07 19:48 GMT+02:00 David Kastrup : >> Thomas Morley writes: >> >>> 2018-08-06 21:40 GMT+02:00 Thomas Morley : 2018-08-05 18:14 GMT+02:00 Thomas Morley : > Inspired by your work I come up with the attached. Attached an improved and simplified version. It's tested with 2/3/4-voices divisi, all in one score. Although not tested, I see no reason why it shouldn't work with even more voices. >>> >>> >>> Further improvements. >>> >>> It's now possible to omit 'catch-me, _iff_ single instrument-staves >>> and divisi-staves belong exculsively to the same container-context >>> like StaffGroup, GrandStaff, ChoirStaff or PianoStaff with removed >>> "Keep_alive_together_engraver", which is most likely always the case. >>> For ungrouped single/divisi 'catch-me is still neccesary. >> >> Ok, let me chime in: I've basically developed some of the low-level >> mechanisms for divisi staves. > > You mean that 'make-dead-when stuff? Well, that's the internal part of the low end. But it's usually driven by the remove-layer property. You are not actually using it? > It does not work in 2.18.2. Sure. -- David Kastrup ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: New snippet: remove staff if another is alive (for wind divisi)
2018-08-07 19:48 GMT+02:00 David Kastrup : > Thomas Morley writes: > >> 2018-08-06 21:40 GMT+02:00 Thomas Morley : >>> 2018-08-05 18:14 GMT+02:00 Thomas Morley : >>> Inspired by your work I come up with the attached. >>> >>> Attached an improved and simplified version. >>> It's tested with 2/3/4-voices divisi, all in one score. >>> Although not tested, I see no reason why it shouldn't work with even >>> more voices. >> >> >> Further improvements. >> >> It's now possible to omit 'catch-me, _iff_ single instrument-staves >> and divisi-staves belong exculsively to the same container-context >> like StaffGroup, GrandStaff, ChoirStaff or PianoStaff with removed >> "Keep_alive_together_engraver", which is most likely always the case. >> For ungrouped single/divisi 'catch-me is still neccesary. > > Ok, let me chime in: I've basically developed some of the low-level > mechanisms for divisi staves. You mean that 'make-dead-when stuff? It does not work in 2.18.2. The 'staff-grouper grob-object? > There are no user-level commands or music > functions or Scheme abstractions making use of them. There is no parser > support (like for << \\ >>) but it's likely that isn't really required. Up to now I can't think of any parser-supported syntax. Seems all works so far with simple overrides. > But there certainly is a need for a user level interface, and from the > description this sounds like you are off to a good start. > > Think you can turn this (assuming it isn't already) into something > obvious and general enough that it would be satisfying to document and > use it without having to meddle with the low-level mechanisms at least, > say, 85% of the time? With my most recent coding the user has to do three things: (1) Initiate a divisi-Staff, applying p.e. \override VerticalAxisGroup.details.combined = #'(1 2) (2) Awake the divisi-Staff via \switchOn in the musical-content (3) Let it all happen with \override VerticalAlignment.before-line-breaking = %#(divisis "flutes" "trumpets" "cors") %#(divisis) #(divisis "flutes") at Score level. That's all. The whole scheme-coding could be included. Though, there are some points I don't like or have concerns. @(1) The argument '(1 2) will result in: combine voices 1 and 2 and kill the the single printing of them. But it relies on unchanged order of the lists processed. I'm currently not sure this is warrented, although testings didn't fail so far. Ofcourse I used details.combined to avoid a real custom-grob-property, some for 'catch-me. If we think of implementing something like this coding we should probably turn those in own grob-properties @(2) It's done by switchOff = \set Staff.keepAliveInterfaces = #'() switchOn = \unset Staff.keepAliveInterfaces I'm not sure I like this, it feels clumsy. @(3) Here I'm fine so far, having a procedure doing all automagically, unless container-contexts are missing. Currently I'm a bit at a loss how to proceed. Ideas? Cheers, Harm ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: New snippet: remove staff if another is alive (for wind divisi)
Thomas Morley writes: > 2018-08-06 21:40 GMT+02:00 Thomas Morley : >> 2018-08-05 18:14 GMT+02:00 Thomas Morley : >> >>> Inspired by your work I come up with the attached. >> >> Attached an improved and simplified version. >> It's tested with 2/3/4-voices divisi, all in one score. >> Although not tested, I see no reason why it shouldn't work with even >> more voices. > > > Further improvements. > > It's now possible to omit 'catch-me, _iff_ single instrument-staves > and divisi-staves belong exculsively to the same container-context > like StaffGroup, GrandStaff, ChoirStaff or PianoStaff with removed > "Keep_alive_together_engraver", which is most likely always the case. > For ungrouped single/divisi 'catch-me is still neccesary. Ok, let me chime in: I've basically developed some of the low-level mechanisms for divisi staves. There are no user-level commands or music functions or Scheme abstractions making use of them. There is no parser support (like for << \\ >>) but it's likely that isn't really required. But there certainly is a need for a user level interface, and from the description this sounds like you are off to a good start. Think you can turn this (assuming it isn't already) into something obvious and general enough that it would be satisfying to document and use it without having to meddle with the low-level mechanisms at least, say, 85% of the time? -- David Kastrup ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: New snippet: remove staff if another is alive (for wind divisi)
2018-08-06 21:40 GMT+02:00 Thomas Morley : > 2018-08-05 18:14 GMT+02:00 Thomas Morley : > >> Inspired by your work I come up with the attached. > > Attached an improved and simplified version. > It's tested with 2/3/4-voices divisi, all in one score. > Although not tested, I see no reason why it shouldn't work with even > more voices. Further improvements. It's now possible to omit 'catch-me, _iff_ single instrument-staves and divisi-staves belong exculsively to the same container-context like StaffGroup, GrandStaff, ChoirStaff or PianoStaff with removed "Keep_alive_together_engraver", which is most likely always the case. For ungrouped single/divisi 'catch-me is still neccesary. Cheers, Harm \version "2.19.82" \pointAndClickOff %% relies on: %% %% VerticalAxisGroup.details.catch-me %% VerticalAxisGroup.details.combined %% %% About `catch-me` %% Inside of container-contexts like StaffGroup, GrandStaff, ChoirStaff or %% PianoStaff with removed "Keep_alive_together_engraver" %% `catch-me` may be omitted. %% To get divisis work outside of such containers `catch-me` needs to be set %% to a value matching one of the optional arguments of the divisis-procedure %% Currently we use strings for `catch-me` and the arguments of the %% divisis-procedure, a symbol would work as well. %% %% About `combined` %% `combined` labels divisi-staffs. It is supposed to be a list of positive %% integers, representing the combined instruments. %% p.e. To combine flute-III and flute-IV, set `combined` to '(3 4) %% %% %% More inline comments below %% %% %% Limitations: %% Staves can't be started/ended mid-line. %% TODOs %% Killing/awakening relies on the order single instrument-staves are entered. %% Is it safe to assume the order of lists with VerticalAxisGroups will %% not be confused? %% c/p from lily-library.scm #(define (split-at-predicate pred lst) "Split LST into two lists at the first element that returns #f for (PRED previous_element element). Return the two parts as a pair. Example: (split-at-predicate < '(1 2 3 2 1)) ==> ((1 2 3) . (2 1))" (let ((i (and (pair? lst) (list-index (lambda (x y) (not (pred x y))) lst (cdr lst) (if i (call-with-values (lambda () (split-at lst (1+ i))) cons) (list lst #(define (sort-vags vags) ;; Returns sublists of VAGs in same StaffGrouper (define (helper l1 l2) (if (null? l1) (reverse l2) (let ((splitted-l1 (split-at-predicate (lambda (x y) (equal? (ly:grob-object x 'staff-grouper) (ly:grob-object y 'staff-grouper))) l1))) (helper (cdr splitted-l1) (cons (car splitted-l1) l2) (helper vags '())) #(define (select-vags vags) ;; Return two sublists containing VerticalAxisGroups with and without ;; setted 'combined. (call-with-values (lambda () (partition (lambda (vag) (pair? (assoc-get 'combined (ly:grob-property vag 'details) '( vags)) (lambda (x y) (list x y #(define (kill-selected-vags sorted-vags) ;; `sorted-vags` is supposed to be a list of two sublists, containing ;; VerticalAxisGroups for divisi and non-divisi-staves (if (pair? (car sorted-vags)) (for-each (lambda (i) ;; if divisi staves are alive, kill selected other staves ;; relying on the combined-values (for-each (lambda (x) (ly:pointer-group-interface::add-grob x 'make-dead-when (list-ref (car sorted-vags) i))) ;; get a list of VerticalAxisGroups used with ;; divisi-staves (map (lambda (index) (list-ref (cadr sorted-vags) (1- index))) ;; get the 'combined-value from 'details, which is ;; supposed to be a list. ;; TODO 'combined is read here and in `splitted` above. ;; Find a method to spare one go (assoc-get 'combined (ly:grob-property (list-ref (car sorted-vags) i) 'details) '() (iota (length (car sorted-vags)) #(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 (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 ;; empty lists removed (if (null? vags-array) '() (remove
Re: New snippet: remove staff if another is alive (for wind divisi)
2018-08-06 21:40 GMT+02:00 Thomas Morley : > 2018-08-05 18:14 GMT+02:00 Thomas Morley : > >> Inspired by your work I come up with the attached. > > Attached an improved and simplified version. > It's tested with 2/3/4-voices divisi, all in one score. > Although not tested, I see no reason why it shouldn't work with even > more voices. I forgot to update the explaining comment before the \score. It should now read: %% For divisi instruments initiate Staff-contexts for every single instrument. %% Set `VerticalAxisGroup.details.catch-me` appropiate. %% %% Initiate every desired divisi-Staff. %% Staves meant for divisi should be labed with %% `VerticalAxisGroup.details.combined` set to a list of positive integers, %% representing the combined voices. Set appropriate `catch-me` as well. %% Apply \RemoveAllEmptyStaves to every divisi-Staff. \score { Cheers, Harm ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: New snippet: remove staff if another is alive (for wind divisi)
2018-08-05 18:14 GMT+02:00 Thomas Morley : > Inspired by your work I come up with the attached. Attached an improved and simplified version. It's tested with 2/3/4-voices divisi, all in one score. Although not tested, I see no reason why it shouldn't work with even more voices. HTH, Harm \version "2.19.82" \pointAndClickOff %% relies on: %% %% VerticalAxisGroup.details.catch-me %% VerticalAxisGroup.details.combined %% %% see inline comments below %% %% %% Limitations: %% Staves can't be started/ended mid-line. #(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` (relevant-vags-list (filter (lambda (vag) (equal? group (assoc-get 'catch-me (ly:grob-property vag 'details vags-list)) ;; Split them into those supposed to contain combinations and ;; others. ;; Done by reading the property `details.combined`. Which is ;; supposed to be a list, containing numbers, representing the ;; combined voices. ;; I.e. if we have 4 flutes, all combined, `details.combined` ;; should be '(1 2 3 4) ;; (splitted (call-with-values (lambda () (partition (lambda (vag) (pair? (assoc-get 'combined (ly:grob-property vag 'details) '( relevant-vags-list)) (lambda (x y) (list x y) (if (pair? (car splitted)) (for-each (lambda (i) ;; if divisi staves are alive, kill selected other staves ;; relying on the combined-values (for-each (lambda (x) (ly:pointer-group-interface::add-grob x 'make-dead-when (list-ref (car splitted) i))) ;; get a list of VerticalAxisGroups used with divisi-staves (map (lambda (index) (list-ref (cadr splitted) (1- index))) ;; get the 'combined-value from 'details, which is ;; supposed to be a list. (assoc-get 'combined (ly:grob-property (list-ref (car splitted) i) 'details) '() (iota (length (car splitted))) 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 "a2") #(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' } corI = \repeat unfold 6 { c''2 c''4 c'' } corII = \repeat unfold 6 { g'2 g'4 g' } corIII = \repeat unfold 6 { e'2 e'4 e' } corIV = \repeat unfold 6 { c'2 c'4 c' } %% %% controlling divisis %% colors only for better viewing; ofcourse coding could be more concise %% p.e. deleting redundant \break-commands, they should likely be part of an %% own voice anyway; using s1*x etc %% %% 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
Re: New snippet: remove staff if another is alive (for wind divisi)
2018-08-03 23:14 GMT+02:00 Saul Tobin : > Hi all, > > I just put together a snippet to make managing shared wind staves more > automatic, particularly with triple winds that may be combined in different > ways. > > \version "2.19.82" > > #(define remove-if-sibling >(lambda (offsets) > (lambda (grob) >(let* ( >;; The parent of a VerticalAxisGroup is a VerticalAlignment >(parent (ly:grob-parent grob 1)) >;; Get the children VerticalAxisGroups of the parent >(siblings (ly:grob-object parent 'elements)) >(siblings-list > (if (ly:grob-array? siblings) > (ly:grob-array->list siblings) > '())) >;; Find the siblings above or below me by offsets >(my-vindex (ly:grob-get-vertical-axis-group-index grob)) >(enemy-indices (map (lambda (offset) (+ offset my-vindex)) > offsets)) >(enemy-vaxis? (lambda (v) (member > (ly:grob-get-vertical-axis-group-index v) >enemy-indices))) >(enemy-vaxes > (filter enemy-vaxis? siblings-list)) >) > ;; Suicide if an enemy sibling is alive > (map > (lambda (enemy-vaxis) > (ly:pointer-group-interface::add-grob grob 'make-dead-when > enemy-vaxis)) > enemy-vaxes) > ) >) > ) >) > > %% Two Staff Example > > global = { > s1 > \break > s1 > \break > s1*2 > } > > I = { > c'''1 > \context Staff = "1" { \set Staff.keepAliveInterfaces = #'() } > c'''1 > c'''1 > \context Staff = "1" { \unset Staff.keepAliveInterfaces } > c'''1 > } > > II = { > e''1 > e''1 > e''1 > e''1 > } > > << > \new Staff = "1+2" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(1)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \partcombine \I \II >> > \new Staff = "1" \with { > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \I >> > \new Staff = "2" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(-2)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \II >> >>> > > %% Three Staff Example > > global = { > s1 > \break > s1 > \break > s1 > \break > s1*2 > } > > I = { > c'''1 > \context Staff = "1" { \set Staff.keepAliveInterfaces = #'() } > c'''1 > c'''1 > c'''1 > \context Staff = "1" { \unset Staff.keepAliveInterfaces } > c'''1 > } > > II = { > e''1 > e''1 > e''1 > e''1 > e''1 > } > > III = { > a'1 > a'1 > \context Staff = "3" { \set Staff.keepAliveInterfaces = #'() } > a'1 > a'1 > a'1 > } > > << > \new Staff = "1+2+3" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(2 5)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \I \II \III >> > \new Staff = "1+2" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(1 -1)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \partcombine \I \II >> > \new Staff = "1" \with { > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \I >> > \new Staff = "2+3" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(2 -3)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \partcombine \II \III >> > \new Staff = "2" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(-1 -3 -4)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \II >> > \new Staff = "3" \with { > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \III >> >>> > > ___ > lilypond-user mailing list > lilypond-user@gnu.org > https://lists.gnu.org/mailman/listinfo/lilypond-user > Hi, I had a closer look at your code. You select via vertical-axis-group-index. This makes for a not intuitive argument of your `remove-if-sibling`-procedure. Even worse, the needed arguments may need to be changed if other staves are added to the score. Also I think divisis should be controlled, well, from the divisi-staves. Inspired by your work I come up with the attached. Cheers, Harm divisi-saul-02-test.pdf Description: Adobe PDF document \version "2.19.82"
Re: New snippet: remove staff if another is alive (for wind divisi)
Those errors are from this expression in the three staff example: << \global \I \II \III >>. Lilypond is implicitly creating three Voices instead of treating it as a single Voice with simultaneous music. If you replace that expression with { <> << \global \I \II \III >> }, the errors go away. Since the partcombiner doesn't currently support more than 2 arguments, this is something that requires a workaround if you want to do three parts on a single staff. Anyway, it doesn't affect the point of this snippet, which is automatically hiding staves based on which other staves are alive on each system. On Fri, Aug 3, 2018 at 2:23 PM Ben wrote: > On 8/3/2018 5:14 PM, Saul Tobin wrote: > > Hi all, > > I just put together a snippet to make managing shared wind staves more > automatic, particularly with triple winds that may be combined in different > ways. > > \version "2.19.82" > > #(define remove-if-sibling >(lambda (offsets) > (lambda (grob) >(let* ( >;; The parent of a VerticalAxisGroup is a VerticalAlignment >(parent (ly:grob-parent grob 1)) >;; Get the children VerticalAxisGroups of the parent >(siblings (ly:grob-object parent 'elements)) >(siblings-list > (if (ly:grob-array? siblings) > (ly:grob-array->list siblings) > '())) >;; Find the siblings above or below me by offsets >(my-vindex (ly:grob-get-vertical-axis-group-index grob)) >(enemy-indices (map (lambda (offset) (+ offset my-vindex)) > offsets)) >(enemy-vaxis? (lambda (v) (member > (ly:grob-get-vertical-axis-group-index v) >enemy-indices))) >(enemy-vaxes > (filter enemy-vaxis? siblings-list)) >) > ;; Suicide if an enemy sibling is alive > (map > (lambda (enemy-vaxis) > (ly:pointer-group-interface::add-grob grob 'make-dead-when > enemy-vaxis)) > enemy-vaxes) > ) >) > ) >) > > %% Two Staff Example > > global = { > s1 > \break > s1 > \break > s1*2 > } > > I = { > c'''1 > \context Staff = "1" { \set Staff.keepAliveInterfaces = #'() } > c'''1 > c'''1 > \context Staff = "1" { \unset Staff.keepAliveInterfaces } > c'''1 > } > > II = { > e''1 > e''1 > e''1 > e''1 > } > > << > \new Staff = "1+2" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(1)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \partcombine \I \II >> > \new Staff = "1" \with { > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \I >> > \new Staff = "2" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(-2)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \II >> > >> > > %% Three Staff Example > > global = { > s1 > \break > s1 > \break > s1 > \break > s1*2 > } > > I = { > c'''1 > \context Staff = "1" { \set Staff.keepAliveInterfaces = #'() } > c'''1 > c'''1 > c'''1 > \context Staff = "1" { \unset Staff.keepAliveInterfaces } > c'''1 > } > > II = { > e''1 > e''1 > e''1 > e''1 > e''1 > } > > III = { > a'1 > a'1 > \context Staff = "3" { \set Staff.keepAliveInterfaces = #'() } > a'1 > a'1 > a'1 > } > > << > \new Staff = "1+2+3" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(2 5)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \I \II \III >> > \new Staff = "1+2" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(1 -1)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \partcombine \I \II >> > \new Staff = "1" \with { > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \I >> > \new Staff = "2+3" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(2 -3)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \partcombine \II \III >> > \new Staff = "2" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(-1 -3 -4)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \II >> > \new Staff = "3" \with { > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \III >> >
Re: New snippet: remove staff if another is alive (for wind divisi)
On 8/3/2018 5:14 PM, Saul Tobin wrote: Hi all, I just put together a snippet to make managing shared wind staves more automatic, particularly with triple winds that may be combined in different ways. \version "2.19.82" #(define remove-if-sibling (lambda (offsets) (lambda (grob) (let* ( ;; The parent of a VerticalAxisGroup is a VerticalAlignment (parent (ly:grob-parent grob 1)) ;; Get the children VerticalAxisGroups of the parent (siblings (ly:grob-object parent 'elements)) (siblings-list (if (ly:grob-array? siblings) (ly:grob-array->list siblings) '())) ;; Find the siblings above or below me by offsets (my-vindex (ly:grob-get-vertical-axis-group-index grob)) (enemy-indices (map (lambda (offset) (+ offset my-vindex)) offsets)) (enemy-vaxis? (lambda (v) (member (ly:grob-get-vertical-axis-group-index v) enemy-indices))) (enemy-vaxes (filter enemy-vaxis? siblings-list)) ) ;; Suicide if an enemy sibling is alive (map (lambda (enemy-vaxis) (ly:pointer-group-interface::add-grob grob 'make-dead-when enemy-vaxis)) enemy-vaxes) ) ) ) ) %% Two Staff Example global = { s1 \break s1 \break s1*2 } I = { c'''1 \context Staff = "1" { \set Staff.keepAliveInterfaces = #'() } c'''1 c'''1 \context Staff = "1" { \unset Staff.keepAliveInterfaces } c'''1 } II = { e''1 e''1 e''1 e''1 } << \new Staff = "1+2" \with { \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling '(1)) \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \partcombine \I \II >> \new Staff = "1" \with { \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \I >> \new Staff = "2" \with { \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling '(-2)) \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \II >> >> %% Three Staff Example global = { s1 \break s1 \break s1 \break s1*2 } I = { c'''1 \context Staff = "1" { \set Staff.keepAliveInterfaces = #'() } c'''1 c'''1 c'''1 \context Staff = "1" { \unset Staff.keepAliveInterfaces } c'''1 } II = { e''1 e''1 e''1 e''1 e''1 } III = { a'1 a'1 \context Staff = "3" { \set Staff.keepAliveInterfaces = #'() } a'1 a'1 a'1 } << \new Staff = "1+2+3" \with { \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling '(2 5)) \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \I \II \III >> \new Staff = "1+2" \with { \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling '(1 -1)) \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \partcombine \I \II >> \new Staff = "1" \with { \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \I >> \new Staff = "2+3" \with { \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling '(2 -3)) \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \partcombine \II \III >> \new Staff = "2" \with { \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling '(-1 -3 -4)) \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \II >> \new Staff = "3" \with { \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \III >> >> Hello, Thanks for sharing this with us! One question... When I just copy and paste your snippet into Frescobaldi as is, I get a few errors. ? = Interpreting music... Interpreting music... Interpreting music... Interpreting music... Interpreting music... Preprocessing graphical objects... Interpreting music... Preprocessing graphical objects... document.ly:103:3: warning: this Voice needs a \voiceXx or \shiftXx setting e''1 document.ly:102:3: warning: this Voice needs a \voiceXx or \shiftXx setting e''1 document.ly:101:3: warning: this Voice needs a \voiceXx or \shiftXx setting e''1 document.ly:100:3: warning: this Voice needs a \voiceXx or \shiftXx setting e''1 document.ly:99:3: warning: this Voice needs a \voiceXx or \shiftXx setting e''1 Finding the ideal number of pages... Fitting music on 1 page... Drawing systems... Layout output to `./tmp-lilypond-BWUill'... Converting to `document.pdf'... Deleting
New snippet: remove staff if another is alive (for wind divisi)
Hi all, I just put together a snippet to make managing shared wind staves more automatic, particularly with triple winds that may be combined in different ways. \version "2.19.82" #(define remove-if-sibling (lambda (offsets) (lambda (grob) (let* ( ;; The parent of a VerticalAxisGroup is a VerticalAlignment (parent (ly:grob-parent grob 1)) ;; Get the children VerticalAxisGroups of the parent (siblings (ly:grob-object parent 'elements)) (siblings-list (if (ly:grob-array? siblings) (ly:grob-array->list siblings) '())) ;; Find the siblings above or below me by offsets (my-vindex (ly:grob-get-vertical-axis-group-index grob)) (enemy-indices (map (lambda (offset) (+ offset my-vindex)) offsets)) (enemy-vaxis? (lambda (v) (member (ly:grob-get-vertical-axis-group-index v) enemy-indices))) (enemy-vaxes (filter enemy-vaxis? siblings-list)) ) ;; Suicide if an enemy sibling is alive (map (lambda (enemy-vaxis) (ly:pointer-group-interface::add-grob grob 'make-dead-when enemy-vaxis)) enemy-vaxes) ) ) ) ) %% Two Staff Example global = { s1 \break s1 \break s1*2 } I = { c'''1 \context Staff = "1" { \set Staff.keepAliveInterfaces = #'() } c'''1 c'''1 \context Staff = "1" { \unset Staff.keepAliveInterfaces } c'''1 } II = { e''1 e''1 e''1 e''1 } << \new Staff = "1+2" \with { \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling '(1)) \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \partcombine \I \II >> \new Staff = "1" \with { \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \I >> \new Staff = "2" \with { \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling '(-2)) \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \II >> >> %% Three Staff Example global = { s1 \break s1 \break s1 \break s1*2 } I = { c'''1 \context Staff = "1" { \set Staff.keepAliveInterfaces = #'() } c'''1 c'''1 c'''1 \context Staff = "1" { \unset Staff.keepAliveInterfaces } c'''1 } II = { e''1 e''1 e''1 e''1 e''1 } III = { a'1 a'1 \context Staff = "3" { \set Staff.keepAliveInterfaces = #'() } a'1 a'1 a'1 } << \new Staff = "1+2+3" \with { \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling '(2 5)) \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \I \II \III >> \new Staff = "1+2" \with { \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling '(1 -1)) \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \partcombine \I \II >> \new Staff = "1" \with { \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \I >> \new Staff = "2+3" \with { \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling '(2 -3)) \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \partcombine \II \III >> \new Staff = "2" \with { \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling '(-1 -3 -4)) \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \II >> \new Staff = "3" \with { \override VerticalAxisGroup.remove-empty = ##t \override VerticalAxisGroup.remove-first = ##t } << \global \III >> >> ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user