[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Spam] RE: Clef change placement
From: |
Jacques Menu |
Subject: |
Re: [Spam] RE: Clef change placement |
Date: |
Tue, 4 Feb 2020 09:18:40 +0100 |
Thanks Aaron, great example!
JM
> Le 4 févr. 2020 à 06:05, Aaron Hill <address@hidden> a écrit :
>
> 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
>