]> git.donarmstrong.com Git - lilypond.git/blob - lily/music-iterator.cc
release: 0.1.9
[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     {
132         Translator * a =report_l->
133             find_get_translator_l (m-> type_str_, m->id_str_);
134             p->set_translator (a);
135     }
136
137
138   if (! p->report_to_l())
139          p ->set_translator (report_l);
140   
141   return p;
142 }
143
144 Music_iterator*
145 Music_iterator::get_iterator_p (Music*m)const
146 {
147   Music_iterator*p = static_get_iterator_p (m,report_to_l());
148   p->daddy_iter_l_ = (Music_iterator*)this;
149   p->construct_children();
150   return p;
151 }
152
153 Music_iterator::Music_iterator()
154 {
155   daddy_iter_l_ =0;
156   first_b_ = true;
157 }
158
159 /* ************** */
160
161 Chord_iterator::Chord_iterator (Chord const *chord_C)
162 {
163   chord_C_ = chord_C;
164 }
165
166 void
167 Chord_iterator::construct_children()
168 {
169   int j = 0;
170   for (PCursor<Music*> i (chord_C_->music_p_list_.top());  //, int j = 0; 
171         i.ok(); j++, i++) 
172           {
173         Music_iterator * mi =  get_iterator_p (i.ptr());
174         if ( mi->ok()) 
175           {
176             set_translator (mi->report_to_l()->ancestor_l (
177                 chord_C_->multi_level_i_) );
178             children_p_list_.bottom().add (mi);
179           }
180         else 
181             delete mi;
182     }
183 }
184 void
185 Chord_iterator::do_print() const
186 {
187 #ifndef NPRINT
188   for (PCursor<Music_iterator*> i (children_p_list_.top()); i.ok (); i++) 
189     {
190         i->print();
191     }
192 #endif
193 }
194
195 void
196 Chord_iterator::process_and_next (Moment until)
197 {
198   for (PCursor<Music_iterator*> i (children_p_list_.top()); i.ok ();) 
199     {
200         if  (i->next_moment() == until) 
201           {
202             i->process_and_next (until);
203           }
204         if (!i->ok()) 
205             delete i.remove_p();
206         else
207             i++;
208     }
209   Music_iterator::process_and_next (until);
210 }
211
212
213 IMPLEMENT_IS_TYPE_B1(Chord_iterator,Music_iterator);
214
215 Moment
216 Chord_iterator::next_moment()const
217 {
218   Moment next_ = infinity_mom;
219   for (PCursor<Music_iterator*> i (children_p_list_.top()); i.ok (); i++)
220         next_ = next_ <? i->next_moment() ;
221   return next_;
222 }
223
224
225
226 bool
227 Chord_iterator::ok()const
228 {
229   return children_p_list_.size();
230 }
231
232 /* ************** */
233
234 void
235 Voice_iterator::do_print()const
236 {
237   if (iter_p_)
238         iter_p_->print();
239 }
240
241 Voice_iterator::Voice_iterator (Voice const*v)
242   : PCursor<Music*> ( v->music_p_list_)
243 {
244   here_mom_ = v->offset_mom_;
245   voice_C_ = v;
246   iter_p_ =0;
247 }
248
249 void
250 Voice_iterator::construct_children()
251 {
252   while (PCursor<Music*>::ok()) 
253     {
254         start_next_element();
255         if ( !iter_p_->ok()) 
256           {
257             leave_element();
258           }
259         else 
260           {
261             set_voice_translator();
262             break;
263           }
264     }
265 }
266
267 void 
268 Voice_iterator::leave_element()
269 {
270   delete iter_p_;
271   iter_p_ =0;
272   MInterval elt_time = ptr()->time_int ();
273   if (!elt_time.empty_b())
274         here_mom_ += elt_time.length();
275   PCursor<Music*>::next();
276 }
277
278 void
279 Voice_iterator::start_next_element()
280 {
281   assert (!iter_p_);
282   iter_p_ = get_iterator_p (ptr());
283 }
284
285 void
286 Voice_iterator::set_voice_translator()
287 {
288   if (iter_p_->report_to_l()->depth_i () > report_to_l ()->depth_i ())
289         set_translator (iter_p_->report_to_l());
290 }
291
292 Voice_iterator::~Voice_iterator()
293 {
294   assert (! iter_p_);
295 }
296
297
298 IMPLEMENT_IS_TYPE_B1(Voice_iterator,Music_iterator);
299
300 void
301 Voice_iterator::process_and_next (Moment until)
302 {
303   while (1) 
304     {
305         Moment local_until = until - here_mom_;
306         while ( iter_p_->ok()) 
307           {
308             Moment here = iter_p_->next_moment();
309             if (here != local_until)
310                 goto loopexit;
311             
312             iter_p_->process_and_next (local_until);
313           }
314
315         if (!iter_p_->ok()) 
316           {
317             leave_element();
318             if ( PCursor<Music*>::ok()) 
319               {
320                 start_next_element();
321                 set_voice_translator();
322               }
323             else 
324               {
325                 goto loopexit;
326               }
327           }
328     }
329
330 loopexit:
331
332   Music_iterator::process_and_next (until);
333 }
334
335 Moment
336 Voice_iterator::next_moment()const
337 {
338   return iter_p_->next_moment() + here_mom_;
339 }
340
341 bool
342 Voice_iterator::ok()const
343 {
344   return iter_p_;
345 }
346
347
348 IMPLEMENT_IS_TYPE_B1(Request_chord_iterator,Music_iterator);
349
350 void
351 Request_chord_iterator::construct_children()
352 {
353   get_req_translator_l();
354 }
355
356 Request_chord_iterator::Request_chord_iterator (Request_chord*el_l)
357 {
358   elt_l_ = el_l;
359   elt_duration_ = el_l->time_int().length (); 
360   last_b_ = false;
361 }
362
363
364 bool
365 Request_chord_iterator::ok()const
366 {
367   return (elt_duration_ && !last_b_) || first_b_; 
368 }
369
370
371
372 Moment
373 Request_chord_iterator::next_moment()const
374 {
375   Moment m (0);
376   if  (!first_b_) 
377         m = elt_duration_;
378   return m;
379 }
380
381 void
382 Request_chord_iterator::do_print() const
383 {
384 #ifndef NPRINT
385   DOUT << "duration: " << elt_duration_;
386 #endif
387 }
388 void
389 Request_chord_iterator::process_and_next (Moment mom)
390 {
391   if ( first_b_) 
392     {
393         for (PCursor<Music*> i (elt_l_->music_p_list_); i.ok(); i++) 
394           {
395             assert (i->is_type_b (Request::static_name()));
396             Request * req_l = (Request*)i.ptr();
397             bool gotcha = report_to_l()->try_request (req_l);
398             if (!gotcha)
399                 req_l->warning ("Junking request: " + String (req_l->name()));
400
401           }
402         first_b_ = false;
403     }
404
405   if ( mom >= elt_duration_)
406         last_b_ = true;  
407 }