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 "part-combine-music-iterator.hh"
10 #include "translator-group.hh"
12 #include "music-sequence.hh"
13 #include "lily-guile.hh"
15 #include "music-iterator.hh"
16 #include "interpretation-context-handle.hh"
18 class New_pc_iterator : public Music_iterator
21 VIRTUAL_COPY_CONS (Music_iterator);
24 DECLARE_SCHEME_CALLBACK(constructor, ());
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 &);
30 virtual void construct_children ();
31 virtual Moment pending_moment () const;
32 virtual void do_quit();
33 virtual void process (Moment);
35 virtual SCM get_pending_events (Moment)const;
36 virtual Music_iterator *try_music_in_children (Music *) const;
38 virtual bool ok () const;
41 Music_iterator * first_iter_;
42 Music_iterator * second_iter_;
52 Interpretation_context_handle one_;
53 Interpretation_context_handle two_;
54 Interpretation_context_handle null_;
55 Interpretation_context_handle shared_;
57 void chords_together ();
65 New_pc_iterator::New_pc_iterator ()
70 split_list_ = SCM_EOL;
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);
106 New_pc_iterator::New_pc_iterator (New_pc_iterator const &src)
107 : Music_iterator (src)
113 first_iter_ = src.first_iter_->clone ();
114 if (src.second_iter_)
115 second_iter_ = src.second_iter_->clone ();
117 split_list_ = src.split_list_;
120 scm_gc_unprotect_object (first_iter_->self_scm());
122 scm_gc_unprotect_object (second_iter_->self_scm());
126 New_pc_iterator::pending_moment () const
130 if (first_iter_->ok ())
131 p = p <? first_iter_->pending_moment ();
133 if (second_iter_->ok ())
134 p = p <? second_iter_->pending_moment ();
139 New_pc_iterator::ok () const
141 return first_iter_->ok () || second_iter_->ok ();
145 New_pc_iterator::chords_together ()
147 if (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 ());
161 New_pc_iterator::solo1 ()
168 first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
169 first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
171 second_iter_->substitute_outlet (two_.report_to (), null_.report_to ());
172 second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
176 event = make_music_by_name (ly_symbol2scm ("SoloOneEvent"));
178 first_iter_-> try_music_in_children (event);
182 New_pc_iterator::unisono ()
184 if (state_ == UNISONO)
190 first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
191 first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
193 second_iter_->substitute_outlet (two_.report_to (), null_.report_to ());
194 second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
199 event = make_music_by_name (ly_symbol2scm ("UnisonoEvent"));
201 first_iter_-> try_music_in_children (event);
206 New_pc_iterator::solo2 ()
213 second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
214 second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ());
216 first_iter_->substitute_outlet (one_.report_to (), null_.report_to ());
217 first_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
221 event = make_music_by_name (ly_symbol2scm ("SoloTwoEvent"));
223 second_iter_-> try_music_in_children (event);
228 New_pc_iterator::apart ()
236 first_iter_->substitute_outlet (null_.report_to (), one_.report_to ());
237 first_iter_->substitute_outlet (shared_.report_to (), one_.report_to ());
239 second_iter_->substitute_outlet (null_.report_to (), two_.report_to ());
240 second_iter_->substitute_outlet (shared_.report_to (), two_.report_to ()); }
244 New_pc_iterator::construct_children ()
246 split_list_ = get_music ()->get_mus_property ("split-list");
247 SCM lst = get_music ()->get_mus_property ("elements");
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),
255 = report_to ()->find_create_translator (ly_symbol2scm ("Voice"),
258 shared_ .set_translator (tr);
260 Translator_group *null
261 = report_to ()->find_create_translator (ly_symbol2scm ("Devnull"),
263 null_.set_translator (null);
265 Translator_group *one = tr->find_create_translator (ly_symbol2scm ("Voice"),
268 one_.set_translator (one);
270 set_translator (one);
271 first_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_car (lst))));
274 Translator_group *two = tr->find_create_translator (ly_symbol2scm ("Voice"),
276 two_.set_translator (two);
277 set_translator (two);
278 second_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_cadr (lst))));
284 char const * syms[] = {
286 "DynamicLineSpanner",
295 for (char const**p = syms; *p; p++)
297 SCM sym = ly_symbol2scm (*p);
298 one->execute_pushpop_property (sym,
299 ly_symbol2scm ("direction"), gh_int2scm (1));
301 two->execute_pushpop_property (sym,
302 ly_symbol2scm ("direction"), gh_int2scm (-1));
308 New_pc_iterator::process (Moment m)
310 Moment now = report_to ()->now_mom ();
313 for (; gh_pair_p (split_list_); split_list_ = gh_cdr (split_list_))
315 splitm = unsmob_moment (gh_caar (split_list_));
319 SCM tag = gh_cdar (split_list_);
321 if (tag == ly_symbol2scm ("chords"))
323 else if (tag == ly_symbol2scm ("apart"))
325 else if (tag == ly_symbol2scm ("unisono"))
327 else if (tag == ly_symbol2scm ("solo1"))
329 else if (tag == ly_symbol2scm ("solo2"))
333 String s = "Unknown split directive: "
334 + (gh_symbol_p (tag) ? ly_symbol2string (tag) : String ("not a symbol"));
335 programming_error (s);
339 if (first_iter_->ok ())
340 first_iter_->process (m);
342 if (second_iter_->ok ())
343 second_iter_->process (m);
347 New_pc_iterator::try_music_in_children (Music *m) const
349 Music_iterator * i = first_iter_->try_music (m);
353 return second_iter_->try_music (m);
358 New_pc_iterator::get_pending_events (Moment m)const
362 s = gh_append2 (s,first_iter_->get_pending_events (m));
364 s = gh_append2 (second_iter_->get_pending_events (m),s);
368 IMPLEMENT_CTOR_CALLBACK (New_pc_iterator);