]> git.donarmstrong.com Git - lilypond.git/blob - lily/sequential-music-iterator.cc
de480844e5b105677b42830671a8caa56cf1f37c
[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--2000 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 Sequential_music_iterator::Sequential_music_iterator ()
16 {
17   cursor_ = 0;
18   here_mom_ = 0;
19   iter_p_ =0;
20 }
21
22 Sequential_music_iterator::Sequential_music_iterator (Sequential_music_iterator const &src)
23   : Music_iterator (src)
24 {
25   cursor_ = src.cursor_;
26   here_mom_ = src.here_mom_;
27   if (src.iter_p_)
28     iter_p_ = src.iter_p_->clone ();
29   else
30     iter_p_ = 0;
31 }
32
33 Sequential_music_iterator::~Sequential_music_iterator()
34 {
35   delete iter_p_;
36 }
37
38 void
39 Sequential_music_iterator::construct_children()
40 {
41   cursor_ = dynamic_cast<Music_sequence const*> (music_l_)->music_list ();
42   
43   while (gh_pair_p (cursor_ ))
44     {
45       iter_p_ =  get_iterator_p (unsmob_music (gh_car (cursor_)));
46       
47       if (iter_p_->ok()) 
48         {
49           descend_to_child ();
50           return;
51         }
52
53       delete iter_p_ ;
54       iter_p_ =0;
55       cursor_ = gh_cdr (cursor_);
56     }
57 }
58  /*
59   move to context of child iterator if it is deeper down in the
60   hierarchy.
61   */
62
63 void
64 Sequential_music_iterator::descend_to_child ()
65 {
66        
67   Translator_group  * child_report = child_report = iter_p_->report_to_l ();
68   if (dynamic_cast<Grace_iterator*> (iter_p_))
69     child_report = child_report->daddy_trans_l_;
70     
71   if (report_to_l()->depth_i () < child_report->depth_i ())
72     set_translator (child_report);
73 }
74
75
76 /*
77   Retrieve all music (starting at HERE), until a music with length L >
78   0 is found.  From the precondition, we know that UNTIL is later than
79   the earliest event. Hence we know
80   
81   L >= (UNTIL - HERE)
82
83   so something that comes after this thing with L > 0 happens after
84
85   HERE + L >= HERE + (UNTIL - HERE) = UNTIL
86
87   Hence all events after the one with L>0 are uninteresting, so we
88   ignore them.
89   
90 */
91
92 SCM
93 Sequential_music_iterator::get_music (Moment until)const
94 {
95   SCM s = SCM_EOL;
96   if (until <  pending_moment ())
97     return s;
98
99   SCM curs = cursor_;
100   Music_iterator * iter = iter_p_->clone ();
101   while (1)
102     {
103       SCM nm = iter->get_music (until - here_mom_);
104       s = gh_append2 (nm, s);
105       
106       Moment m = 0;
107       for (SCM i = nm; gh_pair_p(i); i = gh_cdr (i))
108         m = m >? unsmob_music (gh_car (i))->length_mom ();
109
110       delete iter;
111
112       curs = gh_cdr (curs);
113
114       if (!gh_pair_p (curs) ||  m > Moment (0))
115         return s;
116       else
117         {
118           iter = get_iterator_p (unsmob_music (gh_car (curs)));
119         }      
120     }
121   return s;
122 }
123 /*
124   Skip events till UNTIL. We don't do any other side effects (such as
125   moving descending to child iterator contexts, because they might
126   depend on \context specs and \translator changes being executed
127     
128  */
129 void
130 Sequential_music_iterator::skip (Moment until)
131 {
132   while (1)
133     {
134       Moment l =iter_p_->music_length_mom ();
135       if (l >= until - here_mom_)
136         iter_p_->skip (until - here_mom_);
137
138       if (iter_p_->ok ())
139         return ; 
140       
141       here_mom_ = here_mom_ + l;
142       delete iter_p_;
143       iter_p_ =0;
144
145       cursor_ = gh_cdr (cursor_);
146
147       if (!gh_pair_p (cursor_))
148         return ;
149       else
150         iter_p_ = get_iterator_p (unsmob_music (gh_car (cursor_)));
151     }
152 }
153
154 void
155 Sequential_music_iterator::process (Moment until)
156 {
157   while (1)
158     {
159       iter_p_->process (until - here_mom_);
160
161       /*
162         if the iter is still OK, there must be events left that have
163         
164           TIME > LEFT
165           
166       */
167       if (iter_p_->ok ())
168         return ;
169
170       here_mom_ += iter_p_->music_length_mom ();
171
172       descend_to_child ();
173       delete iter_p_;
174       iter_p_ =0;
175
176       cursor_ = gh_cdr (cursor_);
177
178       if (!gh_pair_p (cursor_))
179         return ;
180       else
181         {
182           delete iter_p_;
183           iter_p_ = get_iterator_p (unsmob_music (gh_car (cursor_)));
184         }      
185     }
186
187 }
188
189 Moment
190 Sequential_music_iterator::pending_moment() const
191 {
192   return iter_p_->pending_moment() + here_mom_;
193 }
194
195
196 bool
197 Sequential_music_iterator::ok() const
198 {
199   return iter_p_;
200 }
201
202 Music_iterator*
203 Sequential_music_iterator::try_music_in_children (Music *m) const
204
205   return iter_p_ ? iter_p_->try_music (m) : 0;
206 }