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 ()
23 Part_combine_music_iterator::~Part_combine_music_iterator ()
25 delete second_iter_p_;
30 Part_combine_music_iterator::next_moment () const
32 Moment first_next = first_iter_p_->next_moment ();
33 Moment second_next = second_iter_p_->next_moment ();
34 return first_next <? second_next;
38 Part_combine_music_iterator::ok () const
41 return first_iter_p_->ok ();
45 Part_combine_music_iterator::do_print () const
47 first_iter_p_->print ();
48 second_iter_p_->print ();
52 Part_combine_music_iterator::construct_children ()
54 Part_combine_music const * m = dynamic_cast<Part_combine_music const*> (music_l_);
56 first_iter_p_ = get_iterator_p (m->first_l ());
57 second_iter_p_ = get_iterator_p (m->second_l ());
61 Part_combine_music_iterator::change_to (Music_iterator *it, String to_type,
64 Translator_group * current = it->report_to_l ();
65 Translator_group * last = 0;
68 Cut & Paste from from Auto_change_iterator from Change_iterator (ugh).
70 TODO: abstract this function
73 /* find the type of translator that we're changing.
75 If \translator Staff = bass, then look for Staff = *
77 while (current && current->type_str_ != to_type)
80 current = current->daddy_trans_l_;
83 if (current && current->id_str_ == to_id)
86 msg += _ ("Can't switch translators, I'm there already");
92 Translator_group * dest =
93 it->report_to_l ()->find_create_translator_l (to_type, to_id);
94 current->remove_translator_p (last);
95 dest->add_translator (last);
100 We could change the current translator's id, but that would make
103 last->translator_id_str_ = change_l ()->change_to_id_str_;
105 error (_f ("I'm one myself: `%s'", to_type.ch_C ()));
108 error (_f ("none of these in my family: `%s'", to_id.ch_C ()));
111 Pitch_interrogate_req* first_spanish_inquisition; // nobody expects it
112 Pitch_interrogate_req* second_spanish_inquisition; // won't strike twice
115 Part_combine_music_iterator::do_process_and_next (Moment m)
117 Moment first_next = first_iter_p_->next_moment ();
118 Moment second_next = second_iter_p_->next_moment ();
120 Part_combine_music const * p = dynamic_cast<Part_combine_music const* > (music_l_);
122 String to_id = unirhythm_b_ ? "one" : "two";
124 different rhythm for combined voices: separate
125 same rhythm for separated voices: combine
127 Arg. Voices should be separated for small intervals, eg < 3.
128 This should be \property settable, and, we need the outcome
129 of the spanish_inquisition's...
131 Can't we first do a process_and_next go into a fake/tmp tree,
132 use + junk the result, and then do the real process_and_next...?
135 if ((first_next != second_next && unirhythm_b_)
136 || (first_next == second_next && !unirhythm_b_))
138 unirhythm_b_ = !unirhythm_b_;
139 to_id = unirhythm_b_ ? "one" : "two";
140 change_to (second_iter_p_, p->what_str_, to_id);
143 Translator_group * fd =
144 first_iter_p_->report_to_l ()->find_create_translator_l (p->what_str_,
146 Translator_group * sd =
147 second_iter_p_->report_to_l ()->find_create_translator_l (p->what_str_,
150 fd->set_property ("unirhythm", unirhythm_b_ ? SCM_BOOL_T : SCM_BOOL_F);
151 sd->set_property ("unirhythm", unirhythm_b_ ? SCM_BOOL_T : SCM_BOOL_F);
152 first_iter_p_->report_to_l ()->set_property ("unirhythm", unirhythm_b_ ? SCM_BOOL_T : SCM_BOOL_F);
153 second_iter_p_->report_to_l ()->set_property ("unirhythm", unirhythm_b_ ? SCM_BOOL_T : SCM_BOOL_F);
156 first_iter_p_->process_and_next (m);
158 if (second_next <= m)
159 second_iter_p_->process_and_next (m);
161 Music_iterator::do_process_and_next (m);
166 * "a2" string is fine, but "Soli" strings are one request late??
168 The problem seems to be: we need to do_try_music for the
169 spanish_inquisition to work; but the properties that we set
170 need to be set *before* we do_try_music?
172 * setting of stem directions by a2-engraver don't work
174 * separate for small ( <3 ?) intervals too
176 Later (because currently, we only handle thread switching, really):
178 Maybe different modes exist?
180 * Wind instruments (Flute I/II)
184 Rules for Hymnals/SATB (John Henckel <henckel@iname.com>):
186 1. if S and A differ by less than a third, the stems should be up/down.
187 2. else if S and A have different values, the stems should be up/down.
188 3. else if A sings "la" or higher, both S and A stems should be down.
189 4. else both stems should be up
191 * This may get really tricky: combining voices/staffs: string instruments
195 if (!first_spanish_inquisition)
196 first_spanish_inquisition = new Pitch_interrogate_req;
197 Music_iterator* fit = first_iter_p_->try_music (first_spanish_inquisition);
199 if (!second_spanish_inquisition)
200 second_spanish_inquisition = new Pitch_interrogate_req;
201 Music_iterator* sit = second_iter_p_->try_music (second_spanish_inquisition);
203 if ((first_next == second_next)
204 && !compare (&first_spanish_inquisition->pitch_arr_,
205 &second_spanish_inquisition->pitch_arr_))
207 fd->set_property ("unison", SCM_BOOL_T);
208 sd->set_property ("unison", SCM_BOOL_T);
209 first_iter_p_->report_to_l ()->set_property ("unison", SCM_BOOL_T);
210 second_iter_p_->report_to_l ()->set_property ("unison", SCM_BOOL_T);
214 fd->set_property ("unison", SCM_BOOL_F);
215 sd->set_property ("unison", SCM_BOOL_F);
216 first_iter_p_->report_to_l ()->set_property ("unison", SCM_BOOL_F);
217 second_iter_p_->report_to_l ()->set_property ("unison", SCM_BOOL_F);
220 if (first_spanish_inquisition->pitch_arr_.size () &&
221 second_spanish_inquisition->pitch_arr_.size ())
223 first_spanish_inquisition->pitch_arr_.sort (Musical_pitch::compare);
224 second_spanish_inquisition->pitch_arr_.sort (Musical_pitch::compare);
225 SCM interval = gh_int2scm (first_spanish_inquisition->pitch_arr_.top ().semitone_pitch ()
226 - second_spanish_inquisition->pitch_arr_[0].semitone_pitch ());
227 fd->set_property ("interval", interval);
228 sd->set_property ("interval", interval);
229 first_iter_p_->report_to_l ()->set_property ("interval", interval);
230 second_iter_p_->report_to_l ()->set_property ("interval", interval);
233 if (first_spanish_inquisition->pitch_arr_.size ()
234 && !second_spanish_inquisition->pitch_arr_.size ())
236 fd->set_property ("solo", SCM_BOOL_T);
237 first_iter_p_->report_to_l ()->set_property ("solo", SCM_BOOL_T);
241 fd->set_property ("solo", SCM_BOOL_F);
242 first_iter_p_->report_to_l ()->set_property ("solo", SCM_BOOL_F);
246 if (!first_spanish_inquisition->pitch_arr_.size ()
247 && second_spanish_inquisition->pitch_arr_.size ())
249 sd->set_property ("solo", SCM_BOOL_T);
250 second_iter_p_->report_to_l ()->set_property ("solo", SCM_BOOL_T);
254 sd->set_property ("solo", SCM_BOOL_F);
255 second_iter_p_->report_to_l ()->set_property ("solo", SCM_BOOL_F);
258 first_spanish_inquisition->pitch_arr_.clear ();
259 second_spanish_inquisition->pitch_arr_.clear ();
263 Part_combine_music_iterator::try_music_in_children (Music *m) const
265 Music_iterator * i = first_iter_p_->try_music (m);
269 return second_iter_p_->try_music (m);