]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/tie-performer.cc
Doc: edit comments basic-authors.texi - unneeded commas
[lilypond.git] / lily / tie-performer.cc
index f415317ae7fee72df7843ac3198ed67285613f54..e6cb44de8f317a8fbe56a7e24e95d98354bceaa4 100644 (file)
@@ -1,31 +1,62 @@
 /*
-  tie-performer.cc -- implement Tie_performer
+  This file is part of LilyPond, the GNU music typesetter.
 
-  source file of the GNU LilyPond music typesetter
+  Copyright (C) 1998--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
 
-  (c) 1998--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  LilyPond is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LilyPond is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "context.hh"
-#include "audio-item.hh"
-#include "pqueue.hh"
 #include "performer.hh"
 
-class Tie_performer : public Performer
+#include "audio-item.hh"
+#include "context.hh"
+#include "stream-event.hh"
+#include "translator.icc"
+// #include "international.hh"
+#include <deque>
+
+struct Head_event_tuple
 {
-  Music *event_;
-  Music *last_event_;
-  Array<Audio_element_info> now_heads_;
-  Array<Audio_element_info> heads_to_tie_;
+  Audio_element_info head_;
+  Moment moment_;
+  Head_event_tuple () { }
+  Head_event_tuple (Audio_element_info h, Moment m)
+  {
+    head_ = h;
+    moment_ = m;
+  }
+};
 
-  bool ties_created_;
+
+class Tie_performer : public Performer
+{
+  Stream_event *event_;
+  // We don't really need a deque here. A vector would suffice. However,
+  // for some strange reason, using vectors always leads to memory 
+  // corruption in the STL templates! (i.e. after the first
+  // now_heads_.push_back (inf_mom), the now_heads_.size() will be 
+  // something like 3303820998 :(
+  deque<Head_event_tuple> now_heads_;
+  deque<Head_event_tuple> now_tied_heads_;
+  deque<Head_event_tuple> heads_to_tie_;
 
 protected:
-  virtual void stop_translation_timestep ();
-  virtual void start_translation_timestep ();
+  void stop_translation_timestep ();
+  void start_translation_timestep ();
   virtual void acknowledge_audio_element (Audio_element_info);
-  virtual bool try_music (Music *);
-  virtual void process_music ();
+  void process_music ();
+  DECLARE_TRANSLATOR_LISTENER (tie);
 public:
   TRANSLATOR_DECLARATIONS (Tie_performer);
 };
@@ -33,19 +64,13 @@ public:
 Tie_performer::Tie_performer ()
 {
   event_ = 0;
-  last_event_ = 0;
-  ties_created_ = false;
 }
 
-bool
-Tie_performer::try_music (Music *mus)
+IMPLEMENT_TRANSLATOR_LISTENER (Tie_performer, tie);
+void
+Tie_performer::listen_tie (Stream_event *ev)
 {
-  if (mus->is_mus_type ("tie-event"))
-    {
-      event_ = mus;
-    }
-
-  return true;
+  event_ = ev;
 }
 
 void
@@ -60,20 +85,34 @@ Tie_performer::acknowledge_audio_element (Audio_element_info inf)
 {
   if (Audio_note *an = dynamic_cast<Audio_note *> (inf.elem_))
     {
-      now_heads_.push (inf);
-      for (int i = heads_to_tie_.size (); i--;)
-       {
-         Music *right_mus = inf.event_;
-
-         Audio_note *th = dynamic_cast<Audio_note *> (heads_to_tie_[i].elem_);
-         Music *left_mus = heads_to_tie_[i].event_;
-
-         if (right_mus && left_mus
-             && ly_c_equal_p (right_mus->get_property ("pitch"),
-                              left_mus->get_property ("pitch")))
+//       message (_f ("acknowledge_audio_element, Size of now_heads_=%d", now_heads_.size ()));
+      Head_event_tuple inf_mom (inf, now_mom ());
+      if (an->tie_event_)
+        now_tied_heads_.push_back (inf_mom);
+      else
+        now_heads_.push_back (inf_mom);
+
+//       message (_f ("acknowledge_audio_element, added, Size of now_heads_=%d", now_heads_.size ()));
+      // Find a previous note that ties to the current note. If it exists, 
+      // remove it from the heads_to_tie vector and create the tie
+      deque<Head_event_tuple>::iterator it;
+      bool found = false;
+      Stream_event *right_mus = inf.event_;
+      for ( it = heads_to_tie_.begin() ; (!found) && (it < heads_to_tie_.end()); it++ )
+        {
+         Audio_element_info et = (*it).head_;
+         Audio_note *th = dynamic_cast<Audio_note *> (et.elem_);
+         Stream_event *left_mus = et.event_;
+
+         if (th && right_mus && left_mus
+             && ly_is_equal (right_mus->get_property ("pitch"),
+                             left_mus->get_property ("pitch")))
            {
-             an->tie_to (th);
-             ties_created_ = true;
+             found = true;
+             Moment skip = now_mom() - (*it).moment_ - th->length_mom_;
+             an->tie_to (th, skip);
+             // this invalidates the iterator, we are leaving the loop anyway
+             heads_to_tie_.erase (it);
            }
        }
     }
@@ -89,26 +128,37 @@ Tie_performer::start_translation_timestep ()
 void
 Tie_performer::stop_translation_timestep ()
 {
-  if (ties_created_)
+  // We might have dangling open ties like c~ d. Close them, unless we have
+  // tieWaitForNote set...
+  if (!to_boolean (get_property ("tieWaitForNote")))
     {
       heads_to_tie_.clear ();
-      last_event_ = 0;
-      ties_created_ = false;
     }
 
   if (event_)
     {
-      heads_to_tie_ = now_heads_;
-      last_event_ = event_;
+      for (vsize i = now_heads_.size (); i--;)
+        heads_to_tie_.push_back (now_heads_[i]);
     }
+
+  for (vsize i = now_tied_heads_.size (); i--;)
+    heads_to_tie_.push_back (now_tied_heads_[i]);
+
   event_ = 0;
   now_heads_.clear ();
+  now_tied_heads_.clear ();
 }
 
 ADD_TRANSLATOR (Tie_performer,
-               /* descr */ "Generate ties between noteheads of equal pitch.",
-               /* creats*/ "",
-               /* accepts */ "tie-event",
-               /* acks  */ "",
-               /* reads */ "tieMelismaBusy",
-               /* write */ "");
+               /* doc */
+               "Generate ties between note heads of equal pitch.",
+
+               /* create */
+               "",
+
+               /* read */
+               "tieWaitForNote",
+
+               /* write */
+               "tieMelismaBusy"
+               );