]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/ambitus-engraver.cc
2003 -> 2004
[lilypond.git] / lily / ambitus-engraver.cc
index fb0af0286b813b1cf4b57b8f167a673759203c6d..e5f952e9a68ee5328d3a013fb06e6f01331b1a6b 100644 (file)
@@ -3,14 +3,14 @@
 
   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.
  *
@@ -64,75 +64,80 @@ class Ambitus_engraver : public Engraver
 {
 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?
@@ -140,22 +145,14 @@ Ambitus_engraver::acknowledge_grob (Grob_info info)
                  // 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 ());
                }
            }
        }
@@ -165,16 +162,39 @@ Ambitus_engraver::acknowledge_grob (Grob_info info)
 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 */       "");