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_))
299 if (Stem* stem_l = dynamic_cast<Stem *> (info.elem_l_))
301 Rhythmic_req *rhythmic_req = dynamic_cast <Rhythmic_req *> (info.req_l_);
304 programming_error ("Stem must have rhythmic structure");
310 Don't (start) auto-beam over empty stems.
311 ugly check for rests!
312 --> doesn't even work: stem-dir is not set
314 ../flower/include/drul-array.hh:26: Real & Drul_array<double>::elem<Real>(enum Direction): Assertion `d==1 || d== -1' failed.
315 /home/fred/root/usr/scripts/src/out/Linux/li: line 8: 14641 Aborted (core dumped) lilypond $opts
318 if (stem_l->extent (Y_AXIS).empty_b ())
325 if (!stem_l->head_l_arr_.size ())
341 now that we have last_add_mom_, perhaps we can (should) do away
342 with these individual junk_beams
345 int durlog =rhythmic_req->duration_.durlog_i_;
354 if shortest duration would change
355 reconsider ending/starting beam first.
357 Moment mom = rhythmic_req->duration_.length_mom ();
358 consider_end_and_begin (mom);
361 if (mom < shortest_mom_)
363 if (stem_l_arr_p_->size ())
366 consider_end_and_begin (shortest_mom_);
372 Moment now = now_mom ();
374 grouping_p_->add_stem (now - beam_start_moment_ + beam_start_location_, durlog - 2);
375 stem_l_arr_p_->push (stem_l);
377 extend_mom_ = extend_mom_ >? now + rhythmic_req->length_mom ();
382 Auto_beam_engraver::junk_beam ()
384 assert (stem_l_arr_p_);
386 delete stem_l_arr_p_;
390 shortest_mom_ = Moment (1, 8);
394 Auto_beam_engraver::process_acknowledged ()
398 Moment now = now_mom ();
399 if ((extend_mom_ < now)
400 || ((extend_mom_ == now) && (last_add_mom_ != now )))
404 else if (!stem_l_arr_p_->size ())