2 new-part-combine-music-iterator.cc -- implement Part_combine_iterator
4 source file of the GNU LilyPond music typesetter
6 (c) 2004 Han-Wen Nienhuys
11 #include "music-sequence.hh"
12 #include "lily-guile.hh"
14 #include "music-iterator.hh"
15 #include "interpretation-context-handle.hh"
17 class Part_combine_iterator : public Music_iterator
20 Part_combine_iterator ();
22 DECLARE_SCHEME_CALLBACK(constructor, ());
24 virtual void derived_substitute (Context *f, Context *t) ;
25 virtual void derived_mark () const;
26 Part_combine_iterator (Part_combine_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_;
52 TODO: this is getting of hand...
54 Interpretation_context_handle one_;
55 Interpretation_context_handle two_;
56 Interpretation_context_handle null_;
57 Interpretation_context_handle shared_;
58 Interpretation_context_handle solo_;
60 void substitute_both (Context * to1,
63 void kill_mmrest (Context *);
64 void chords_together ();
67 void apart (bool silent);
68 void unisono (bool silent);
72 Part_combine_iterator::Part_combine_iterator ()
76 split_list_ = SCM_EOL;
78 playing_state_ = APART;
82 Part_combine_iterator::derived_mark () const
85 scm_gc_mark (first_iter_->self_scm());
87 scm_gc_mark(second_iter_->self_scm());
91 Part_combine_iterator::derived_substitute (Context *f,
95 first_iter_->substitute_outlet (f,t);
97 second_iter_->substitute_outlet (f,t);
101 Part_combine_iterator::do_quit ()
106 second_iter_->quit();
108 null_.set_translator (0);
109 one_ .set_translator (0);
110 two_.set_translator (0);
111 shared_.set_translator (0);
112 solo_.set_translator (0);
116 Part_combine_iterator::pending_moment () const
120 if (first_iter_->ok ())
121 p = p <? first_iter_->pending_moment ();
123 if (second_iter_->ok ())
124 p = p <? second_iter_->pending_moment ();
129 Part_combine_iterator::ok () const
131 return first_iter_->ok () || second_iter_->ok ();
135 Part_combine_iterator::chords_together ()
137 if (state_ == TOGETHER)
141 playing_state_ = TOGETHER;
144 substitute_both (shared_.get_outlet (), shared_.get_outlet());
150 Part_combine_iterator::kill_mmrest (Context * tg)
152 static Music * mmrest;
155 mmrest = make_music_by_name (ly_symbol2scm ("MultiMeasureRestEvent"));
156 mmrest->set_property ("duration", SCM_EOL);
159 tg->try_music (mmrest);
163 Part_combine_iterator::solo1 ()
170 substitute_both (solo_.get_outlet (),
171 null_.get_outlet ());
173 kill_mmrest (two_.get_outlet ());
174 kill_mmrest (shared_.get_outlet ());
176 if (playing_state_ != SOLO1)
180 event = make_music_by_name (ly_symbol2scm ("SoloOneEvent"));
182 first_iter_-> try_music_in_children (event);
184 playing_state_ = SOLO1;
189 Part_combine_iterator::substitute_both (Context * to1,
192 Context *tos[] = {to1,to2};
193 Music_iterator *mis[] = {first_iter_, second_iter_};
194 Interpretation_context_handle *hs[] = {
201 for (int i = 0; i < 2 ; i++)
203 for (int j = 0; hs[j]; j++)
204 if (hs[j]->get_outlet () != tos[i])
205 mis[i]->substitute_outlet (hs[j]->get_outlet (), tos[i]);
208 for (int j = 0; hs[j]; j++)
210 Context * t = hs[j]->get_outlet ();
211 if (t != to1 && t != to2)
218 Part_combine_iterator::unisono (bool silent)
220 Status newstate = (silent) ? UNISILENCE : UNISONO;
222 if (newstate == state_)
226 substitute_both (shared_.get_outlet (), null_.get_outlet ());
228 kill_mmrest (two_.get_outlet ());
229 kill_mmrest (shared_.get_outlet ());
231 if (playing_state_ != UNISONO
232 && newstate == UNISONO)
236 event = make_music_by_name (ly_symbol2scm ("UnisonoEvent"));
238 first_iter_-> try_music_in_children (event);
239 playing_state_ = UNISONO;
246 Part_combine_iterator::solo2 ()
254 substitute_both (null_.get_outlet (), solo_.get_outlet ());
256 if (playing_state_ != SOLO2)
260 event = make_music_by_name (ly_symbol2scm ("SoloTwoEvent"));
262 second_iter_-> try_music_in_children (event);
263 playing_state_ = SOLO2;
269 Part_combine_iterator::apart (bool silent)
272 playing_state_ = APART;
279 substitute_both (one_.get_outlet (), two_.get_outlet ());
285 Part_combine_iterator::construct_children ()
287 split_list_ = get_music ()->get_property ("split-list");
288 SCM lst = get_music ()->get_property ("elements");
290 SCM props = scm_list_n (/*
291 used to have tweaks here.
297 = get_outlet ()->find_create_context (ly_symbol2scm ("Voice"),
300 shared_.set_translator (tr);
303 If we don't, we get a new staff for every Voice.
308 = get_outlet ()->find_create_context (ly_symbol2scm ("Voice"),
311 solo_ .set_translator (solo_tr);
314 = get_outlet ()->find_create_context (ly_symbol2scm ("Devnull"),
318 programming_error ("No Devnull found?");
320 null_.set_translator (null);
322 Context *one = tr->find_create_context (ly_symbol2scm ("Voice"),
325 one_.set_translator (one);
327 set_translator (one);
328 first_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_car (lst))));
331 Context *two = tr->find_create_context (ly_symbol2scm ("Voice"),
333 two_.set_translator (two);
334 set_translator (two);
335 second_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_cadr (lst))));
341 char const * syms[] = {
343 "DynamicLineSpanner",
353 for (char const**p = syms; *p; p++)
355 SCM sym = ly_symbol2scm (*p);
356 execute_pushpop_property (one, sym,
357 ly_symbol2scm ("direction"), gh_int2scm (1));
359 execute_pushpop_property (two, sym,
360 ly_symbol2scm ("direction"), gh_int2scm (-1));
366 Part_combine_iterator::process (Moment m)
368 Moment now = get_outlet ()->now_mom ();
371 for (; gh_pair_p (split_list_); split_list_ = gh_cdr (split_list_))
373 splitm = unsmob_moment (gh_caar (split_list_));
377 SCM tag = gh_cdar (split_list_);
379 if (tag == ly_symbol2scm ("chords"))
381 else if (tag == ly_symbol2scm ("apart")
382 || tag == ly_symbol2scm ("apart-silence")
383 || tag == ly_symbol2scm ("apart-spanner"))
384 apart (tag == ly_symbol2scm ("apart-silence"));
385 else if (tag == ly_symbol2scm ("unisono"))
387 else if (tag == ly_symbol2scm ("unisilence"))
389 else if (tag == ly_symbol2scm ("solo1"))
391 else if (tag == ly_symbol2scm ("solo2"))
393 else if (gh_symbol_p (tag))
395 String s = "Unknown split directive: "
396 + (gh_symbol_p (tag) ? ly_symbol2string (tag) : String ("not a symbol"));
397 programming_error (s);
401 if (first_iter_->ok ())
402 first_iter_->process (m);
404 if (second_iter_->ok ())
405 second_iter_->process (m);
409 Part_combine_iterator::try_music_in_children (Music *m) const
411 Music_iterator * i = first_iter_->try_music (m);
415 return second_iter_->try_music (m);
418 IMPLEMENT_CTOR_CALLBACK (Part_combine_iterator);