2 chord-tremolo-engraver.cc -- implement Chord_tremolo_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
10 #include "repeated-music.hh"
12 #include "rhythmic-head.hh"
13 #include "engraver-group-engraver.hh"
18 #include "chord-tremolo-iterator.hh"
19 #include "stem-tremolo.hh"
20 #include "math.h" // ceil
22 #include "translator.icc"
26 This acknowledges repeated music with "tremolo" style. It typesets
31 - perhaps use engraver this to steer other engravers? That would
32 create dependencies between engravers, which is bad.
34 - create dots if appropriate.
36 - create TremoloBeam iso Beam?
38 class Chord_tremolo_engraver
: public Engraver
41 TRANSLATOR_DECLARATIONS (Chord_tremolo_engraver
);
45 /// moment (global time) where beam started.
49 int total_duration_flags_
;
51 /// location within measure where beam started.
52 Moment beam_start_location_
;
54 bool body_is_sequential_
;
56 Spanner
*finished_beam_
;
59 virtual void finalize ();
60 virtual bool try_music (Music
*);
61 void stop_translation_timestep ();
62 void start_translation_timestep ();
63 void process_music ();
64 DECLARE_ACKNOWLEDGER (stem
);
67 Chord_tremolo_engraver::Chord_tremolo_engraver ()
69 beam_
= finished_beam_
= 0;
73 body_is_sequential_
= false;
77 Chord_tremolo_engraver::try_music (Music
*m
)
79 if (m
->is_mus_type ("repeated-music")
80 && m
->get_property ("iterator-ctor") == Chord_tremolo_iterator::constructor_proc
83 Moment l
= m
->get_length ();
85 start_mom_
= now_mom ();
86 stop_mom_
= start_mom_
+ l
;
88 Music
*body
= Repeated_music::body (m
);
89 body_is_sequential_
= body
->is_mus_type ("sequential-music");
91 int elt_count
= body_is_sequential_
? scm_ilength (body
->get_property ("elements")) : 1;
93 if (body_is_sequential_
&& elt_count
!= 2)
94 m
->origin ()->warning (_f ("expect 2 elements for chord tremolo, found %d", elt_count
));
99 Rational total_dur
= l
.main_part_
;
100 Rational note_dur
= total_dur
/ Rational (elt_count
* Repeated_music::repeat_count (repeat_
));
102 total_duration_flags_
= max (0, (intlog2 (total_dur
.den ()) - 2));
104 flags_
= intlog2 (note_dur
.den ()) -2;
113 Chord_tremolo_engraver::process_music ()
115 if (repeat_
&& body_is_sequential_
&& !beam_
)
117 beam_
= make_spanner ("Beam", repeat_
->self_scm ());
118 beam_
->set_property ("chord-tremolo", SCM_BOOL_T
);
120 beam_start_location_
= robust_scm2moment (get_property ("measurePosition"), Moment (0));
125 Chord_tremolo_engraver::finalize ()
130 repeat_
->origin ()->warning (_ ("unterminated chord tremolo"));
136 Chord_tremolo_engraver::typeset_beam ()
142 Chord_tremolo_engraver::acknowledge_stem (Grob_info info
)
146 Grob
*s
= info
.grob ();
148 if (start_mom_
== now_mom ())
149 Stem::set_beaming (s
, flags_
, RIGHT
);
151 Stem::set_beaming (s
, flags_
, LEFT
);
153 if (Stem::duration_log (s
) != 1)
154 beam_
->set_property ("gap-count", scm_from_int (flags_
- total_duration_flags_
));
156 if (info
.music_cause ()->is_mus_type ("rhythmic-event"))
157 Beam::add_stem (beam_
, s
);
160 String s
= _ ("stem must have Rhythmic structure");
161 if (info
.music_cause ())
162 info
.music_cause ()->origin ()->warning (s
);
169 && !body_is_sequential_
)
171 stem_tremolo_
= make_item ("StemTremolo", repeat_
->self_scm ());
172 stem_tremolo_
->set_property ("flag-count",
173 scm_from_int (flags_
));
174 stem_tremolo_
->set_object ("stem",
175 info
.grob ()->self_scm ());
176 stem_tremolo_
->set_parent (info
.grob (), X_AXIS
);
181 Chord_tremolo_engraver::start_translation_timestep ()
183 if (beam_
&& stop_mom_
== now_mom ())
185 finished_beam_
= beam_
;
192 Chord_tremolo_engraver::stop_translation_timestep ()
198 programming_error ("beam and stem tremolo?");
205 ADD_ACKNOWLEDGER (Chord_tremolo_engraver
, stem
);
206 ADD_TRANSLATOR (Chord_tremolo_engraver
,
207 /* doc */ "Generates beams for tremolo repeats.",
209 /* accept */ "repeated-music",