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
22 DECLARE_SCHEME_CALLBACK(constructor, ());
24 virtual void derived_substitute (Translator_group*f, Translator_group*t) ;
25 virtual void derived_mark () const;
26 New_pc_iterator (New_pc_iterator const &);
28 virtual void construct_children ();
29 virtual Moment pending_moment () const;
30 virtual void do_quit();
31 virtual void process (Moment);
33 virtual Music_iterator *try_music_in_children (Music *) const;
35 virtual bool ok () const;
38 Music_iterator * first_iter_;
39 Music_iterator * second_iter_;
49 Status playing_state_;
51 Interpretation_context_handle one_;
52 Interpretation_context_handle two_;
53 Interpretation_context_handle null_;
54 Interpretation_context_handle shared_;
56 void kill_mmrest (Translator_group*);
57 void chords_together ();
60 void apart (bool silent);
61 void unisono (bool silent);
65 New_pc_iterator::New_pc_iterator ()
69 split_list_ = SCM_EOL;
71 playing_state_ = APART;
75 New_pc_iterator::derived_mark () const
78 scm_gc_mark (first_iter_->self_scm());
80 scm_gc_mark(second_iter_->self_scm());
84 New_pc_iterator::derived_substitute (Translator_group*f,
88 first_iter_->substitute_outlet (f,t);
90 second_iter_->substitute_outlet (f,t);
94 New_pc_iterator::do_quit ()
101 one_ .set_translator (0);
102 two_.set_translator (0);
103 shared_.set_translator (0);
109 New_pc_iterator::pending_moment () const
113 if (first_iter_->ok ())
114 p = p <? first_iter_->pending_moment ();
116 if (second_iter_->ok ())
117 p = p <? second_iter_->pending_moment ();
122 New_pc_iterator::ok () const
124 return first_iter_->ok () || second_iter_->ok ();
128 New_pc_iterator::chords_together ()
130 if (state_ == TOGETHER)
134 playing_state_ = TOGETHER;
136 first_iter_->substitute_outlet (one_.get_outlet (), shared_.get_outlet ());
137 first_iter_->substitute_outlet (null_.get_outlet (), shared_.get_outlet ());
138 second_iter_->substitute_outlet (two_.get_outlet (), shared_.get_outlet ());
139 second_iter_->substitute_outlet (null_.get_outlet (), shared_.get_outlet ());
145 New_pc_iterator::kill_mmrest (Translator_group * tg)
147 static Music * mmrest;
150 mmrest = make_music_by_name (ly_symbol2scm ("MultiMeasureRestEvent"));
151 mmrest->set_mus_property ("duration", SCM_EOL);
154 tg->try_music (mmrest);
158 New_pc_iterator::solo1 ()
165 first_iter_->substitute_outlet (null_.get_outlet (), shared_.get_outlet ());
166 first_iter_->substitute_outlet (one_.get_outlet (), shared_.get_outlet ());
168 second_iter_->substitute_outlet (two_.get_outlet (), null_.get_outlet ());
169 second_iter_->substitute_outlet (shared_.get_outlet (), null_.get_outlet ());
170 kill_mmrest (two_.get_outlet ());
171 kill_mmrest (shared_.get_outlet ());
173 if (playing_state_ != SOLO1)
177 event = make_music_by_name (ly_symbol2scm ("SoloOneEvent"));
179 first_iter_-> try_music_in_children (event);
181 playing_state_ = SOLO1;
185 New_pc_iterator::unisono (bool silent)
187 Status newstate = (silent) ? UNISILENCE : UNISONO;
189 if (newstate == state_)
194 first_iter_->substitute_outlet (null_.get_outlet (), shared_.get_outlet ());
195 first_iter_->substitute_outlet (one_.get_outlet (), shared_.get_outlet ());
197 second_iter_->substitute_outlet (two_.get_outlet (), null_.get_outlet ());
198 second_iter_->substitute_outlet (shared_.get_outlet (), null_.get_outlet ());
199 kill_mmrest (two_.get_outlet ());
200 kill_mmrest (shared_.get_outlet ());
202 if (playing_state_ != UNISONO
203 && newstate == UNISONO)
207 event = make_music_by_name (ly_symbol2scm ("UnisonoEvent"));
209 first_iter_-> try_music_in_children (event);
210 playing_state_ = UNISONO;
217 New_pc_iterator::solo2 ()
225 second_iter_->substitute_outlet (null_.get_outlet (), shared_.get_outlet ());
226 second_iter_->substitute_outlet (two_.get_outlet (), shared_.get_outlet ());
228 first_iter_->substitute_outlet (one_.get_outlet (), null_.get_outlet ());
229 first_iter_->substitute_outlet (shared_.get_outlet (), null_.get_outlet ());
230 kill_mmrest (one_.get_outlet ());
231 kill_mmrest (shared_.get_outlet ());
233 if (playing_state_ != SOLO2)
237 event = make_music_by_name (ly_symbol2scm ("SoloTwoEvent"));
239 second_iter_-> try_music_in_children (event);
240 playing_state_ = SOLO2;
246 New_pc_iterator::apart (bool silent)
249 playing_state_ = APART;
257 first_iter_->substitute_outlet (null_.get_outlet (), one_.get_outlet ());
258 first_iter_->substitute_outlet (shared_.get_outlet (), one_.get_outlet ());
260 second_iter_->substitute_outlet (null_.get_outlet (), two_.get_outlet ());
261 second_iter_->substitute_outlet (shared_.get_outlet (), two_.get_outlet ()); }
265 New_pc_iterator::construct_children ()
267 split_list_ = get_music ()->get_mus_property ("split-list");
268 SCM lst = get_music ()->get_mus_property ("elements");
270 SCM props = scm_list_n (/*
271 used to have tweaks here.
277 = get_outlet ()->find_create_translator (ly_symbol2scm ("Voice"),
280 shared_ .set_translator (tr);
282 Translator_group *null
283 = get_outlet ()->find_create_translator (ly_symbol2scm ("Devnull"),
287 programming_error ("No Devnull found?");
289 null_.set_translator (null);
291 Translator_group *one = tr->find_create_translator (ly_symbol2scm ("Voice"),
294 one_.set_translator (one);
296 set_translator (one);
297 first_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_car (lst))));
300 Translator_group *two = tr->find_create_translator (ly_symbol2scm ("Voice"),
302 two_.set_translator (two);
303 set_translator (two);
304 second_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_cadr (lst))));
310 char const * syms[] = {
312 "DynamicLineSpanner",
322 for (char const**p = syms; *p; p++)
324 SCM sym = ly_symbol2scm (*p);
325 execute_pushpop_property (one, sym,
326 ly_symbol2scm ("direction"), gh_int2scm (1));
328 execute_pushpop_property (two, sym,
329 ly_symbol2scm ("direction"), gh_int2scm (-1));
335 New_pc_iterator::process (Moment m)
337 Moment now = get_outlet ()->now_mom ();
340 for (; gh_pair_p (split_list_); split_list_ = gh_cdr (split_list_))
342 splitm = unsmob_moment (gh_caar (split_list_));
346 SCM tag = gh_cdar (split_list_);
348 if (tag == ly_symbol2scm ("chords"))
350 else if (tag == ly_symbol2scm ("apart")
351 || tag == ly_symbol2scm ("apart-silence")
352 || tag == ly_symbol2scm ("apart-spanner"))
353 apart (tag == ly_symbol2scm ("apart-silence"));
354 else if (tag == ly_symbol2scm ("unisono"))
356 else if (tag == ly_symbol2scm ("unisilence"))
358 else if (tag == ly_symbol2scm ("solo1"))
360 else if (tag == ly_symbol2scm ("solo2"))
364 String s = "Unknown split directive: "
365 + (gh_symbol_p (tag) ? ly_symbol2string (tag) : String ("not a symbol"));
366 programming_error (s);
370 if (first_iter_->ok ())
371 first_iter_->process (m);
373 if (second_iter_->ok ())
374 second_iter_->process (m);
378 New_pc_iterator::try_music_in_children (Music *m) const
380 Music_iterator * i = first_iter_->try_music (m);
384 return second_iter_->try_music (m);
387 IMPLEMENT_CTOR_CALLBACK (New_pc_iterator);