]> git.donarmstrong.com Git - lilypond.git/blob - lily/music-iterator.cc
Issue 4550 (2/2) Avoid "using namespace std;" in included files
[lilypond.git] / lily / music-iterator.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1997--2015 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 <cstdio>
21
22 #include "warn.hh"
23 #include "music.hh"
24 #include "context.hh"
25 #include "event-iterator.hh"
26 #include "input.hh"
27 #include "international.hh"
28 #include "music-wrapper.hh"
29 #include "music-wrapper-iterator.hh"
30 #include "simple-music-iterator.hh"
31
32
33 Music_iterator::Music_iterator ()
34 {
35   music_ = 0;
36   smobify_self ();
37 }
38
39 Music_iterator::~Music_iterator ()
40 {
41 }
42
43 Context *
44 Music_iterator::get_outlet () const
45 {
46   return handle_.get_context ();
47 }
48
49 void
50 Music_iterator::set_context (Context *trans)
51 {
52   handle_.set_context (trans);
53 }
54
55 void
56 Music_iterator::construct_children ()
57 {
58 }
59
60 Moment
61 Music_iterator::pending_moment () const
62 {
63   return 0;
64 }
65
66 void
67 Music_iterator::process (Moment)
68 {
69 }
70
71 bool
72 Music_iterator::ok () const
73 {
74   return false;
75 }
76
77 SCM
78 Music_iterator::get_static_get_iterator (Music *m)
79 {
80   Music_iterator *p = 0;
81
82   SCM ctor = m->get_property ("iterator-ctor");
83   SCM iter = SCM_EOL;
84   if (ly_is_procedure (ctor))
85     {
86       iter = scm_call_0 (ctor);
87       p = unsmob<Music_iterator> (iter);
88     }
89   else
90     {
91       if (dynamic_cast<Music_wrapper *> (m))
92         p = new Music_wrapper_iterator;
93       else if (m->is_mus_type ("event"))
94         p = new Event_iterator;
95       else
96         p = new Simple_music_iterator;
97
98       iter = p->self_scm ();
99       p->unprotect ();
100     }
101
102   p->music_ = m;
103   assert (m);
104   p->music_length_ = m->get_length ();
105   p->start_mom_ = m->start_mom ();
106
107   return iter;
108 }
109
110 Moment
111 Music_iterator::music_get_length () const
112 {
113   return music_length_;
114 }
115
116 Moment
117 Music_iterator::music_start_mom ()const
118 {
119   return start_mom_;
120 }
121
122 void
123 Music_iterator::init_context (Music *m, Context *report)
124 {
125   music_ = m;
126   assert (m);
127   if (! get_outlet ())
128     set_context (report);
129 }
130
131 void
132 Music_iterator::substitute_outlet (Context *f, Context *t)
133 {
134   if (f != t)
135     {
136       if (get_outlet () == f)
137         set_context (t);
138       derived_substitute (f, t);
139     }
140 }
141
142 void
143 Music_iterator::derived_substitute (Context *, Context *)
144 {
145 }
146
147 SCM
148 Music_iterator::get_iterator (Music *m) const
149 {
150   SCM ip = get_static_get_iterator (m);
151   Music_iterator *p = unsmob<Music_iterator> (ip);
152
153   p->init_context (m, get_outlet ());
154
155   p->construct_children ();
156   return ip;
157 }
158
159 /* Descend to a bottom context; implicitly create a new one if necessary */
160 void
161 Music_iterator::descend_to_bottom_context ()
162 {
163   assert (get_outlet ());
164   if (!get_outlet ()->is_bottom_context ())
165     set_context (get_outlet ()->get_default_interpreter ());
166 }
167
168 void
169 Music_iterator::report_event (Music *m)
170 {
171   descend_to_bottom_context ();
172
173   /*
174     FIXME: then don't do it.
175   */
176   if (!m->is_mus_type ("event"))
177     m->origin ()->programming_error ("Sending non-event to context");
178
179   m->send_to_context (get_outlet ());
180 }
181
182 IMPLEMENT_CTOR_CALLBACK (Music_iterator);
183
184 Music *
185 Music_iterator::get_music () const
186 {
187   return music_;
188 }
189
190 /****************************************************************/
191
192 const char Music_iterator::type_p_name_[] = "ly:iterator?";
193
194 SCM
195 Music_iterator::mark_smob () const
196 {
197   derived_mark ();
198   /*
199     Careful with GC, although we intend the following as pointers
200     only, we _must_ mark them.
201   */
202   /* Use handle_ directly as get_outlet is a virtual function and we
203      need to protect the context until Music_iterator::quit is being
204      run. */
205   if (handle_.get_context ())
206     scm_gc_mark (handle_.get_context ()->self_scm ());
207   if (music_)
208     scm_gc_mark (music_->self_scm ());
209
210   return SCM_EOL;
211 }
212
213 int
214 Music_iterator::print_smob (SCM port, scm_print_state *) const
215 {
216   char s[1000];
217
218   sprintf (s, "#<%s>", class_name ());
219   scm_puts (s, port);
220   return 1;
221 }
222
223 void
224 Music_iterator::derived_mark ()const
225 {
226 }
227
228 void
229 Music_iterator::quit ()
230 {
231   do_quit ();
232   handle_.set_context (0);
233 }
234
235 void
236 Music_iterator::do_quit ()
237 {
238 }
239
240 bool
241 Music_iterator::run_always ()const
242 {
243   return false;
244 }
245
246 bool
247 is_child_context (Context *me, Context *child)
248 {
249   while (child && child != me)
250     child = child->get_parent_context ();
251
252   return child == me;
253 }
254
255 /*
256   move to context of child iterator if it is deeper down in the
257   hierarchy.
258 */
259 void
260 Music_iterator::descend_to_child (Context *child_report)
261 {
262   Context *me_report = get_outlet ();
263   if (is_child_context (me_report, child_report))
264     set_context (child_report);
265 }