]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/simultaneous-music-iterator.cc
Web-ja: update introduction
[lilypond.git] / lily / simultaneous-music-iterator.cc
index 3e0ad4fae72cc504185da470df43bc4c8b2c9ff3..e892776b61a39e6f4814eb350500ab706a45c4ee 100644 (file)
@@ -1,7 +1,7 @@
 /*
   This file is part of LilyPond, the GNU music typesetter.
 
-  Copyright (C) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
+  Copyright (C) 1997--2015 Han-Wen Nienhuys <hanwen@xs4all.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
@@ -39,7 +39,7 @@ void
 Simultaneous_music_iterator::derived_substitute (Context *f, Context *t)
 {
   for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s))
-    unsmob_iterator (scm_car (s))->substitute_outlet (f, t);
+    unsmob<Music_iterator> (scm_car (s))->substitute_outlet (f, t);
 }
 
 void
@@ -53,10 +53,10 @@ Simultaneous_music_iterator::construct_children ()
   SCM *tail = &children_list_;
   for (; scm_is_pair (i); i = scm_cdr (i), j++)
     {
-      Music *mus = unsmob_music (scm_car (i));
+      Music *mus = unsmob<Music> (scm_car (i));
 
       SCM scm_iter = get_static_get_iterator (mus);
-      Music_iterator *mi = unsmob_iterator (scm_iter);
+      Music_iterator *mi = unsmob<Music_iterator> (scm_iter);
 
       /* if create_separate_contexts_ is set, create a new context with the
          number number as name */
@@ -82,15 +82,20 @@ Simultaneous_music_iterator::construct_children ()
     }
 }
 
+// If we have some iterators with definite next moment and no of them
+// remain after processing, we take the iterators with indefinite next
+// moment along.  That makes sure that no Lyric_combine_music_iterator
+// will outstay its welcome (issue 2010).
+
 void
 Simultaneous_music_iterator::process (Moment until)
 {
   SCM *proc = &children_list_;
+  bool finite = !pending_moment ().main_part_.is_infinity ();
   while (scm_is_pair (*proc))
     {
-      Music_iterator *i = unsmob_iterator (scm_car (*proc));
-      if (i->run_always ()
-          || i->pending_moment () == until)
+      Music_iterator *i = unsmob<Music_iterator> (scm_car (*proc));
+      if (i->run_always () || i->pending_moment () == until)
         i->process (until);
       if (!i->ok ())
         {
@@ -98,7 +103,26 @@ Simultaneous_music_iterator::process (Moment until)
           *proc = scm_cdr (*proc);
         }
       else
-        proc = SCM_CDRLOC (*proc);
+        {
+          proc = SCM_CDRLOC (*proc);
+        }
+    }
+  // If there were definite-ended iterators and all of them died, take
+  // the rest of the iterators along with them.  They have
+  // likely lost their reference iterators.  Basing this on the actual
+  // music contexts is not reliable since something like
+  // \new Voice = blah {
+  //    << \context Voice = blah { c4 d }
+  //       \addlyrics { oh no }
+  //    >> e f
+  // }
+  // cannot wait for the death of context blah before ending the
+  // simultaneous iterator.
+  if (finite && pending_moment ().main_part_.is_infinity ())
+    {
+      for (SCM p = children_list_; scm_is_pair (p); p = scm_cdr (p))
+        unsmob<Music_iterator> (scm_car (p))->quit ();
+      children_list_ = SCM_EOL;
     }
 }
 
@@ -110,7 +134,7 @@ Simultaneous_music_iterator::pending_moment () const
 
   for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s))
     {
-      Music_iterator *it = unsmob_iterator (scm_car (s));
+      Music_iterator *it = unsmob<Music_iterator> (scm_car (s));
       next = min (next, it->pending_moment ());
     }
 
@@ -120,16 +144,13 @@ Simultaneous_music_iterator::pending_moment () const
 bool
 Simultaneous_music_iterator::ok () const
 {
-  bool run_always_ok = false;
   for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s))
     {
-      Music_iterator *it = unsmob_iterator (scm_car (s));
-      if (!it->run_always ())
+      Music_iterator *it = unsmob<Music_iterator> (scm_car (s));
+      if (it->ok ())
         return true;
-      else
-        run_always_ok = run_always_ok || it->ok ();
     }
-  return run_always_ok;
+  return false;
 }
 
 bool
@@ -137,7 +158,7 @@ Simultaneous_music_iterator::run_always () const
 {
   for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s))
     {
-      Music_iterator *it = unsmob_iterator (scm_car (s));
+      Music_iterator *it = unsmob<Music_iterator> (scm_car (s));
       if (it->run_always ())
         return true;
     }
@@ -148,7 +169,7 @@ void
 Simultaneous_music_iterator::do_quit ()
 {
   for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s))
-    unsmob_iterator (scm_car (s))->quit ();
+    unsmob<Music_iterator> (scm_car (s))->quit ();
 }
 
 IMPLEMENT_CTOR_CALLBACK (Simultaneous_music_iterator);