]> git.donarmstrong.com Git - lilypond.git/blob - lily/sequential-music-iterator.cc
bfeb3cd9254c92f01d42cf0d7fbb5971907a2e86
[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   if (iter_p_)
36     {
37 #if 0
38       if (iter_p_->ok () )
39         music_l_->origin ()->warning (_ ("Must stop before this music ends"));
40 #endif
41       delete iter_p_;
42     }
43 }
44
45 void
46 Sequential_music_iterator::construct_children()
47 {
48   cursor_ = dynamic_cast<Music_sequence const*> (music_l_)->music_list ();
49   
50   while (gh_pair_p (cursor_ ))
51     {
52       iter_p_ =  get_iterator_p (unsmob_music (gh_car (cursor_)));
53       
54       if (iter_p_->ok()) 
55         {
56           descend_to_child ();
57           return;
58         }
59
60       delete iter_p_ ;
61       iter_p_ =0;
62       cursor_ = gh_cdr (cursor_);
63     }
64 }
65  /*
66   move to context of child iterator if it is deeper down in the
67   hierarchy.
68   */
69
70 void
71 Sequential_music_iterator::descend_to_child ()
72 {
73        
74   Translator_group  * child_report = child_report = iter_p_->report_to_l ();
75   if (dynamic_cast<Grace_iterator*> (iter_p_))
76     child_report = child_report->daddy_trans_l_;
77     
78   if (report_to_l()->depth_i () < child_report->depth_i ())
79     set_translator (child_report);
80 }
81
82
83 /*
84   
85   
86   Hier staat in feite: haal alle muziek op (startend op tijd HERE) tot
87   je iets met lengte L > 0 tegenkomt.  Aangezien de preconditie is dat
88   UNTIL het eerstvolgende event is, weet je (per definitie)
89
90   L >= (UNTIL - HERE)
91
92   en iets wat hierna komt (op tijd T) komt dus na tijd
93
94   HERE + L >= HERE + (UNTIL - HERE) = UNTIL
95
96   Dus als je een L>0 tegenkomt, wil je de rest niet meer. Aangezien
97   alles wat tot nu toe hebt gespaard op HERE begint, is dat precies wat
98   je nodig hebt.
99
100   Misschien kan je deze comment erbij stoppen, en moeten we de
101   eigenschappen van het muziek datatype wat formaliseren, zodat deze
102   redenering helderder is.
103 */
104
105 SCM
106 Sequential_music_iterator::get_music (Moment until)const
107 {
108   SCM s = SCM_EOL;
109   if (until <  pending_moment ())
110     return s;
111
112   SCM curs = cursor_;
113   Music_iterator * iter = iter_p_->clone ();
114   while (1)
115     {
116       SCM nm = iter->get_music (until - here_mom_);
117       s = gh_append2 (nm, s);
118       
119       Moment m = 0;
120       for (SCM i = nm; gh_pair_p(i); i = gh_cdr (i))
121         m = m >? unsmob_music (gh_car (i))->length_mom ();
122
123       delete iter;
124
125       curs = gh_cdr (curs);
126
127       if (!gh_pair_p (curs) ||  m > Moment (0))
128         return s;
129       else
130         {
131           iter = get_iterator_p (unsmob_music (gh_car (curs)));
132         }      
133     }
134   return s;
135 }
136 /*
137   Skip events till UNTIL. We don't do any other side effects (such as
138   moving descending to child iterator contexts, because they might
139   depend on \context specs and \translator changes being executed
140     
141  */
142 void
143 Sequential_music_iterator::skip (Moment until)
144 {
145   SCM curs = cursor_;
146   while (1)
147     {
148       Moment l =iter_p_->music_length_mom ();
149       if (l >= until - here_mom_)
150         iter_p_->skip (until - here_mom_);
151
152       if (iter_p_->ok ())
153         return ; 
154       
155       here_mom_ = here_mom_ + l;
156       delete iter_p_;
157       iter_p_ =0;
158
159       curs = gh_cdr (curs);
160
161       if (!gh_pair_p (curs))
162         return ;
163       else
164         iter_p_ = get_iterator_p (unsmob_music (gh_car (curs)));
165     }
166 }
167
168 void
169 Sequential_music_iterator::process (Moment until)
170 {
171   while (1)
172     {
173       iter_p_->process (until - here_mom_);
174
175       /*
176         if the iter is still OK, there must be events left that have
177         
178           TIME > LEFT
179           
180       */
181       if (iter_p_->ok ())
182         return ;
183
184       here_mom_ += iter_p_->music_length_mom ();
185
186       descend_to_child ();
187       delete iter_p_;
188       iter_p_ =0;
189
190       cursor_ = gh_cdr (cursor_);
191
192       if (!gh_pair_p (cursor_))
193         return ;
194       else
195         {
196           delete iter_p_;
197           iter_p_ = get_iterator_p (unsmob_music (gh_car (cursor_)));
198         }      
199     }
200
201 }
202
203 Moment
204 Sequential_music_iterator::pending_moment() const
205 {
206   return iter_p_->pending_moment() + here_mom_;
207 }
208
209
210 bool
211 Sequential_music_iterator::ok() const
212 {
213   return iter_p_;
214 }
215
216 Music_iterator*
217 Sequential_music_iterator::try_music_in_children (Music *m) const
218
219   return iter_p_ ? iter_p_->try_music (m) : 0;
220 }