On 27 February 2012 13:48, Graham Percival <gra...@percival-music.ca> wrote:

> What would be involved in making a clean solution for this?  I
> imagine that a separate TextMark engraver (just like the
> RehearsalMark engraver and MetronomeMark engravers) would do the
> trick, but that's a bunch of icky C++ code.  Is there any way to
> use scheme to create a new engraver that behaves like an existing
> engraver (i.e. TextMark), but has its own data (so it doesn't
> merge the rehearsal mark event with the "text mark" event?)

Attached is a scheme engraver I hacked up a few years ago.  It
naturally has a few limitations, particularly if you use multiple
\mark \default commands at the same timestep.

Cheers,
Neil
\version "2.15.8"

#(define (multi-mark-engraver ctx)
   (let ((texts '())
         (final-texts '())
         (events '()))

     `((start-translation-timestep
        . ,(lambda (trans)
             (set! final-texts '())))

       (listeners
        (mark-event
         . ,(lambda (trans ev)	      
              (set! events (cons ev events)))))

       (acknowledgers
        (break-alignment-interface
         . ,(lambda (trans grob source)
              (for-each (lambda (mark)
                          (set! (ly:grob-parent mark X) grob))
                        texts))))

       (process-music
        . ,(lambda (trans)
             (for-each
              (lambda (ev)
                (let* ((mark-grob
                        (ly:engraver-make-grob trans 'RehearsalMark ev))
                       (label (ly:event-property ev 'label))
                       (formatter (ly:context-property ctx 'markFormatter)))

                  (if (and (procedure? formatter)
                           (not (markup? label)))
                      (begin
                       (if (not (number? label))
                           (set! label
                                 (ly:context-property ctx 'rehearsalMark)))
                       
                       (if (and (integer? label)
                                (exact? label))
                           (set! (ly:context-property ctx 'rehearsalMark)
                                 (1+ label)))
                       
                       (if (number? label)
                           (set! label (apply formatter (list label ctx)))
                           (ly:warning "rehearsalMark must have integer value"))))

                  (if (markup? label)
                      (begin
                       (set! (ly:grob-property mark-grob 'text) label)
                       (let ((dir (ly:event-property ev 'direction)))
                         (and (ly:dir? dir)
                              (set! (ly:grob-property mark-grob 'direction)
                                    dir))))
                      (ly:warning "mark label must be a markup object"))

                  (set! texts (cons mark-grob texts))))
              (reverse events))))

       (stop-translation-timestep
        . ,(lambda (trans)
             (if (pair? texts)
                 (let ((staves (ly:context-property ctx 'stavesFound))
                       (priority-index 0))
                   (for-each (lambda (grob)
                               (let ((my-priority (ly:grob-property grob 'outside-staff-priority 1500)))
                                 (for-each (lambda (stave)
                                             (ly:pointer-group-interface::add-grob grob 'side-support-elements
                                               stave))
                                           staves)
                                 (set! (ly:grob-property grob 'outside-staff-priority) (+ my-priority priority-index))
                                 (set! priority-index (1+ priority-index))
                                 (set! final-texts (cons grob final-texts))))
                             (reverse texts))
                     (set! texts '())
                     (set! events '())))))

        (finalize
         . ,(lambda (trans)
              (and (pair? final-texts)
                   (for-each (lambda (grob)
                               (set! (ly:grob-property grob 'break-visibility)
                                     end-of-line-visible))
                             final-texts)))))))

\layout {
  \context {
    \Score
    \remove "Mark_engraver"
    \consists #multi-mark-engraver
  }
}

markDown =
#(define-music-function (parser location text) (markup?)
   (make-music 'MarkEvent
               'direction DOWN
               'label text))

\relative c' {
  \mark "1"
  \mark "2"
  \mark "3"
  \markDown "1"
  \markDown "2"
  \markDown "3"  
  c1
}

\relative c' {
 c1
 \mark \default
 \mark "play violently"
 d
}
_______________________________________________
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel

Reply via email to