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_try_music (Music* m)
43 Mag dit? Nu word-i toch maar geswallowed, en
44 komt er dus ook geen announce...
46 if (Skip_req* s = dynamic_cast <Skip_req*> (m))
56 Auto_beam_engraver::do_process_requests ()
58 consider_end_and_begin (shortest_mom_);
62 Auto_beam_engraver::consider_end_and_begin (Moment test_mom)
67 Time_description const *time = &timer_l_->time_;
68 int num = time->whole_per_measure_ / time->one_beat_;
69 int den = time->one_beat_.den_i ();
70 String time_str = String ("time") + to_str (num) + "_" + to_str (den);
73 if (test_mom.num () != 1)
74 type_str = to_str (test_mom.num ());
75 if (test_mom.den () != 1)
76 type_str = type_str + "_" + to_str (test_mom.den ());
79 Determine end moment for auto beaming (and begin, mostly 0==anywhere)
80 In order of increasing priority:
83 ii. time<num>_<den>beamAutoEnd
84 iii. time<num>_<den>beamAutoEnd<type>
91 [to be defined in config file]
92 i. easy catch-all rule
93 ii. exceptions for time signature
94 iii. exceptions for time signature, for specific duration type
98 v. override for specific duration type
100 The user overrides should be required for common cases.
104 first guess: begin beam at any position
106 Moment begin_mom (0);
108 first guess: end beam at end of beat
110 Moment end_mom = time->one_beat_;
113 second guess: property generic time exception
115 Scalar begin = get_property (time_str + "beamAutoBegin", 0);
116 if (begin.length_i ())
117 begin_mom = begin.to_rat ();
119 Scalar end = get_property (time_str + "beamAutoEnd", 0);
121 end_mom = end.to_rat ();
124 third guess: property time exception, specific for duration type
126 if (type_str.length_i ())
128 Scalar end_mult = get_property (time_str + "beamAutoEnd" + type_str, 0);
129 if (end_mult.length_i ())
130 end_mom = end_mult.to_rat ();
131 Scalar begin_mult = get_property (time_str + "beamAutoBegin" + type_str, 0);
132 if (begin_mult.length_i ())
133 begin_mom = begin_mult.to_rat ();
137 fourth guess [user override]: property plain generic
139 begin = get_property ("beamAutoBegin", 0);
140 if (begin.length_i ())
141 begin_mom = begin.to_rat ();
143 end = get_property ("beamAutoEnd", 0);
145 end_mom = end.to_rat ();
148 fifth guess [user override]: property plain, specific for duration type
150 if (type_str.length_i ())
152 Scalar end_mult = get_property (String ("beamAutoEnd") + type_str, 0);
153 if (end_mult.length_i ())
154 end_mom = end_mult.to_rat ();
155 Scalar begin_mult = get_property (String ("beamAutoBegin") + type_str, 0);
156 if (begin_mult.length_i ())
157 begin_mom = begin_mult.to_rat ();
162 r = time->whole_in_measure_.mod_rat (end_mom);
166 if (stem_l_arr_p_ && !r)
170 Allow already started autobeam to end
172 Scalar on = get_property ("beamAuto", 0);
177 r = time->whole_in_measure_.mod_rat (begin_mom);
178 if (!stem_l_arr_p_ && (!begin_mom || !r))
184 Auto_beam_engraver::begin_beam ()
186 assert (!stem_l_arr_p_);
187 stem_l_arr_p_ = new Array<Stem*>;
188 assert (!grouping_p_);
189 grouping_p_ = new Beaming_info_list;
190 beam_start_moment_ = now_mom ();
191 beam_start_location_ = timer_l_->time_.whole_in_measure_;
195 Auto_beam_engraver::create_beam_p ()
197 Beam* beam_p = new Beam;
199 for (int i = 0; i < stem_l_arr_p_->size (); i++)
200 beam_p->add_stem ((*stem_l_arr_p_)[i]);
202 /* urg, copied from Beam_engraver */
203 Scalar prop = get_property ("beamslopedamping", 0);
205 beam_p->set_elt_property (damping_scm_sym, gh_int2scm( prop));
207 prop = get_property ("beamquantisation", 0);
209 beam_p->quantisation_ = (Beam::Quantisation)(int)prop;
211 announce_element (Score_element_info (beam_p, 0));
216 Auto_beam_engraver::end_beam ()
218 if (stem_l_arr_p_->size () < 2)
224 finished_beam_p_ = create_beam_p ();
225 finished_grouping_p_ = grouping_p_;
226 delete stem_l_arr_p_;
229 shortest_mom_ = Moment (1, 8);
234 Auto_beam_engraver::typeset_beam ()
236 if (finished_beam_p_)
238 finished_grouping_p_->beamify ();
239 finished_beam_p_->set_beaming (finished_grouping_p_);
240 typeset_element (finished_beam_p_);
241 finished_beam_p_ = 0;
243 delete finished_grouping_p_;
244 finished_grouping_p_= 0;
249 Auto_beam_engraver::do_post_move_processing ()
254 Auto_beam_engraver::do_pre_move_processing ()
260 Auto_beam_engraver::do_removal_processing ()
262 /* finished beams may be typeset */
264 /* but unfinished may need another announce/acknoledge pass */
270 Auto_beam_engraver::same_grace_state_b (Score_element* e)
272 bool gr = (e->get_elt_property (grace_scm_sym) != SCM_BOOL_F) ;
274 return gr == get_property ("weAreGraceContext",0).to_bool ();
278 Auto_beam_engraver::acknowledge_element (Score_element_info info)
280 if (!same_grace_state_b (info.elem_l_) || !timer_l_)
285 if (Beam *b = dynamic_cast<Beam *> (info.elem_l_))
289 else if (Bar *b = dynamic_cast<Bar *> (info.elem_l_))
293 else if (Rest* rest_l = dynamic_cast<Rest *> (info.elem_l_))
297 else if (Stem* stem_l = dynamic_cast<Stem *> (info.elem_l_))
299 Rhythmic_req *rhythmic_req = dynamic_cast <Rhythmic_req *> (info.req_l_);
302 programming_error ("Stem must have rhythmic structure");
313 now that we have last_add_mom_, perhaps we can (should) do away
314 with these individual junk_beams
317 int durlog =rhythmic_req->duration_.durlog_i_;
323 if shortest duration would change
324 reconsider ending/starting beam first.
326 Moment mom = rhythmic_req->duration_.length_mom ();
327 consider_end_and_begin (mom);
330 if (mom < shortest_mom_)
332 if (stem_l_arr_p_->size ())
335 consider_end_and_begin (shortest_mom_);
341 Moment now = now_mom ();
343 grouping_p_->add_stem (now - beam_start_moment_ + beam_start_location_, durlog - 2);
344 stem_l_arr_p_->push (stem_l);
346 extend_mom_ = extend_mom_ >? now + rhythmic_req->length_mom ();
353 Auto_beam_engraver::junk_beam ()
355 assert (stem_l_arr_p_);
357 delete stem_l_arr_p_;
361 shortest_mom_ = Moment (1, 8);
365 Auto_beam_engraver::process_acknowledged ()
369 Moment now = now_mom ();
370 if ((extend_mom_ < now)
371 || ((extend_mom_ == now) && (last_add_mom_ != now )))
375 else if (!stem_l_arr_p_->size ())