]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/completion-note-heads-engraver.cc
* The grand 2005-2006 replace.
[lilypond.git] / lily / completion-note-heads-engraver.cc
index 11e7eb29a7223d9d0a4f581fa52afbfa6bbbe089..3ab3a3f6e2865c43695e76c060ec104638b2438a 100644 (file)
@@ -1,14 +1,15 @@
 /*
-  head-grav.cc -- part of GNU LilyPond
+  completion-note-heads-engraver.cc -- Completion_heads_engraver
 
-  (c) 1997--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
 */
 
-#include <ctype.h>
+#include <cctype>
+using namespace std;
 
 #include "rhythmic-head.hh"
-#include "paper-def.hh"
-#include "event.hh"
+#include "output-def.hh"
+#include "music.hh"
 #include "dots.hh"
 #include "dot-column.hh"
 #include "staff-symbol-referencer.hh"
 #include "spanner.hh"
 #include "tie.hh"
 #include "global-context.hh"
+#include "duration.hh"
+#include "pitch.hh"
 
 /*
+  TODO: make matching rest engraver.
+*/
 
+/*
   How does this work?
 
   When we catch the note, we predict the end of the note. We keep the
@@ -30,8 +36,8 @@
   figure out how long the note to typeset should be. It should be no
   longer than what's specified, than what is left to do and it should
   not cross barlines.
-  
-  We copy the reqs into scratch note reqs, to make sure that we get
+
+  We copy the events into scratch note events, to make sure that we get
   all durations exactly right.
 */
 
@@ -40,89 +46,86 @@ class Completion_heads_engraver : public Engraver
   Link_array<Item> notes_;
   Link_array<Item> prev_notes_;
   Link_array<Grob> ties_;
-  
+
   Link_array<Item> dots_;
-  Link_array<Music> note_reqs_;
-  Link_array<Music> scratch_note_reqs_;
+  Link_array<Music> note_events_;
+  Link_array<Music> scratch_note_events_;
 
   Moment note_end_mom_;
-  bool first_b_;
+  bool is_first_;
   Rational left_to_do_;
   Rational do_nothing_until_;
-  
+
   Moment next_barline_moment ();
   Duration find_nearest_duration (Rational length);
-  
+
 public:
   TRANSLATOR_DECLARATIONS (Completion_heads_engraver);
 
 protected:
   virtual void initialize ();
-  virtual void start_translation_timestep ();
-  virtual bool try_music (Music *req) ;
-  virtual void process_music ();
-  virtual void stop_translation_timestep ();
+  void start_translation_timestep ();
+  virtual bool try_music (Music *event);
+  void process_music ();
+  void stop_translation_timestep ();
 };
 
 void
 Completion_heads_engraver::initialize ()
 {
-  first_b_ = false;
+  is_first_ = false;
 }
 
 bool
-Completion_heads_engraver::try_music (Music *m) 
+Completion_heads_engraver::try_music (Music *m)
 {
   if (m->is_mus_type ("note-event"))
     {
-      note_reqs_.push (m);
+      note_events_.push (m);
 
-      first_b_ = true;
+      is_first_ = true;
       Moment musiclen = m->get_length ();
       Moment now = now_mom ();
 
       if (now_mom ().grace_part_)
        {
-         musiclen.grace_part_ = musiclen.main_part_ ;
-         musiclen.main_part_ = Rational (0,1);
+         musiclen.grace_part_ = musiclen.main_part_;
+         musiclen.main_part_ = Rational (0, 1);
        }
-      note_end_mom_  = note_end_mom_ >? (now + musiclen);
-      do_nothing_until_ = Rational (0,0);
-      
+      note_end_mom_ = max (note_end_mom_, (now + musiclen));
+      do_nothing_until_ = Rational (0, 0);
+
       return true;
     }
-  else if  (m->is_mus_type ("busy-playing-event"))
-    {
-      return note_reqs_.size ();
-    }
-  
+  else if (m->is_mus_type ("busy-playing-event"))
+    return note_events_.size () && is_first_;
+
   return false;
-  
 }
 
 /*
   The duration _until_ the next barline.
- */
+*/
 Moment
-Completion_heads_engraver::next_barline_moment ( )
+Completion_heads_engraver::next_barline_moment ()
 {
   Moment *e = unsmob_moment (get_property ("measurePosition"));
   Moment *l = unsmob_moment (get_property ("measureLength"));
   if (!e || !l)
     {
-      programming_error ("No timing props set?");
-      return Moment (1,1);
+      programming_error ("no timing props set?");
+      return Moment (1, 1);
     }
 
   return (*l - *e);
 }
 
