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" + suffix_);
133 SCM s = first_translator->get_property (ly_symbol2scm ("changeMoment"));
137 Moment change_mom = *unsmob_moment (gh_car (s));
138 Moment diff_mom = *unsmob_moment (gh_cdr (s));
140 Moment now = pending_moment ();
142 if (!now.mod_rat (change_mom))
144 SCM interval = SCM_BOOL_F;
145 if (first_until_ < now)
147 if (second_until_ < now)
150 Moment first_mom = first_until_;
151 Moment second_mom = second_until_;
152 Moment diff_until = diff_mom + now;
155 Music_iterator *first_iter = first_iter_p_->clone ();
156 Music_iterator *second_iter = second_iter_p_->clone ();
158 Moment last_pending (-1);
159 Moment pending = now;
160 while (now < diff_until
161 && (first_iter->ok () || second_iter->ok ())
163 // urg, this is a hack, haven't caught this case yet
164 && (pending != last_pending))
166 if (!second_iter->ok ())
167 pending = first_iter->pending_moment ();
168 else if (!first_iter->ok ())
169 pending = second_iter->pending_moment ();
171 pending = first_iter->pending_moment () <? second_iter->pending_moment ();
172 last_pending = pending;
174 Array<Musical_pitch> first_pitches;
175 Array<Duration> first_durations;
176 get_music_info (pending, first_iter, &first_pitches, &first_durations);
178 Array<Musical_pitch> second_pitches;
179 Array<Duration> second_durations;
180 get_music_info (pending, second_iter, &second_pitches, &second_durations);
182 if (first_pitches.size () && second_pitches.size ())
184 first_pitches.sort (Musical_pitch::compare);
185 second_pitches.sort (Musical_pitch::compare);
186 interval = gh_int2scm (first_pitches.top ().steps ()
187 - second_pitches[0].steps ());
189 if (first_durations.size ())
191 first_durations.sort (Duration::compare);
192 first_mom += first_durations.top ().length_mom ();
195 if (second_durations.size ())
197 second_durations.sort (Duration::compare);
198 second_mom += second_durations.top ().length_mom ();
201 if (!first_pitches.empty () && second_pitches.empty ()
202 && !(second_until_ > now))
205 state &= ~UNISILENCE;
206 if (!(state & ~(UNRELATED | SOLO1 | UNISILENCE)))
212 if (first_pitches.empty () && !second_pitches.empty ()
213 && !(first_until_ > now))
216 state &= ~UNISILENCE;
217 if (!(state & ~(UNRELATED | SOLO2 | UNISILENCE)))
223 if (!compare (&first_durations, &second_durations))
225 state &= ~UNISILENCE;
226 if (!(state & ~(UNIRHYTHM | UNISON)))
230 state &= ~(UNIRHYTHM | UNISILENCE);
232 if (!first_pitches.empty ()
233 &&!compare (&first_pitches, &second_pitches))
235 state &= ~UNISILENCE;
236 if (!(state & ~(UNIRHYTHM | UNISON)))
242 if (first_pitches.empty () && second_pitches.empty ())
244 if (!(state & ~(UNIRHYTHM | UNISILENCE)))
250 state &= ~(UNISILENCE);
252 if (gh_number_p (interval))
254 SCM s = first_translator->get_property (ly_symbol2scm ("splitInterval"));
255 int i = gh_scm2int (interval);
257 && gh_number_p (gh_car (s))
258 && gh_number_p (gh_cdr (s))
259 && i >= gh_scm2int (gh_car (s))
260 && i <= gh_scm2int (gh_cdr (s)))
262 if (!(state & ~(SPLIT_INTERVAL | UNIRHYTHM | UNISON)))
263 state |= SPLIT_INTERVAL;
266 state &= ~(SPLIT_INTERVAL);
269 if (first && !first_pitches.empty ())
270 first_until_ = first_mom;
271 if (first && !second_pitches.empty ())
272 second_until_ = second_mom;
275 if (first_iter->ok ())
276 first_iter->skip (pending);
277 if (second_iter->ok ())
278 second_iter->skip (pending);
288 Part_combine_music_iterator::process (Moment m)
293 - Use three named contexts (be it Thread or Voice): one, two, solo.
294 Let user pre-set (pushproperty) stem direction, remove
295 dynamic-engraver, and such.
297 **** Tried this, but won't work:
299 Consider thread switching: threads "one", "two" and "both".
300 User can't pre-set the (most important) stem direction at
304 if (suffix_.empty_b ())
305 suffix_ = first_iter_p_->report_to_l ()->daddy_trans_l_->id_str_.cut_str (3, INT_MAX);
307 int state = get_state (m);
313 Part_combine_music const *p = dynamic_cast<Part_combine_music const* > (music_l_);
316 bool previously_combined_b = first_iter_p_->report_to_l ()->daddy_trans_l_
317 == second_iter_p_->report_to_l ()->daddy_trans_l_;
319 bool combine_b = previously_combined_b;
321 if (!(state & UNIRHYTHM)
322 || (state & SPLIT_INTERVAL)
323 || (state & (SOLO1 | SOLO2)))
325 else if (state & (UNIRHYTHM | UNISILENCE))
328 if (combine_b != previously_combined_b)
329 change_to (second_iter_p_, p->what_str_, (combine_b ? "one" : "two")
332 Translator_group *first_translator = first_iter_p_->report_to_l ()->find_create_translator_l (p->what_str_, "one" + suffix_);
333 Translator_group *second_translator = second_iter_p_->report_to_l ()->find_create_translator_l (p->what_str_, "two" + suffix_);
338 SCM b = (state & UNIRHYTHM) ? SCM_BOOL_T : SCM_BOOL_F;
339 first_translator->set_property ("unirhythm", b);
340 second_translator->set_property ("unirhythm", b);
342 b = (state & SPLIT_INTERVAL) ? SCM_BOOL_T : SCM_BOOL_F;
343 first_translator->set_property ("split-interval", b);
344 second_translator->set_property ("split-interval", b);
346 b = (state & UNISILENCE) ? SCM_BOOL_T : SCM_BOOL_F;
347 first_translator->set_property ("unisilence", b);
348 second_translator->set_property ("unisilence", b);
350 // difference in definition...
351 //b = ((state & UNISON) ? SCM_BOOL_T : SCM_BOOL_F;
352 b = ((state & UNISON) && (state & UNIRHYTHM)) ? SCM_BOOL_T : SCM_BOOL_F;
353 first_translator->set_property ("unison", b);
354 second_translator->set_property ("unison", b);
356 SCM b1 = (state & SOLO1) ? SCM_BOOL_T : SCM_BOOL_F;
357 SCM b2 = (state & SOLO2) ? SCM_BOOL_T : SCM_BOOL_F;
358 first_translator->set_property ("solo", b1);
359 second_translator->set_property ("solo", b2);
361 if (first_iter_p_->ok ())
362 first_iter_p_->process (m);
364 if (second_iter_p_->ok ())
365 second_iter_p_->process (m);
369 Part_combine_music_iterator::try_music_in_children (Music *m) const
371 Music_iterator * i = first_iter_p_->try_music (m);
375 return second_iter_p_->try_music (m);
380 Part_combine_music_iterator::get_music (Moment m)const
384 s = gh_append2 (s,first_iter_p_->get_music (m));
386 s = gh_append2 (second_iter_p_->get_music (m),s);