source file of the GNU LilyPond music typesetter
- (C) 2002 Juergen Reuter <reuter@ipd.uka.de>
+ (c) 2002--2004 Juergen Reuter <reuter@ipd.uka.de>
*/
#include "engraver.hh"
#include "item.hh"
#include "note-head.hh"
#include "staff-symbol-referencer.hh"
-#include "musical-request.hh"
+#include "event.hh"
#include "pitch.hh"
/*
*
* - If a piece consists of several loosely coupled sections, should
* there be multiple ambitus grobs allowed, one for each section?
- * Then there probably should be some "\ambitus" request added to
+ * Then there probably should be some "\ambitus" event added to
* mudela, stating where an ambitus grob should be placed. This
* ambitus grob should then represent the ambitus in the range of time
- * between this "\ambitus" request and the next one (or the end of the
- * piece, if there is no more such request). To be compliant with the
+ * between this "\ambitus" event and the next one (or the end of the
+ * piece, if there is no more such event). To be compliant with the
* current implementation, we might implicitly assume an "\ambitus"
- * request at the beginning of the piece, but then the question where
+ * event at the beginning of the piece, but then the question where
* to put this first ambitus grob (before/after the clef?) becomes
* even more urgent.
*
{
public:
TRANSLATOR_DECLARATIONS(Ambitus_engraver);
- virtual void start_translation_timestep ();
+ virtual void process_music ();
virtual void acknowledge_grob (Grob_info);
- virtual void create_grobs ();
virtual void stop_translation_timestep ();
+ virtual void finalize ();
private:
void create_ambitus ();
- Item *ambitus_p_;
- int isActive;
+ Item *ambitus_;
+ int/*bool*/ is_typeset;
Pitch pitch_min, pitch_max;
};
Ambitus_engraver::Ambitus_engraver ()
{
- ambitus_p_ = 0; isActive = 0;
+ ambitus_ = 0;
+ is_typeset = 0;
- // (pitch_min > pitch_max) means that pitches are not yet
- // initialized
- pitch_min = Pitch (0, 0, +1);
- pitch_max = Pitch (0, 0, -1);
+ /*
+ * (pitch_min > pitch_max) means that pitches are not yet
+ * initialized
+ */
+ pitch_min = Pitch (0, 0, SHARP);
+ pitch_max = Pitch (0, 0, FLAT);
}
void
-Ambitus_engraver::stop_translation_timestep ()
+Ambitus_engraver::process_music ()
{
- if (!ambitus_p_) {
+ /*
+ * Ensure that ambitus is created in the very first timestep (on
+ * which lily does not call start_translation_timestep ()).
+ * Otherwise, if a voice begins with a rest, the ambitus grob will
+ * be placed after the rest.
+ */
+ if (!ambitus_) {
create_ambitus ();
}
- if (ambitus_p_ && isActive)
- {
- SCM key_signature = get_property ("keySignature");
- ambitus_p_->set_grob_property ("keySignature", key_signature);
- typeset_grob (ambitus_p_);
- //ambitus_p_ = 0;
- isActive = 0;
- }
}
void
-Ambitus_engraver::start_translation_timestep ()
+Ambitus_engraver::stop_translation_timestep ()
{
- if (!ambitus_p_) {
- create_ambitus ();
- }
-}
+ if (ambitus_ && !is_typeset)
+ {
+ /*
+ * Evaluate centralCPosition not until now, since otherwise we
+ * may then oversee a clef that is defined in a staff context if
+ * we are in a voice context; centralCPosition would then be
+ * assumed to be 0.
+ */
+ SCM c0 = get_property ("centralCPosition");
+ ambitus_->set_grob_property ("c0-position", c0);
-void
-Ambitus_engraver::create_grobs ()
-{
- if (!ambitus_p_) {
- create_ambitus ();
- }
+ /*
+ * Similar for keySignature.
+ */
+ SCM key_signature = get_property ("keySignature");
+ ambitus_->set_grob_property ("accidentals", key_signature);
+
+ typeset_grob (ambitus_);
+ is_typeset = 1;
+ }
}
void
Ambitus_engraver::acknowledge_grob (Grob_info info)
{
- if (!ambitus_p_) {
- create_ambitus ();
- }
- if (!ambitus_p_)
- return;
- Item *item = dynamic_cast <Item *>(info.grob_l_);
+ Item *item = dynamic_cast <Item *>(info.grob_);
if (item)
{
- if (Note_head::has_interface (info.grob_l_))
+ if (Note_head::has_interface (info.grob_))
{
- Note_req *nr = dynamic_cast<Note_req*> (info.music_cause ());
- if (nr)
+ Music *nr = info.music_cause ();
+ if (nr && nr->is_mus_type ("note-event"))
{
Pitch pitch = *unsmob_pitch (nr->get_mus_property ("pitch"));
if (Pitch::compare (pitch_min, pitch_max) > 0) // already init'd?
// not yet init'd; use current pitch to init min/max
pitch_min = pitch;
pitch_max = pitch;
- ambitus_p_->set_grob_property ("pitch-min",
- pitch_min.smobbed_copy ());
- ambitus_p_->set_grob_property ("pitch-max",
- pitch_max.smobbed_copy ());
}
else if (Pitch::compare (pitch, pitch_max) > 0) // new max?
{
pitch_max = pitch;
- ambitus_p_->set_grob_property ("pitch-max",
- pitch_max.smobbed_copy ());
}
else if (Pitch::compare (pitch, pitch_min) < 0) // new min?
{
pitch_min = pitch;
- ambitus_p_->set_grob_property ("pitch-min",
- pitch_min.smobbed_copy ());
}
}
}
void
Ambitus_engraver::create_ambitus ()
{
- SCM basicProperties = get_property ("Ambitus");
- SCM c0 = get_property ("centralCPosition");
- ambitus_p_ = new Item (basicProperties); isActive = 1;
- ambitus_p_->set_grob_property ("centralCPosition", c0);
- announce_grob (ambitus_p_, SCM_EOL);
+ ambitus_ = make_item ("Ambitus");
+ is_typeset = 0; // UGH.
+ announce_grob (ambitus_, SCM_EOL);
+}
+
+void
+Ambitus_engraver::finalize ()
+{
+ if (ambitus_)
+ {
+ if (Pitch::compare (pitch_min, pitch_max) <= 0)
+ {
+ ambitus_->set_grob_property ("pitch-min",
+ pitch_min.smobbed_copy ());
+ ambitus_->set_grob_property ("pitch-max",
+ pitch_max.smobbed_copy ());
+ }
+ else // have not seen any pitch, so forget about the ambitus
+ {
+ /*
+ * Do not print a warning on empty ambitus range, since this
+ * most probably arises from an empty voice, such as shared
+ * global timesig/clef definitions.
+ */
+ ambitus_->suicide();
+ }
+ }
}
ENTER_DESCRIPTION(Ambitus_engraver,
/* descr */ "",
/* creats*/ "Ambitus",
-/* acks */ "note-head-interface",
+/* accepts */ "",
+/* acks */ "note-head-interface",
/* reads */ "",
/* write */ "");