lilypond-user
[Top][All Lists]
Advanced

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

Re: [Spam] RE: Clef change placement


From: Aaron Hill
Subject: Re: [Spam] RE: Clef change placement
Date: Mon, 03 Feb 2020 21:05:15 -0800
User-agent: Roundcube Webmail/1.4.2

On 2020-02-03 1:54 pm, Rutger Hofman wrote:
I would also welcome this feature. How difficult is it to write a
[Scheme] engraver?

The mechanics of defining and using a Scheme engraver are relatively simple:

%%%%
\version "2.19.83"

Custom_engraver = #(lambda (context)
  ;; The let block can define variables to track
  ;; the state of an instance of the engraver.
  (let ((some-condition? #f)
        (some-counter 0)
        (some-list '()))

    ;; An engraver is an association list (alist) with
    ;; specific symbols mapping to procedures or alists
    ;; of their own.  The make-engraver utility macro
    ;; can simplify defining the alist for an engraver.
    (make-engraver

      ;; Procedures for one-time setup and cleanup.
      ((initialize engraver)
        (format #t "\n initialize: ~a" engraver))
      ((finalize engraver)
        (format #t "\n finalize: ~a" engraver))

      ;; Procedures for each processing stage in the music.
      ((start-translation-timestep engraver)
        (format #t "\n  start-translation-timestep: ~a ~a" engraver
          (ly:context-now context)))
      ((stop-translation-timestep engraver)
        (format #t "\n  stop-translation-timestep: ~a ~a" engraver
          (ly:context-now context)))
      ((process-music engraver)
        (format #t "\n   process-music: ~a" engraver))
      ((process-acknowledged engraver)
        (format #t "\n   process-acknowledged: ~a" engraver))

      ;; Procedures for handling events.
      (listeners
        ((time-signature-event engraver event)
          (format #t "\n   time-signature-event: ~a ~a" engraver
            (ly:event-property event 'origin)))
        ((note-event engraver event)
          (format #t "\n   note-event: ~a ~a" engraver
            (ly:event-property event 'origin))))

      ;; Procedures for handling grobs.
      (acknowledgers
        ((note-head-interface engraver grob source-engraver)
          (format #t "\n    note-head-interface: ~a ~a ~a"
            engraver grob source-engraver))
        ((accidental-interface engraver grob source-engraver)
          (format #t "\n    accidental-interface: ~a ~a ~a"
            engraver grob source-engraver)))
      (end-acknowledgers
        ((beam-interface engraver grob source-engraver)
          (format #t "\n    beam-interface (end): ~a ~a ~a"
            engraver grob source-engraver))
        ((slur-interface engraver grob source-engraver)
          (format #t "\n    slur-interface (end): ~a ~a ~a"
            engraver grob source-engraver)))
    )))

\new Staff \with { \consists \Custom_engraver }
\fixed c' { \time 3/4 a8 b( cis'2) }
%%%%

The above snippet shows examples of all possible handlers. In practice, an engraver would define only the procedures, listeners, and acknowledgers that are relevant.

While most of the engravers in LilyPond are implemented in C++, there are a few to be found in scheme-engravers.scm. However, the C++ engravers can still be useful for figuring out how things should work in an engraver, providing you have rudimentary knowledge of the language. Many of the C++ functions are exported to or have equivalents in Scheme; so an interesting learning exercise would be to take one of the simpler C++ engravers and reimplement it within Scheme.


-- Aaron Hill



reply via email to

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