-Duration  
+Duration
 Completion_heads_engraver::find_nearest_duration (Rational length)
 {
-  int log_limit= 6;
+  int log_limit = 6;
 
-  Duration d (0,0);
+  Duration d (0, 0);
 
   /*
     this could surely be done more efficient. Left to the reader as an
@@ -135,9 +138,7 @@ Completion_heads_engraver::find_nearest_duration (Rational length)
          continue;
        }
       else
-       {
-         d = Duration (d.duration_log () + 1, 2);
-       }
+       d = Duration (d.duration_log () + 1, 2);
     }
 
   if (d.duration_log () >= log_limit)
@@ -148,31 +149,29 @@ Completion_heads_engraver::find_nearest_duration (Rational length)
       // scale up.
       d = d.compressed (length / d.get_length ());
     }
-  
+
   return d;
 }
 
 void
 Completion_heads_engraver::process_music ()
 {
-  if (!first_b_ && !left_to_do_)
-    return ;
-  
-  first_b_ = false;
+  if (!is_first_ && !left_to_do_)
+    return;
+
+  is_first_ = false;
 
-  Moment now =  now_mom ();
+  Moment now = now_mom ();
   if (do_nothing_until_ > now.main_part_)
-    return ;
-  
+    return;
+
   Duration note_dur;
   Duration *orig = 0;
   if (left_to_do_)
-    {
-      note_dur = find_nearest_duration (left_to_do_);
-    }
+    note_dur = find_nearest_duration (left_to_do_);
   else
     {
-      orig = unsmob_duration (note_reqs_[0]->get_property ("duration"));
+      orig = unsmob_duration (note_events_[0]->get_property ("duration"));
       note_dur = *orig;
     }
   Moment nb = next_barline_moment ();
@@ -182,85 +181,77 @@ Completion_heads_engraver::process_music ()
 
       Moment next = now;
       next.main_part_ += note_dur.get_length ();
-      
+
       get_global_context ()->add_moment_to_process (next);
       do_nothing_until_ = next.main_part_;
     }
 
   if (orig)
-    {
-      left_to_do_ = orig->get_length ();
-    }
+    left_to_do_ = orig->get_length ();
 
   if (orig && note_dur.get_length () != orig->get_length ())
     {
-      if (!scratch_note_reqs_.size ())
-       for (int i = 0; i < note_reqs_.size (); i++)
+      if (!scratch_note_events_.size ())
+       for (int i = 0; i < note_events_.size (); i++)
          {
-           Music * m = note_reqs_[i]->clone ();
-           scratch_note_reqs_.push (m);
+           Music *m = note_events_[i]->clone ();
+           scratch_note_events_.push (m);
          }
     }
 
-  
   for (int i = 0;
-       left_to_do_ && i < note_reqs_.size (); i++)
+       left_to_do_ && i < note_events_.size (); i++)
     {
-      Item *note  = make_item ("NoteHead");
-      
-      Music * req =  note_reqs_[i];
-      if (scratch_note_reqs_.size ())
+      Music *event = note_events_[i];
+      if (scratch_note_events_.size ())
        {
-         req = scratch_note_reqs_[i];
-         SCM pits = note_reqs_[i]->get_property ("pitch");
-         req->set_property ("pitch",pits);
+         event = scratch_note_events_[i];
+         SCM pits = note_events_[i]->get_property ("pitch");
+         event->set_property ("pitch", pits);
        }
-      
-      req->set_property ("duration", note_dur.smobbed_copy ());
+
+      event->set_property ("duration", note_dur.smobbed_copy ());
+
+      Item *note = make_item ("NoteHead", event->self_scm ());
       note->set_property ("duration-log",
-                                gh_int2scm (note_dur.duration_log ()));
-      
-      int dots= note_dur.dot_count ();
+                         scm_from_int (note_dur.duration_log ()));
+
+      int dots = note_dur.dot_count ();
       if (dots)
        {
-         Item * d = make_item ("Dots");
+         Item *d = make_item ("Dots", SCM_EOL);
          Rhythmic_head::set_dots (note, d);
 
          /*
-          measly attempt to save an eeny-weenie bit of memory.
+           measly attempt to save an eeny-weenie bit of memory.
          */
-         if (dots != gh_scm2int (d->get_property ("dot-count")))
-           d->set_property ("dot-count", gh_int2scm (dots));
+         if (dots != scm_to_int (d->get_property ("dot-count")))
+           d->set_property ("dot-count", scm_from_int (dots));
 
          d->set_parent (note, Y_AXIS);
-         announce_grob (d, SCM_EOL);
          dots_.push (d);
        }
 
