]> git.donarmstrong.com Git - lilypond.git/blob - lily/sequential-iterator.cc
* lily/include/music-iterator.hh (class Music_iterator): add
[lilypond.git] / lily / sequential-iterator.cc
1 /*
2   Sequential_iterator.cc -- implement Sequential_iterator
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "translator-group.hh"
10
11 #include "sequential-iterator.hh"
12 #include "music-list.hh"
13
14 Grace_fixup *copy_grace_fixups (Grace_fixup* src);
15 Grace_fixup *get_grace_fixups (SCM cursor);
16
17 /*
18   
19   TODO: handling of grace notes is exquisite pain.  This handling
20   should be formally specified and then the implementation verified.
21
22 */
23
24 /*
25   Invariant for the data structure.
26
27
28   if (gh_pair_p (cursor_))
29     iter_->music_ == unsmob_music (ly_car (cursor_))
30   else
31     iter_ == 0;
32
33   The length of musiclist from start to up to cursor_ (cursor_ not
34   including), is summed
35
36   here_mom_  = sum (length (musiclist [start ... cursor>))  %)  
37   
38  */
39 Sequential_iterator::Sequential_iterator ()
40 {
41   here_mom_ = Moment (0);
42   list_ = SCM_EOL;
43   cursor_ = SCM_EOL; 
44   grace_fixups_ = 0;
45   iter_ =0;
46 }
47
48 SCM 
49 Sequential_iterator::get_music_list () const
50 {
51   return SCM_EOL;
52 }
53
54 void
55 Sequential_iterator::do_quit ()
56 {
57   if (iter_)
58     iter_->quit();
59 }
60
61
62 Sequential_iterator::Sequential_iterator (Sequential_iterator const &src)
63   : Music_iterator (src)
64 {
65   grace_fixups_ = copy_grace_fixups (src.grace_fixups_);
66   cursor_ = src.cursor_;
67   list_ = src.cursor_;
68   here_mom_ = src.here_mom_;
69   iter_ = 0;
70
71   if (src.iter_)
72     {
73       iter_ = src.iter_->clone ();
74       scm_gc_unprotect_object (iter_->self_scm());
75     }
76 }
77
78 void
79 Sequential_iterator::derived_mark ()const
80 {
81   if (iter_)
82     scm_gc_mark (iter_->self_scm());
83   scm_gc_mark (list_);
84   scm_gc_mark (cursor_);
85 }
86
87
88 void
89 Sequential_iterator::derived_substitute (Translator_group*f,Translator_group*t)
90 {
91   if (iter_)
92     iter_->substitute_outlet (f,t);
93   
94 }
95
96 Grace_fixup *
97 get_grace_fixups (SCM cursor)
98 {
99   Moment here;
100   Moment last (-1);
101   Grace_fixup *head = 0;
102   Grace_fixup **tail = &head;
103
104   for (; gh_pair_p (cursor); cursor = ly_cdr (cursor))
105     {
106       Music * mus = unsmob_music (ly_car (cursor));
107       Moment s = mus->start_mom ();
108       Moment l =mus->get_length () - s;
109
110       if (s.grace_part_)
111         {
112           if (last != Moment (-1))
113             {
114               Grace_fixup *p =new Grace_fixup;
115               p->start_ = last;
116               p->length_ = here - last;
117               p->grace_start_ = s.grace_part_;
118               p->next_ = 0;
119               *tail = p;
120               tail = &(*tail)->next_; 
121             }
122
123           here.grace_part_ = s.grace_part_;
124         }
125       
126       if (l.to_bool())
127         {
128           last = here;
129           here += l;
130         }
131     }
132   return  head;
133 }
134
135 Grace_fixup *
136 copy_grace_fixups (Grace_fixup* src)
137 {
138   Grace_fixup * head = 0;
139   Grace_fixup **dest = &head;
140
141   while (src)
142     {
143       *dest = new Grace_fixup (*src);
144       dest = & (*dest)->next_;
145       src = src ->next_;
146     }
147
148   return head;
149 }
150
151 void
152 Sequential_iterator::construct_children ()
153 {
154   list_ = get_music_list ();
155   cursor_ = list_; 
156
157   iter_ = 0;
158   if (gh_pair_p (cursor_))
159     {
160       Music *m  =unsmob_music (ly_car (cursor_));
161       iter_ = unsmob_iterator (get_iterator (m));
162     }
163   
164   while (iter_ && !iter_->ok ())
165     {
166       next_element (true);
167     }
168
169   here_mom_ = get_music ()->start_mom ();
170   grace_fixups_ = get_grace_fixups (cursor_);
171
172   /*
173     iter_->ok () is tautology, but what the heck.
174    */
175   if (iter_ && iter_->ok ()) 
176     descend_to_child ();
177 }
178
179
180 /*
181   maintain invariants: change cursor, iter and here_mom_ in one fell
182   swoop.
183 */
184 void
185 Sequential_iterator::next_element (bool)
186 {
187   Moment len =iter_->music_get_length () - iter_->music_start_mom ();
188   assert (!grace_fixups_  || grace_fixups_->start_ >= here_mom_);
189   
190   if (len.main_part_ && grace_fixups_ &&
191       grace_fixups_->start_ == here_mom_)
192     {
193       here_mom_ += grace_fixups_->length_;
194       here_mom_.grace_part_ += grace_fixups_->grace_start_;
195
196       Grace_fixup * n =grace_fixups_->next_;
197       delete grace_fixups_;
198       grace_fixups_ = n;
199     }
200   else if (len.grace_part_ && !len.main_part_)
201     {
202       here_mom_.grace_part_ =0;
203     }
204   else
205     {
206       /*
207         !len.grace_part_ || len.main_part_
208
209         We skip over a big chunk (mainpart != 0). Any starting graces
210         in that chunk should be in len.grace_part_
211
212       */
213       here_mom_ += len;
214     }
215   
216   cursor_ = ly_cdr (cursor_);
217
218   iter_->quit();
219   if (gh_pair_p (cursor_))
220     iter_ = unsmob_iterator (get_iterator (unsmob_music (ly_car (cursor_))));
221   else
222     iter_ = 0;
223 }
224
225 /*
226   move to context of child iterator if it is deeper down in the
227   hierarchy.
228   */
229 void
230 Sequential_iterator::descend_to_child ()
231 {
232   Translator_group  * child_report = child_report = iter_->report_to ();
233   Translator_group * me_report = report_to ();
234
235   Translator_group * c = child_report;
236   while (c && c != me_report)
237     {
238       c= c->daddy_trans_;
239     }
240   
241   if (c == me_report)
242     set_translator (child_report);
243 }
244
245
246 /*
247   Retrieve all music (starting at HERE), until a music with length L >
248   0 is found.  From the precondition, we know that UNTIL is later than
249   the earliest event. Hence we know
250   
251   L >= (UNTIL - HERE)
252
253   so something that comes after this thing with L > 0 happens after
254
255   HERE + L >= HERE + (UNTIL - HERE) = UNTIL
256
257   Hence all events after the one with L>0 are uninteresting, so we
258   ignore them.
259   
260 */
261
262 SCM
263 Sequential_iterator::get_pending_events (Moment until) const
264 {
265   SCM s = SCM_EOL;
266   if (until <  pending_moment ())
267     return s;
268
269   Sequential_iterator * me =
270     dynamic_cast<Sequential_iterator*> (clone ());
271   while (me->ok ())
272     {
273       SCM nm = me->iter_->get_pending_events (until - me->here_mom_);
274       s = gh_append2 (nm, s);
275       
276       Moment m = 0;
277       for (SCM i = nm; gh_pair_p (i); i = ly_cdr (i))
278         {
279           Music *mus=unsmob_music (ly_car (i));
280           m = m >? (mus->get_length () - mus->start_mom ());
281         }
282       if (m > Moment (0))
283         break ;
284       else
285         me->next_element (false);
286     }
287
288   scm_gc_unprotect_object (me->self_scm());
289   return s;
290 }
291
292
293 /*
294   Skip events till UNTIL. We don't do any other side effects such as
295   descending to child iterator contexts, because they might depend on
296   \context specs and \translator changes being executed
297  */
298 void
299 Sequential_iterator::skip (Moment until)
300 {
301   while (ok ())
302     {
303       if (grace_fixups_ &&
304           grace_fixups_->start_ == here_mom_
305           && (grace_fixups_->start_ + grace_fixups_->length_
306               + Moment (Rational (0), grace_fixups_->grace_start_) == until))
307         {
308           /*
309             do the stuff/note/rest preceding a grace.
310            */
311           iter_->skip (iter_->music_get_length ());
312         }
313       else if (iter_->music_get_length () >= until - here_mom_)
314         iter_->skip (until - here_mom_ + iter_->music_start_mom ());
315
316       if (iter_->ok ())
317         return ; 
318
319       next_element (false);
320     }
321 }
322
323 void
324 Sequential_iterator::process (Moment until)
325 {
326   while (iter_)
327     {
328       if (grace_fixups_ &&
329           grace_fixups_->start_ == here_mom_
330           && (grace_fixups_->start_ + grace_fixups_->length_
331               + Moment (Rational (0), grace_fixups_->grace_start_) == until))
332         {
333           /*
334             do the stuff/note/rest preceding a grace.
335            */
336           iter_->process (iter_->music_get_length ());
337         }
338       else
339         iter_->process (until - here_mom_ + iter_->music_start_mom ());
340
341       /*
342         if the iter is still OK, there must be events left that have
343         
344           TIME > LEFT
345           
346       */
347       if (iter_->ok ())
348         return ;
349
350       descend_to_child ();
351       next_element (true);
352     }
353 }
354
355 Moment
356 Sequential_iterator::pending_moment () const
357 {
358   Moment cp = iter_->pending_moment ();
359
360   /*
361     Fix-up a grace note halfway in the music.
362   */
363   if (grace_fixups_ && here_mom_ == grace_fixups_->start_
364       && grace_fixups_->length_ + iter_->music_start_mom () == cp)
365     {
366       return here_mom_ + grace_fixups_->length_ + Moment (0, grace_fixups_->grace_start_);
367     }
368
369   /*
370     Fix-up a grace note at  the start of the music.
371   */
372   return cp + here_mom_ - iter_->music_start_mom ();
373 }
374
375
376 bool
377 Sequential_iterator::ok () const
378 {
379   return iter_;
380 }
381
382 Music_iterator*
383 Sequential_iterator::try_music_in_children (Music *m) const
384
385   return iter_ ? iter_->try_music (m) : 0;
386 }
387
388 IMPLEMENT_CTOR_CALLBACK (Sequential_iterator);
389
390 bool
391 Sequential_iterator::run_always () const
392 {
393   return iter_ ? iter_->run_always () : false; 
394 }