]> git.donarmstrong.com Git - lilypond.git/blob - lily/new-part-combine-iterator.cc
This commit was manufactured by cvs2svn to create tag 'lilypond_2_1_17'.
[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   enum  {
47     APART, TOGETHER,
48     SOLO1, SOLO2,
49     UNISONO,
50   } state_;
51
52   Interpretation_context_handle one_;
53   Interpretation_context_handle two_;
54   Interpretation_context_handle null_;
55   Interpretation_context_handle shared_;
56
57   void chords_together ();
58   void apart ();
59   void solo1 ();
60   void solo2 ();
61   void unisono ();
62 };
63
64
65 New_pc_iterator::New_pc_iterator ()
66 {
67   is_shared_  =false;
68   first_iter_ = 0;
69   second_iter_ = 0;
70   split_list_ = SCM_EOL;
71   state_ = APART;
72 }
73
74 void
75 New_pc_iterator::derived_mark () const
76 {
77   if (first_iter_)
78     scm_gc_mark (first_iter_->self_scm());
79   if (second_iter_)
80     scm_gc_mark(second_iter_->self_scm());
81 }
82
83 void
84 New_pc_iterator::derived_substitute (Translator_group*f,
85                                      Translator_group*t)
86 {
87   if (first_iter_)
88     first_iter_->substitute_outlet (f,t);
89   if (second_iter_)
90     second_iter_->substitute_outlet (f,t);
91 }
92
93 void
94 New_pc_iterator::do_quit ()
95 {
96   if (first_iter_)
97     first_iter_->quit();
98   if (second_iter_)
99     second_iter_->quit();
100
101   one_ .set_translator (0);
102   two_.set_translator (0);
103   shared_.set_translator (0);
104 }
105
106 New_pc_iterator::New_pc_iterator (New_pc_iterator const &src)
107   : Music_iterator (src)
108 {
109   first_iter_ = 0;
110   second_iter_ = 0;
111
112   if(src.first_iter_)
113     first_iter_ = src.first_iter_->clone ();
114   if (src.second_iter_)
115     second_iter_ = src.second_iter_->clone ();
116
117   split_list_ = src.split_list_;
118   
119   if (first_iter_)
120     scm_gc_unprotect_object (first_iter_->self_scm());
121   if (second_iter_)
122     scm_gc_unprotect_object (second_iter_->self_scm());
123 }
124
125 Moment
126 New_pc_iterator::pending_moment () const
127 {
128   Moment p;
129   p.set_infinite (1);
130   if (first_iter_->ok ())
131     p = p <? first_iter_->pending_moment ();
132
133   if (second_iter_->ok ())
134     p = p <? second_iter_->pending_moment ();
135   return p;
136 }
137
138 bool
139 New_pc_iterator::ok () const
140 {
141   return first_iter_->ok () || second_iter_->ok ();
142 }
143
144 void
145 New_pc_iterator::chords_together ()
146 {
147   if (state_ == TOGETHER)
148     return;
149   else
150     {
151       state_ = TOGETHER;
152       first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
153       first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
154       second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ());
155       second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
156     }
157 }
158
159
160 void
161 New_pc_iterator::solo1 ()
162 {
163   if (state_ == SOLO1)
164     return;
165   else
166     {
167       state_ = SOLO1;
168       first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
169       first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
170
171       second_iter_->substitute_outlet (two_.report_to (), null_.report_to ());
172       second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
173
174       static Music* event;
175       if (!event)
176         event = make_music_by_name (ly_symbol2scm ("SoloOneEvent"));
177
178     first_iter_-> try_music_in_children (event);
179     }
180 }
181 void
182 New_pc_iterator::unisono ()
183 {
184   if (state_ == UNISONO)
185     return;
186   else
187     {
188       state_ = UNISONO;
189
190       first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
191       first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
192
193       second_iter_->substitute_outlet (two_.report_to (), null_.report_to ());
194       second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
195
196
197       static Music* event;
198       if (!event)
199         event = make_music_by_name (ly_symbol2scm ("UnisonoEvent"));
200
201       first_iter_-> try_music_in_children (event);      
202     }
203 }
204
205 void
206 New_pc_iterator::solo2 ()
207 {
208   if (state_ == SOLO2)
209     return;
210   else
211     {
212       state_ = SOLO2;
213       second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
214       second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ());
215
216       first_iter_->substitute_outlet (one_.report_to (), null_.report_to ());
217       first_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
218
219       static Music* event;
220       if (!event)
221         event = make_music_by_name (ly_symbol2scm ("SoloTwoEvent"));
222
223       second_iter_-> try_music_in_children (event);
224     }
225 }
226
227 void
228 New_pc_iterator::apart ()
229 {
230   if (state_ == APART)
231     return;
232   else
233     {
234       state_ = APART;
235   
236       first_iter_->substitute_outlet (null_.report_to (), one_.report_to ());
237       first_iter_->substitute_outlet (shared_.report_to (), one_.report_to ());
238   
239       second_iter_->substitute_outlet (null_.report_to (), two_.report_to ());
240       second_iter_->substitute_outlet (shared_.report_to (), two_.report_to ());    }
241 }
242
243 void
244 New_pc_iterator::construct_children ()
245 {
246   split_list_ =  get_music ()->get_mus_property ("split-list");
247   SCM lst =  get_music ()->get_mus_property ("elements");
248
249   SCM props = scm_list_n (scm_list_n (ly_symbol2scm ("denies"), ly_symbol2scm ("Thread"), SCM_UNDEFINED),
250                           scm_list_n (ly_symbol2scm ("consists"), ly_symbol2scm ("Rest_engraver"), SCM_UNDEFINED),
251                           scm_list_n (ly_symbol2scm ("consists"), ly_symbol2scm ("Note_heads_engraver"), SCM_UNDEFINED),
252                           SCM_UNDEFINED);
253
254   Translator_group *tr
255     =  report_to ()->find_create_translator (ly_symbol2scm ("Voice"),
256                                              "shared",props);
257
258   shared_ .set_translator (tr); 
259   set_translator (tr);
260   Translator_group *null
261     =  report_to ()->find_create_translator (ly_symbol2scm ("Devnull"),
262                                              "", SCM_EOL);
263   null_.set_translator (null);
264
265   Translator_group *one = tr->find_create_translator (ly_symbol2scm ("Voice"),
266                                                       "one", props);
267
268   one_.set_translator (one);
269
270   set_translator (one);
271   first_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_car (lst))));
272
273
274   Translator_group *two = tr->find_create_translator (ly_symbol2scm ("Voice"),
275                                                       "two", props);
276   two_.set_translator (two);
277   set_translator (two);
278   second_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_cadr (lst))));
279
280
281   set_translator (tr);
282
283
284   char const * syms[] = {
285     "Stem",
286     "DynamicLineSpanner",
287     "Tie",
288     "Dots",
289     "Slur",
290     "TextScript",
291     "Script",
292     0
293   };
294   
295   for (char const**p = syms; *p; p++)
296     {
297       SCM sym = ly_symbol2scm (*p);
298       one->execute_pushpop_property (sym,
299                                      ly_symbol2scm ("direction"), gh_int2scm (1));
300
301       two->execute_pushpop_property (sym,
302                                      ly_symbol2scm ("direction"), gh_int2scm (-1));
303     }
304
305 }
306
307 void
308 New_pc_iterator::process (Moment m)
309 {
310   Moment now = report_to ()->now_mom ();
311   Moment *splitm = 0;
312   
313   for (; gh_pair_p (split_list_); split_list_ = gh_cdr (split_list_))
314     {
315       splitm = unsmob_moment (gh_caar (split_list_));
316       if (*splitm > now)
317         break ;
318
319       SCM tag = gh_cdar (split_list_);
320       
321       if (tag == ly_symbol2scm ("chords"))
322         chords_together ();
323       else if (tag == ly_symbol2scm ("apart"))
324         apart ();
325       else if (tag == ly_symbol2scm ("unisono"))
326         unisono ();
327       else if (tag == ly_symbol2scm ("solo1"))
328         solo1 ();
329       else if (tag == ly_symbol2scm ("solo2"))
330         solo2 ();
331       else
332         {
333           String s =  "Unknown split directive: "
334             + (gh_symbol_p (tag) ? ly_symbol2string (tag) : String ("not a symbol")); 
335           programming_error (s);
336         }
337     }
338   
339   if (first_iter_->ok ())
340     first_iter_->process (m);
341   
342   if (second_iter_->ok ())
343     second_iter_->process (m);
344 }
345
346 Music_iterator*
347 New_pc_iterator::try_music_in_children (Music *m) const
348 {
349   Music_iterator * i =  first_iter_->try_music (m);
350   if (i)
351     return i;
352   else
353     return second_iter_->try_music (m);
354 }
355
356
357 SCM
358 New_pc_iterator::get_pending_events (Moment m)const
359 {
360   SCM s = SCM_EOL;
361   if (first_iter_)
362     s = gh_append2 (s,first_iter_->get_pending_events (m));
363   if (second_iter_)
364     s = gh_append2 (second_iter_->get_pending_events (m),s);
365   return s;
366 }
367
368 IMPLEMENT_CTOR_CALLBACK (New_pc_iterator);