lilypond-user
[Top][All Lists]
Advanced

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

Re: Create custom arpeggio-like engraver


From: Jean Abou Samra
Subject: Re: Create custom arpeggio-like engraver
Date: Sun, 21 Nov 2021 12:37:13 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.3.1



Le 17/11/2021 à 20:50, Dimitris Marinakis a écrit :
I need a generic engraver that works similar to the default arpeggio one but I don't want to override the arpeggio engraver or any other default ones in case I need to have multiple events simultaneously.

I saw a similar thread with a custom arpeggio stencil that had both up and down arrows but I need to keep this engraver its own thing in this case.

I thought about searching inside the lilypond internal files to see how the default arpeggio spanner works but if someone else can help me through this I'd really appreciate it.

Essentially, I'm interested in the ability of the arpeggio spanner to calculate its length based on the distance of the outer notes. I will replace the line stencil with something that will scale up/stretch depending on the vertical length of that spanner.

Sorry if my terminology is wrong (engraver, spanner etc.)


How about this?

\version "2.22.1"

#(define-event-class 'custom-arpeggio-event 'music-event)

#(define (define-event! type properties)
   (set-object-property! type
                         'music-description
                         (cdr (assq 'description properties)))
   (set! properties (assoc-set! properties 'name type))
   (set! properties (assq-remove! properties 'description))
   (hashq-set! music-name-to-property-table type properties)
   (set! music-descriptions
         (sort (cons (cons type properties)
                     music-descriptions)
               alist<?)))

#(define-event!
  'CustomArpeggioEvent
  '((types . (custom-arpeggio-event post-event event))
    (description . "")))

#(set-object-property! 'CustomArpeggio 'is-grob? #t)
#(set-object-property! 'CustomArpeggio 'translation-type? ly:grob-properties?)

\layout {
  \context {
    \Global
    \grobdescriptions #(acons 'CustomArpeggio
                              (assq-ref all-grob-descriptions 'Arpeggio)
                              all-grob-descriptions)
  }
}

#(ly:register-translator
  (lambda (context)
    (let ((arpeggio-event #f)
          (arpeggio #f))
      (make-engraver
        (listeners
          ((custom-arpeggio-event engraver event)
             (set! arpeggio-event event)))
        ((process-music engraver)
           (if arpeggio-event
               (set! arpeggio
                     (ly:engraver-make-grob engraver 'CustomArpeggio arpeggio-event))))
        (acknowledgers
          ((rhythmic-head-interface engraver grob source-engraver)
             (if arpeggio
                 (ly:pointer-group-interface::add-grob arpeggio 'side-support-elements grob)))
          ((stem-interface engraver grob source-engraver)
             (if arpeggio
                 (begin
                   (ly:grob-set-parent! arpeggio Y grob)
                   (ly:pointer-group-interface::add-grob arpeggio 'stems grob))))
          ((note-column-interface engraver grob source-engraver)
             (if arpeggio
                 (ly:pointer-group-interface::add-grob grob 'conditional-elements arpeggio)))
          ((arpeggio-interface engraver grob source-engraver)
             ; NB ==============================================
             ; Place custom arpeggios on the left of normal ones.
             ; If this is not what you want, flip 'arpeggio' and
             ; 'grob' below.
             ; =================================================
             (ly:pointer-group-interface::add-grob arpeggio 'side-support-elements grob)))
        ((stop-translation-timestep engraver)
           (set! arpeggio-event #f)
           (set! arpeggio #f)))))
  'Custom_arpeggio_engraver
  '())

\layout {
  \context {
    \Voice
    \consists Custom_arpeggio_engraver
  }
}

customArpeggio = #(make-music 'CustomArpeggioEvent)

{
  <c' c''>\customArpeggio
  \override CustomArpeggio.color = red
  <c' c''>\arpeggio\customArpeggio
}


The engraver is adapted from the default Arpeggio_engraver,
of which the C++ code can be found at
https://gitlab.com/lilypond/lilypond/-/blob/master/lily/arpeggio-engraver.cc
For information on Scheme engravers, see
https://extending-lilypond.readthedocs.io/en/latest/translation.html

To get the vertical extent of the CustomArpeggio in
a stencil callback, read the 'positions property. For
example:

\score {
  \layout {
    #(layout-set-staff-size 30)
  }
  {
    \override CustomArpeggio.stencil =
      #(lambda (grob)
         (let ((positions (interval-scale (ly:grob-property grob 'positions)
(ly:staff-symbol-staff-space grob))))
           (ly:stencil-translate-axis
            (grob-interpret-markup
             grob
             (make-draw-squiggle-line-markup
              0.5
              (cons 0 (interval-length positions))
              #t))
            (car positions)
            Y)))
    <c c''>\arpeggio\customArpeggio
  }
}

Best,
Jean



reply via email to

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