2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1997--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
20 #include "simultaneous-music-iterator.hh"
24 #include "context-def.hh"
26 Simultaneous_music_iterator::Simultaneous_music_iterator ()
28 create_separate_contexts_ = false;
29 children_list_ = SCM_EOL;
33 Simultaneous_music_iterator::derived_mark () const
35 scm_gc_mark (children_list_);
39 Simultaneous_music_iterator::derived_substitute (Context *f, Context *t)
41 for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s))
42 unsmob<Music_iterator> (scm_car (s))->substitute_outlet (f, t);
46 Simultaneous_music_iterator::construct_children ()
50 SCM i = get_music ()->get_property ("elements");
52 children_list_ = SCM_EOL;
53 SCM *tail = &children_list_;
54 for (; scm_is_pair (i); i = scm_cdr (i), j++)
56 Music *mus = unsmob<Music> (scm_car (i));
58 SCM scm_iter = get_static_get_iterator (mus);
59 Music_iterator *mi = unsmob<Music_iterator> (scm_iter);
61 /* if create_separate_contexts_ is set, create a new context with the
62 number number as name */
64 SCM name = ly_symbol2scm (get_outlet ()->context_name ().c_str ());
65 Context *c = (j && create_separate_contexts_)
66 ? get_outlet ()->find_create_context (name, ::to_string (j), SCM_EOL)
72 mi->init_context (mus, c);
73 mi->construct_children ();
77 *tail = scm_cons (scm_iter, *tail);
78 tail = SCM_CDRLOC (*tail);
85 // If there are non-run-always iterators and all of them die, take the
86 // rest of them along.
88 Simultaneous_music_iterator::process (Moment until)
90 bool had_good = false;
92 SCM *proc = &children_list_;
93 while (scm_is_pair (*proc))
95 Music_iterator *i = unsmob<Music_iterator> (scm_car (*proc));
96 bool run_always = i->run_always ();
97 if (run_always || i->pending_moment () == until)
104 *proc = scm_cdr (*proc);
110 proc = SCM_CDRLOC (*proc);
113 // If there were non-run-always iterators and all of them died, take
114 // the rest of the run-always iterators along with them. They have
115 // likely lost their reference iterators. Basing this on the actual
116 // music contexts is not reliable since something like
117 // \new Voice = blah {
118 // << \context Voice = blah { c4 d }
119 // \addlyrics { oh no }
122 // cannot wait for the death of context blah before ending the
123 // simultaneous iterator.
124 if (had_bad && !had_good)
126 for (SCM p = children_list_; scm_is_pair (p); p = scm_cdr (p))
127 unsmob<Music_iterator> (scm_car (p))->quit ();
128 children_list_ = SCM_EOL;
133 Simultaneous_music_iterator::pending_moment () const
136 next.set_infinite (1);
138 for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s))
140 Music_iterator *it = unsmob<Music_iterator> (scm_car (s));
141 next = min (next, it->pending_moment ());
148 Simultaneous_music_iterator::ok () const
150 bool run_always_ok = false;
151 for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s))
153 Music_iterator *it = unsmob<Music_iterator> (scm_car (s));
154 if (!it->run_always ())
157 run_always_ok = run_always_ok || it->ok ();
159 return run_always_ok;
163 Simultaneous_music_iterator::run_always () const
165 for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s))
167 Music_iterator *it = unsmob<Music_iterator> (scm_car (s));
168 if (it->run_always ())
175 Simultaneous_music_iterator::do_quit ()
177 for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s))
178 unsmob<Music_iterator> (scm_car (s))->quit ();
181 IMPLEMENT_CTOR_CALLBACK (Simultaneous_music_iterator);