2 Sequential_music_iterator.cc -- implement Sequential_music_iterator
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 #include "translator-group.hh"
11 #include "sequential-music-iterator.hh"
12 #include "music-list.hh"
13 #include "request-chord-iterator.hh"
18 TODO: handling of grace notes is excuisite pain. This handling
19 should be formally specified and then the implementation verified.
24 Invariant for the data structure.
27 if (gh_pair_p (cursor_))
28 iter_p_->music_l_ == unsmob_music (gh_car (cursor_))
32 The length of musiclist from start to up to cursor_ (cursor_ not
35 here_mom_ = sum (length (musiclist [start ... cursor>)) %)
38 Sequential_music_iterator::Sequential_music_iterator ()
41 here_mom_ = Moment (0);
46 Sequential_music_iterator::Sequential_music_iterator (Sequential_music_iterator const &src)
47 : Music_iterator (src)
49 grace_skips_ = src.grace_skips_;
50 cursor_ = src.cursor_;
51 here_mom_ = src.here_mom_;
53 iter_p_ = src.iter_p_->clone ();
58 Sequential_music_iterator::~Sequential_music_iterator ()
67 if (start_music.grace)
68 here.grace -= start_music.grace
76 get_grace_skips (SCM cursor)
81 Grace_skip **tail = &head;
83 for (; gh_pair_p (cursor); cursor = gh_cdr (cursor))
85 Music * mus = unsmob_music (gh_car (cursor));
86 Moment l =mus->length_mom ();
87 Moment s = mus->start_mom ();
91 if (last != Moment (-1))
93 Grace_skip *p =new Grace_skip;
95 p->length_ = (here - last).main_part_;
96 p->grace_start_ = s.grace_part_;
99 tail = &(*tail)->next_;
102 here.grace_part_ = s.grace_part_;
115 Sequential_music_iterator::construct_children ()
117 cursor_ = dynamic_cast<Music_sequence const*> (music_l ())->music_list ();
119 iter_p_ = gh_pair_p (cursor_) ? get_iterator_p (unsmob_music (gh_car (cursor_))) : 0;
120 while (iter_p_ && !iter_p_->ok ())
125 grace_skips_ = get_grace_skips (cursor_);
127 here_mom_ = music_l ()->start_mom ();
130 iter_p_->ok () is tautology, but what the heck.
132 if (iter_p_ && iter_p_->ok ())
138 maintain invariants: change cursor, iter and here_mom_ in one fell
142 Sequential_music_iterator::next_element ()
144 Moment len =iter_p_->music_length_mom ();
145 Moment start = iter_p_->music_start_mom ();
146 assert (!grace_skips_ || grace_skips_->start_ >= here_mom_);
148 if (len.main_part_ && grace_skips_ &&
149 grace_skips_->start_.main_part_ == here_mom_.main_part_)
152 sk.main_part_ = grace_skips_->length_;
154 here_mom_.grace_part_ = grace_skips_->grace_start_;
156 Grace_skip * n =grace_skips_->next_;
160 else if (len.grace_part_ && !len.main_part_)
162 here_mom_.grace_part_ =0;
167 !len.grace_part_ || len.main_part_
169 We skip over a big chunk (mainpart != 0). Any starting graces
170 in that chunk are compensated by subtracting START.
173 here_mom_ += len - start;
177 cursor_ = gh_cdr (cursor_);
179 if (gh_pair_p (cursor_))
180 iter_p_ = get_iterator_p (unsmob_music (gh_car (cursor_)));
186 move to context of child iterator if it is deeper down in the
190 Sequential_music_iterator::descend_to_child ()
192 Translator_group * child_report = child_report = iter_p_->report_to_l ();
193 Translator_group * me_report = report_to_l ();
195 Translator_group * c = child_report;
196 while (c && c != me_report)
198 c= c->daddy_trans_l_;
202 set_translator (child_report);
207 Retrieve all music (starting at HERE), until a music with length L >
208 0 is found. From the precondition, we know that UNTIL is later than
209 the earliest event. Hence we know
213 so something that comes after this thing with L > 0 happens after
215 HERE + L >= HERE + (UNTIL - HERE) = UNTIL
217 Hence all events after the one with L>0 are uninteresting, so we
223 Sequential_music_iterator::get_music (Moment until)const
226 if (until < pending_moment ())
229 Sequential_music_iterator * me =
230 dynamic_cast<Sequential_music_iterator*> (clone ());
233 SCM nm = me->iter_p_->get_music (until - me->here_mom_);
234 s = gh_append2 (nm, s);
237 for (SCM i = nm; gh_pair_p (i); i = gh_cdr (i))
238 m = m >? unsmob_music (gh_car (i))->length_mom ();
250 Skip events till UNTIL. We don't do any other side effects such as
251 descending to child iterator contexts, because they might depend on
252 \context specs and \translator changes being executed
256 Sequential_music_iterator::skip (Moment until)
260 Moment l =iter_p_->music_length_mom ();
261 if (l >= until - here_mom_)
262 iter_p_->skip (until - here_mom_);
272 Sequential_music_iterator::process (Moment until)
277 grace_skips_->start_ == here_mom_
278 && (grace_skips_->start_ + grace_skips_->length_).main_part_ ==
282 do the stuff/note/rest preceding a grace.
286 iter_p_->process (u - here_mom_);
289 iter_p_->process (until - here_mom_ + iter_p_->music_start_mom ());
292 if the iter is still OK, there must be events left that have
306 Sequential_music_iterator::pending_moment () const
308 Moment cp = iter_p_->pending_moment ();
311 Fix-up a grace note halfway in the music.
313 if (grace_skips_ && here_mom_ == grace_skips_->start_
314 && cp.main_part_ >= grace_skips_->length_)
317 cp.grace_part_ = grace_skips_->grace_start_;
323 Fix-up a grace note at the start of the music.
325 return cp + here_mom_ - iter_p_->music_start_mom ();
330 Sequential_music_iterator::ok () const
336 Sequential_music_iterator::try_music_in_children (Music *m) const
338 return iter_p_ ? iter_p_->try_music (m) : 0;
340 IMPLEMENT_CTOR_CALLBACK (Sequential_music_iterator);