]> git.donarmstrong.com Git - lilypond.git/blob - lily/new-part-combine-iterator.cc
* ly/engraver-init.ly (AncientRemoveEmptyStaffContext): move
[lilypond.git] / lily / new-part-combine-iterator.cc
1 /*   
2   new-part-combine-music-iterator.cc -- implement New_pc_iterator
3
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 2004 Han-Wen Nienhuys
7  */
8
9 #include "part-combine-music-iterator.hh"
10 #include "translator-group.hh"
11 #include "event.hh"
12 #include "music-sequence.hh"
13 #include "lily-guile.hh"
14 #include "warn.hh"
15 #include "music-iterator.hh"
16 #include "interpretation-context-handle.hh"
17
18 class New_pc_iterator : public Music_iterator
19 {
20 public:
21   VIRTUAL_COPY_CONS (Music_iterator);
22   New_pc_iterator ();
23
24   DECLARE_SCHEME_CALLBACK(constructor, ()); 
25 protected:
26   virtual void derived_substitute (Translator_group*f, Translator_group*t) ;
27   virtual void derived_mark () const;
28   New_pc_iterator (New_pc_iterator const &);
29
30   virtual void construct_children ();
31   virtual Moment pending_moment () const;
32   virtual void do_quit(); 
33   virtual void process (Moment);
34
35   virtual SCM get_pending_events (Moment)const;
36   virtual Music_iterator *try_music_in_children (Music *) const;
37
38   virtual bool ok () const;
39
40 private:
41   Music_iterator * first_iter_;
42   Music_iterator * second_iter_;
43   bool is_shared_ ;
44   SCM split_list_;
45
46   Interpretation_context_handle one_;
47   Interpretation_context_handle two_;
48   Interpretation_context_handle null_;
49   Interpretation_context_handle shared_;
50
51   void chords_together ();
52   void apart ();
53   void solo1 ();
54   void solo2 ();
55   void unisono ();
56 };
57
58
59 New_pc_iterator::New_pc_iterator ()
60 {
61   is_shared_  =false;
62   first_iter_ = 0;
63   second_iter_ = 0;
64   split_list_ = SCM_EOL;
65 }
66
67 void
68 New_pc_iterator::derived_mark () const
69 {
70   if (first_iter_)
71     scm_gc_mark (first_iter_->self_scm());
72   if (second_iter_)
73     scm_gc_mark(second_iter_->self_scm());
74 }
75
76 void
77 New_pc_iterator::derived_substitute (Translator_group*f,
78                                      Translator_group*t)
79 {
80   if (first_iter_)
81     first_iter_->substitute_outlet (f,t);
82   if (second_iter_)
83     second_iter_->substitute_outlet (f,t);
84 }
85
86 void
87 New_pc_iterator::do_quit ()
88 {
89   if (first_iter_)
90     first_iter_->quit();
91   if (second_iter_)
92     second_iter_->quit();
93
94   one_ .set_translator (0);
95   two_.set_translator (0);
96   shared_.set_translator (0);
97 }
98
99 New_pc_iterator::New_pc_iterator (New_pc_iterator const &src)
100   : Music_iterator (src)
101 {
102   first_iter_ = 0;
103   second_iter_ = 0;
104
105   if(src.first_iter_)
106     first_iter_ = src.first_iter_->clone ();
107   if (src.second_iter_)
108     second_iter_ = src.second_iter_->clone ();
109
110   split_list_ = src.split_list_;
111   
112   if (first_iter_)
113     scm_gc_unprotect_object (first_iter_->self_scm());
114   if (second_iter_)
115     scm_gc_unprotect_object (second_iter_->self_scm());
116 }
117
118 Moment
119 New_pc_iterator::pending_moment () const
120 {
121   Moment p;
122   p.set_infinite (1);
123   if (first_iter_->ok ())
124     p = p <? first_iter_->pending_moment ();
125
126   if (second_iter_->ok ())
127     p = p <? second_iter_->pending_moment ();
128   return p;
129 }
130
131 bool
132 New_pc_iterator::ok () const
133 {
134   return first_iter_->ok () || second_iter_->ok ();
135 }
136
137 void
138 New_pc_iterator::chords_together ()
139 {
140   first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
141   first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
142   second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ());
143   second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
144 }
145
146
147 void
148 New_pc_iterator::solo1 ()
149 {
150   first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
151   first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
152
153   second_iter_->substitute_outlet (two_.report_to (), null_.report_to ());
154   second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
155 }
156
157 void
158 New_pc_iterator::unisono ()
159 {
160   /*
161     like solo1, but should set a2 string.
162    */
163   first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
164   first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
165
166   second_iter_->substitute_outlet (two_.report_to (), null_.report_to ());
167   second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
168 }
169
170
171 void
172 New_pc_iterator::solo2 ()
173 {
174   second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
175   second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ());
176
177   first_iter_->substitute_outlet (one_.report_to (), null_.report_to ());
178   first_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
179 }
180
181
182 void
183 New_pc_iterator::apart ()
184 {
185   first_iter_->substitute_outlet (null_.report_to (), one_.report_to ());
186   first_iter_->substitute_outlet (shared_.report_to (), one_.report_to ());
187   
188   second_iter_->substitute_outlet (null_.report_to (), two_.report_to ());
189   second_iter_->substitute_outlet (shared_.report_to (), two_.report_to ());
190 }
191
192
193 void
194 New_pc_iterator::construct_children ()
195 {
196   split_list_ =  get_music ()->get_mus_property ("split-list");
197   SCM lst =  get_music ()->get_mus_property ("elements");
198
199   SCM props = scm_list_n (scm_list_n (ly_symbol2scm ("denies"), ly_symbol2scm ("Thread"), SCM_UNDEFINED),
200                           scm_list_n (ly_symbol2scm ("consists"), ly_symbol2scm ("Rest_engraver"), SCM_UNDEFINED),
201                           scm_list_n (ly_symbol2scm ("consists"), ly_symbol2scm ("Note_heads_engraver"), SCM_UNDEFINED),
202                           SCM_UNDEFINED);
203
204   Translator_group *tr
205     =  report_to ()->find_create_translator (ly_symbol2scm ("Voice"),
206                                              "shared",props);
207
208   shared_ .set_translator (tr); 
209   set_translator (tr);
210   Translator_group *null
211     =  report_to ()->find_create_translator (ly_symbol2scm ("Devnull"),
212                                              "", SCM_EOL);
213   null_.set_translator (null);
214
215   Translator_group *one = tr->find_create_translator (ly_symbol2scm ("Voice"),
216                                                       "one", props);
217
218   one_.set_translator (one);
219   one->execute_pushpop_property (ly_symbol2scm ("Stem"),
220                                  ly_symbol2scm ("direction"), gh_int2scm (1));
221
222   set_translator (one);
223   first_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_car (lst))));
224
225
226   Translator_group *two = tr->find_create_translator (ly_symbol2scm ("Voice"),
227                                                       "two", props);
228   two_.set_translator (two);
229   two_.report_to ()->execute_pushpop_property (ly_symbol2scm ("Stem"),
230                                   ly_symbol2scm ("direction"), gh_int2scm (-1));
231   set_translator (two);
232   second_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_cadr (lst))));
233
234
235   set_translator (tr);
236 }
237
238 void
239 New_pc_iterator::process (Moment m)
240 {
241   Moment now = report_to ()->now_mom ();
242   Moment *splitm = 0;
243   
244   for (; gh_pair_p (split_list_); split_list_ = gh_cdr (split_list_))
245     {
246       splitm = unsmob_moment (gh_caar (split_list_));
247       if (*splitm > now)
248         break ;
249
250       SCM tag = gh_cdar (split_list_);
251       
252       if (tag == ly_symbol2scm ("chords"))
253         chords_together ();
254       else if (tag == ly_symbol2scm ("apart"))
255         apart ();
256       else if (tag == ly_symbol2scm ("unisono"))
257         unisono ();
258       else if (tag == ly_symbol2scm ("solo1"))
259         solo1 ();
260       else if (tag == ly_symbol2scm ("solo2"))
261         solo2 ();
262       else
263         {
264           String s =  "Unknown split directive: " + ly_symbol2string (tag);
265           programming_error (s);
266         }
267     }
268   
269   if (first_iter_->ok ())
270     first_iter_->process (m);
271   
272   if (second_iter_->ok ())
273     second_iter_->process (m);
274 }
275
276 Music_iterator*
277 New_pc_iterator::try_music_in_children (Music *m) const
278 {
279   Music_iterator * i =  first_iter_->try_music (m);
280   if (i)
281     return i;
282   else
283     return second_iter_->try_music (m);
284 }
285
286
287 SCM
288 New_pc_iterator::get_pending_events (Moment m)const
289 {
290   SCM s = SCM_EOL;
291   if (first_iter_)
292     s = gh_append2 (s,first_iter_->get_pending_events (m));
293   if (second_iter_)
294     s = gh_append2 (second_iter_->get_pending_events (m),s);
295   return s;
296 }
297
298 IMPLEMENT_CTOR_CALLBACK (New_pc_iterator);