]> git.donarmstrong.com Git - lilypond.git/blob - lily/music-iterator.cc
release: 0.1.8
[lilypond.git] / lily / music-iterator.cc
1 /*
2   music-iterator.cc -- implement {Music,Chord,Voice}_iterator
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
7 */
8
9 #include "music-list.hh"
10 #include "music-iterator.hh"
11 #include "translator.hh"
12 #include "request.hh"
13 #include "debug.hh"
14
15
16 IMPLEMENT_IS_TYPE_B(Music_iterator);
17
18 Chord_iterator::~Chord_iterator()
19 {
20 }
21
22 void
23 Music_iterator::do_print()const
24 {
25
26 }
27
28 void
29 Music_iterator::print() const
30 {
31 #ifndef NPRINT
32     if ( !check_debug)
33         return ;
34     DOUT << name() << "{";
35     DOUT << "report to " << 
36         report_to_l() << " (" << report_to_l ()->name () << ")\n";
37     DOUT << "next at " << next_moment() << " ";
38     do_print();
39     DOUT << "}\n";
40 #endif
41 }
42
43 Translator *
44 Music_iterator::get_req_translator_l()
45 {
46     assert (report_to_l());
47     if (report_to_l()->is_bottom_engraver_b ())
48         return report_to_l();
49
50     set_translator (report_to_l()->get_default_interpreter ());
51     return report_to_l();
52 }
53
54 void
55 Music_iterator::push_translator (Translator*t)
56 {
57     report_to_l_arr_.push (t);
58     t->iterator_count_ ++;
59 }
60
61 void
62 Music_iterator::pop_translator()
63 {
64     report_to_l()->iterator_count_ --;
65     assert (report_to_l()->iterator_count_ >=0);
66     report_to_l_arr_.pop();
67 }
68
69 Translator* 
70 Music_iterator::report_to_l()const
71 {
72     if (! report_to_l_arr_.size())
73         return 0;
74     return report_to_l_arr_.top();
75 }
76
77
78 void
79 Music_iterator::set_translator (Translator*trans)
80 {   
81     if (report_to_l()==trans)
82         return;
83     if ( report_to_l())
84         pop_translator();
85     if (trans)
86         push_translator (trans);
87 }
88
89 void
90 Music_iterator::construct_children()
91 {
92
93 }
94
95 Music_iterator::~Music_iterator()
96 {
97     set_translator (0);
98 }
99
100 Moment
101 Music_iterator::next_moment()const
102 {
103     return 0;
104 }
105
106 void
107 Music_iterator::process_and_next (Moment)
108 {
109     first_b_ = false;
110 }
111
112 bool
113 Music_iterator::ok()const
114 {
115     return first_b_;
116 }
117
118 Music_iterator*
119 Music_iterator::static_get_iterator_p (Music *m,
120                                       Translator *report_l)
121 {
122     Music_iterator * p =0;
123     if (m->is_type_b (Request_chord::static_name()))
124         p = new Request_chord_iterator ((Request_chord*) m);
125     else if (m->is_type_b (Chord::static_name())) 
126         p =  new Chord_iterator ((Chord*) m);
127     else if (m->is_type_b (Voice::static_name())) 
128         p =  new Voice_iterator ((Voice*) m);
129     
130     if (m -> type_str_ != "") {
131         Translator * a =report_l->
132             find_get_translator_l (m-> type_str_, m->id_str_);
133             p->set_translator (a);
134     } 
135
136
137     if (! p->report_to_l())
138          p ->set_translator (report_l);
139     
140     return p;
141 }
142
143 Music_iterator*
144 Music_iterator::get_iterator_p (Music*m)const
145 {
146     Music_iterator*p = static_get_iterator_p (m,report_to_l());
147     p->daddy_iter_l_ = (Music_iterator*)this;
148     p->construct_children();
149     return p;
150 }
151
152 Music_iterator::Music_iterator()
153 {
154     daddy_iter_l_ =0;
155     first_b_ = true;
156 }
157
158 /* ************** */
159
160 Chord_iterator::Chord_iterator (Chord const *chord_C)
161 {
162     chord_C_ = chord_C;
163 }
164
165 void
166 Chord_iterator::construct_children()
167 {
168     int j = 0;
169     for (PCursor<Music*> i (chord_C_->music_p_list_.top());  //, int j = 0; 
170         i.ok(); j++, i++) {
171         Music_iterator * mi =  get_iterator_p (i.ptr());
172         if ( mi->ok()) {
173             set_translator (mi->report_to_l()->ancestor_l (
174                 chord_C_->multi_level_i_) );
175             children_p_list_.bottom().add (mi);
176         } else 
177             delete mi;
178     }
179 }
180 void
181 Chord_iterator::do_print() const
182 {
183 #ifndef NPRINT
184     for (PCursor<Music_iterator*> i (children_p_list_.top()); i.ok (); i++) {
185         i->print();
186     }
187 #endif
188 }
189
190 void
191 Chord_iterator::process_and_next (Moment until)
192 {
193     for (PCursor<Music_iterator*> i (children_p_list_.top()); i.ok ();) {
194         if  (i->next_moment() == until) {
195             i->process_and_next (until);
196         }
197         if (!i->ok()) 
198             delete i.remove_p();
199         else
200             i++;
201     }
202     Music_iterator::process_and_next (until);
203 }
204
205
206 IMPLEMENT_IS_TYPE_B1(Chord_iterator,Music_iterator);
207
208 Moment
209 Chord_iterator::next_moment()const
210 {
211     Moment next_ = infinity_mom;
212     for (PCursor<Music_iterator*> i (children_p_list_.top()); i.ok (); i++)
213         next_ = next_ <? i->next_moment() ;
214     return next_;
215 }
216
217
218
219 bool
220 Chord_iterator::ok()const
221 {
222     return children_p_list_.size();
223 }
224
225 /* ************** */
226
227 void
228 Voice_iterator::do_print()const
229 {
230     if (iter_p_)
231         iter_p_->print();
232 }
233
234 Voice_iterator::Voice_iterator (Voice const*v)
235     : PCursor<Music*> ( v->music_p_list_)
236 {
237     here_mom_ = v->offset_mom_;
238     voice_C_ = v;
239     iter_p_ =0;
240 }
241
242 void
243 Voice_iterator::construct_children()
244 {
245     while (PCursor<Music*>::ok()) {
246         start_next_element();
247         if ( !iter_p_->ok()) {
248             leave_element();
249         } else {
250             set_voice_translator();
251             break;
252         }
253     }
254 }
255
256 void 
257 Voice_iterator::leave_element()
258 {
259     delete iter_p_;
260     iter_p_ =0;
261     MInterval elt_time = ptr()->time_int ();
262     if (!elt_time.empty_b())
263         here_mom_ += elt_time.length();
264     PCursor<Music*>::next();
265 }
266
267 void
268 Voice_iterator::start_next_element()
269 {
270     assert (!iter_p_);
271     iter_p_ = get_iterator_p (ptr());
272 }
273
274 void
275 Voice_iterator::set_voice_translator()
276 {
277     if (iter_p_->report_to_l()->depth_i () > report_to_l ()->depth_i ())
278         set_translator (iter_p_->report_to_l());
279 }
280
281 Voice_iterator::~Voice_iterator()
282 {
283     assert (! iter_p_);
284 }
285
286
287 IMPLEMENT_IS_TYPE_B1(Voice_iterator,Music_iterator);
288
289 void
290 Voice_iterator::process_and_next (Moment until)
291 {
292     while (1) {
293         Moment local_until = until - here_mom_;
294         while ( iter_p_->ok()) {
295             Moment here = iter_p_->next_moment();
296             if (here != local_until)
297                 goto loopexit;
298             
299             iter_p_->process_and_next (local_until);
300         }
301
302         if (!iter_p_->ok()) {
303             leave_element();
304             if ( PCursor<Music*>::ok()) {
305                 start_next_element();
306                 set_voice_translator();
307             } else {
308                 goto loopexit;
309             }
310         }
311     }
312
313 loopexit:
314
315     Music_iterator::process_and_next (until);
316 }
317
318 Moment
319 Voice_iterator::next_moment()const
320 {
321     return iter_p_->next_moment() + here_mom_;
322 }
323
324 bool
325 Voice_iterator::ok()const
326 {
327     return iter_p_;
328 }
329
330
331 IMPLEMENT_IS_TYPE_B1(Request_chord_iterator,Music_iterator);
332
333 void
334 Request_chord_iterator::construct_children()
335 {
336     get_req_translator_l();
337 }
338
339 Request_chord_iterator::Request_chord_iterator (Request_chord*el_l)
340 {
341     elt_l_ = el_l;
342     elt_duration_ = el_l->time_int().length (); 
343     last_b_ = false;
344 }
345
346
347 bool
348 Request_chord_iterator::ok()const
349 {
350     return (elt_duration_ && !last_b_) || first_b_; 
351 }
352
353
354
355 Moment
356 Request_chord_iterator::next_moment()const
357 {
358     Moment m (0);
359     if  (!first_b_) 
360         m = elt_duration_;
361     return m;
362 }
363
364 void
365 Request_chord_iterator::do_print() const
366 {
367 #ifndef NPRINT
368     DOUT << "duration: " << elt_duration_;
369 #endif
370 }
371 void
372 Request_chord_iterator::process_and_next (Moment mom)
373 {
374     if ( first_b_) {
375         for (PCursor<Music*> i (elt_l_->music_p_list_); i.ok(); i++) {
376             assert (i->is_type_b (Request::static_name()));
377             Request * req_l = (Request*)i.ptr();
378             bool gotcha = report_to_l()->try_request (req_l);
379             if (!gotcha)
380                 req_l->warning ("Junking request: " + String (req_l->name()));
381
382         }
383         first_b_ = false;
384     }
385
386     if ( mom >= elt_duration_)
387         last_b_ = true;  
388 }