]> git.donarmstrong.com Git - lilypond.git/blob - lily/sequential-music-iterator.cc
release: 1.5.0
[lilypond.git] / lily / sequential-music-iterator.cc
1 /*
2   Sequential_music_iterator.cc -- implement Sequential_music_iterator
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8 #include "grace-iterator.hh"
9 #include "translator-group.hh"
10 #include "debug.hh"
11 #include "sequential-music-iterator.hh"
12 #include "music-list.hh"
13 #include "request-chord-iterator.hh"
14
15 /*
16   Invariant for the data structure.
17
18
19   if (gh_pair_p (cursor_))
20     iter_p_->music_l_ == unsmob_music (gh_car (cursor_))
21   else
22     iter_p_ == 0;
23
24   The length of musiclist from start to up to cursor_ (cursor_ not
25   including), is summed
26
27   here_mom_  = sum (length (musiclist [start ... cursor>))  %)  
28   
29  */
30
31
32 Sequential_music_iterator::Sequential_music_iterator ()
33 {
34   cursor_ = SCM_EOL;
35   here_mom_ = Moment (0);
36   grace_skips_ = 0;
37   iter_p_ =0;
38 }
39
40 Sequential_music_iterator::Sequential_music_iterator (Sequential_music_iterator const &src)
41   : Music_iterator (src)
42 {
43   grace_skips_ = src.grace_skips_;
44   cursor_ = src.cursor_;
45   here_mom_ = src.here_mom_;
46   if (src.iter_p_)
47     iter_p_ = src.iter_p_->clone ();
48   else
49     iter_p_ = 0;
50 }
51
52 Sequential_music_iterator::~Sequential_music_iterator ()
53 {
54   delete iter_p_;
55 }
56
57
58 Grace_skip *
59 get_grace_skips (SCM cursor)
60 {
61   Moment here (0);
62   Moment last (here);
63   Grace_skip *head = 0;
64   Grace_skip **tail = &head;
65   bool first = true; 
66
67   
68   for (; gh_pair_p (cursor); cursor = gh_cdr (cursor))
69     {
70       Music * mus = unsmob_music (gh_car (cursor));
71       Moment l =mus->length_mom ();
72       if (l.main_part_)
73         {
74           first = false;
75           last = here;
76           here += l;
77         }
78       else if(l.grace_mom_ && !first)
79         {
80           assert (!l.main_part_);
81           Grace_skip *p =new Grace_skip;
82           p->start_ = last;
83           p->length_ = (here - last).main_part_;
84           p->grace_length_ = l.grace_mom_;
85           p->next_ = 0;
86           *tail = p;
87           tail = &(*tail)->next_; 
88         }
89     }
90   return  head;
91 }
92
93 void
94 Sequential_music_iterator::construct_children ()
95 {
96   cursor_ = dynamic_cast<Music_sequence const*> (music_l ())->music_list ();
97
98   iter_p_ = gh_pair_p (cursor_) ?  get_iterator_p (unsmob_music (gh_car (cursor_))) : 0;
99   while (iter_p_ && !iter_p_->ok ())
100     {
101       next_element ();
102     }
103
104   grace_skips_ = get_grace_skips (cursor_);
105
106   here_mom_ = music_l ()->start_mom ();
107
108   /*
109     iter_p_->ok () is tautology, but what the heck.
110    */
111   if (iter_p_ && iter_p_->ok ()) 
112     descend_to_child ();
113 }
114
115
116 /*
117   maintain invariants: change cursor, iter and here_mom_ in one fell
118   swoop.
119 */
120 void
121 Sequential_music_iterator::next_element ()
122 {
123   Moment len =iter_p_->music_length_mom ();
124   Moment start  = iter_p_->music_start_mom ();
125   assert (!grace_skips_  || grace_skips_->start_ >= here_mom_);
126
127   if (len.main_part_ && grace_skips_ && grace_skips_->start_ == here_mom_)
128     {
129       Moment sk;
130       sk.main_part_ = grace_skips_->length_;
131       here_mom_ +=  sk;
132       here_mom_.grace_mom_ = - grace_skips_->grace_length_;
133
134       Grace_skip * n =grace_skips_->next_;
135       delete       grace_skips_;
136       grace_skips_ = n;
137     }
138   else if (len.grace_mom_)
139     {
140       here_mom_.grace_mom_ =0;
141     }
142   else
143     {
144       here_mom_ += len - start;
145     }
146   
147   delete iter_p_;
148   cursor_ = gh_cdr (cursor_);
149
150   if (gh_pair_p (cursor_))
151     iter_p_ = get_iterator_p (unsmob_music (gh_car (cursor_)));
152   else
153     iter_p_ = 0;
154 }
155
156 /*
157   move to context of child iterator if it is deeper down in the
158   hierarchy.
159   */
160
161 void
162 Sequential_music_iterator::descend_to_child ()
163 {
164   Translator_group  * child_report = child_report = iter_p_->report_to_l ();
165   Translator_group * me_report = report_to_l ();
166
167   if (dynamic_cast<Grace_iterator*> (iter_p_))
168     child_report = child_report->daddy_trans_l_;
169
170   Translator_group * c = child_report;
171   while (c && c != me_report)
172     {
173       c= c->daddy_trans_l_;
174     }
175   
176   if (c == me_report)
177     set_translator (child_report);
178 }
179
180
181 /*
182   Retrieve all music (starting at HERE), until a music with length L >
183   0 is found.  From the precondition, we know that UNTIL is later than
184   the earliest event. Hence we know
185   
186   L >= (UNTIL - HERE)
187
188   so something that comes after this thing with L > 0 happens after
189
190   HERE + L >= HERE + (UNTIL - HERE) = UNTIL
191
192   Hence all events after the one with L>0 are uninteresting, so we
193   ignore them.
194   
195 */
196
197 SCM
198 Sequential_music_iterator::get_music (Moment until)const
199 {
200   SCM s = SCM_EOL;
201   if (until <  pending_moment ())
202     return s;
203
204   Sequential_music_iterator * me =
205     dynamic_cast<Sequential_music_iterator*> (clone ());
206   while (me->ok ())
207     {
208       SCM nm = me->iter_p_->get_music (until - me->here_mom_);
209       s = gh_append2 (nm, s);
210       
211       Moment m = 0;
212       for (SCM i = nm; gh_pair_p (i); i = gh_cdr (i))
213         m = m >? unsmob_music (gh_car (i))->length_mom ();
214
215       if (m > Moment (0))
216         break ;
217       else
218         me->next_element ();
219     }
220   delete me;
221   
222   return s;
223 }
224 /*
225   Skip events till UNTIL. We don't do any other side effects such as
226   descending to child iterator contexts, because they might depend on
227   \context specs and \translator changes being executed
228     
229  */
230 void
231 Sequential_music_iterator::skip (Moment until)
232 {
233   while (ok ())
234     {
235       Moment l =iter_p_->music_length_mom ();
236       if (l >= until - here_mom_)
237         iter_p_->skip (until - here_mom_);
238
239       if (iter_p_->ok ())
240         return ; 
241
242       next_element ();
243     }
244 }
245
246 void
247 Sequential_music_iterator::process (Moment until)
248 {
249   while (iter_p_)
250     {
251       if (grace_skips_ &&
252           grace_skips_->start_ == here_mom_
253           && (grace_skips_->start_ + grace_skips_->length_).main_part_ ==
254           until.main_part_)
255         {
256           /*
257             do the stuff/note/rest preceding a grace.
258            */
259           Moment u = until;
260           u.grace_mom_ = 0;
261           iter_p_->process (u - here_mom_);
262         }
263       else
264         iter_p_->process (until - here_mom_ + iter_p_->music_start_mom ());
265
266       /*
267         if the iter is still OK, there must be events left that have
268         
269           TIME > LEFT
270           
271       */
272       if (iter_p_->ok ())
273         return ;
274
275       descend_to_child ();
276       next_element ();
277     }
278 }
279
280 Moment
281 Sequential_music_iterator::pending_moment () const
282 {
283   Moment cp = iter_p_->pending_moment ();
284
285   if (grace_skips_
286       && here_mom_ == grace_skips_->start_
287       && cp.main_part_ >=  grace_skips_->length_)
288     {
289       cp += here_mom_ ;
290       cp.grace_mom_ = - grace_skips_->grace_length_;
291       return cp;
292     }
293   else
294     return cp + here_mom_ - iter_p_->music_start_mom ();
295 }
296
297
298 bool
299 Sequential_music_iterator::ok () const
300 {
301   return iter_p_;
302 }
303
304 Music_iterator*
305 Sequential_music_iterator::try_music_in_children (Music *m) const
306
307   return iter_p_ ? iter_p_->try_music (m) : 0;
308 }
309 IMPLEMENT_CTOR_CALLBACK (Sequential_music_iterator);