]> git.donarmstrong.com Git - lilypond.git/blob - lily/sequential-iterator.cc
* lily/sequential-iterator.cc (run_always): implement run_always().
[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 Grace_fixup *
89 get_grace_fixups (SCM cursor)
90 {
91   Moment here;
92   Moment last (-1);
93   Grace_fixup *head = 0;
94   Grace_fixup **tail = &head;
95
96   for (; gh_pair_p (cursor); cursor = ly_cdr (cursor))
97     {
98       Music * mus = unsmob_music (ly_car (cursor));
99       Moment s = mus->start_mom ();
100       Moment l =mus->get_length () - s;
101
102       if (s.grace_part_)
103         {
104           if (last != Moment (-1))
105             {
106               Grace_fixup *p =new Grace_fixup;
107               p->start_ = last;
108               p->length_ = here - last;
109               p->grace_start_ = s.grace_part_;
110               p->next_ = 0;
111               *tail = p;
112               tail = &(*tail)->next_; 
113             }
114
115           here.grace_part_ = s.grace_part_;
116         }
117       
118       if (l.to_bool())
119         {
120           last = here;
121           here += l;
122         }
123     }
124   return  head;
125 }
126
127 Grace_fixup *
128 copy_grace_fixups (Grace_fixup* src)
129 {
130   Grace_fixup * head = 0;
131   Grace_fixup **dest = &head;
132
133   while (src)
134     {
135       *dest = new Grace_fixup (*src);
136       dest = & (*dest)->next_;
137       src = src ->next_;
138     }
139
140   return head;
141 }
142
143 void
144 Sequential_iterator::construct_children ()
145 {
146   list_ = get_music_list ();
147   cursor_ = list_; 
148
149   iter_ = 0;
150   if (gh_pair_p (cursor_))
151     {
152       Music *m  =unsmob_music (ly_car (cursor_));
153       iter_ = unsmob_iterator (get_iterator (m));
154     }
155   
156   while (iter_ && !iter_->ok ())
157     {
158       next_element (true);
159     }
160
161   here_mom_ = get_music ()->start_mom ();
162   grace_fixups_ = get_grace_fixups (cursor_);
163
164   /*
165     iter_->ok () is tautology, but what the heck.
166    */
167   if (iter_ && iter_->ok ()) 
168     descend_to_child ();
169 }
170
171
172 /*
173   maintain invariants: change cursor, iter and here_mom_ in one fell
174   swoop.
175 */
176 void
177 Sequential_iterator::next_element (bool)
178 {
179   Moment len =iter_->music_get_length () - iter_->music_start_mom ();
180   assert (!grace_fixups_  || grace_fixups_->start_ >= here_mom_);
181   
182   if (len.main_part_ && grace_fixups_ &&
183       grace_fixups_->start_ == here_mom_)
184     {
185       here_mom_ += grace_fixups_->length_;
186       here_mom_.grace_part_ += grace_fixups_->grace_start_;
187
188       Grace_fixup * n =grace_fixups_->next_;
189       delete grace_fixups_;
190       grace_fixups_ = n;
191     }
192   else if (len.grace_part_ && !len.main_part_)
193     {
194       here_mom_.grace_part_ =0;
195     }
196   else
197     {
198       /*
199         !len.grace_part_ || len.main_part_
200
201         We skip over a big chunk (mainpart != 0). Any starting graces
202         in that chunk should be in len.grace_part_
203
204       */
205       here_mom_ += len;
206     }
207   
208   cursor_ = ly_cdr (cursor_);
209
210   iter_->quit();
211   if (gh_pair_p (cursor_))
212     iter_ = unsmob_iterator (get_iterator (unsmob_music (ly_car (cursor_))));
213   else
214     iter_ = 0;
215 }
216
217 /*
218   move to context of child iterator if it is deeper down in the
219   hierarchy.
220   */
221 void
222 Sequential_iterator::descend_to_child ()
223 {
224   Translator_group  * child_report = child_report = iter_->report_to ();
225   Translator_group * me_report = report_to ();
226
227   Translator_group * c = child_report;
228   while (c && c != me_report)
229     {
230       c= c->daddy_trans_;
231     }
232   
233   if (c == me_report)
234     set_translator (child_report);
235 }
236
237
238 /*
239   Retrieve all music (starting at HERE), until a music with length L >
240   0 is found.  From the precondition, we know that UNTIL is later than
241   the earliest event. Hence we know
242   
243   L >= (UNTIL - HERE)
244
245   so something that comes after this thing with L > 0 happens after
246
247   HERE + L >= HERE + (UNTIL - HERE) = UNTIL
248
249   Hence all events after the one with L>0 are uninteresting, so we
250   ignore them.
251   
252 */
253
254 SCM
255 Sequential_iterator::get_pending_events (Moment until) const
256 {
257   SCM s = SCM_EOL;
258   if (until <  pending_moment ())
259     return s;
260
261   Sequential_iterator * me =
262     dynamic_cast<Sequential_iterator*> (clone ());
263   while (me->ok ())
264     {
265       SCM nm = me->iter_->get_pending_events (until - me->here_mom_);
266       s = gh_append2 (nm, s);
267       
268       Moment m = 0;
269       for (SCM i = nm; gh_pair_p (i); i = ly_cdr (i))
270         {
271           Music *mus=unsmob_music (ly_car (i));
272           m = m >? (mus->get_length () - mus->start_mom ());
273         }
274       if (m > Moment (0))
275         break ;
276       else
277         me->next_element (false);
278     }
279
280   scm_gc_unprotect_object (me->self_scm());
281   return s;
282 }
283
284
285 /*
286   Skip events till UNTIL. We don't do any other side effects such as
287   descending to child iterator contexts, because they might depend on
288   \context specs and \translator changes being executed
289  */
290 void
291 Sequential_iterator::skip (Moment until)
292 {
293   while (ok ())
294     {
295       if (grace_fixups_ &&
296           grace_fixups_->start_ == here_mom_
297           && (grace_fixups_->start_ + grace_fixups_->length_
298               + Moment (Rational (0), grace_fixups_->grace_start_) == until))
299         {
300           /*
301             do the stuff/note/rest preceding a grace.
302            */
303           iter_->skip (iter_->music_get_length ());
304         }
305       else if (iter_->music_get_length () >= until - here_mom_)
306         iter_->skip (until - here_mom_ + iter_->music_start_mom ());
307
308       if (iter_->ok ())
309         return ; 
310
311       next_element (false);
312     }
313 }
314
315 void
316 Sequential_iterator::process (Moment until)
317 {
318   while (iter_)
319     {
320       if (grace_fixups_ &&
321           grace_fixups_->start_ == here_mom_
322           && (grace_fixups_->start_ + grace_fixups_->length_
323               + Moment (Rational (0), grace_fixups_->grace_start_) == until))
324         {
325           /*
326             do the stuff/note/rest preceding a grace.
327            */
328           iter_->process (iter_->music_get_length ());
329         }
330       else
331         iter_->process (until - here_mom_ + iter_->music_start_mom ());
332
333       /*
334         if the iter is still OK, there must be events left that have
335         
336           TIME > LEFT
337           
338       */
339       if (iter_->ok ())
340         return ;
341
342       descend_to_child ();
343       next_element (true);
344     }
345 }
346
347 Moment
348 Sequential_iterator::pending_moment () const
349 {
350   Moment cp = iter_->pending_moment ();
351
352   /*
353     Fix-up a grace note halfway in the music.
354   */
355   if (grace_fixups_ && here_mom_ == grace_fixups_->start_
356       && grace_fixups_->length_ + iter_->music_start_mom () == cp)
357     {
358       return here_mom_ + grace_fixups_->length_ + Moment (0, grace_fixups_->grace_start_);
359     }
360
361   /*
362     Fix-up a grace note at  the start of the music.
363   */
364   return cp + here_mom_ - iter_->music_start_mom ();
365 }
366
367
368 bool
369 Sequential_iterator::ok () const
370 {
371   return iter_;
372 }
373
374 Music_iterator*
375 Sequential_iterator::try_music_in_children (Music *m) const
376
377   return iter_ ? iter_->try_music (m) : 0;
378 }
379
380 IMPLEMENT_CTOR_CALLBACK (Sequential_iterator);
381
382 bool
383 Sequential_iterator::run_always () const
384 {
385   return iter_ ? iter_->run_always () : false; 
386 }