/*
This file is part of LilyPond, the GNU music typesetter.
- Copyright (C) 1997--2010 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
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
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 */
+ number number as name */
SCM name = ly_symbol2scm (get_outlet ()->context_name ().c_str ());
Context *c = (j && create_separate_contexts_)
- ? get_outlet ()->find_create_context (name, to_string (j), SCM_EOL)
- : get_outlet ();
+ ? get_outlet ()->find_create_context (name, ::to_string (j), SCM_EOL)
+ : get_outlet ();
if (!c)
- c = get_outlet ();
+ c = get_outlet ();
mi->init_context (mus, c);
mi->construct_children ();
if (mi->ok ())
- {
- *tail = scm_cons (scm_iter, *tail);
- tail = SCM_CDRLOC (*tail);
- }
+ {
+ *tail = scm_cons (scm_iter, *tail);
+ tail = SCM_CDRLOC (*tail);
+ }
else
- mi->quit ();
+ mi->quit ();
}
}
+// 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)
- i->process (until);
+ Music_iterator *i = unsmob<Music_iterator> (scm_car (*proc));
+ if (i->run_always () || i->pending_moment () == until)
+ i->process (until);
if (!i->ok ())
- {
- i->quit ();
- *proc = scm_cdr (*proc);
- }
+ {
+ i->quit ();
+ *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;
}
}
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 ());
}
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 ())
- return true;
- else
- run_always_ok = run_always_ok || it->ok ();
+ Music_iterator *it = unsmob<Music_iterator> (scm_car (s));
+ if (it->ok ())
+ return true;
}
- return run_always_ok;
+ return false;
}
bool
{
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;
+ return true;
}
return false;
}
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);