On 2021-10-28 11:27 am, Kieren MacMillan wrote:
2. Maybe even better: Would a Scheme engraver be able to extract (and “delete”/omit) *all* dynamics from one context (e.g., the piano_upper context) and inject them into a second context (e.g., piano_dynamics)? If so, what would be the most elegant way of indicating that a single/particular dynamic marking *shouldn’t* be extracted/pushed by the engraver?

Not an engraver, but a dispatcher trick could be a first step:

%%%%
\version "2.22.0"

#(define event-transfer-sink (ly:make-dispatcher))
eventTransferSink = \applyContext
#(lambda (ctxt)
 (ly:connect-dispatchers
  (ly:context-event-source ctxt)
  event-transfer-sink))

#(define event-transfer-source (ly:make-dispatcher))
eventTransferSource =
#(define-music-function (event-type) (symbol?)
  (define (event-proc ev)
   (ly:broadcast event-transfer-sink (ly:event-deep-copy ev)))
  (define (context-proc ctxt)
   (ly:connect-dispatchers
    event-transfer-source
    (ly:context-events-below ctxt)))
  (ly:add-listener event-proc event-transfer-source event-type)
  #{ \applyContext #context-proc #})

piano_upper = {
  c'4\p d' e' f'
  g'1\mp
  g'4\f f' e' d'
  c'1
}

piano_lower = {
  \clef bass
  c1
  g,1
  g,1
  c1\ff
}

\score {
  <<
    \new PianoStaff <<
\new Staff \with { \eventTransferSource dynamic-event } \piano_upper \new Dynamics \with { \eventTransferSink } { #(skip-of-length piano_upper) } \new Staff \with { \eventTransferSource dynamic-event } \piano_lower
    >>
  >>
}
%%%%

This duplicates events by necessity, because I do not believe you can guarantee that the event transfer process is first to intercept an event. As such, it may have already been processed by another engraver. In the above example, you can \omit DynamicText within the two staves and get what looks to be the desired goal, but that would mean losing all such grobs in those contexts.


-- Aaron Hill

Reply via email to