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 "sequential-music-iterator.hh"
12 #include "translator-group.hh"
13 #include "musical-request.hh"
16 Part_combine_music_iterator::Part_combine_music_iterator ()
27 Part_combine_music_iterator::~Part_combine_music_iterator ()
29 delete second_iter_p_;
34 Part_combine_music_iterator::next_moment () const
36 Moment first_next = infinity_mom;
37 if (first_iter_p_->ok ())
38 first_next = first_iter_p_->next_moment ();
39 Moment second_next = infinity_mom;
40 if (second_iter_p_->ok ())
41 second_next = second_iter_p_->next_moment ();
42 if (first_next == infinity_mom && second_next == infinity_mom)
44 return first_next <? second_next;
48 Part_combine_music_iterator::ok () const
51 return first_iter_p_->ok () || second_iter_p_->ok ();
55 Part_combine_music_iterator::do_print () const
57 first_iter_p_->print ();
58 second_iter_p_->print ();
62 Part_combine_music_iterator::construct_children ()
64 Part_combine_music const * m = dynamic_cast<Part_combine_music const*> (music_l_);
66 first_iter_p_ = get_iterator_p (m->first_l ());
67 second_iter_p_ = get_iterator_p (m->second_l ());
71 Part_combine_music_iterator::change_to (Music_iterator *it, String to_type,
74 Translator_group * current = it->report_to_l ();
75 Translator_group * last = 0;
78 Cut & Paste from from Auto_change_iterator from Change_iterator (ugh).
80 TODO: abstract this function
83 /* find the type of translator that we're changing.
85 If \translator Staff = bass, then look for Staff = *
87 while (current && current->type_str_ != to_type)
90 current = current->daddy_trans_l_;
93 if (current && current->id_str_ == to_id)
96 msg += _ ("Can't switch translators, I'm there already");
102 Translator_group * dest =
103 it->report_to_l ()->find_create_translator_l (to_type, to_id);
104 current->remove_translator_p (last);
105 dest->add_translator (last);
110 We could change the current translator's id, but that would make
113 last->translator_id_str_ = change_l ()->change_to_id_str_;
115 error (_f ("I'm one myself: `%s'", to_type.ch_C ()));
118 error (_f ("none of these in my family: `%s'", to_id.ch_C ()));
121 Pitch_interrogate_req* first_spanish_inquisition; // nobody expects it
122 Pitch_interrogate_req* second_spanish_inquisition; // won't strike twice
124 Rhythm_interrogate_req* first_rhythmic_inquisition;
125 Rhythm_interrogate_req* second_rhythmic_inquisition;
127 #include <iostream.h>
130 Part_combine_music_iterator::do_process_and_next (Moment m)
132 Part_combine_music const * p = dynamic_cast<Part_combine_music const* > (music_l_);
134 now_ = next_moment ();
136 Music* first_music = 0;
137 Music* second_music = 0;
140 Hmm, shouldn't we check per iterator if next_moment < m?
142 if (first_iter_p_->ok ())
144 first_music = first_iter_p_->get_next_music ();
145 first_iter_p_->process_and_next (m);
148 if (second_iter_p_->ok ())
150 second_music = second_iter_p_->get_next_music ();
151 second_iter_p_->process_and_next (m);
154 Music_iterator::do_process_and_next (m);
159 * Maybe we need a Skip_engraver?
161 (check): can this all be handled now?
163 Maybe different modes exist?
165 * Wind instruments (Flute I/II)
169 Rules for Hymnals/SATB (John Henckel <henckel@iname.com>):
171 1. if S and A differ by less than a third, the stems should be up/down.
172 2. else if S and A have different values, the stems should be up/down.
173 3. else if A sings "la" or higher, both S and A stems should be down.
174 4. else both stems should be up
176 * This may get really tricky: combining voices/staffs: string instruments
180 if (!first_spanish_inquisition)
181 first_spanish_inquisition = new Pitch_interrogate_req;
182 first_iter_p_->try_music (first_spanish_inquisition);
184 if (!second_spanish_inquisition)
185 second_spanish_inquisition = new Pitch_interrogate_req;
186 second_iter_p_->try_music (second_spanish_inquisition);
188 Array<Musical_pitch>* first_pitches = &first_spanish_inquisition->pitch_arr_;
189 Array<Musical_pitch>* second_pitches = &second_spanish_inquisition->pitch_arr_;
191 if (!first_rhythmic_inquisition)
192 first_rhythmic_inquisition = new Rhythm_interrogate_req;
193 first_iter_p_->try_music (first_rhythmic_inquisition);
195 if (!second_rhythmic_inquisition)
196 second_rhythmic_inquisition = new Rhythm_interrogate_req;
197 second_iter_p_->try_music (second_rhythmic_inquisition);
199 Array<Duration>* first_durations = &first_rhythmic_inquisition->duration_arr_;
200 Array<Duration>* second_durations = &second_rhythmic_inquisition->duration_arr_;
202 if (!first_durations->empty ())
203 cout << "first_durations: " << first_durations->top ().length_mom ().str () << endl;
205 // if (Rhythmic_req *r = dynamic_cast<Rhythmic_req*> (first_music))
207 cout << "first_music: " << first_music->length_mom ().str ();
209 SCM interval = SCM_BOOL_F;
210 if (first_pitches->size () && second_pitches->size ())
212 first_pitches->sort (Musical_pitch::compare);
213 second_pitches->sort (Musical_pitch::compare);
214 interval = gh_int2scm (first_pitches->top ().steps ()
215 - (*second_pitches)[0].steps ());
217 if (first_durations->size ())
219 first_durations->sort (Duration::compare);
220 Moment new_until = now_ + first_durations->top ().length_mom ();
221 if (new_until > first_until_)
222 first_until_ = new_until;
225 if (second_durations->size ())
227 second_durations->sort (Duration::compare);
228 Moment new_until = now_ + second_durations->top ().length_mom ();
229 if (new_until > second_until_)
230 second_until_ = new_until;
233 Translator_group * fir = first_iter_p_->report_to_l ();
234 Translator_group * sir = second_iter_p_->report_to_l ();
236 bool solo_b = (first_pitches->empty () != second_pitches->empty ())
237 && !(first_until_ > now_ && second_until_ > now_);
239 bool unirhythm_b = !solo_b && !compare (first_durations, second_durations);
240 bool unison_b = unirhythm_b && !first_pitches->empty ()
241 &&!compare (first_pitches, second_pitches);
242 bool unisilence_b = unirhythm_b && first_pitches->empty ();
244 Translator_group * fd = fir->find_create_translator_l (p->what_str_, "one");
245 Translator_group * sd = sir->find_create_translator_l (p->what_str_, "two");
247 bool split_interval_b = false;
248 if (gh_number_p (interval))
250 SCM s = fd->get_property (ly_symbol2scm ("splitInterval"));
251 int i = gh_scm2int (interval);
253 && gh_number_p (gh_car (s))
254 && gh_number_p (gh_cdr (s))
255 && i >= gh_scm2int (gh_car (s))
256 && i <= gh_scm2int (gh_cdr (s)))
257 split_interval_b = true;
261 Hmm, maybe we should set/check combined_b_ against
263 first_iter_p_->report_to_l () == second_iter_p_->report_to_l ()
268 String to_id = combined_b_ ? "one" : "two";
269 if ((!unirhythm_b && combined_b_)
270 || (split_interval_b && combined_b_)
271 || (solo_b && combined_b_)
272 /*|| (unisilence_b && combined_b_) */
273 || ((unirhythm_b || unison_b || unisilence_b)
274 && !combined_b_ && !split_interval_b && !solo_b))
276 combined_b_ = !combined_b_;
277 to_id = combined_b_ ? "one" : "two";
278 change_to (second_iter_p_, p->what_str_, to_id);
282 sir = second_iter_p_->report_to_l ();
284 SCM b = unirhythm_b ? SCM_BOOL_T : SCM_BOOL_F;
285 fd->set_property ("unirhythm", b);
286 sd->set_property ("unirhythm", b);
288 b = split_interval_b ? SCM_BOOL_T : SCM_BOOL_F;
289 fd->set_property ("split-interval", b);
290 sd->set_property ("split-interval", b);
292 b = unisilence_b ? SCM_BOOL_T : SCM_BOOL_F;
293 fd->set_property ("unisilence", b);
294 sd->set_property ("unisilence", b);
296 b = unison_b ? SCM_BOOL_T : SCM_BOOL_F;
297 fd->set_property ("unison", b);
298 sd->set_property ("unison", b);
300 b = solo_b ? SCM_BOOL_T : SCM_BOOL_F;
301 if (first_pitches->size ())
303 fd->set_property ("solo", b);
304 sd->set_property ("solo", SCM_BOOL_F);
307 if (second_pitches->size ())
309 fd->set_property ("solo", SCM_BOOL_F);
310 sd->set_property ("solo", b);
313 first_pitches->clear ();
314 second_pitches->clear ();
315 first_durations->clear ();
316 second_durations->clear ();
320 Part_combine_music_iterator::try_music_in_children (Music *m) const
322 Music_iterator * i = first_iter_p_->try_music (m);
326 return second_iter_p_->try_music (m);