-      Pitch *pit =unsmob_pitch (req->get_property ("pitch"));
+      Pitch *pit = unsmob_pitch (event->get_property ("pitch"));
 
       int pos = pit->steps ();
       SCM c0 = get_property ("middleCPosition");
-      if (gh_number_p (c0))
-       pos += gh_scm2int (c0);
+      if (scm_is_number (c0))
+       pos += scm_to_int (c0);
 
-      note->set_property ("staff-position",   gh_int2scm (pos));
-      announce_grob (note,req->self_scm ());
+      note->set_property ("staff-position", scm_from_int (pos));
       notes_.push (note);
     }
-  
+
   if (prev_notes_.size () == notes_.size ())
     {
-      for (int i= 0; i < notes_.size (); i++)
+      for (int i = 0; i < notes_.size (); i++)
        {
-         Grob * p = make_spanner ("Tie");
-         Tie::set_interface (p); // cannot remove yet!
-         
+         Grob *p = make_spanner ("Tie", SCM_EOL);
          Tie::set_head (p, LEFT, prev_notes_[i]);
          Tie::set_head (p, RIGHT, notes_[i]);
-         
+
          ties_.push (p);
-         announce_grob (p, SCM_EOL);
        }
     }
 
@@ -268,41 +259,27 @@ Completion_heads_engraver::process_music ()
 
   /*
     don't do complicated arithmetic with grace notes.
-   */
+  */
   if (orig
-      &&  now_mom ().grace_part_ )
-    {
-      left_to_do_ = Rational (0,0);
-    }
+      && now_mom ().grace_part_)
+    left_to_do_ = Rational (0, 0);
 }
+
 void
 Completion_heads_engraver::stop_translation_timestep ()
 {
-  for (int i = ties_.size (); i--;)
-    typeset_grob (ties_[i]); 
   ties_.clear ();
-  
-  for (int i=0; i < notes_.size (); i++)
-    {
-      typeset_grob (notes_[i]);
-    }
+
   if (notes_.size ())
     prev_notes_ = notes_;
   notes_.clear ();
-  
-  for (int i=0; i < dots_.size (); i++)
-    {
-      typeset_grob (dots_[i]);
-    }
+
   dots_.clear ();
 
-  for (int i = scratch_note_reqs_.size (); i--;)
-    {
-      scm_gc_unprotect_object (scratch_note_reqs_[i]->self_scm () );
-    }
-  
-  scratch_note_reqs_.clear ();
+  for (int i = scratch_note_events_.size (); i--;)
+    scratch_note_events_[i]->unprotect ();
+
+  scratch_note_events_.clear ();
 }
 
 void
@@ -311,7 +288,7 @@ Completion_heads_engraver::start_translation_timestep ()
   Moment now = now_mom ();
   if (note_end_mom_.main_part_ <= now.main_part_)
     {
-      note_reqs_.clear ();
+      note_events_.clear ();
       prev_notes_.clear ();
     }
 }
@@ -320,12 +297,13 @@ Completion_heads_engraver::Completion_heads_engraver ()
 {
 }
 
-ENTER_DESCRIPTION (Completion_heads_engraver,
-/* descr */       "This engraver replaces "
-"@code{Note_heads_engraver}. It plays some trickery to "
-"break long notes and automatically tie them into the next measure.",
-/* creats*/       "NoteHead Dots Tie",
-/* accepts */     "busy-playing-event note-event",
-/* acks  */      "",
-/* reads */       "middleCPosition measurePosition measureLength",
-/* write */       "");
+#include "translator.icc"
+
+ADD_TRANSLATOR (Completion_heads_engraver,
+               /* doc */ "This engraver replaces "
+               "@code{Note_heads_engraver}. It plays some trickery to "
+               "break long notes and automatically tie them into the next measure.",
+               /* create */ "NoteHead Dots Tie",
+               /* accept */ "busy-playing-event note-event",
+               /* read */ "middleCPosition measurePosition measureLength",
+               /* write */ "");