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_;
50 Status playing_state_;
53 TODO: this is getting of hand...
55 Interpretation_context_handle one_;
56 Interpretation_context_handle two_;
57 Interpretation_context_handle null_;
58 Interpretation_context_handle shared_;
59 Interpretation_context_handle solo_;
61 void substitute_both (Context * to1,
64 void kill_mmrest (Context *);
65 void chords_together ();
68 void apart (bool silent);
69 void unisono (bool silent);
73 Part_combine_iterator::Part_combine_iterator ()
77 split_list_ = SCM_EOL;
79 playing_state_ = APART;
83 Part_combine_iterator::derived_mark () const
86 scm_gc_mark (first_iter_->self_scm ());
88 scm_gc_mark (second_iter_->self_scm ());
92 Part_combine_iterator::derived_substitute (Context *f,
96 first_iter_->substitute_outlet (f,t);
98 second_iter_->substitute_outlet (f,t);
102 Part_combine_iterator::do_quit ()
105 first_iter_->quit ();
107 second_iter_->quit ();
109 null_.set_translator (0);
110 one_ .set_translator (0);
111 two_.set_translator (0);
112 shared_.set_translator (0);
113 solo_.set_translator (0);
117 Part_combine_iterator::pending_moment () const
121 if (first_iter_->ok ())
122 p = p <? first_iter_->pending_moment ();
124 if (second_iter_->ok ())
125 p = p <? second_iter_->pending_moment ();
130 Part_combine_iterator::ok () const
132 return first_iter_->ok () || second_iter_->ok ();
136 Part_combine_iterator::chords_together ()
138 if (state_ == TOGETHER)
142 playing_state_ = TOGETHER;
145 substitute_both (shared_.get_outlet (), shared_.get_outlet ());
151 Part_combine_iterator::kill_mmrest (Context * tg)
153 static Music * mmrest;
156 mmrest = make_music_by_name (ly_symbol2scm ("MultiMeasureRestEvent"));
157 mmrest->set_property ("duration", SCM_EOL);
160 tg->try_music (mmrest);
164 Part_combine_iterator::solo1 ()
171 substitute_both (solo_.get_outlet (),
172 null_.get_outlet ());
174 kill_mmrest (two_.get_outlet ());
175 kill_mmrest (shared_.get_outlet ());
177 if (playing_state_ != SOLO1)
181 event = make_music_by_name (ly_symbol2scm ("SoloOneEvent"));
183 first_iter_-> try_music_in_children (event);
185 playing_state_ = SOLO1;
190 Part_combine_iterator::substitute_both (Context * to1,
193 Context *tos[] = {to1,to2};
194 Music_iterator *mis[] = {first_iter_, second_iter_};
195 Interpretation_context_handle *hs[] = {
202 for (int i = 0; i < 2 ; i++)
204 for (int j = 0; hs[j]; j++)
205 if (hs[j]->get_outlet () != tos[i])
206 mis[i]->substitute_outlet (hs[j]->get_outlet (), tos[i]);
209 for (int j = 0; hs[j]; j++)
211 Context * t = hs[j]->get_outlet ();
212 if (t != to1 && t != to2)
219 Part_combine_iterator::unisono (bool silent)
221 Status newstate = (silent) ? UNISILENCE : UNISONO;
223 if (newstate == state_)
227 substitute_both (shared_.get_outlet (), null_.get_outlet ());
229 kill_mmrest (two_.get_outlet ());
230 kill_mmrest (shared_.get_outlet ());
232 if (playing_state_ != UNISONO
233 && newstate == UNISONO)
237 event = make_music_by_name (ly_symbol2scm ("UnisonoEvent"));
239 first_iter_-> try_music_in_children (event);
240 playing_state_ = UNISONO;
247 Part_combine_iterator::solo2 ()
255 substitute_both (null_.get_outlet (), solo_.get_outlet ());
257 if (playing_state_ != SOLO2)
261 event = make_music_by_name (ly_symbol2scm ("SoloTwoEvent"));
263 second_iter_-> try_music_in_children (event);
264 playing_state_ = SOLO2;
270 Part_combine_iterator::apart (bool silent)
273 playing_state_ = APART;
280 substitute_both (one_.get_outlet (), two_.get_outlet ());
286 Part_combine_iterator::construct_children ()
288 start_moment_ = get_outlet ()->now_mom ();
289 split_list_ = get_music ()->get_property ("split-list");
290 SCM lst = get_music ()->get_property ("elements");
292 SCM props = scm_list_n (/*
293 used to have tweaks here.
299 = get_outlet ()->find_create_context (ly_symbol2scm ("Voice"),
302 shared_.set_translator (tr);
305 If we don't, we get a new staff for every Voice.
310 = get_outlet ()->find_create_context (ly_symbol2scm ("Voice"),
313 solo_ .set_translator (solo_tr);
316 = get_outlet ()->find_create_context (ly_symbol2scm ("Devnull"),
320 programming_error ("No Devnull found?");
322 null_.set_translator (null);
324 Context *one = tr->find_create_context (ly_symbol2scm ("Voice"),
327 one_.set_translator (one);
329 set_translator (one);
330 first_iter_ = unsmob_iterator (get_iterator (unsmob_music (ly_car (lst))));
333 Context *two = tr->find_create_context (ly_symbol2scm ("Voice"),
335 two_.set_translator (two);
336 set_translator (two);
337 second_iter_ = unsmob_iterator (get_iterator (unsmob_music (ly_cadr (lst))));
343 char const * syms[] = {
345 "DynamicLineSpanner",
355 for (char const**p = syms; *p; p++)
357 SCM sym = ly_symbol2scm (*p);
358 execute_pushpop_property (one, sym,
359 ly_symbol2scm ("direction"), scm_int2num (1));
361 execute_pushpop_property (two, sym,
362 ly_symbol2scm ("direction"), scm_int2num (-1));
368 Part_combine_iterator::process (Moment m)
370 Moment now = get_outlet ()->now_mom ();
373 for (; ly_c_pair_p (split_list_); split_list_ = ly_cdr (split_list_))
375 splitm = unsmob_moment (ly_caar (split_list_));
376 if (splitm && *splitm + start_moment_ > now)
379 SCM tag = ly_cdar (split_list_);
381 if (tag == ly_symbol2scm ("chords"))
383 else if (tag == ly_symbol2scm ("apart")
384 || tag == ly_symbol2scm ("apart-silence")
385 || tag == ly_symbol2scm ("apart-spanner"))
386 apart (tag == ly_symbol2scm ("apart-silence"));
387 else if (tag == ly_symbol2scm ("unisono"))
389 else if (tag == ly_symbol2scm ("unisilence"))
391 else if (tag == ly_symbol2scm ("solo1"))
393 else if (tag == ly_symbol2scm ("solo2"))
395 else if (ly_c_symbol_p (tag))
397 String s = "Unknown split directive: "
398 + (ly_c_symbol_p (tag) ? ly_symbol2string (tag) : String ("not a symbol"));
399 programming_error (s);
403 if (first_iter_->ok ())
404 first_iter_->process (m);
406 if (second_iter_->ok ())
407 second_iter_->process (m);
411 Part_combine_iterator::try_music_in_children (Music *m) const
413 Music_iterator * i = first_iter_->try_music (m);
417 return second_iter_->try_music (m);
420 IMPLEMENT_CTOR_CALLBACK (Part_combine_iterator);