2 part-combine-music-iterator.cc -- implement Part_combine_music_iterator
4 source file of the GNU LilyPond music typesetter
6 (c) 2000 Jan Nieuwenhuizen <janneke@gnu.org>
9 #include "part-combine-music.hh"
10 #include "part-combine-music-iterator.hh"
11 #include "translator-group.hh"
12 #include "musical-request.hh"
13 #include "music-sequence.hh"
16 Part_combine_music_iterator::Part_combine_music_iterator ()
24 Part_combine_music_iterator::~Part_combine_music_iterator ()
26 delete second_iter_p_;
31 Part_combine_music_iterator::pending_moment () const
35 if (first_iter_p_->ok ())
36 p = p <? first_iter_p_->pending_moment ();
38 if (second_iter_p_->ok ())
39 p = p <? second_iter_p_->pending_moment ();
44 Part_combine_music_iterator::ok () const
46 return first_iter_p_->ok () || second_iter_p_->ok ();
50 Part_combine_music_iterator::construct_children ()
52 Part_combine_music const * m = dynamic_cast<Part_combine_music const*> (music_l_);
54 first_iter_p_ = get_iterator_p (m->first_l ());
55 second_iter_p_ = get_iterator_p (m->second_l ());
59 Part_combine_music_iterator::change_to (Music_iterator *it, String to_type,
62 Translator_group * current = it->report_to_l ();
63 Translator_group * last = 0;
66 Cut & Paste from from Auto_change_iterator from Change_iterator (ugh).
68 TODO: abstract this function
71 /* find the type of translator that we're changing.
73 If \translator Staff = bass, then look for Staff = *
75 while (current && current->type_str_ != to_type)
78 current = current->daddy_trans_l_;
81 if (current && current->id_str_ == to_id)
84 msg += _ ("Can't switch translators, I'm there already");
90 Translator_group * dest =
91 it->report_to_l ()->find_create_translator_l (to_type, to_id);
92 current->remove_translator_p (last);
93 dest->add_group_translator (last);
98 We could change the current translator's id, but that would make
101 last->translator_id_str_ = change_l ()->change_to_id_str_;
103 error (_f ("I'm one myself: `%s'", to_type.ch_C ()));
106 error (_f ("none of these in my family: `%s'", to_id.ch_C ()));
111 get_music_info (Moment m, Music_iterator* iter, Array<Musical_pitch> *pitches, Array<Duration> *durations)
115 for (SCM i = iter->get_music (m); gh_pair_p (i); i = gh_cdr (i))
117 Music *m = unsmob_music (gh_car (i));
118 if (Melodic_req *r = dynamic_cast<Melodic_req *> (m))
119 pitches->push (r->pitch_);
120 if (Rhythmic_req *r = dynamic_cast<Rhythmic_req *> (m))
121 durations->push (r->duration_);
127 Part_combine_music_iterator::get_state (Moment)
130 Part_combine_music const *p = dynamic_cast<Part_combine_music const* > (music_l_);
131 Translator_group *first_translator = first_iter_p_->report_to_l ()->find_create_translator_l (p->what_str_, "one");
133 SCM s = first_translator->get_property (ly_symbol2scm ("changeMoment"));
134 Moment change_mom = *unsmob_moment (gh_car (s));
135 Moment diff_mom = *unsmob_moment (gh_cdr (s));
137 Moment now = pending_moment ();
139 if (!now.mod_rat (change_mom))
141 SCM interval = SCM_BOOL_F;
142 Moment first_mom = first_until_ - now;
143 Moment second_mom = second_until_ - now;
146 Music_iterator *first_iter = first_iter_p_->clone ();
147 Music_iterator *second_iter = second_iter_p_->clone ();
148 while ((first_mom <? second_mom) < diff_mom
149 && (first_iter->ok () || second_iter->ok ()))
152 if (!second_iter->ok ())
153 m = first_iter->pending_moment ();
154 else if (!first_iter->ok ())
155 m = second_iter->pending_moment ();
157 m = first_iter->pending_moment () <? second_iter->pending_moment ();
159 Array<Musical_pitch> first_pitches;
160 Array<Duration> first_durations;
161 get_music_info (m, first_iter, &first_pitches, &first_durations);
163 Array<Musical_pitch> second_pitches;
164 Array<Duration> second_durations;
165 get_music_info (m, second_iter, &second_pitches, &second_durations);
167 if (first_pitches.size () && second_pitches.size ())
169 first_pitches.sort (Musical_pitch::compare);
170 second_pitches.sort (Musical_pitch::compare);
171 interval = gh_int2scm (first_pitches.top ().steps ()
172 - second_pitches[0].steps ());
174 if (first_durations.size ())
176 first_durations.sort (Duration::compare);
177 first_mom += first_durations.top ().length_mom ();
179 first_until_ = first_mom + now;
182 if (second_durations.size ())
184 second_durations.sort (Duration::compare);
185 second_mom += second_durations.top ().length_mom ();
187 second_until_ = second_mom + now;
192 printf ("now: %s\n", now.str ().ch_C ());
194 for (int i = 0; i < first_pitches.size (); i++)
196 printf ("%s, ", first_pitches[i].str ().ch_C ());
198 printf ("\nsecond: ");
199 for (int i = 0; i < second_pitches.size (); i++)
201 printf ("%s, ", second_pitches[i].str ().ch_C ());
206 if (!first_pitches.empty () && second_pitches.empty ()
207 && !(second_until_ > now))
210 state &= ~UNISILENCE;
211 if (!(state & ~(UNRELATED | SOLO1 | UNISILENCE)))
217 if (first_pitches.empty () && !second_pitches.empty ()
218 && !(first_until_ > now))
221 state &= ~UNISILENCE;
222 if (!(state & ~(UNRELATED | SOLO2 | UNISILENCE)))
228 if (!compare (&first_durations, &second_durations))
230 state &= ~UNISILENCE;
231 if (!(state & ~(UNIRHYTHM | UNISON)))
235 state &= ~(UNIRHYTHM | UNISILENCE);
237 if (!first_pitches.empty ()
238 &&!compare (&first_pitches, &second_pitches))
240 state &= ~UNISILENCE;
241 if (!(state & ~(UNIRHYTHM | UNISON)))
247 if (first_pitches.empty () && second_pitches.empty ())
249 if (!(state & ~(UNIRHYTHM | UNISILENCE)))
253 state &= ~(UNISILENCE);
255 if (gh_number_p (interval))
257 SCM s = first_translator->get_property (ly_symbol2scm ("splitInterval"));
258 int i = gh_scm2int (interval);
260 && gh_number_p (gh_car (s))
261 && gh_number_p (gh_cdr (s))
262 && i >= gh_scm2int (gh_car (s))
263 && i <= gh_scm2int (gh_cdr (s)))
265 if (!(state & ~(SPLIT_INTERVAL | UNIRHYTHM | UNISON)))
266 state |= SPLIT_INTERVAL;
269 state &= ~(SPLIT_INTERVAL);
273 Moment next = (first_mom <? second_mom) + now;
274 if (first_iter->ok ())
275 first_iter->skip (next);
276 if (second_iter->ok ())
277 second_iter->skip (next);
279 if (first_iter->ok ())
280 first_iter->skip (first_mom + now);
281 if (second_iter->ok ())
282 second_iter->skip (second_mom + now);
292 Part_combine_music_iterator::process (Moment m)
297 - Use three named contexts (be it Thread or Voice): one, two, solo.
298 Let user pre-set (pushproperty) stem direction, remove
299 dynamic-engraver, and such.
302 int state = get_state (m);
308 Part_combine_music const *p = dynamic_cast<Part_combine_music const* > (music_l_);
310 bool combined_b = first_iter_p_->report_to_l ()->daddy_trans_l_
311 == second_iter_p_->report_to_l ()->daddy_trans_l_;
313 String to_id = combined_b ? "one" : "two";
314 if ((!(state & UNIRHYTHM) && combined_b)
315 || ((state & SPLIT_INTERVAL) && combined_b)
316 || ((state & (SOLO1 | SOLO2)) && combined_b)
317 || (((state & (UNIRHYTHM | UNISILENCE))
318 && !combined_b && !(state & SPLIT_INTERVAL)
319 && !(state & (SOLO1 | SOLO2)))))
321 combined_b = !combined_b;
322 to_id = combined_b ? "one" : "two";
323 change_to (second_iter_p_, p->what_str_, to_id);
327 Translator_group *first_translator = first_iter_p_->report_to_l ()->find_create_translator_l (p->what_str_, "one");
328 Translator_group *second_translator = second_iter_p_->report_to_l ()->find_create_translator_l (p->what_str_, "two");
333 SCM b = (state & UNIRHYTHM) ? SCM_BOOL_T : SCM_BOOL_F;
334 first_translator->set_property ("unirhythm", b);
335 second_translator->set_property ("unirhythm", b);
337 b = (state & SPLIT_INTERVAL) ? SCM_BOOL_T : SCM_BOOL_F;
338 first_translator->set_property ("split-interval", b);
339 second_translator->set_property ("split-interval", b);
341 b = (state & UNISILENCE) ? SCM_BOOL_T : SCM_BOOL_F;
342 first_translator->set_property ("unisilence", b);
343 second_translator->set_property ("unisilence", b);
345 // difference in definition...
346 //b = ((state & UNISON) ? SCM_BOOL_T : SCM_BOOL_F;
347 b = ((state & UNISON) && (state & UNIRHYTHM)) ? SCM_BOOL_T : SCM_BOOL_F;
348 first_translator->set_property ("unison", b);
349 second_translator->set_property ("unison", b);
351 SCM b1 = (state & SOLO1) ? SCM_BOOL_T : SCM_BOOL_F;
352 SCM b2 = (state & SOLO1) ? SCM_BOOL_T : SCM_BOOL_F;
353 first_translator->set_property ("solo", b1);
354 second_translator->set_property ("solo", b2);
356 if (first_iter_p_->ok ())
357 first_iter_p_->process (m);
359 if (second_iter_p_->ok ())
360 second_iter_p_->process (m);
364 Part_combine_music_iterator::try_music_in_children (Music *m) const
366 Music_iterator * i = first_iter_p_->try_music (m);
370 return second_iter_p_->try_music (m);
375 Part_combine_music_iterator::get_music (Moment m)const
379 s = gh_append2 (s,first_iter_p_->get_music (m));
381 s = gh_append2 (second_iter_p_->get_music (m),s);