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"
14 #include "abbreviation-beam.hh"
18 #include "timing-engraver.hh"
19 #include "engraver-group-engraver.hh"
21 ADD_THIS_TRANSLATOR (Auto_beam_engraver);
23 Auto_beam_engraver::Auto_beam_engraver ()
26 shortest_mom_ = Moment (1, 8);
28 finished_grouping_p_ = 0;
34 Auto_beam_engraver::do_creation_processing ()
36 Translator * t = daddy_grav_l ()->get_simple_translator ("Timing_engraver");
37 timer_l_ = dynamic_cast<Timing_engraver*> (t);
41 Auto_beam_engraver::do_try_music (Music*)
47 Auto_beam_engraver::do_process_requests ()
49 consider_end_and_begin (shortest_mom_);
53 Auto_beam_engraver::consider_end_and_begin (Moment test_mom)
58 Time_description const *time = &timer_l_->time_;
59 int num = time->whole_per_measure_ / time->one_beat_;
60 int den = time->one_beat_.den_i ();
61 String time_str = String ("time") + to_str (num) + "_" + to_str (den);
64 if (test_mom.num () != 1)
65 type_str = to_str (test_mom.num ());
66 if (test_mom.den () != 1)
67 type_str = type_str + "_" + to_str (test_mom.den ());
70 Determine end moment for auto beaming (and begin, mostly 0==anywhere)
71 In order of increasing priority:
74 ii. time<num>_<den>beamAutoEnd
75 iii. time<num>_<den>beamAutoEnd<type>
82 [to be defined in config file]
83 i. easy catch-all rule
84 ii. exceptions for time signature
85 iii. exceptions for time signature, for specific duration type
89 v. override for specific duration type
91 The user overrides should be required for common cases.
95 first guess: begin beam at any position
99 first guess: end beam at end of beat
101 Moment end_mom = time->one_beat_;
104 second guess: property generic time exception
106 Scalar begin = get_property (time_str + "beamAutoBegin", 0);
107 if (begin.length_i ())
108 begin_mom = begin.to_rat ();
110 Scalar end = get_property (time_str + "beamAutoEnd", 0);
112 end_mom = end.to_rat ();
115 third guess: property time exception, specific for duration type
117 if (type_str.length_i ())
119 Scalar end_mult = get_property (time_str + "beamAutoEnd" + type_str, 0);
120 if (end_mult.length_i ())
121 end_mom = end_mult.to_rat ();
122 Scalar begin_mult = get_property (time_str + "beamAutoBegin" + type_str, 0);
123 if (begin_mult.length_i ())
124 begin_mom = begin_mult.to_rat ();
128 fourth guess [user override]: property plain generic
130 begin = get_property ("beamAutoBegin", 0);
131 if (begin.length_i ())
132 begin_mom = begin.to_rat ();
134 end = get_property ("beamAutoEnd", 0);
136 end_mom = end.to_rat ();
139 fifth guess [user override]: property plain, specific for duration type
141 if (type_str.length_i ())
143 Scalar end_mult = get_property (String ("beamAutoEnd") + type_str, 0);
144 if (end_mult.length_i ())
145 end_mom = end_mult.to_rat ();
146 Scalar begin_mult = get_property (String ("beamAutoBegin") + type_str, 0);
147 if (begin_mult.length_i ())
148 begin_mom = begin_mult.to_rat ();
153 r = time->whole_in_measure_.mod_rat (end_mom);
157 if (stem_l_arr_p_ && !r)
161 Allow already started autobeam to end
163 Scalar on = get_property ("beamAuto", 0);
168 r = time->whole_in_measure_.mod_rat (begin_mom);
169 if (!stem_l_arr_p_ && (!begin_mom || !r))
175 Auto_beam_engraver::begin_beam ()
177 assert (!stem_l_arr_p_);
178 stem_l_arr_p_ = new Array<Stem*>;
179 assert (!grouping_p_);
180 grouping_p_ = new Beaming_info_list;
181 beam_start_moment_ = now_mom ();
182 beam_start_location_ = timer_l_->time_.whole_in_measure_;
186 Auto_beam_engraver::create_beam_p ()
188 Beam* beam_p = new Beam;
190 for (int i = 0; i < stem_l_arr_p_->size (); i++)
193 watch out for stem tremolos and abbreviation beams
195 if ((*stem_l_arr_p_)[i]->beam_l_)
200 beam_p->add_stem ((*stem_l_arr_p_)[i]);
203 /* urg, copied from Beam_engraver */
204 Scalar prop = get_property ("beamslopedamping", 0);
206 beam_p->set_elt_property (damping_scm_sym, gh_int2scm( prop));
208 prop = get_property ("beamquantisation", 0);
210 beam_p->quantisation_ = (Beam::Quantisation)(int)prop;
212 announce_element (Score_element_info (beam_p, 0));
217 Auto_beam_engraver::end_beam ()
219 if (stem_l_arr_p_->size () < 2)
225 finished_beam_p_ = create_beam_p ();
226 if (finished_beam_p_)
227 finished_grouping_p_ = grouping_p_;
228 delete stem_l_arr_p_;
231 shortest_mom_ = Moment (1, 8);
236 Auto_beam_engraver::typeset_beam ()
238 if (finished_beam_p_)
240 finished_grouping_p_->beamify ();
241 finished_beam_p_->set_beaming (finished_grouping_p_);
242 typeset_element (finished_beam_p_);
243 finished_beam_p_ = 0;
245 delete finished_grouping_p_;
246 finished_grouping_p_= 0;
251 Auto_beam_engraver::do_post_move_processing ()
254 don't beam over skips
258 Moment now = now_mom ();
259 if (extend_mom_ < now)
267 Auto_beam_engraver::do_pre_move_processing ()
273 Auto_beam_engraver::do_removal_processing ()
275 /* finished beams may be typeset */
277 /* but unfinished may need another announce/acknoledge pass */
283 Auto_beam_engraver::same_grace_state_b (Score_element* e)
285 bool gr = (e->get_elt_property (grace_scm_sym) != SCM_BOOL_F) ;
287 return gr == get_property ("weAreGraceContext",0).to_bool ();
291 Auto_beam_engraver::acknowledge_element (Score_element_info info)
293 if (!same_grace_state_b (info.elem_l_) || !timer_l_)
298 if (Beam *b = dynamic_cast<Beam *> (info.elem_l_))
302 else if (Abbreviation_beam *b = dynamic_cast<Abbreviation_beam*> (info.elem_l_))
306 else if (Bar *b = dynamic_cast<Bar *> (info.elem_l_))
310 else if (Rest* rest_l = dynamic_cast<Rest *> (info.elem_l_))
316 if (Stem* stem_l = dynamic_cast<Stem *> (info.elem_l_))
318 Rhythmic_req *rhythmic_req = dynamic_cast <Rhythmic_req *> (info.req_l_);
321 programming_error ("Stem must have rhythmic structure");
326 Don't (start) auto-beam over empty stems; skips or rests
328 if (!stem_l->head_l_arr_.size ())
342 int durlog =rhythmic_req->duration_.durlog_i_;
351 if shortest duration would change
352 reconsider ending/starting beam first.
354 Moment mom = rhythmic_req->duration_.length_mom ();
355 consider_end_and_begin (mom);
358 if (mom < shortest_mom_)
360 if (stem_l_arr_p_->size ())
363 consider_end_and_begin (shortest_mom_);
369 Moment now = now_mom ();
371 grouping_p_->add_stem (now - beam_start_moment_ + beam_start_location_,
373 stem_l_arr_p_->push (stem_l);
375 extend_mom_ = extend_mom_ >? now + rhythmic_req->length_mom ();
380 Auto_beam_engraver::junk_beam ()
382 assert (stem_l_arr_p_);
384 delete stem_l_arr_p_;
388 shortest_mom_ = Moment (1, 8);
392 Auto_beam_engraver::process_acknowledged ()
396 Moment now = now_mom ();
397 if ((extend_mom_ < now)
398 || ((extend_mom_ == now) && (last_add_mom_ != now )))
402 else if (!stem_l_arr_p_->size ())