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