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"
15 Part_combine_music_iterator::Part_combine_music_iterator ()
26 Part_combine_music_iterator::~Part_combine_music_iterator ()
28 delete second_iter_p_;
33 Part_combine_music_iterator::next_moment () const
35 Moment first_next = infinity_mom;
36 if (first_iter_p_->ok ())
37 first_next = first_iter_p_->next_moment ();
38 Moment second_next = infinity_mom;
39 if (second_iter_p_->ok ())
40 second_next = second_iter_p_->next_moment ();
41 if (first_next == infinity_mom && second_next == infinity_mom)
43 return first_next <? second_next;
47 Part_combine_music_iterator::ok () const
50 return first_iter_p_->ok () || second_iter_p_->ok ();
54 Part_combine_music_iterator::do_print () const
56 first_iter_p_->print ();
57 second_iter_p_->print ();
61 Part_combine_music_iterator::construct_children ()
63 Part_combine_music const * m = dynamic_cast<Part_combine_music const*> (music_l_);
65 first_iter_p_ = get_iterator_p (m->first_l ());
66 second_iter_p_ = get_iterator_p (m->second_l ());
70 Part_combine_music_iterator::change_to (Music_iterator *it, String to_type,
73 Translator_group * current = it->report_to_l ();
74 Translator_group * last = 0;
77 Cut & Paste from from Auto_change_iterator from Change_iterator (ugh).
79 TODO: abstract this function
82 /* find the type of translator that we're changing.
84 If \translator Staff = bass, then look for Staff = *
86 while (current && current->type_str_ != to_type)
89 current = current->daddy_trans_l_;
92 if (current && current->id_str_ == to_id)
95 msg += _ ("Can't switch translators, I'm there already");
101 Translator_group * dest =
102 it->report_to_l ()->find_create_translator_l (to_type, to_id);
103 current->remove_translator_p (last);
104 dest->add_group_translator (last);
109 We could change the current translator's id, but that would make
112 last->translator_id_str_ = change_l ()->change_to_id_str_;
114 error (_f ("I'm one myself: `%s'", to_type.ch_C ()));
117 error (_f ("none of these in my family: `%s'", to_id.ch_C ()));
120 Pitch_interrogate_req* first_spanish_inquisition; // nobody expects it
121 Pitch_interrogate_req* second_spanish_inquisition; // won't strike twice
123 Rhythm_interrogate_req* first_rhythmic_inquisition;
124 Rhythm_interrogate_req* second_rhythmic_inquisition;
127 Part_combine_music_iterator::do_process_and_next (Moment m)
129 Part_combine_music const * p = dynamic_cast<Part_combine_music const* > (music_l_);
131 now_ = next_moment ();
134 Hmm, shouldn't we check per iterator if next_moment < m?
136 if (first_iter_p_->ok ())
137 first_iter_p_->process_and_next (m);
139 if (second_iter_p_->ok ())
140 second_iter_p_->process_and_next (m);
142 Music_iterator::do_process_and_next (m);
147 * Maybe we need a Skip_engraver?
149 (check): can this all be handled now?
151 Maybe different modes exist?
153 * Wind instruments (Flute I/II)
157 Rules for Hymnals/SATB (John Henckel <henckel@iname.com>):
159 1. if S and A differ by less than a third, the stems should be up/down.
160 2. else if S and A have different values, the stems should be up/down.
161 3. else if A sings "la" or higher, both S and A stems should be down.
162 4. else both stems should be up
164 * This may get really tricky: combining voices/staffs: string instruments
168 if (!first_spanish_inquisition)
169 first_spanish_inquisition = new Pitch_interrogate_req;
170 first_iter_p_->try_music (first_spanish_inquisition);
172 if (!second_spanish_inquisition)
173 second_spanish_inquisition = new Pitch_interrogate_req;
174 second_iter_p_->try_music (second_spanish_inquisition);
176 Array<Musical_pitch>* first_pitches = &first_spanish_inquisition->pitch_arr_;
177 Array<Musical_pitch>* second_pitches = &second_spanish_inquisition->pitch_arr_;
179 if (!first_rhythmic_inquisition)
180 first_rhythmic_inquisition = new Rhythm_interrogate_req;
181 first_iter_p_->try_music (first_rhythmic_inquisition);
183 if (!second_rhythmic_inquisition)
184 second_rhythmic_inquisition = new Rhythm_interrogate_req;
185 second_iter_p_->try_music (second_rhythmic_inquisition);
187 Array<Duration>* first_durations = &first_rhythmic_inquisition->duration_arr_;
188 Array<Duration>* second_durations = &second_rhythmic_inquisition->duration_arr_;
190 SCM interval = SCM_BOOL_F;
191 if (first_pitches->size () && second_pitches->size ())
193 first_pitches->sort (Musical_pitch::compare);
194 second_pitches->sort (Musical_pitch::compare);
195 interval = gh_int2scm (first_pitches->top ().steps ()
196 - (*second_pitches)[0].steps ());
198 if (first_durations->size ())
200 first_durations->sort (Duration::compare);
201 Moment new_until = now_ + first_durations->top ().length_mom ();
202 if (new_until > first_until_)
203 first_until_ = new_until;
206 if (second_durations->size ())
208 second_durations->sort (Duration::compare);
209 Moment new_until = now_ + second_durations->top ().length_mom ();
210 if (new_until > second_until_)
211 second_until_ = new_until;
214 Translator_group * fir = first_iter_p_->report_to_l ();
215 Translator_group * sir = second_iter_p_->report_to_l ();
217 bool solo_b = (first_pitches->empty () != second_pitches->empty ())
218 && !(first_until_ > now_ && second_until_ > now_);
220 bool unirhythm_b = !solo_b && !compare (first_durations, second_durations);
221 bool unison_b = unirhythm_b && !first_pitches->empty ()
222 &&!compare (first_pitches, second_pitches);
223 bool unisilence_b = unirhythm_b && first_pitches->empty ();
225 Translator_group * fd = fir->find_create_translator_l (p->what_str_, "one");
226 Translator_group * sd = sir->find_create_translator_l (p->what_str_, "two");
228 bool split_interval_b = false;
229 if (gh_number_p (interval))
231 SCM s = fd->get_property (ly_symbol2scm ("splitInterval"));
232 int i = gh_scm2int (interval);
234 && gh_number_p (gh_car (s))
235 && gh_number_p (gh_cdr (s))
236 && i >= gh_scm2int (gh_car (s))
237 && i <= gh_scm2int (gh_cdr (s)))
238 split_interval_b = true;
242 Hmm, maybe we should set/check combined_b_ against
244 first_iter_p_->report_to_l () == second_iter_p_->report_to_l ()
249 String to_id = combined_b_ ? "one" : "two";
250 if ((!unirhythm_b && combined_b_)
251 || (split_interval_b && combined_b_)
252 || (solo_b && combined_b_)
253 /*|| (unisilence_b && combined_b_) */
254 || ((unirhythm_b || unison_b || unisilence_b)
255 && !combined_b_ && !split_interval_b && !solo_b))
257 combined_b_ = !combined_b_;
258 to_id = combined_b_ ? "one" : "two";
259 change_to (second_iter_p_, p->what_str_, to_id);
263 sir = second_iter_p_->report_to_l ();
265 SCM b = unirhythm_b ? SCM_BOOL_T : SCM_BOOL_F;
266 fd->set_property ("unirhythm", b);
267 sd->set_property ("unirhythm", b);
269 b = split_interval_b ? SCM_BOOL_T : SCM_BOOL_F;
270 fd->set_property ("split-interval", b);
271 sd->set_property ("split-interval", b);
273 b = unisilence_b ? SCM_BOOL_T : SCM_BOOL_F;
274 fd->set_property ("unisilence", b);
275 sd->set_property ("unisilence", b);
277 b = unison_b ? SCM_BOOL_T : SCM_BOOL_F;
278 fd->set_property ("unison", b);
279 sd->set_property ("unison", b);
281 b = solo_b ? SCM_BOOL_T : SCM_BOOL_F;
282 if (first_pitches->size ())
284 fd->set_property ("solo", b);
285 sd->set_property ("solo", SCM_BOOL_F);
288 if (second_pitches->size ())
290 fd->set_property ("solo", SCM_BOOL_F);
291 sd->set_property ("solo", b);
294 first_pitches->clear ();
295 second_pitches->clear ();
296 first_durations->clear ();
297 second_durations->clear ();
301 Part_combine_music_iterator::try_music_in_children (Music *m) const
303 Music_iterator * i = first_iter_p_->try_music (m);
307 return second_iter_p_->try_music (m);