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::next_moment () const
33 Moment first_next = infinity_mom;
34 if (first_iter_p_->ok ())
35 first_next = first_iter_p_->next_moment ();
36 Moment second_next = infinity_mom;
37 if (second_iter_p_->ok ())
38 second_next = second_iter_p_->next_moment ();
39 if (first_next == infinity_mom && second_next == infinity_mom)
41 return first_next <? second_next;
45 Part_combine_music_iterator::ok () const
48 return first_iter_p_->ok () || second_iter_p_->ok ();
52 Part_combine_music_iterator::do_print () const
54 first_iter_p_->print ();
55 second_iter_p_->print ();
59 Part_combine_music_iterator::construct_children ()
61 Part_combine_music const * m = dynamic_cast<Part_combine_music const*> (music_l_);
63 first_iter_p_ = get_iterator_p (m->first_l ());
64 second_iter_p_ = get_iterator_p (m->second_l ());
68 Part_combine_music_iterator::change_to (Music_iterator *it, String to_type,
71 Translator_group * current = it->report_to_l ();
72 Translator_group * last = 0;
75 Cut & Paste from from Auto_change_iterator from Change_iterator (ugh).
77 TODO: abstract this function
80 /* find the type of translator that we're changing.
82 If \translator Staff = bass, then look for Staff = *
84 while (current && current->type_str_ != to_type)
87 current = current->daddy_trans_l_;
90 if (current && current->id_str_ == to_id)
93 msg += _ ("Can't switch translators, I'm there already");
99 Translator_group * dest =
100 it->report_to_l ()->find_create_translator_l (to_type, to_id);
101 current->remove_translator_p (last);
102 dest->add_group_translator (last);
107 We could change the current translator's id, but that would make
110 last->translator_id_str_ = change_l ()->change_to_id_str_;
112 error (_f ("I'm one myself: `%s'", to_type.ch_C ()));
115 error (_f ("none of these in my family: `%s'", to_id.ch_C ()));
119 Part_combine_music_iterator::do_process_and_next (Moment m)
121 Part_combine_music const * p = dynamic_cast<Part_combine_music const* > (music_l_);
123 Moment now = next_moment ();
125 Array<Musical_pitch> first_pitches;
126 Array<Duration> first_durations;
127 if (first_iter_p_->ok ())
129 Music_iterator* i = first_iter_p_->clone ();
130 Moment until = i->next_moment ();
132 /* Urg, silly first_b_ stuff */
133 if (now && i->next ())
134 until = i->next_moment ();
136 /* How about a 'now_moment ()' for iterators? */
137 for (; i->ok () && i->next_moment () == until; i->next ())
139 if (Music_sequence* m = dynamic_cast<Music_sequence *> (i->get_music ()))
141 for (SCM s = m->music_list (); gh_pair_p (s); s = gh_cdr (s))
143 Music *u = unsmob_music (gh_car (s));
144 if (Melodic_req *r = dynamic_cast<Melodic_req *> (u))
145 first_pitches.push (r->pitch_);
146 if (Rhythmic_req *r = dynamic_cast<Rhythmic_req *> (u))
147 first_durations.push (r->duration_);
153 Array<Musical_pitch> second_pitches;
154 Array<Duration> second_durations;
155 if (second_iter_p_->ok ())
157 Music_iterator* i = second_iter_p_->clone ();
158 Moment until = i->next_moment ();
160 /* Urg, silly second_b_ stuff */
161 if (now && i->next ())
162 until = i->next_moment ();
164 /* How about a 'now_moment ()' for iterators? */
165 for (; i->ok () && i->next_moment () == until; i->next ())
167 if (Music_sequence* m = dynamic_cast<Music_sequence *> (i->get_music ()))
169 for (SCM s = m->music_list (); gh_pair_p (s); s = gh_cdr (s))
171 Music *u = unsmob_music (gh_car (s));
172 if (Melodic_req *r = dynamic_cast<Melodic_req *> (u))
173 second_pitches.push (r->pitch_);
174 if (Rhythmic_req *r = dynamic_cast<Rhythmic_req *> (u))
175 second_durations.push (r->duration_);
181 SCM interval = SCM_BOOL_F;
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 Moment new_until = now + first_durations.top ().length_mom ();
193 if (new_until > first_until_)
194 first_until_ = new_until;
197 if (second_durations.size ())
199 second_durations.sort (Duration::compare);
200 Moment new_until = now + second_durations.top ().length_mom ();
201 if (new_until > second_until_)
202 second_until_ = new_until;
206 printf ("now: %s\n", now.str ().ch_C ());
208 for (int i = 0; i < first_pitches.size (); i++)
210 printf ("%s, ", first_pitches[i].str ().ch_C ());
212 printf ("\nsecond: ");
213 for (int i = 0; i < second_pitches.size (); i++)
215 printf ("%s, ", second_pitches[i].str ().ch_C ());
220 Translator_group * fir = first_iter_p_->report_to_l ();
221 Translator_group * sir = second_iter_p_->report_to_l ();
223 bool solo_b = (first_pitches.empty () != second_pitches.empty ())
224 && !(first_until_ > now && second_until_ > now);
226 bool unirhythm_b = !solo_b && !compare (&first_durations, &second_durations);
227 bool unison_b = unirhythm_b && !first_pitches.empty ()
228 &&!compare (&first_pitches, &second_pitches);
229 bool unisilence_b = unirhythm_b && first_pitches.empty ();
231 Translator_group * fd = fir->find_create_translator_l (p->what_str_, "one");
232 Translator_group * sd = sir->find_create_translator_l (p->what_str_, "two");
234 bool split_interval_b = false;
235 if (gh_number_p (interval))
237 SCM s = fd->get_property (ly_symbol2scm ("splitInterval"));
238 int i = gh_scm2int (interval);
240 && gh_number_p (gh_car (s))
241 && gh_number_p (gh_cdr (s))
242 && i >= gh_scm2int (gh_car (s))
243 && i <= gh_scm2int (gh_cdr (s)))
244 split_interval_b = true;
247 bool combined_b = first_iter_p_->report_to_l ()->daddy_trans_l_
248 == second_iter_p_->report_to_l ()->daddy_trans_l_;
250 String to_id = combined_b ? "one" : "two";
251 if ((!unirhythm_b && combined_b)
252 || (split_interval_b && combined_b)
253 || (solo_b && combined_b)
254 /*|| (unisilence_b && combined_b) */
255 || ((unirhythm_b || unison_b || unisilence_b)
256 && !combined_b && !split_interval_b && !solo_b))
258 combined_b = !combined_b;
259 to_id = combined_b ? "one" : "two";
260 change_to (second_iter_p_, p->what_str_, to_id);
264 sir = second_iter_p_->report_to_l ();
266 SCM b = unirhythm_b ? SCM_BOOL_T : SCM_BOOL_F;
267 fd->set_property ("unirhythm", b);
268 sd->set_property ("unirhythm", b);
270 b = split_interval_b ? SCM_BOOL_T : SCM_BOOL_F;
271 fd->set_property ("split-interval", b);
272 sd->set_property ("split-interval", b);
274 b = unisilence_b ? SCM_BOOL_T : SCM_BOOL_F;
275 fd->set_property ("unisilence", b);
276 sd->set_property ("unisilence", b);
278 b = unison_b ? SCM_BOOL_T : SCM_BOOL_F;
279 fd->set_property ("unison", b);
280 sd->set_property ("unison", b);
282 b = solo_b ? SCM_BOOL_T : SCM_BOOL_F;
283 if (first_pitches.size ())
285 fd->set_property ("solo", b);
286 sd->set_property ("solo", SCM_BOOL_F);
289 if (second_pitches.size ())
291 fd->set_property ("solo", SCM_BOOL_F);
292 sd->set_property ("solo", b);
296 Hmm, shouldn't we check per iterator if next_moment < m?
298 if (first_iter_p_->ok ())
299 first_iter_p_->process_and_next (m);
301 if (second_iter_p_->ok ())
302 second_iter_p_->process_and_next (m);
304 Music_iterator::do_process_and_next (m);
308 Part_combine_music_iterator::try_music_in_children (Music *m) const
310 Music_iterator * i = first_iter_p_->try_music (m);
314 return second_iter_p_->try_music (m);