Le 24/03/2021 à 20:06, Peter Crighton a écrit :
On Wed, 24 Mar 2021 at 18:35, Jean Abou Samra <j...@abou-samra.fr <mailto:j...@abou-samra.fr>> wrote:

    Le 24/03/2021 à 15:15, Peter Crighton a écrit :
    > I am working on some chord charts, sheet music that only
    includes one
    > ChordNames context. See the reduced example below.
    >
    > I am now running into a problem when using the multi-mark-engraver
    >
    (https://lists.gnu.org/archive/html/lilypond-user/2011-08/msg00157.html
    <https://lists.gnu.org/archive/html/lilypond-user/2011-08/msg00157.html>
    >
    <https://lists.gnu.org/archive/html/lilypond-user/2011-08/msg00157.html
    <https://lists.gnu.org/archive/html/lilypond-user/2011-08/msg00157.html>>)
    > in order to have multiple rehearsal marks at the same time. As I
    in my
    > template use \override RehearsalMark.outside-staff-priority = ##f to
    > have all marks appear at the same vertical level (relative to the
    > chord symbols) and the multi-mark-engraver also in some way
    works with
    > outside-staff-priority, using the two together results in the error
    > Wrong type argument in position 1: #f.
    > Any ideas on how to get this working together? A change to the
    > multi-mark-engraver I could apply? A good alternative to
    > multi-mark-engraver? Another way to vertically level rehearsal marks
    > other than through disabling outside-staff-priority?

    If you want marks aligned on the same level exactly, why not put
    them in
    the same markup altogether?

    \mark \markup { \bold A some more text }

    Then you don't need the multi-mark-engraver.


Sorry, I wasn’t clear. The alignment to the same level is in order to get them aligned to the chord symbols. If I have several marks at the same time, they might very well be not level. I’ll need them as separate marks to be able to process them separately. There might be situations like one mark appearing before and one after a line break(, but at the same point in time in the code).

Okay. Here is a version of the engraver that caters for this case. I've also cleaned it up somewhat.

Let me know if you encounter any issues with it.

Best,
Jean

\version "2.22.0"

#(use-modules (srfi srfi-26))

#(define-macro (prepend! thing lst)
   `(set! ,lst (cons ,thing ,lst)))

#(define (make-mark ctx engraver event)
   (let* ((mark-grob
           (ly:engraver-make-grob engraver 'RehearsalMark event))
          (ev-label (ly:event-property event 'label))
          (actual-label (if (null? ev-label)
                            (ly:context-property ctx 'rehearsalMark)
                            ev-label))
          (formatter (ly:context-property ctx 'markFormatter))
          (label
            (cond
              ((markup? actual-label)
               actual-label)
              ((not (procedure? formatter))
               (ly:warning "markFormatter must be a procedure")
               empty-markup)
              ((integer? actual-label)
               (formatter actual-label ctx))
              (else
                (ly:warning "rehearsal mark label must be markup, number or \\default")
                empty-markup))))
     (if (integer? actual-label)
         (ly:context-set-property! ctx 'rehearsalMark (1+ actual-label)))
     (ly:grob-set-property! mark-grob 'text label)
     mark-grob))

#(define (Multi_mark_engraver ctx)
   (let ((texts '())
         (final-texts '())
         (events '()))
     (make-engraver
       ((start-translation-timestep engraver)
          (set! final-texts '()))
       (listeners
         ((mark-event engraver event)
            (prepend! event events)))
       ((process-music engraver)
          (for-each (lambda (event)
                      (prepend! (make-mark ctx engraver event)
                                texts))
                    (reverse! events)))
       ((stop-translation-timestep engraver)
          (let ((staves (ly:context-property ctx 'stavesFound)))
            (let loop ((remaining-texts (reverse texts))
                       (i 0))
              (if (not (null? remaining-texts))
                  (let* ((grob (car remaining-texts))
                         (my-found-priority
                          (ly:grob-property grob 'outside-staff-priority))
                         (my-priority (if (or (not my-found-priority)
                                              (null? my-found-priority))
                                          1500
                                          my-found-priority)))
                    (for-each
                      (cute ly:pointer-group-interface::add-grob
                            grob
                            'side-support-elements
                            <>)
                      staves)
                    (ly:grob-set-property! grob
                                           'outside-staff-priority
                                           (+ my-priority i))
                    (prepend! grob final-texts)
                    (loop (cdr remaining-texts)
                          (1+ i))))))
          (set! texts '())
          (set! events '()))
        ((finalize engraver)
           (for-each
             (cute ly:grob-set-property! <> 'break-visibility end-of-line-visible)
             final-texts)))))


#(ly:register-translator
   Multi_mark_engraver
   'Multi_mark_engraver
   '((grobs-created . (RehearsalMark))
     (events-accepted . (mark-event))
     (properties-read . (markFormatter
                         rehearsalMark
                         stavesFound))
     (properties-written . (rehearsalMark))
     (description . "\
An alternative to the Mark_engraver that accepts several marks at the
same moment.")))


\layout {
  \context {
    \Score
    \remove "Mark_engraver"
    \consists "Multi_mark_engraver"
  }
}

Reply via email to