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>
10 #include "auto-beam-engraver.hh"
11 #include "musical-request.hh"
14 #include "rhythmic-grouping.hh"
18 #include "time-description.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;
32 Auto_beam_engraver::do_process_requests ()
34 consider_end_and_begin ();
38 Auto_beam_engraver::consider_end_and_begin ()
40 Time_description const *time = get_staff_info().time_C_;
41 int num = time->whole_per_measure_ / time->one_beat_;
42 int den = time->one_beat_.den_i ();
43 String time_str = String ("time") + to_str (num) + "_" + to_str (den);
45 if (shortest_mom_.num () != 1)
46 type_str = to_str (shortest_mom_.num ());
47 if (shortest_mom_.den () != 1)
48 type_str = type_str + "_" + to_str (shortest_mom_.den ());
51 Determine end moment for auto beaming (and begin, mostly 0==anywhere)
52 In order of increasing priority:
55 ii. time<num>_<den>beamAutoEnd
56 iii. time<num>_<den>beamAutoEnd<type>
63 [to be defined in config file]
64 i. easy catch-all rule
65 ii. exceptions for time signature
66 iii. exceptions for time signature, for specific duration type
70 v. override for specific duration type
72 The user overrides should be required for common cases.
76 first guess: begin beam at any position
80 first guess: end beam at end of beat
82 Moment end_mom = time->one_beat_;
85 second guess: property generic time exception
87 Scalar begin = get_property (time_str + "beamAutoBegin", 0);
88 if (begin.length_i ())
89 begin_mom = begin.to_rat ();
91 Scalar end = get_property (time_str + "beamAutoEnd", 0);
93 end_mom = end.to_rat ();
96 third guess: property time exception, specific for duration type
98 if (type_str.length_i ())
100 Scalar end_mult = get_property (time_str + "beamAutoEnd" + type_str, 0);
101 if (end_mult.length_i ())
102 end_mom = end_mult.to_rat ();
103 Scalar begin_mult = get_property (time_str + "beamAutoBegin" + type_str, 0);
104 if (begin_mult.length_i ())
105 begin_mom = begin_mult.to_rat ();
109 fourth guess [user override]: property plain generic
111 begin = get_property ("beamAutoBegin", 0);
112 if (begin.length_i ())
113 begin_mom = begin.to_rat ();
115 end = get_property ("beamAutoEnd", 0);
117 end_mom = end.to_rat ();
120 fifth guess [user override]: property plain, specific for duration type
122 if (type_str.length_i ())
124 Scalar end_mult = get_property (String ("beamAutoEnd") + type_str, 0);
125 if (end_mult.length_i ())
126 end_mom = end_mult.to_rat ();
127 Scalar begin_mult = get_property (String ("beamAutoBegin") + type_str, 0);
128 if (begin_mult.length_i ())
129 begin_mom = begin_mult.to_rat ();
134 r = time->whole_in_measure_.mod_rat (end_mom);
138 if (stem_l_arr_p_ && !r)
142 Allow already started autobeam to end
144 Scalar on = get_property ("beamAuto", 0);
149 r = time->whole_in_measure_.mod_rat (begin_mom);
150 if (!stem_l_arr_p_ && (!begin_mom || !r))
156 Auto_beam_engraver::begin_beam ()
158 assert (!stem_l_arr_p_);
159 stem_l_arr_p_ = new Array<Stem*>;
160 assert (!grouping_p_);
161 grouping_p_ = new Rhythmic_grouping;
165 Auto_beam_engraver::create_beam_p ()
167 Beam* beam_p = new Beam;
169 for (int i = 0; i < stem_l_arr_p_->size (); i++)
170 beam_p->add_stem ((*stem_l_arr_p_)[i]);
172 /* urg, copied from Beam_engraver */
173 Scalar prop = get_property ("beamslopedamping", 0);
175 beam_p->set_elt_property (damping_scm_sym, gh_int2scm( prop));
177 prop = get_property ("beamquantisation", 0);
179 beam_p->quantisation_ = (Beam::Quantisation)(int)prop;
181 announce_element (Score_element_info (beam_p, 0));
186 Auto_beam_engraver::end_beam ()
188 if (stem_l_arr_p_->size () < 2)
194 finished_beam_p_ = create_beam_p ();
195 finished_grouping_p_ = grouping_p_;
196 delete stem_l_arr_p_;
199 shortest_mom_ = Moment (1, 8);
204 Auto_beam_engraver::typeset_beam ()
206 if (finished_beam_p_)
208 Rhythmic_grouping const * rg_C = get_staff_info().rhythmic_C_;
209 rg_C->extend (finished_grouping_p_->interval());
210 finished_beam_p_->set_grouping (*rg_C, *finished_grouping_p_);
211 typeset_element (finished_beam_p_);
212 finished_beam_p_ = 0;
214 delete finished_grouping_p_;
215 finished_grouping_p_= 0;
220 Auto_beam_engraver::do_post_move_processing ()
225 Auto_beam_engraver::do_pre_move_processing ()
231 Auto_beam_engraver::do_removal_processing ()
239 Auto_beam_engraver::same_grace_state_b (Score_element* e)
241 bool gr = (e->get_elt_property (grace_scm_sym) != SCM_BOOL_F) ;
243 return gr == get_property ("weAreGraceContext",0).to_bool ();
247 Auto_beam_engraver::acknowledge_element (Score_element_info info)
251 if (Beam *b = dynamic_cast<Beam *> (info.elem_l_))
253 if (same_grace_state_b (b))
256 else if (Bar *b = dynamic_cast<Bar *> (info.elem_l_))
258 if (same_grace_state_b (b))
261 else if (Rhythmic_req *rhythmic_req = dynamic_cast <Rhythmic_req *> (info.req_l_))
263 if (Rest* rest_l = dynamic_cast<Rest *> (info.elem_l_))
265 if (same_grace_state_b (rest_l))
268 else if (Stem* stem_l = dynamic_cast<Stem *> (info.elem_l_))
271 if we're a nice grace beam, but the new note is regular,
272 gracefully end beam, and consider starting a regular one.
275 When does that happen !? --hwn
278 if (stem_l_arr_p_ && stem_l_arr_p_->size ()
279 && grace_b (stem_l_arr_p_->top ())
280 && !grace_b (stem_l))
283 consider_end_and_begin ();
288 if (same_grace_state_b (stem_l))
293 now that we have last_add_mom_, perhaps we can (should) do away
294 with these individual junk_beams
296 else if (rhythmic_req->duration_.durlog_i_ <= 2)
300 Moment start = get_staff_info().time_C_->whole_in_measure_;
301 if (!grouping_p_->child_fit_b (start))
306 if shortest duration would change
307 reconsider ending/starting beam first.
309 Moment mom = rhythmic_req->duration_.length_mom ();
310 if (mom < shortest_mom_)
312 if (stem_l_arr_p_->size ())
315 consider_end_and_begin ();
319 grouping_p_->add_child (start, rhythmic_req->length_mom ());
321 stem_l_arr_p_->push (stem_l);
322 Moment now = now_mom ();
324 extend_mom_ = extend_mom_ >? now + rhythmic_req->length_mom ();
334 Auto_beam_engraver::junk_beam ()
336 assert (stem_l_arr_p_);
338 delete stem_l_arr_p_;
342 shortest_mom_ = Moment (1, 8);
346 Auto_beam_engraver::process_acknowledged ()
350 Moment now = now_mom ();
351 if ((extend_mom_ < now)
352 || ((extend_mom_ == now) && (last_add_mom_ != now )))
356 else if (!stem_l_arr_p_->size ())