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"
17 #include "timing-engraver.hh"
18 #include "engraver-group-engraver.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;
33 Auto_beam_engraver::do_creation_processing ()
35 Translator * t = daddy_grav_l ()->get_simple_translator ("Timing_engraver");
36 timer_l_ = dynamic_cast<Timing_engraver*> (t);
40 Auto_beam_engraver::do_process_requests ()
42 consider_end_and_begin ();
46 Auto_beam_engraver::consider_end_and_begin ()
51 Time_description const *time = &timer_l_->time_;
52 int num = time->whole_per_measure_ / time->one_beat_;
53 int den = time->one_beat_.den_i ();
54 String time_str = String ("time") + to_str (num) + "_" + to_str (den);
56 if (shortest_mom_.num () != 1)
57 type_str = to_str (shortest_mom_.num ());
58 if (shortest_mom_.den () != 1)
59 type_str = type_str + "_" + to_str (shortest_mom_.den ());
62 Determine end moment for auto beaming (and begin, mostly 0==anywhere)
63 In order of increasing priority:
66 ii. time<num>_<den>beamAutoEnd
67 iii. time<num>_<den>beamAutoEnd<type>
74 [to be defined in config file]
75 i. easy catch-all rule
76 ii. exceptions for time signature
77 iii. exceptions for time signature, for specific duration type
81 v. override for specific duration type
83 The user overrides should be required for common cases.
87 first guess: begin beam at any position
91 first guess: end beam at end of beat
93 Moment end_mom = time->one_beat_;
96 second guess: property generic time exception
98 Scalar begin = get_property (time_str + "beamAutoBegin", 0);
99 if (begin.length_i ())
100 begin_mom = begin.to_rat ();
102 Scalar end = get_property (time_str + "beamAutoEnd", 0);
104 end_mom = end.to_rat ();
107 third guess: property time exception, specific for duration type
109 if (type_str.length_i ())
111 Scalar end_mult = get_property (time_str + "beamAutoEnd" + type_str, 0);
112 if (end_mult.length_i ())
113 end_mom = end_mult.to_rat ();
114 Scalar begin_mult = get_property (time_str + "beamAutoBegin" + type_str, 0);
115 if (begin_mult.length_i ())
116 begin_mom = begin_mult.to_rat ();
120 fourth guess [user override]: property plain generic
122 begin = get_property ("beamAutoBegin", 0);
123 if (begin.length_i ())
124 begin_mom = begin.to_rat ();
126 end = get_property ("beamAutoEnd", 0);
128 end_mom = end.to_rat ();
131 fifth guess [user override]: property plain, specific for duration type
133 if (type_str.length_i ())
135 Scalar end_mult = get_property (String ("beamAutoEnd") + type_str, 0);
136 if (end_mult.length_i ())
137 end_mom = end_mult.to_rat ();
138 Scalar begin_mult = get_property (String ("beamAutoBegin") + type_str, 0);
139 if (begin_mult.length_i ())
140 begin_mom = begin_mult.to_rat ();
145 r = time->whole_in_measure_.mod_rat (end_mom);
149 if (stem_l_arr_p_ && !r)
153 Allow already started autobeam to end
155 Scalar on = get_property ("beamAuto", 0);
160 r = time->whole_in_measure_.mod_rat (begin_mom);
161 if (!stem_l_arr_p_ && (!begin_mom || !r))
167 Auto_beam_engraver::begin_beam ()
169 assert (!stem_l_arr_p_);
170 stem_l_arr_p_ = new Array<Stem*>;
171 assert (!grouping_p_);
172 grouping_p_ = new Beaming_info_list;
173 beam_start_moment_ = now_mom ();
174 beam_start_location_ = timer_l_->time_.whole_in_measure_;
178 Auto_beam_engraver::create_beam_p ()
180 Beam* beam_p = new Beam;
182 for (int i = 0; i < stem_l_arr_p_->size (); i++)
183 beam_p->add_stem ((*stem_l_arr_p_)[i]);
185 /* urg, copied from Beam_engraver */
186 Scalar prop = get_property ("beamslopedamping", 0);
188 beam_p->set_elt_property (damping_scm_sym, gh_int2scm( prop));
190 prop = get_property ("beamquantisation", 0);
192 beam_p->quantisation_ = (Beam::Quantisation)(int)prop;
194 announce_element (Score_element_info (beam_p, 0));
199 Auto_beam_engraver::end_beam ()
201 if (stem_l_arr_p_->size () < 2)
207 finished_beam_p_ = create_beam_p ();
208 finished_grouping_p_ = grouping_p_;
209 delete stem_l_arr_p_;
212 shortest_mom_ = Moment (1, 8);
217 Auto_beam_engraver::typeset_beam ()
219 if (finished_beam_p_)
221 finished_grouping_p_->beamify ();
222 finished_beam_p_->set_beaming (finished_grouping_p_);
223 typeset_element (finished_beam_p_);
224 finished_beam_p_ = 0;
226 delete finished_grouping_p_;
227 finished_grouping_p_= 0;
232 Auto_beam_engraver::do_post_move_processing ()
237 Auto_beam_engraver::do_pre_move_processing ()
243 Auto_beam_engraver::do_removal_processing ()
251 Auto_beam_engraver::same_grace_state_b (Score_element* e)
253 bool gr = (e->get_elt_property (grace_scm_sym) != SCM_BOOL_F) ;
255 return gr == get_property ("weAreGraceContext",0).to_bool ();
259 Auto_beam_engraver::acknowledge_element (Score_element_info info)
261 if (!same_grace_state_b (info.elem_l_) || !timer_l_)
266 if (Beam *b = dynamic_cast<Beam *> (info.elem_l_))
270 else if (Bar *b = dynamic_cast<Bar *> (info.elem_l_))
274 else if (Rest* rest_l = dynamic_cast<Rest *> (info.elem_l_))
278 else if (Stem* stem_l = dynamic_cast<Stem *> (info.elem_l_))
280 Rhythmic_req *rhythmic_req = dynamic_cast <Rhythmic_req *> (info.req_l_);
283 programming_error ("Stem must have rhythmic structure");
294 now that we have last_add_mom_, perhaps we can (should) do away
295 with these individual junk_beams
298 int durlog =rhythmic_req->duration_.durlog_i_;
304 if shortest duration would change
305 reconsider ending/starting beam first.
307 Moment mom = rhythmic_req->duration_.length_mom ();
308 if (mom < shortest_mom_)
310 if (stem_l_arr_p_->size ())
313 consider_end_and_begin ();
319 Moment now = now_mom ();
321 grouping_p_->add_stem (now - beam_start_moment_ + beam_start_location_, durlog - 2);
322 stem_l_arr_p_->push (stem_l);
324 extend_mom_ = extend_mom_ >? now + rhythmic_req->length_mom ();
331 Auto_beam_engraver::junk_beam ()
333 assert (stem_l_arr_p_);
335 delete stem_l_arr_p_;
339 shortest_mom_ = Moment (1, 8);
343 Auto_beam_engraver::process_acknowledged ()
347 Moment now = now_mom ();
348 if ((extend_mom_ < now)
349 || ((extend_mom_ == now) && (last_add_mom_ != now )))
353 else if (!stem_l_arr_p_->size ())