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 ()
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);
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 (!beam_p_ && (!begin_mom || !r))
156 Auto_beam_engraver::begin_beam ()
158 DOUT << String ("starting autobeam at: ") + now_mom ().str () + "\n";
161 grouping_p_ = new Rhythmic_grouping;
163 /* urg, copied from Beam_engraver */
164 Scalar prop = get_property ("beamslopedamping", 0);
166 beam_p_->damping_i_ = prop;
168 prop = get_property ("beamquantisation", 0);
170 beam_p_->quantisation_ = (Beam::Quantisation)(int)prop;
172 // must set minVerticalAlign = = maxVerticalAlign to get sane results
173 // see input/test/beam-interstaff.ly
174 prop = get_property ("minVerticalAlign", 0);
176 beam_p_->vertical_align_drul_[MIN] = prop;
178 prop = get_property ("maxVerticalAlign", 0);
180 beam_p_->vertical_align_drul_[MAX] = prop;
182 announce_element (Score_element_info (beam_p_, 0));
186 Auto_beam_engraver::end_beam ()
188 DOUT << String ("ending autobeam at: ") + now_mom ().str () + "\n";
189 if (beam_p_->stems_.size () < 2)
191 DOUT << "junking autombeam: less than two stems\n";
196 finished_beam_p_ = beam_p_;
197 finished_grouping_p_ = grouping_p_;
205 Auto_beam_engraver::typeset_beam ()
207 if (finished_beam_p_)
209 Rhythmic_grouping const * rg_C = get_staff_info().rhythmic_C_;
210 rg_C->extend (finished_grouping_p_->interval());
211 finished_beam_p_->set_grouping (*rg_C, *finished_grouping_p_);
212 typeset_element (finished_beam_p_);
213 finished_beam_p_ = 0;
215 delete finished_grouping_p_;
216 finished_grouping_p_= 0;
221 Auto_beam_engraver::do_post_move_processing ()
226 Auto_beam_engraver::do_pre_move_processing ()
232 Auto_beam_engraver::do_removal_processing ()
237 DOUT << "Unfinished beam\n";
243 Auto_beam_engraver::acknowledge_element (Score_element_info info)
245 if (Beam *b = dynamic_cast<Beam *> (info.elem_l_))
249 DOUT << "junking autobeam: beam encountered\n";
253 if (Bar *b = dynamic_cast<Bar *> (info.elem_l_))
257 DOUT << "junking autobeam: bar encountered\n";
264 Rhythmic_req *rhythmic_req = dynamic_cast <Rhythmic_req *> (info.req_l_);
268 if (dynamic_cast<Rest *> (info.elem_l_))
270 DOUT << "junking autobeam: rest encountered\n";
275 Stem* stem_l = dynamic_cast<Stem *> (info.elem_l_);
279 if (stem_l->beam_l_ && (stem_l->beam_l_ != beam_p_))
281 DOUT << "junking autobeam: beamed stem encountered\n";
288 now that we have last_add_mom_, perhaps we can (should) do away
289 with these individual junk_beams
291 if (rhythmic_req->duration_.durlog_i_<= 2)
293 DOUT << "ending autobeam: stem doesn't fit in beam\n";
298 Moment start = get_staff_info().time_C_->whole_in_measure_;
299 if (!grouping_p_->child_fit_b (start))
301 DOUT << "ending autobeam: stem doesn't fit in group\n";
307 if shortest duration would change
308 reconsider ending/starting beam first.
310 Moment mom = rhythmic_req->duration_.length_mom ();
311 if (mom < shortest_mom_)
314 consider_end_and_begin ();
316 grouping_p_->add_child (start, rhythmic_req->length_mom ());
317 stem_l->flag_i_ = rhythmic_req->duration_.durlog_i_;
318 beam_p_->add_stem (stem_l);
319 Moment now = now_mom ();
321 extend_mom_ = extend_mom_ >? now + rhythmic_req->length_mom ();
327 Auto_beam_engraver::junk_beam ()
338 Auto_beam_engraver::process_acknowledged ()
342 Moment now = now_mom ();
343 if ((extend_mom_ < now)
344 || ((extend_mom_ == now) && (last_add_mom_ != now )))
346 DOUT << String ("junking autobeam: no stem added since: ")
347 + last_add_mom_.str () + "\n";
350 else if (!beam_p_->stems_.size ())
352 DOUT << "junking started autobeam: no stems\n";