From: David Kastrup Date: Sun, 5 Oct 2014 22:31:58 +0000 (+0200) Subject: Issue 2010: \lyricsto may turn into a voice-mangling zombie X-Git-Tag: release/2.19.16-1~19 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=b12ee555e33d483eed0832d8502ad7a282ef9796;p=lilypond.git Issue 2010: \lyricsto may turn into a voice-mangling zombie The problem here was that the simultaneous iterator might keep rerhythmed lyrics around when the associated voice has died already, blocking the simultaneous iterator. The solution is that when removing the last regular iterator to remove all remaining lyric-combined iterators at the same time. --- diff --git a/lily/simultaneous-music-iterator.cc b/lily/simultaneous-music-iterator.cc index 92bf91b25a..3e42ed96c0 100644 --- a/lily/simultaneous-music-iterator.cc +++ b/lily/simultaneous-music-iterator.cc @@ -82,23 +82,50 @@ Simultaneous_music_iterator::construct_children () } } +// If there are non-run-always iterators and all of them die, take the +// rest of them along. void Simultaneous_music_iterator::process (Moment until) { + bool had_good = false; + bool had_bad = false; SCM *proc = &children_list_; while (scm_is_pair (*proc)) { Music_iterator *i = Music_iterator::unsmob (scm_car (*proc)); - if (i->run_always () - || i->pending_moment () == until) + bool run_always = i->run_always (); + if (run_always || i->pending_moment () == until) i->process (until); if (!i->ok ()) { + if (!run_always) + had_bad = true; i->quit (); *proc = scm_cdr (*proc); } else - proc = SCM_CDRLOC (*proc); + { + if (!run_always) + had_good = true; + proc = SCM_CDRLOC (*proc); + } + } + // If there were non-run-always iterators and all of them died, take + // the rest of the run-always 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 (had_bad && !had_good) + { + for (SCM p = children_list_; scm_is_pair (p); p = scm_cdr (p)) + Music_iterator::unsmob (scm_car (p))->quit (); + children_list_ = SCM_EOL; } }