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 "grouping.hh"
18 #include "time-description.hh"
20 ADD_THIS_TRANSLATOR (Auto_beam_engraver);
22 Auto_beam_engraver::Auto_beam_engraver ()
26 finished_grouping_p_ = 0;
31 Auto_beam_engraver::do_process_requests ()
33 consider_end_and_begin ();
37 Auto_beam_engraver::consider_end_and_begin ()
39 Time_description const *time = get_staff_info().time_C_;
41 Scalar begin = get_property ("beamAutoBegin", 0);
42 Moment begin_mom = begin.to_rat ();
44 Scalar end = get_property ("beamAutoEnd", 0);
45 Moment end_mom = end.to_rat ();
49 int type = 1 << (mult_i_ + 2);
50 Scalar end_mult = get_property (String ("beamAutoEnd")
52 if (end_mult.length_i ())
53 end_mom = end_mult.to_rat ();
54 else if (Moment (type, 4) / end_mom > Moment (4))
55 end_mom /= Moment (type, 8);
60 f = fmod (time->whole_in_measure_, end_mom);
65 Real epsilon_f = Moment (1, 512);
66 if (beam_p_ && (abs (f) < epsilon_f))
70 Allow already started autobeam to end
72 Scalar on = get_property ("beamAuto", 0);
77 f = fmod (time->whole_in_measure_, begin_mom);
78 if (!beam_p_ && (!begin_mom || (abs (f) < epsilon_f)))
84 Auto_beam_engraver::begin_beam ()
86 DOUT << String ("starting autobeam at: ") + now_moment ().str () + "\n";
88 grouping_p_ = new Rhythmic_grouping;
90 /* urg, copied from Beam_engraver */
91 Scalar prop = get_property ("beamslopedamping", 0);
93 beam_p_->damping_i_ = prop;
95 prop = get_property ("beamquantisation", 0);
97 beam_p_->quantisation_ = (Beam::Quantisation)(int)prop;
99 // must set minVerticalAlign = = maxVerticalAlign to get sane results
100 // see input/test/beam-interstaff.ly
101 prop = get_property ("minVerticalAlign", 0);
103 beam_p_->vertical_align_drul_[MIN] = prop;
105 prop = get_property ("maxVerticalAlign", 0);
107 beam_p_->vertical_align_drul_[MAX] = prop;
109 announce_element (Score_element_info (beam_p_, 0));
113 Auto_beam_engraver::end_beam ()
115 DOUT << String ("ending autobeam at: ") + now_moment ().str () + "\n";
116 if (beam_p_->stems_.size () < 2)
118 DOUT << "junking autombeam: less than two stems\n";
123 finished_beam_p_ = beam_p_;
124 finished_grouping_p_ = grouping_p_;
132 Auto_beam_engraver::typeset_beam ()
134 if (finished_beam_p_)
136 Rhythmic_grouping const * rg_C = get_staff_info().rhythmic_C_;
137 rg_C->extend (finished_grouping_p_->interval());
138 finished_beam_p_->set_grouping (*rg_C, *finished_grouping_p_);
139 typeset_element (finished_beam_p_);
140 finished_beam_p_ = 0;
142 delete finished_grouping_p_;
143 finished_grouping_p_= 0;
148 Auto_beam_engraver::do_post_move_processing ()
153 Auto_beam_engraver::do_pre_move_processing ()
159 Auto_beam_engraver::do_removal_processing ()
164 DOUT << "Unfinished beam\n";
170 Auto_beam_engraver::acknowledge_element (Score_element_info info)
172 if (Beam *b = dynamic_cast<Beam *> (info.elem_l_))
176 DOUT << "junking autobeam: beam encountered\n";
180 if (Bar *b = dynamic_cast<Bar *> (info.elem_l_))
184 DOUT << "junking autobeam: bar encountered\n";
191 Rhythmic_req *rhythmic_req = dynamic_cast <Rhythmic_req *> (info.req_l_);
195 if (dynamic_cast<Rest *> (info.elem_l_))
197 DOUT << "junking autobeam: rest encountered\n";
202 Stem* stem_l = dynamic_cast<Stem *> (info.elem_l_);
206 if (stem_l->beam_l_ && (stem_l->beam_l_ != beam_p_))
208 DOUT << "junking autobeam: beamed stem encountered\n";
215 now that we have last_add_mom_, perhaps we can (should) do away
216 with these individual junk_beams
218 if (rhythmic_req->duration_.durlog_i_<= 2)
220 DOUT << "ending autobeam: stem doesn't fit in beam\n";
225 Moment start = get_staff_info().time_C_->whole_in_measure_;
226 if (!grouping_p_->child_fit_b (start))
228 DOUT << "ending autobeam: stem doesn't fit in group\n";
233 int m = (rhythmic_req->duration_.durlog_i_ - 2);
235 if multiplicity would become greater,
236 reconsider ending/starting beam first.
241 consider_end_and_begin ();
244 grouping_p_->add_child (start, rhythmic_req->duration ());
245 stem_l->flag_i_ = rhythmic_req->duration_.durlog_i_;
246 beam_p_->add_stem (stem_l);
247 Moment now = now_moment ();
249 extend_mom_ = extend_mom_ >? now + rhythmic_req->duration ();
255 Auto_beam_engraver::junk_beam ()
258 for (int i=0; i < beam_p_->stems_.size (); i++)
260 Stem* s = beam_p_->stems_[i];
261 s->beams_i_drul_[LEFT] = 0;
262 s->beams_i_drul_[RIGHT] = 0;
275 Auto_beam_engraver::process_acknowledged ()
279 Moment now = now_moment ();
280 if ((extend_mom_ < now)
281 || ((extend_mom_ == now) && (last_add_mom_ != now )))
283 DOUT << String ("junking autobeam: no stem added since: ")
284 + last_add_mom_.str () + "\n";
287 else if (!beam_p_->stems_.size ())
289 DOUT << "junking started autobeam: no stems\n";