| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Engravers are C++ classes that catch music events and
create the appropriate grobs for display on the page. Though the
majority of engravers are responsible for the creation of a single grob,
in some cases (e.g. New_fingering_engraver), several different grobs
may be created.
Engravers listen for events and acknowledge grobs. Events are passed to the engraver in time-step order during the iteration phase. Grobs are made available to the engraver when they are created by other engravers during the iteration phase.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
An engraver inherits the following public methods from the Translator base class, which can be used to process listened events and acknowledged grobs:
virtual void initialize ()
void start_translation_timestep ()
void process_music ()
void process_acknowledged ()
void stop_translation_timestep ()
virtual void finalize ()
These methods are listed in order of translation time, with
initialize () and finalize () bookending the whole
process. initialize () can be used for one-time initialization
of context properties before translation starts, whereas
finalize () is often used to tie up loose ends at the end of
translation: for example, an unterminated spanner might be completed
automatically or reported with a warning message.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
At each timestep in the music, translation proceeds by calling the following methods in turn:
start_translation_timestep () is called before any user
information enters the translators, i.e., no property operations
(\set, \override, etc.) or events have been processed yet.
process_music () and process_acknowledged () are called
after all events in the current time step have been heard, or all
grobs in the current time step have been acknowledged. The latter
tends to be used exclusively with engravers which only acknowledge
grobs, whereas the former is the default method for main processing
within engravers.
stop_translation_timestep () is called after all user
information has been processed prior to beginning the translation for
the next timestep.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In certain cases, an engraver might need to ensure private Scheme
variables (with type SCM) do not get swept away by Guile’s garbage
collector: for example, a cache of the previous key signature which
must persist between timesteps. The method
virtual derived_mark () const can be used in such cases:
Engraver_name::derived_mark ()
{
scm_gc_mark (private_scm_member_)
}
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
External interfaces to the engraver are implemented by protected macros including one or more of the following:
DECLARE_TRANSLATOR_LISTENER (event_name)
IMPLEMENT_TRANSLATOR_LISTENER (Engraver_name, event_name)
where event_name is the type of event required to provide the input the engraver needs and Engraver_name is the name of the engraver.
Following declaration of a listener, the method is implemented as follows:
IMPLEMENT_TRANSLATOR_LISTENER (Engraver_name, event_name)
void
Engraver_name::listen_event_name (Stream event *event)
{
...body of listener method...
}
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Some engravers also need information from grobs as they are created and as they terminate. The mechanism and methods to obtain this information are set up by the macros:
DECLARE_ACKNOWLEDGER (grob_interface)
DECLARE_END_ACKNOWLEDGER (grob_interface)
where grob_interface is an interface supported by the
grob(s) which should be acknowledged. For example, the following
code would declare acknowledgers for a NoteHead grob (via the
note-head-interface) and any grobs which support the
side-position-interface:
DECLARE_ACKNOWLEDGER (note_head) DECLARE_ACKNOWLEDGER (side_position) |
The DECLARE_END_ACKNOWLEDGER () macro sets up a spanner-specific
acknowledger which will be called whenever a spanner ends.
Following declaration of an acknowledger, the method is coded as follows:
void
Engraver_name::acknowledge_interface_name (Grob_info info)
{
...body of acknowledger method...
}
|
Acknowledge functions are called in the order engravers are
\consist-ed (the only exception is if you set
must-be-last to #t).
There will always be a call to process-acknowledged () whenever
grobs have been created, and reading stuff from grobs should be
delayed until then since other acknowledgers might write stuff
into a grob even after your acknowledger has been called. So the basic
workflow is to use the various acknowledgers to record the grobs
you are interested in and write stuff into them (or do read/write
stuff that more or less is accumulative and/or really unrelated to other
engravers), and then use the process-acknowledged () hook for
processing (including reading) the grobs you had recorded.
You can create new grobs in process-acknowledged (). That will lead
to a new cycle of acknowledger () calls followed by a new cycle of
process-acknowledged () calls.
Only when all those cycles are over is stop-translator-timestep ()
called, and then creating grobs is no longer an option. You can still
‘process’ parts of the grob there (if that means just reading out
properties and possibly setting context properties based on them) but
stop-translation-timestep () is a cleanup hook, and other engravers
might have already cleaned up stuff you might have wanted to use.
Creating grobs in there is not possible since engravers and other code may
no longer be in a state where they could process them, possibly causing
a crash.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
An engraver must have a public macro
TRANSLATOR_DECLARATIONS (Engraver_name)
where Engraver_name is the name of the engraver. This
defines the common variables and methods used by every engraver.
At the end of the engraver file, one or both of the following macros are generally called to document the engraver in the Internals Reference:
ADD_ACKNOWLEDGER (Engraver_name, grob_interface)
ADD_TRANSLATOR (Engraver_name, Engraver_doc,
Engraver_creates, Engraver_reads, Engraver_writes)
where Engraver_name is the name of the engraver, grob_interface
is the name of the interface that will be acknowledged,
Engraver_doc is a docstring for the engraver,
Engraver_creates is the set of grobs created by the engraver,
Engraver_reads is the set of properties read by the engraver,
and Engraver_writes is the set of properties written by
the engraver.
The ADD_ACKNOWLEDGER and ADD_TRANSLATOR macros use a
non-standard indentation system. Each interface, grob, read property,
and write property is on its own line, and the closing parenthesis
and semicolon for the macro all occupy a separate line beneath the final
interface or write property. See existing engraver files for more
information.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated by gub on July 13, 2020 using texi2html 1.82.