2 beam-engraver.cc -- implement Beam_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 #include "engraver-group-engraver.hh"
10 #include "engraver.hh"
11 #include "musical-request.hh"
16 #include "score-engraver.hh"
18 #include "drul-array.hh"
22 class Beam_engraver
: public Engraver
24 Drul_array
<Span_req
*> reqs_drul_
;
26 Link_array
<Stem
> stems_
;
29 Spanner
*finished_beam_p_
;
31 Span_req
* prev_start_req_
;
33 Beaming_info_list
* beam_info_p_
;
34 Beaming_info_list
* finished_beam_info_p_
;
36 /// location within measure where beam started.
37 Moment beam_start_location_
;
39 /// moment (global time) where beam started.
40 Moment beam_start_mom_
;
43 void set_melisma (bool);
45 virtual void stop_translation_timestep ();
46 virtual void start_translation_timestep ();
47 virtual void finalize ();
48 virtual void create_grobs ();
49 virtual void acknowledge_grob (Grob_info
);
50 virtual bool try_music (Music
*);
51 virtual void process_music ();
55 VIRTUAL_COPY_CONS (Translator
);
59 Beam_engraver::Beam_engraver ()
63 finished_beam_info_p_
=0;
65 reqs_drul_
[LEFT
] = reqs_drul_
[RIGHT
] =0;
70 Beam_engraver::try_music (Music
*m
)
72 if (Span_req
* c
= dynamic_cast<Span_req
*> (m
))
74 if (scm_equal_p (c
->get_mus_property ("span-type"),
75 ly_str02scm ("abort")) == SCM_BOOL_T
)
77 reqs_drul_
[START
] = 0;
83 else if (scm_equal_p (c
->get_mus_property ("span-type"),
84 ly_str02scm ("beam")) == SCM_BOOL_T
)
87 Direction d
=c
->get_span_dir ();
89 if (d
== STOP
&& !beam_p_
)
91 m
->origin ()->warning (_ ("can't find start of beam"));
97 SCM m
= get_property ("automaticMelismata");
98 SCM b
= get_property ("noAutoBeaming");
99 if (to_boolean (m
) && to_boolean (b
))
113 Beam_engraver::set_melisma (bool m
)
115 daddy_trans_l_
->set_property ("beamMelismaBusy", m
? SCM_BOOL_T
:SCM_BOOL_F
);
119 Beam_engraver::process_music ()
121 if (reqs_drul_
[STOP
])
124 reqs_drul_
[STOP
]->origin ()->warning (_ ("can't find start of beam"));
126 finished_beam_p_
= beam_p_
;
127 finished_beam_info_p_
= beam_info_p_
;
136 Score_engraver
* e
= 0;
137 Translator
* t
= daddy_grav_l ();
138 for (; !e
&& t
; t
= t
->daddy_trans_l_
)
140 e
= dynamic_cast<Score_engraver
*> (t
);
144 programming_error ("No score engraver!");
152 Beam_engraver::create_grobs ()
154 if (reqs_drul_
[START
])
158 reqs_drul_
[START
]->origin ()->warning (_ ("already have a beam"));
162 prev_start_req_
= reqs_drul_
[START
];
163 beam_p_
= new Spanner (get_property ("Beam"));
164 SCM smp
= get_property ("measurePosition");
165 Moment mp
= (unsmob_moment (smp
)) ? *unsmob_moment (smp
) : Moment (0);
167 beam_start_location_
= mp
;
168 beam_start_mom_
= now_mom ();
170 beam_info_p_
= new Beaming_info_list
;
172 /* urg, must copy to Auto_beam_engraver too */
174 announce_grob (beam_p_
, reqs_drul_
[START
]);
176 reqs_drul_
[STOP
] = 0;
177 reqs_drul_
[START
] = 0;
181 Beam_engraver::typeset_beam ()
183 if (finished_beam_p_
)
185 finished_beam_info_p_
->beamify ();
187 Beam::set_beaming (finished_beam_p_
, finished_beam_info_p_
);
188 typeset_grob (finished_beam_p_
);
189 delete finished_beam_info_p_
;
190 finished_beam_info_p_
=0;
191 finished_beam_p_
= 0;
193 reqs_drul_
[STOP
] = 0;
198 Beam_engraver::start_translation_timestep ()
200 reqs_drul_
[START
] =0;
202 SCM m
= get_property ("automaticMelismata");
203 SCM b
= get_property ("noAutoBeaming");
204 if (to_boolean (m
) && to_boolean (b
)) {
211 Beam_engraver::stop_translation_timestep ()
217 Beam_engraver::finalize ()
222 prev_start_req_
->origin ()->warning (_ ("unterminated beam"));
225 we don't typeset it, (we used to, but it was commented
226 out. Reason unknown) */
233 Beam_engraver::acknowledge_grob (Grob_info info
)
237 if (Rest::has_interface (info
.elem_l_
))
239 info
.elem_l_
->add_offset_callback (Beam::rest_collision_callback_proc
, Y_AXIS
);
241 else if (Stem::has_interface (info
.elem_l_
))
243 Moment now
= now_mom();
245 if(bool (now
.grace_part_
) != bool (beam_start_mom_
.grace_part_
))
248 Item
*stem_l
= dynamic_cast<Item
*> (info
.elem_l_
);
249 if (Stem::beam_l (stem_l
))
252 Rhythmic_req
*rhythmic_req
= dynamic_cast <Rhythmic_req
*> (info
.req_l_
);
255 String s
= _ ("stem must have Rhythmic structure");
257 info
.req_l_
->origin ()->warning (s
);
264 int durlog
= unsmob_duration (rhythmic_req
->get_mus_property ("duration"))-> duration_log ();
267 rhythmic_req
->origin ()->warning (_ ("stem doesn't fit in beam"));
268 prev_start_req_
->origin ()->warning (_ ("beam was started here"));
272 [r4 c8] can just as well be modern notation.
276 stem_l
->set_grob_property ("duration-log",
277 gh_int2scm (durlog
));
278 Moment stem_location
= now
- beam_start_mom_
+ beam_start_location_
;
279 beam_info_p_
->add_stem (stem_location
,
281 Beam::add_stem (beam_p_
, stem_l
);
288 ADD_THIS_TRANSLATOR (Beam_engraver
);