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

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

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

Shevek
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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

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

Thomas Morley-2
2017-06-16 23:47 GMT+02:00 Shevek <[hidden email]>:

> 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

_______________________________________________
lilypond-devel mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-devel
Loading...