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);
44 int type = 1 << (mult_i_ + 2);
45 String type_str = to_str (type);
48 Determine end moment for auto beaming (and begin, mostly 0==anywhere)
49 In order of increasing priority:
52 ii. time<num>_<den>beamAutoEnd
53 iii. time<num>_<den>beamAutoEnd<type>
60 [to be defined in config file]
61 i. easy catch-all rule
62 ii. exceptions for time signature
63 iii. exceptions for time signature, for specific duration type
67 v. override for specific duration type
69 The user overrides should be required for common cases.
73 first guess: begin beam at any position
77 first guess: end beam at end of beat
79 Moment end_mom = time->one_beat_;
82 second guess: property generic time exception
84 Scalar begin = get_property (time_str + "beamAutoBegin", 0);
85 if (begin.length_i ())
86 begin_mom = begin.to_rat ();
88 Scalar end = get_property (time_str + "beamAutoEnd", 0);
90 end_mom = end.to_rat ();
93 third guess: property time exception, specific for duration type
97 Scalar end_mult = get_property (time_str + "beamAutoEnd" + type_str, 0);
98 if (end_mult.length_i ())
99 end_mom = end_mult.to_rat ();
100 Scalar begin_mult = get_property (time_str + "beamAutoBegin" + type_str, 0);
101 if (begin_mult.length_i ())
102 begin_mom = begin_mult.to_rat ();
106 fourth guess [user override]: property plain generic
108 begin = get_property ("beamAutoBegin", 0);
109 if (begin.length_i ())
110 begin_mom = begin.to_rat ();
112 end = get_property ("beamAutoEnd", 0);
114 end_mom = end.to_rat ();
117 fifth guess [user override]: property plain, specific for duration type
121 Scalar end_mult = get_property (String ("beamAutoEnd") + type_str, 0);
122 if (end_mult.length_i ())
123 end_mom = end_mult.to_rat ();
124 Scalar begin_mult = get_property (String ("beamAutoBegin") + type_str, 0);
125 if (begin_mult.length_i ())
126 begin_mom = begin_mult.to_rat ();
131 r = time->whole_in_measure_.mod_rat (end_mom);
139 Allow already started autobeam to end
141 Scalar on = get_property ("beamAuto", 0);
146 r = time->whole_in_measure_.mod_rat (begin_mom);
147 if (!beam_p_ && (!begin_mom || !r))
153 Auto_beam_engraver::begin_beam ()
155 DOUT << String ("starting autobeam at: ") + now_mom ().str () + "\n";
158 grouping_p_ = new Rhythmic_grouping;
160 /* urg, copied from Beam_engraver */
161 Scalar prop = get_property ("beamslopedamping", 0);
163 beam_p_->damping_i_ = prop;
165 prop = get_property ("beamquantisation", 0);
167 beam_p_->quantisation_ = (Beam::Quantisation)(int)prop;
169 // must set minVerticalAlign = = maxVerticalAlign to get sane results
170 // see input/test/beam-interstaff.ly
171 prop = get_property ("minVerticalAlign", 0);
173 beam_p_->vertical_align_drul_[MIN] = prop;
175 prop = get_property ("maxVerticalAlign", 0);
177 beam_p_->vertical_align_drul_[MAX] = prop;
179 announce_element (Score_element_info (beam_p_, 0));
183 Auto_beam_engraver::end_beam ()
185 DOUT << String ("ending autobeam at: ") + now_mom ().str () + "\n";
186 if (beam_p_->stems_.size () < 2)
188 DOUT << "junking autombeam: less than two stems\n";
193 finished_beam_p_ = beam_p_;
194 finished_grouping_p_ = grouping_p_;
202 Auto_beam_engraver::typeset_beam ()
204 if (finished_beam_p_)
206 Rhythmic_grouping const * rg_C = get_staff_info().rhythmic_C_;
207 rg_C->extend (finished_grouping_p_->interval());
208 finished_beam_p_->set_grouping (*rg_C, *finished_grouping_p_);
209 typeset_element (finished_beam_p_);
210 finished_beam_p_ = 0;
212 delete finished_grouping_p_;
213 finished_grouping_p_= 0;
218 Auto_beam_engraver::do_post_move_processing ()
223 Auto_beam_engraver::do_pre_move_processing ()
229 Auto_beam_engraver::do_removal_processing ()
234 DOUT << "Unfinished beam\n";
240 Auto_beam_engraver::acknowledge_element (Score_element_info info)
242 if (Beam *b = dynamic_cast<Beam *> (info.elem_l_))
246 DOUT << "junking autobeam: beam encountered\n";
250 if (Bar *b = dynamic_cast<Bar *> (info.elem_l_))
254 DOUT << "junking autobeam: bar encountered\n";
261 Rhythmic_req *rhythmic_req = dynamic_cast <Rhythmic_req *> (info.req_l_);
265 if (dynamic_cast<Rest *> (info.elem_l_))
267 DOUT << "junking autobeam: rest encountered\n";
272 Stem* stem_l = dynamic_cast<Stem *> (info.elem_l_);
276 if (stem_l->beam_l_ && (stem_l->beam_l_ != beam_p_))
278 DOUT << "junking autobeam: beamed stem encountered\n";
285 now that we have last_add_mom_, perhaps we can (should) do away
286 with these individual junk_beams
288 if (rhythmic_req->duration_.durlog_i_<= 2)
290 DOUT << "ending autobeam: stem doesn't fit in beam\n";
295 Moment start = get_staff_info().time_C_->whole_in_measure_;
296 if (!grouping_p_->child_fit_b (start))
298 DOUT << "ending autobeam: stem doesn't fit in group\n";
303 int m = (rhythmic_req->duration_.durlog_i_ - 2);
305 if multiplicity would become greater,
306 reconsider ending/starting beam first.
311 consider_end_and_begin ();
314 grouping_p_->add_child (start, rhythmic_req->length_mom ());
315 stem_l->flag_i_ = rhythmic_req->duration_.durlog_i_;
316 beam_p_->add_stem (stem_l);
317 Moment now = now_mom ();
319 extend_mom_ = extend_mom_ >? now + rhythmic_req->length_mom ();
325 Auto_beam_engraver::junk_beam ()
329 for (int i=0; i < beam_p_->stems_.size (); i++)
331 Stem* s = beam_p_->stems_[i];
332 s->beams_i_drul_[LEFT] = 0;
333 s->beams_i_drul_[RIGHT] = 0;
347 Auto_beam_engraver::process_acknowledged ()
351 Moment now = now_mom ();
352 if ((extend_mom_ < now)
353 || ((extend_mom_ == now) && (last_add_mom_ != now )))
355 DOUT << String ("junking autobeam: no stem added since: ")
356 + last_add_mom_.str () + "\n";
359 else if (!beam_p_->stems_.size ())
361 DOUT << "junking started autobeam: no stems\n";