lilypond-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: engraver to change staff name based on visibility of related staff?


From: Saul Tobin
Subject: Re: engraver to change staff name based on visibility of related staff?
Date: Wed, 5 Jul 2017 16:27:30 -0700

Hi,

Finally getting a chance to play around with this. Thanks for writing up
this proof of concept! I'm learning a lot.

A few questions:

1) When you build alive?-instr-list you seem to assume a correspondence
between vertical-axis-group-list and instrument-names-list. But is that
actually guaranteed? Is the list of all grobs ordered that way to begin
with, and does filter preserve that ordering?

2) Is there a way to check if two VerticalAxisGroups belong to the same
StaffGroup, for instance? What I want to do is modify this so for each
staff with the callback defined, it only looks at the other staves within
the same lowest-level staff grouping. That way, it could be used in a score
with multiple groups of staves. My first shot at just grabbing the related
staves was:

(filter
 (lambda (x)
   (equal? (ly:grob-parent grob 1) (ly:grob-parent x 1)))
 vertical-axis-group-list)

But it seems all VerticalAlignments are the same or something? Hopefully
it's sort of clear what I'm trying to do?

Thanks!

On Sat, Jun 17, 2017 at 3:42 AM, Thomas Morley <address@hidden>
wrote:

> 2017-06-16 23:47 GMT+02:00 Shevek <address@hidden>:
> > Following up on an aspect of the discussion on parts sharing a staff
> > (http://lilypond.1069038.n5.nabble.com/parts-sharing-a-
> staff-tt203873.html).
> >
> > I've spent quite a few hours over the last day trying to figure out how
> > engravers work and how I might take a crack at writing something to
> > automatically handle changing Staff names for divisi staves. I feel like
> > I've understood most of what I've read, but I'm still totally befuddled.
> > This seems like a difficult problem because:
> >
> > 1) It's completely opaque to me how one would check if a Staff is
> visible or
> > not on a given system. The hara-kiri-group-spanner, as far as I can tell,
> > does its work without telling anybody about it. There's not like a
> boolean
> > function you can call to find out if a context will be visible.
> >
> > 2) One needs to do something in one context depending on what happens in
> a
> > different context. Most of the example engravers just do something in one
> > context. Keep_alive_together_engraver collects grobs from different
> contexts
> > and tells them about each other, but then relies on on them to figure out
> > what to do with that information. That doesn't seem adequate here.
> >
> > 3) Such an engraver would need to step through the score by system, after
> > breaking, rather than event by event, and it might need to be able to
> > backtrack to insert an event to change the instrument name prior to the
> most
> > recent system break. The code and documentation I've read has not given
> me
> > any insight into how one might do such a thing.
> >
> > I'd love some feedback and guidance.
>
>
>
> Hi,
>
> I doubt an engraver will ever work for this purpose. As far as I
> understand an engraver usually puts in stuff far too early. You can
> assign a procedure to a grob via 'after-line-breaking, but you will
> not be able to access whatever the procedure returns _in_ the
> engraver.
> I may be proven wrong, though.
>
> Nevertheless, I tried a different approach:
>
> \version "2.19.62"
>
> %% NB
> %% It's a proof of concept, nothing more!!
> %% Currently it will fail for various reasons with extended examples
> #(define change-instr-names
>   (lambda (grob)
>     (let* ((sys (ly:grob-system grob))
>            (sys-all-elts (ly:grob-object sys 'all-elements))
>            (sys-all-elts-list
>              (if (ly:grob-array? sys-all-elts)
>                  (ly:grob-array->list sys-all-elts)
>                  '()))
>            ;; get all VerticalAxisGroup-grobs per System
>            (vertical-axis-group-list
>              (filter
>                (lambda (g)
>                  (grob::has-interface g 'hara-kiri-group-spanner-
> interface))
>                sys-all-elts-list))
>            ;; get all InstrumentName-grobs per System
>            (instrument-names-list
>              (filter
>                (lambda (g)
>                  (grob::has-interface g 'system-start-text-interface))
>                sys-all-elts-list))
>            ;; construct a nested list like
>            ;;   ((#t #<Grob InstrumentName >)
>            ;;    (#f #<Grob InstrumentName >))
>            ;; the boolean indicates whether the Staff is alive, derived
> from
>            ;; VerticalAxisGroup.Y-extent
>            (alive?-instr-list
>              (map
>                (lambda (v i)
>                  (list (interval-sane? (ly:grob-property v 'Y-extent)) i))
>                vertical-axis-group-list
>                instrument-names-list)))
>
>            ;(pretty-print alive?-instr-list)
>
>       ;; First constructing a list and then fragmenting it in various ways
> is
>       ;; not elegant, to say the least.
>       ;; Just a proof of concept...
>       (if (any not (map car alive?-instr-list))
>           (let* ((instr-to-set
>                    (remove
>                      (lambda (e)
>                        (not (car e)))
>                      alive?-instr-list)))
>             (ly:grob-set-property! (cadar instr-to-set) 'text
>               (make-column-markup
>                 (map
>                   (lambda (arg)
>                     (ly:grob-property arg 'text))
>                   (map cadr alive?-instr-list)))))))))
>
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%
> %% Example
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%
>
> \layout {
>   \context {
>       \Staff
>       \override VerticalAxisGroup.after-line-breaking =
> #change-instr-names
>     \RemoveEmptyStaves
>   }
> }
>
> <<
>   \new Staff \with { instrumentName = "One" shortInstrumentName = "one" }
>     { R1 \break c \break c }
>   \new Staff \with { instrumentName = "Two" shortInstrumentName = "two" }
>     { c1 R c }
> >>
>
>
> Cheers,
>   Harm
>


reply via email to

[Prev in Thread] Current Thread [Next in Thread]