]> git.donarmstrong.com Git - lilypond.git/commitdiff
Fix #129, #228, #7
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Mon, 8 Jan 2007 12:34:15 +0000 (13:34 +0100)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Mon, 8 Jan 2007 12:34:15 +0000 (13:34 +0100)
Store length property in generated tuplet start event. Simplify
Time_scaled_music_iterator.

THANKS
input/regression/part-combine-tuplet-end.ly [new file with mode: 0644]
input/regression/part-combine-tuplet-single.ly [new file with mode: 0644]
input/regression/part-combine-tuplet.ly [deleted file]
input/regression/quote-tuplet-end.ly [new file with mode: 0644]
lily/time-scaled-music-iterator.cc
lily/tuplet-engraver.cc

diff --git a/THANKS b/THANKS
index c15d646d2ba1875250c30b052e8f932462b8c346..5b0def30cf1551a4bf91e29840ce2aabd8fd63b5 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -23,6 +23,7 @@ Mike Amundsen
 
 BUG HUNTERS/SUGGESTIONS
 
+Alard de Boer
 Bertalan Fodor
 Benjamin Drung
 Cameron Horsburgh
diff --git a/input/regression/part-combine-tuplet-end.ly b/input/regression/part-combine-tuplet-end.ly
new file mode 100644 (file)
index 0000000..b6bf597
--- /dev/null
@@ -0,0 +1,19 @@
+\header {
+  
+  texidoc = "End tuplets events are sent to the starting context, so
+even after a switch, a tuplet ends correctly."
+  
+}
+
+\version "2.10.8"
+
+\new Staff <<
+  \partcombine
+  \relative c'' {
+    r2
+    \times 2/3 { g8[ g g] }
+    \times 2/3 { g[ g g] } g1
+  }
+  \relative c'' { R1 g1 }
+>>
+
diff --git a/input/regression/part-combine-tuplet-single.ly b/input/regression/part-combine-tuplet-single.ly
new file mode 100644 (file)
index 0000000..879e163
--- /dev/null
@@ -0,0 +1,22 @@
+
+\header {
+  texidoc = "Tuplets in combined parts only print one bracket."
+  }
+
+\paper { ragged-right = ##T }
+
+\version "2.10.10"
+
+\score {
+  <<
+    \new Staff {
+      \partcombine
+      \relative c'' {
+        \times 2/3 { d4 d d ~ } d2
+      }
+      \relative c'' {
+        \times 2/3 { b4 a g ~ } g2
+      }
+    }
+  >>
+}
diff --git a/input/regression/part-combine-tuplet.ly b/input/regression/part-combine-tuplet.ly
deleted file mode 100644 (file)
index b6bf597..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-\header {
-  
-  texidoc = "End tuplets events are sent to the starting context, so
-even after a switch, a tuplet ends correctly."
-  
-}
-
-\version "2.10.8"
-
-\new Staff <<
-  \partcombine
-  \relative c'' {
-    r2
-    \times 2/3 { g8[ g g] }
-    \times 2/3 { g[ g g] } g1
-  }
-  \relative c'' { R1 g1 }
->>
-
diff --git a/input/regression/quote-tuplet-end.ly b/input/regression/quote-tuplet-end.ly
new file mode 100644 (file)
index 0000000..cbf4752
--- /dev/null
@@ -0,0 +1,22 @@
+\header
+{
+  texidoc  ="Tuplet bracket ends properly when quoting."
+}
+
+\version "2.11.10"
+
+\paper { ragged-right = ##t }
+
+\addQuote x {
+   \times 2/3 { a'8 a' a' } a'4 a'2 |
+}
+
+\new Staff <<
+   \set Staff.quotedEventTypes = #'(note-event tuplet-span-event)
+   \new Voice = "cue" { s1 }
+   \new Voice {
+       \cueDuring #"x" #1 { r4 }
+       c'4
+       \cueDuring #"x" #1 { r2 }
+   }
+>>
index 973a1d8c5eb696d13f802ca1c590b268431fd578..ca33ea786767fb7664712c723def8b4f5f1995b9 100644 (file)
@@ -12,6 +12,7 @@
 #include "international.hh"
 #include "music.hh"
 #include "music-wrapper-iterator.hh"
+#include "stream-event.hh"
 
 /*
   Iterates \times, by sending TupletSpanEvents at the start/end of each
@@ -30,6 +31,9 @@ protected:
   virtual void construct_children ();
   virtual void derived_mark () const;
   virtual Moment pending_moment () const;
+
+  Music *create_event (Direction d);
+  
 private:
 
   /* tupletSpannerDuration */
@@ -39,34 +43,47 @@ private:
   Moment next_split_mom_;
   
   /* Recycle start/stop events if tupletSpannerDuration is set. */
-  Music *start_;
-  Music *stop_;
-
-  bool done_first_;
+  SCM synthesized_events_;
   
   Context_handle tuplet_handler_;
 };
 
+Music*
+Time_scaled_music_iterator::create_event (Direction d)
+{
+  SCM ev_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"),
+                          ly_symbol2scm ("TupletSpanEvent"),
+                          scm_from_int (d));
+  
+  Music *mus = get_music ();
+
+  Music *ev = unsmob_music (ev_scm);
+  ev->set_spot (*mus->origin ());
+  if (d == START)
+    {
+      ev->set_property ("numerator", mus->get_property ("numerator"));
+      ev->set_property ("denominator", mus->get_property ("denominator"));
+      ev->set_property ("tweaks", mus->get_property ("tweaks"));
+      ev->set_property ("length", spanner_duration_.smobbed_copy ()); 
+    }  
+
+  synthesized_events_ = scm_cons (ev_scm, synthesized_events_);
+  return ev;
+}
+
+
 Time_scaled_music_iterator::Time_scaled_music_iterator ()
 {
   spanner_duration_ = next_split_mom_ = 0;
-  done_first_ = 0;
+  synthesized_events_ = SCM_EOL;
 }
 
 
 Moment
 Time_scaled_music_iterator::pending_moment () const
 {
-  if (!done_first_)
-    return Moment (0);
-  
   Moment next_mom = Music_wrapper_iterator::pending_moment ();
-
-  if (spanner_duration_.to_bool () &&
-      next_mom.main_part_ > next_split_mom_)
-    {
-      next_mom = next_split_mom_;
-    }
+  next_mom = min (next_mom, next_split_mom_);
 
   return next_mom;
 }
@@ -75,75 +92,44 @@ Time_scaled_music_iterator::pending_moment () const
 void
 Time_scaled_music_iterator::process (Moment m)
 {
-  if (!done_first_)
-    {
-      done_first_ = true;
-      descend_to_bottom_context ();
-      report_event (start_);
-      tuplet_handler_.set_context (get_outlet());
-    }
-
   if (spanner_duration_.to_bool () &&
       m.main_part_ == next_split_mom_)
     {
       descend_to_bottom_context ();
-      stop_->send_to_context (tuplet_handler_.get_outlet ());
-      
-      tuplet_handler_.set_context (get_outlet ());
-      report_event (start_);
+      if (tuplet_handler_.get_outlet())
+       create_event (STOP)->send_to_context (tuplet_handler_.get_outlet ());
+
+      if (m.main_part_ < music_get_length ().main_part_)
+       {
+         tuplet_handler_.set_context (get_outlet ());
+         report_event (create_event (START));
       
-      next_split_mom_ += spanner_duration_;
-      /* avoid sending events twice at the end */
-      if (next_split_mom_ == get_music ()->get_length ().main_part_)
-       next_split_mom_.set_infinite (1);
+         next_split_mom_ += spanner_duration_;
+       }
+      else
+       {
+         tuplet_handler_.set_context (0);
+       }
     }
-
   Music_wrapper_iterator::process(m);
   if (child_iter_ && child_iter_->ok ())
     descend_to_child (child_iter_->get_outlet ());
   
-  if (m.main_part_ == music_get_length ().main_part_)
-    {
-      stop_->send_to_context (tuplet_handler_.get_outlet ());
-      tuplet_handler_.set_context (0);
-    }
 }
 
 void
 Time_scaled_music_iterator::construct_children ()
 {
-  /*
-    Inheritance trickery:
-    Time_scaled_music_iterator::construct_children initialises start_
-    and stop_, and calls Sequential_music::construct_children, which
-    in turn calls Time_scaled_music_iterator::get_music which reads
-    start_ and stop_.
-   */
-
-  Music *mus = get_music ();
-  Input *origin = mus->origin ();
-
-  SCM tuplet_symbol = ly_symbol2scm ("TupletSpanEvent");
-  SCM start_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"), tuplet_symbol, scm_from_int (START));
-  start_ = unsmob_music (start_scm);
-  start_->set_spot (*origin);
-  start_->set_property ("numerator", mus->get_property ("numerator"));
-  start_->set_property ("denominator", mus->get_property ("denominator"));
-  start_->set_property ("tweaks", mus->get_property ("tweaks"));
-  
-
-  SCM stop_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"), tuplet_symbol, scm_from_int (STOP));
-  stop_ = unsmob_music (stop_scm);
-  stop_->set_spot (*origin);
-
   Moment *mp = unsmob_moment (get_outlet ()->get_property ("tupletSpannerDuration"));
-
   if (mp)
     {
       spanner_duration_ = mp->main_part_;
-      next_split_mom_ = spanner_duration_;
     }
-
+  else
+    {
+      spanner_duration_ = music_get_length ();
+    }
+  
   Music_wrapper_iterator::construct_children ();
 
   if (child_iter_ && child_iter_->ok ())
@@ -153,11 +139,7 @@ Time_scaled_music_iterator::construct_children ()
 void
 Time_scaled_music_iterator::derived_mark () const
 {
-  if (start_)
-    scm_gc_mark (start_->self_scm ());
-  if (stop_)
-    scm_gc_mark (stop_->self_scm ());
-
+  scm_gc_mark (synthesized_events_);
   Music_wrapper_iterator::derived_mark ();
 }
 
index fd280e127e2978475315f8112afa848a9d798248..3d904ac7651ff79af9879251b7bb71433a04a3e6 100644 (file)
@@ -15,6 +15,7 @@
 #include "tuplet-bracket.hh"
 #include "warn.hh"
 #include "item.hh"
+#include "moment.hh"
 
 #include "translator.icc"
 
@@ -26,6 +27,9 @@ struct Tuplet_description
 
   bool full_length_;
   bool full_length_note_;
+  Moment stop_moment_;
+  Moment start_moment_;
+  Moment length_;
   
   Tuplet_description ()
   {
@@ -64,21 +68,51 @@ Tuplet_engraver::listen_tuplet_span (Stream_event *ev)
     {
       Tuplet_description d;
       d.event_ = ev;
+
+      d.length_ = robust_scm2moment (d.event_->get_property ("length"),
+                                    Moment (0));
+      d.start_moment_ = now_mom ();
+      d.stop_moment_ = now_mom () + d.length_;
+
+      for (vsize i=0; i < new_tuplets_.size (); i++)
+       {
+         /*
+           discard duplicates.
+          */
+         if (new_tuplets_[i].stop_moment_ == d.stop_moment_)
+           return;
+       }
+      
       new_tuplets_.push_back (d);
     }
-  else if (dir == STOP && tuplets_.size ())
+  else if (dir == STOP)
+    {
+    if (tuplets_.size ())
     {
       stopped_tuplets_.push_back (tuplets_.back ());
       tuplets_.pop_back ();
     }
+    else
+      ev->origin ()->warning (_f ("No tuplet to end"));
+    }
   else 
-    programming_error (_f ("direction of %s invalid: %d",
-                          "tuplet-span-event", int (dir)));
+    ev->origin ()->programming_error ("direction tuplet-span-event_ invalid.");
 }
 
 void
 Tuplet_engraver::process_music ()
 {
+  /*
+    This may happen if the end of a tuplet is part of a quoted voice.
+   */
+  Moment now = now_mom();
+  for (vsize i = tuplets_.size (); i --; )
+    {
+      stopped_tuplets_.push_back (tuplets_[i]);
+      if (tuplets_[i].stop_moment_ == now)
+       tuplets_.erase (tuplets_.begin () + i);
+    }
+  
   for (vsize i = 0; i < stopped_tuplets_.size (); i++)
     {
       Spanner *bracket = stopped_tuplets_[i].bracket_;
@@ -102,6 +136,7 @@ Tuplet_engraver::process_music ()
              number->set_bound (RIGHT,
                                                      stopped_tuplets_[i].bracket_->get_bound (LEFT));
            }
+         
          // todo: scrap last_tuplets_, use stopped_tuplets_ only.
          // clear stopped_tuplets_ at start_translation_timestep
          last_tuplets_.push_back (bracket);
@@ -131,6 +166,8 @@ Tuplet_engraver::process_music ()
                                          tuplets_[i].event_->self_scm ());
       tuplets_[i].number_->set_object ("bracket", tuplets_[i].bracket_->self_scm ());
       tuplets_[i].bracket_->set_object ("tuplet-number", tuplets_[i].number_->self_scm ());
+      tuplets_[i].stop_moment_.grace_part_ = 0;
+      
       
       if (i < tuplets_.size () - 1 && tuplets_[i + 1].bracket_)
        Tuplet_bracket::add_tuplet_bracket (tuplets_[i].bracket_, tuplets_[i + 1].bracket_);