]> git.donarmstrong.com Git - lilypond.git/blob - lily/simultaneous-music-iterator.cc
unsmob_pitch -> Pitch::unsmob and related
[lilypond.git] / lily / simultaneous-music-iterator.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1997--2014 Han-Wen Nienhuys <hanwen@xs4all.nl>
5
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.
10
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.
15
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/>.
18 */
19
20 #include "simultaneous-music-iterator.hh"
21 #include "music.hh"
22 #include "context.hh"
23 #include "warn.hh"
24 #include "context-def.hh"
25
26 Simultaneous_music_iterator::Simultaneous_music_iterator ()
27 {
28   create_separate_contexts_ = false;
29   children_list_ = SCM_EOL;
30 }
31
32 void
33 Simultaneous_music_iterator::derived_mark () const
34 {
35   scm_gc_mark (children_list_);
36 }
37
38 void
39 Simultaneous_music_iterator::derived_substitute (Context *f, Context *t)
40 {
41   for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s))
42     Music_iterator::unsmob (scm_car (s))->substitute_outlet (f, t);
43 }
44
45 void
46 Simultaneous_music_iterator::construct_children ()
47 {
48   int j = 0;
49
50   SCM i = get_music ()->get_property ("elements");
51
52   children_list_ = SCM_EOL;
53   SCM *tail = &children_list_;
54   for (; scm_is_pair (i); i = scm_cdr (i), j++)
55     {
56       Music *mus = unsmob_music (scm_car (i));
57
58       SCM scm_iter = get_static_get_iterator (mus);
59       Music_iterator *mi = Music_iterator::unsmob (scm_iter);
60
61       /* if create_separate_contexts_ is set, create a new context with the
62          number number as name */
63
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)
67                    : get_outlet ();
68
69       if (!c)
70         c = get_outlet ();
71
72       mi->init_context (mus, c);
73       mi->construct_children ();
74
75       if (mi->ok ())
76         {
77           *tail = scm_cons (scm_iter, *tail);
78           tail = SCM_CDRLOC (*tail);
79         }
80       else
81         mi->quit ();
82     }
83 }
84
85 void
86 Simultaneous_music_iterator::process (Moment until)
87 {
88   SCM *proc = &children_list_;
89   while (scm_is_pair (*proc))
90     {
91       Music_iterator *i = Music_iterator::unsmob (scm_car (*proc));
92       if (i->run_always ()
93           || i->pending_moment () == until)
94         i->process (until);
95       if (!i->ok ())
96         {
97           i->quit ();
98           *proc = scm_cdr (*proc);
99         }
100       else
101         proc = SCM_CDRLOC (*proc);
102     }
103 }
104
105 Moment
106 Simultaneous_music_iterator::pending_moment () const
107 {
108   Moment next;
109   next.set_infinite (1);
110
111   for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s))
112     {
113       Music_iterator *it = Music_iterator::unsmob (scm_car (s));
114       next = min (next, it->pending_moment ());
115     }
116
117   return next;
118 }
119
120 bool
121 Simultaneous_music_iterator::ok () const
122 {
123   bool run_always_ok = false;
124   for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s))
125     {
126       Music_iterator *it = Music_iterator::unsmob (scm_car (s));
127       if (!it->run_always ())
128         return true;
129       else
130         run_always_ok = run_always_ok || it->ok ();
131     }
132   return run_always_ok;
133 }
134
135 bool
136 Simultaneous_music_iterator::run_always () const
137 {
138   for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s))
139     {
140       Music_iterator *it = Music_iterator::unsmob (scm_car (s));
141       if (it->run_always ())
142         return true;
143     }
144   return false;
145 }
146
147 void
148 Simultaneous_music_iterator::do_quit ()
149 {
150   for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s))
151     Music_iterator::unsmob (scm_car (s))->quit ();
152 }
153
154 IMPLEMENT_CTOR_CALLBACK (Simultaneous_music_iterator);