2 new-part-combine-music-iterator.cc -- implement New_pc_iterator
4 source file of the GNU LilyPond music typesetter
6 (c) 2004 Han-Wen Nienhuys
9 #include "translator-group.hh"
11 #include "music-sequence.hh"
12 #include "lily-guile.hh"
14 #include "music-iterator.hh"
15 #include "interpretation-context-handle.hh"
17 class New_pc_iterator : public Music_iterator
20 VIRTUAL_COPY_CONS (Music_iterator);
23 DECLARE_SCHEME_CALLBACK(constructor, ());
25 virtual void derived_substitute (Translator_group*f, Translator_group*t) ;
26 virtual void derived_mark () const;
27 New_pc_iterator (New_pc_iterator const &);
29 virtual void construct_children ();
30 virtual Moment pending_moment () const;
31 virtual void do_quit();
32 virtual void process (Moment);
34 virtual SCM get_pending_events (Moment)const;
35 virtual Music_iterator *try_music_in_children (Music *) const;
37 virtual bool ok () const;
40 Music_iterator * first_iter_;
41 Music_iterator * second_iter_;
51 Status playing_state_;
53 Interpretation_context_handle one_;
54 Interpretation_context_handle two_;
55 Interpretation_context_handle null_;
56 Interpretation_context_handle shared_;
58 void kill_mmrest (Translator_group*);
59 void chords_together ();
62 void apart (bool silent);
63 void unisono (bool silent);
67 New_pc_iterator::New_pc_iterator ()
71 split_list_ = SCM_EOL;
73 playing_state_ = APART;
77 New_pc_iterator::derived_mark () const
80 scm_gc_mark (first_iter_->self_scm());
82 scm_gc_mark(second_iter_->self_scm());
86 New_pc_iterator::derived_substitute (Translator_group*f,
90 first_iter_->substitute_outlet (f,t);
92 second_iter_->substitute_outlet (f,t);
96 New_pc_iterator::do_quit ()
101 second_iter_->quit();
103 one_ .set_translator (0);
104 two_.set_translator (0);
105 shared_.set_translator (0);
108 New_pc_iterator::New_pc_iterator (New_pc_iterator const &src)
109 : Music_iterator (src)
115 first_iter_ = src.first_iter_->clone ();
116 if (src.second_iter_)
117 second_iter_ = src.second_iter_->clone ();
119 split_list_ = src.split_list_;
122 scm_gc_unprotect_object (first_iter_->self_scm());
124 scm_gc_unprotect_object (second_iter_->self_scm());
128 New_pc_iterator::pending_moment () const
132 if (first_iter_->ok ())
133 p = p <? first_iter_->pending_moment ();
135 if (second_iter_->ok ())
136 p = p <? second_iter_->pending_moment ();
141 New_pc_iterator::ok () const
143 return first_iter_->ok () || second_iter_->ok ();
147 New_pc_iterator::chords_together ()
149 if (state_ == TOGETHER)
153 playing_state_ = TOGETHER;
155 first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
156 first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
157 second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ());
158 second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
164 New_pc_iterator::kill_mmrest (Translator_group * tg)
166 static Music * mmrest;
169 mmrest = make_music_by_name (ly_symbol2scm ("MultiMeasureRestEvent"));
170 mmrest->set_mus_property ("duration", SCM_EOL);
173 tg->try_music (mmrest);
177 New_pc_iterator::solo1 ()
184 first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
185 first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
187 second_iter_->substitute_outlet (two_.report_to (), null_.report_to ());
188 second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
189 kill_mmrest (two_.report_to ());
190 kill_mmrest (shared_.report_to ());
192 if (playing_state_ != SOLO1)
196 event = make_music_by_name (ly_symbol2scm ("SoloOneEvent"));
198 first_iter_-> try_music_in_children (event);
200 playing_state_ = SOLO1;
204 New_pc_iterator::unisono (bool silent)
206 Status newstate = (silent) ? UNISILENCE : UNISONO;
208 if (newstate == state_)
213 first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
214 first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
216 second_iter_->substitute_outlet (two_.report_to (), null_.report_to ());
217 second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
218 kill_mmrest (two_.report_to ());
219 kill_mmrest (shared_.report_to ());
221 if (playing_state_ != UNISONO
222 && newstate == UNISONO)
226 event = make_music_by_name (ly_symbol2scm ("UnisonoEvent"));
228 first_iter_-> try_music_in_children (event);
229 playing_state_ = UNISONO;
236 New_pc_iterator::solo2 ()
244 second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
245 second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ());
247 first_iter_->substitute_outlet (one_.report_to (), null_.report_to ());
248 first_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
249 kill_mmrest (one_.report_to ());
250 kill_mmrest (shared_.report_to ());
252 if (playing_state_ != SOLO2)
256 event = make_music_by_name (ly_symbol2scm ("SoloTwoEvent"));
258 second_iter_-> try_music_in_children (event);
259 playing_state_ = SOLO2;
265 New_pc_iterator::apart (bool silent)
268 playing_state_ = APART;
276 first_iter_->substitute_outlet (null_.report_to (), one_.report_to ());
277 first_iter_->substitute_outlet (shared_.report_to (), one_.report_to ());
279 second_iter_->substitute_outlet (null_.report_to (), two_.report_to ());
280 second_iter_->substitute_outlet (shared_.report_to (), two_.report_to ()); }
284 New_pc_iterator::construct_children ()
286 split_list_ = get_music ()->get_mus_property ("split-list");
287 SCM lst = get_music ()->get_mus_property ("elements");
289 SCM props = scm_list_n (scm_list_n (ly_symbol2scm ("denies"), ly_symbol2scm ("Thread"), SCM_UNDEFINED),
290 scm_list_n (ly_symbol2scm ("consists"), ly_symbol2scm ("Rest_engraver"), SCM_UNDEFINED),
291 scm_list_n (ly_symbol2scm ("consists"), ly_symbol2scm ("Note_heads_engraver"), SCM_UNDEFINED),
295 = report_to ()->find_create_translator (ly_symbol2scm ("Voice"),
298 shared_ .set_translator (tr);
300 Translator_group *null
301 = report_to ()->find_create_translator (ly_symbol2scm ("Devnull"),
305 programming_error ("No Devnull found?");
307 null_.set_translator (null);
309 Translator_group *one = tr->find_create_translator (ly_symbol2scm ("Voice"),
312 one_.set_translator (one);
314 set_translator (one);
315 first_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_car (lst))));
318 Translator_group *two = tr->find_create_translator (ly_symbol2scm ("Voice"),
320 two_.set_translator (two);
321 set_translator (two);
322 second_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_cadr (lst))));
328 char const * syms[] = {
330 "DynamicLineSpanner",
339 for (char const**p = syms; *p; p++)
341 SCM sym = ly_symbol2scm (*p);
342 one->execute_pushpop_property (sym,
343 ly_symbol2scm ("direction"), gh_int2scm (1));
345 two->execute_pushpop_property (sym,
346 ly_symbol2scm ("direction"), gh_int2scm (-1));
352 New_pc_iterator::process (Moment m)
354 Moment now = report_to ()->now_mom ();
357 for (; gh_pair_p (split_list_); split_list_ = gh_cdr (split_list_))
359 splitm = unsmob_moment (gh_caar (split_list_));
363 SCM tag = gh_cdar (split_list_);
365 if (tag == ly_symbol2scm ("chords"))
367 else if (tag == ly_symbol2scm ("apart")
368 || tag == ly_symbol2scm ("apart-silence")
369 || tag == ly_symbol2scm ("apart-spanner"))
370 apart (tag == ly_symbol2scm ("apart-silence"));
371 else if (tag == ly_symbol2scm ("unisono"))
373 else if (tag == ly_symbol2scm ("unisilence"))
375 else if (tag == ly_symbol2scm ("solo1"))
377 else if (tag == ly_symbol2scm ("solo2"))
381 String s = "Unknown split directive: "
382 + (gh_symbol_p (tag) ? ly_symbol2string (tag) : String ("not a symbol"));
383 programming_error (s);
387 if (first_iter_->ok ())
388 first_iter_->process (m);
390 if (second_iter_->ok ())
391 second_iter_->process (m);
395 New_pc_iterator::try_music_in_children (Music *m) const
397 Music_iterator * i = first_iter_->try_music (m);
401 return second_iter_->try_music (m);
406 New_pc_iterator::get_pending_events (Moment m)const
410 s = gh_append2 (s,first_iter_->get_pending_events (m));
412 s = gh_append2 (second_iter_->get_pending_events (m),s);
416 IMPLEMENT_CTOR_CALLBACK (New_pc_iterator);