2 auto-beam-engraver.cc -- implement Auto_beam_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 1999 Jan Nieuwenhuizen <janneke@gnu.org>
9 #include "new-beaming.hh"
10 #include "auto-beam-engraver.hh"
11 #include "musical-request.hh"
17 #include "timing-engraver.hh"
18 #include "engraver-group-engraver.hh"
20 ADD_THIS_TRANSLATOR (Auto_beam_engraver);
22 Auto_beam_engraver::Auto_beam_engraver ()
25 shortest_mom_ = Moment (1, 8);
27 finished_grouping_p_ = 0;
33 Auto_beam_engraver::do_creation_processing ()
35 Translator * t = daddy_grav_l ()->get_simple_translator ("Timing_engraver");
36 timer_l_ = dynamic_cast<Timing_engraver*> (t);
40 Auto_beam_engraver::do_try_music (Music*)
46 Auto_beam_engraver::do_process_requests ()
48 consider_end_and_begin (shortest_mom_);
52 Auto_beam_engraver::consider_end_and_begin (Moment test_mom)
57 Time_description const *time = &timer_l_->time_;
58 int num = time->whole_per_measure_ / time->one_beat_;
59 int den = time->one_beat_.den_i ();
60 String time_str = String ("time") + to_str (num) + "_" + to_str (den);
63 if (test_mom.num () != 1)
64 type_str = to_str (test_mom.num ());
65 if (test_mom.den () != 1)
66 type_str = type_str + "_" + to_str (test_mom.den ());
69 Determine end moment for auto beaming (and begin, mostly 0==anywhere)
70 In order of increasing priority:
73 ii. time<num>_<den>beamAutoEnd
74 iii. time<num>_<den>beamAutoEnd<type>
81 [to be defined in config file]
82 i. easy catch-all rule
83 ii. exceptions for time signature
84 iii. exceptions for time signature, for specific duration type
88 v. override for specific duration type
90 The user overrides should be required for common cases.
94 first guess: begin beam at any position
98 first guess: end beam at end of beat
100 Moment end_mom = time->one_beat_;
103 second guess: property generic time exception
105 Scalar begin = get_property (time_str + "beamAutoBegin", 0);
106 if (begin.length_i ())
107 begin_mom = begin.to_rat ();
109 Scalar end = get_property (time_str + "beamAutoEnd", 0);
111 end_mom = end.to_rat ();
114 third guess: property time exception, specific for duration type
116 if (type_str.length_i ())
118 Scalar end_mult = get_property (time_str + "beamAutoEnd" + type_str, 0);
119 if (end_mult.length_i ())
120 end_mom = end_mult.to_rat ();
121 Scalar begin_mult = get_property (time_str + "beamAutoBegin" + type_str, 0);
122 if (begin_mult.length_i ())
123 begin_mom = begin_mult.to_rat ();
127 fourth guess [user override]: property plain generic
129 begin = get_property ("beamAutoBegin", 0);
130 if (begin.length_i ())
131 begin_mom = begin.to_rat ();
133 end = get_property ("beamAutoEnd", 0);
135 end_mom = end.to_rat ();
138 fifth guess [user override]: property plain, specific for duration type
140 if (type_str.length_i ())
142 Scalar end_mult = get_property (String ("beamAutoEnd") + type_str, 0);
143 if (end_mult.length_i ())
144 end_mom = end_mult.to_rat ();
145 Scalar begin_mult = get_property (String ("beamAutoBegin") + type_str, 0);
146 if (begin_mult.length_i ())
147 begin_mom = begin_mult.to_rat ();
152 r = time->whole_in_measure_.mod_rat (end_mom);
156 if (stem_l_arr_p_ && !r)
160 Allow already started autobeam to end
162 Scalar on = get_property ("beamAuto", 0);
167 r = time->whole_in_measure_.mod_rat (begin_mom);
168 if (!stem_l_arr_p_ && (!begin_mom || !r))
174 Auto_beam_engraver::begin_beam ()
176 assert (!stem_l_arr_p_);
177 stem_l_arr_p_ = new Array<Stem*>;
178 assert (!grouping_p_);
179 grouping_p_ = new Beaming_info_list;
180 beam_start_moment_ = now_mom ();
181 beam_start_location_ = timer_l_->time_.whole_in_measure_;
185 Auto_beam_engraver::create_beam_p ()
187 Beam* beam_p = new Beam;
189 for (int i = 0; i < stem_l_arr_p_->size (); i++)
190 beam_p->add_stem ((*stem_l_arr_p_)[i]);
192 /* urg, copied from Beam_engraver */
193 Scalar prop = get_property ("beamslopedamping", 0);
195 beam_p->set_elt_property (damping_scm_sym, gh_int2scm( prop));
197 prop = get_property ("beamquantisation", 0);
199 beam_p->quantisation_ = (Beam::Quantisation)(int)prop;
201 announce_element (Score_element_info (beam_p, 0));
206 Auto_beam_engraver::end_beam ()
208 if (stem_l_arr_p_->size () < 2)
214 finished_beam_p_ = create_beam_p ();
215 finished_grouping_p_ = grouping_p_;
216 delete stem_l_arr_p_;
219 shortest_mom_ = Moment (1, 8);
224 Auto_beam_engraver::typeset_beam ()
226 if (finished_beam_p_)
228 finished_grouping_p_->beamify ();
229 finished_beam_p_->set_beaming (finished_grouping_p_);
230 typeset_element (finished_beam_p_);
231 finished_beam_p_ = 0;
233 delete finished_grouping_p_;
234 finished_grouping_p_= 0;
239 Auto_beam_engraver::do_post_move_processing ()
242 don't beam over skips
246 Moment now = now_mom ();
247 if (extend_mom_ < now)
255 Auto_beam_engraver::do_pre_move_processing ()
261 Auto_beam_engraver::do_removal_processing ()
263 /* finished beams may be typeset */
265 /* but unfinished may need another announce/acknoledge pass */
271 Auto_beam_engraver::same_grace_state_b (Score_element* e)
273 bool gr = (e->get_elt_property (grace_scm_sym) != SCM_BOOL_F) ;
275 return gr == get_property ("weAreGraceContext",0).to_bool ();
279 Auto_beam_engraver::acknowledge_element (Score_element_info info)
281 if (!same_grace_state_b (info.elem_l_) || !timer_l_)
286 if (Beam *b = dynamic_cast<Beam *> (info.elem_l_))
290 else if (Bar *b = dynamic_cast<Bar *> (info.elem_l_))
294 else if (Rest* rest_l = dynamic_cast<Rest *> (info.elem_l_))
300 if (Stem* stem_l = dynamic_cast<Stem *> (info.elem_l_))
302 Rhythmic_req *rhythmic_req = dynamic_cast <Rhythmic_req *> (info.req_l_);
305 programming_error ("Stem must have rhythmic structure");
310 Don't (start) auto-beam over empty stems; skips or rests
312 if (!stem_l->head_l_arr_.size ())
326 int durlog =rhythmic_req->duration_.durlog_i_;
335 if shortest duration would change
336 reconsider ending/starting beam first.
338 Moment mom = rhythmic_req->duration_.length_mom ();
339 consider_end_and_begin (mom);
342 if (mom < shortest_mom_)
344 if (stem_l_arr_p_->size ())
347 consider_end_and_begin (shortest_mom_);
353 Moment now = now_mom ();
355 grouping_p_->add_stem (now - beam_start_moment_ + beam_start_location_,
357 stem_l_arr_p_->push (stem_l);
359 extend_mom_ = extend_mom_ >? now + rhythmic_req->length_mom ();
364 Auto_beam_engraver::junk_beam ()
366 assert (stem_l_arr_p_);
368 delete stem_l_arr_p_;
372 shortest_mom_ = Moment (1, 8);
376 Auto_beam_engraver::process_acknowledged ()
380 Moment now = now_mom ();
381 if ((extend_mom_ < now)
382 || ((extend_mom_ == now) && (last_add_mom_ != now )))
386 else if (!stem_l_arr_p_->size ())