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"
16 Invariant for the data structure.
19 if (gh_pair_p (cursor_))
20 iter_p_->music_l_ == unsmob_music (gh_car (cursor_))
24 The length of musiclist from start to up to cursor_ (cursor_ not
27 here_mom_ = sum (length (musiclist [start ... cursor>)) %)
30 Sequential_music_iterator::Sequential_music_iterator ()
33 here_mom_ = Moment (0);
38 Sequential_music_iterator::Sequential_music_iterator (Sequential_music_iterator const &src)
39 : Music_iterator (src)
41 grace_skips_ = src.grace_skips_;
42 cursor_ = src.cursor_;
43 here_mom_ = src.here_mom_;
45 iter_p_ = src.iter_p_->clone ();
50 Sequential_music_iterator::~Sequential_music_iterator ()
57 get_grace_skips (SCM cursor)
62 Grace_skip **tail = &head;
64 for (; gh_pair_p (cursor); cursor = gh_cdr (cursor))
66 Music * mus = unsmob_music (gh_car (cursor));
67 Moment l =mus->length_mom ();
68 Moment s = mus->start_mom ();
70 if (s.grace_part_ && last >= Moment (0))
72 Grace_skip *p =new Grace_skip;
74 p->length_ = (here - last).main_part_;
75 p->grace_start_ = s.grace_part_;
78 tail = &(*tail)->next_;
83 l.grace_part_ = Rational (0);
92 Sequential_music_iterator::construct_children ()
94 cursor_ = dynamic_cast<Music_sequence const*> (music_l ())->music_list ();
96 iter_p_ = gh_pair_p (cursor_) ? get_iterator_p (unsmob_music (gh_car (cursor_))) : 0;
97 while (iter_p_ && !iter_p_->ok ())
102 grace_skips_ = get_grace_skips (cursor_);
104 here_mom_ = music_l ()->start_mom ();
107 iter_p_->ok () is tautology, but what the heck.
109 if (iter_p_ && iter_p_->ok ())
115 maintain invariants: change cursor, iter and here_mom_ in one fell
119 Sequential_music_iterator::next_element ()
121 Moment len =iter_p_->music_length_mom ();
122 Moment start = iter_p_->music_start_mom ();
123 assert (!grace_skips_ || grace_skips_->start_ >= here_mom_);
125 if (len.main_part_ && grace_skips_ && grace_skips_->start_ == here_mom_)
128 sk.main_part_ = grace_skips_->length_;
130 here_mom_.grace_part_ = grace_skips_->grace_start_;
132 Grace_skip * n =grace_skips_->next_;
136 else if (len.grace_part_ && !len.main_part_)
138 here_mom_.grace_part_ =0;
143 !len.grace_part_ || len.main_part_
145 We skip over a big chunk (mainpart != 0). Any starting graces
146 in that chunk are compensated by subtracting START.
149 here_mom_ += len - start;
153 cursor_ = gh_cdr (cursor_);
155 if (gh_pair_p (cursor_))
156 iter_p_ = get_iterator_p (unsmob_music (gh_car (cursor_)));
162 move to context of child iterator if it is deeper down in the
166 Sequential_music_iterator::descend_to_child ()
168 Translator_group * child_report = child_report = iter_p_->report_to_l ();
169 Translator_group * me_report = report_to_l ();
171 Translator_group * c = child_report;
172 while (c && c != me_report)
174 c= c->daddy_trans_l_;
178 set_translator (child_report);
183 Retrieve all music (starting at HERE), until a music with length L >
184 0 is found. From the precondition, we know that UNTIL is later than
185 the earliest event. Hence we know
189 so something that comes after this thing with L > 0 happens after
191 HERE + L >= HERE + (UNTIL - HERE) = UNTIL
193 Hence all events after the one with L>0 are uninteresting, so we
199 Sequential_music_iterator::get_music (Moment until)const
202 if (until < pending_moment ())
205 Sequential_music_iterator * me =
206 dynamic_cast<Sequential_music_iterator*> (clone ());
209 SCM nm = me->iter_p_->get_music (until - me->here_mom_);
210 s = gh_append2 (nm, s);
213 for (SCM i = nm; gh_pair_p (i); i = gh_cdr (i))
214 m = m >? unsmob_music (gh_car (i))->length_mom ();
226 Skip events till UNTIL. We don't do any other side effects such as
227 descending to child iterator contexts, because they might depend on
228 \context specs and \translator changes being executed
232 Sequential_music_iterator::skip (Moment until)
236 Moment l =iter_p_->music_length_mom ();
237 if (l >= until - here_mom_)
238 iter_p_->skip (until - here_mom_);
248 Sequential_music_iterator::process (Moment until)
253 grace_skips_->start_ == here_mom_
254 && (grace_skips_->start_ + grace_skips_->length_).main_part_ ==
258 do the stuff/note/rest preceding a grace.
262 iter_p_->process (u - here_mom_);
265 iter_p_->process (until - here_mom_ + iter_p_->music_start_mom ());
268 if the iter is still OK, there must be events left that have
282 Sequential_music_iterator::pending_moment () const
284 Moment cp = iter_p_->pending_moment ();
287 Fix-up a grace note halfway in the music.
289 if (grace_skips_ && here_mom_ == grace_skips_->start_
290 && cp.main_part_ >= grace_skips_->length_)
293 cp.grace_part_ = grace_skips_->grace_start_;
299 Fix-up a grace note at the start of the music.
301 return cp + here_mom_ - iter_p_->music_start_mom ();
306 Sequential_music_iterator::ok () const
312 Sequential_music_iterator::try_music_in_children (Music *m) const
314 return iter_p_ ? iter_p_->try_music (m) : 0;
316 IMPLEMENT_CTOR_CALLBACK (Sequential_music_iterator);