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