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