2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1997--2010 Han-Wen Nienhuys <hanwen@xs4all.nl>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
20 #include "engraver.hh"
23 #include "directional-element-interface.hh"
24 #include "duration.hh"
25 #include "international.hh"
28 #include "rhythmic-head.hh"
29 #include "script-interface.hh"
30 #include "staff-symbol-referencer.hh"
31 #include "stem-tremolo.hh"
33 #include "stream-event.hh"
35 #include "translator.icc"
37 class Stem_engraver
: public Engraver
41 Stream_event
*rhythmic_ev_
;
42 Stream_event
*tremolo_ev_
;
44 TRANSLATOR_DECLARATIONS (Stem_engraver
);
47 void make_stem (Grob_info
);
49 DECLARE_TRANSLATOR_LISTENER (tremolo
);
50 DECLARE_ACKNOWLEDGER (rhythmic_head
);
51 void stop_translation_timestep ();
54 Stem_engraver::Stem_engraver ()
63 Stem_engraver::make_stem (Grob_info gi
)
65 /* Announce the cause of the head as cause of the stem. The
66 stem needs a rhythmic structure to fit it into a beam. */
67 stem_
= make_item ("Stem", gi
.grob ()->self_scm ());
71 /* Stem tremolo is never applied to a note by default,
72 is must me requested. But there is a default for the
77 the first and last (quarter) note bothe get one tremolo flag. */
79 = scm_to_int (tremolo_ev_
->get_property ("tremolo-type"));
80 SCM f
= get_property ("tremoloFlags");
83 if (scm_is_number (f
))
84 requested_type
= scm_to_int (f
);
89 context ()->set_property ("tremoloFlags", scm_from_int (requested_type
));
93 we take the duration log from the Event, since the duration-log
94 for a note head is always <= 2.
96 Stream_event
*ev
= gi
.event_cause ();
97 Duration
*dur
= unsmob_duration (ev
->get_property ("duration"));
99 int tremolo_flags
= intlog2 (requested_type
) - 2
100 - (dur
->duration_log () > 2 ? dur
->duration_log () - 2 : 0);
101 if (tremolo_flags
<= 0)
103 tremolo_ev_
->origin ()->warning (_ ("tremolo duration is too long"));
109 tremolo_
= make_item ("StemTremolo", tremolo_ev_
->self_scm ());
111 /* The number of tremolo flags is the number of flags of the
112 tremolo-type minus the number of flags of the note itself. */
113 tremolo_
->set_property ("flag-count", scm_from_int (tremolo_flags
));
114 tremolo_
->set_parent (stem_
, X_AXIS
);
115 stem_
->set_object ("tremolo-flag", tremolo_
->self_scm ());
116 tremolo_
->set_object ("stem", stem_
->self_scm ());
122 Stem_engraver::acknowledge_rhythmic_head (Grob_info gi
)
124 if (Rhythmic_head::get_stem (gi
.grob ()))
127 Stream_event
*cause
= gi
.event_cause ();
130 Duration
*d
= unsmob_duration (cause
->get_property ("duration"));
137 if (Stem::duration_log (stem_
) != d
->duration_log ())
140 gi
.event_cause ()->origin ()->warning (_f ("adding note head to incompatible stem (type = %d)",
141 1 << Stem::duration_log (stem_
)));
142 gi
.event_cause ()->origin ()->warning (_ ("maybe input should specify polyphonic voices"));
145 Stem::add_head (stem_
, gi
.grob ());
149 Stem_engraver::stop_translation_timestep ()
154 /* FIXME: junk these properties. */
155 SCM prop
= get_property ("stemLeftBeamCount");
156 if (scm_is_number (prop
))
158 Stem::set_beaming (stem_
, scm_to_int (prop
), LEFT
);
159 context ()->unset_property (ly_symbol2scm ("stemLeftBeamCount"));
161 prop
= get_property ("stemRightBeamCount");
162 if (scm_is_number (prop
))
164 Stem::set_beaming (stem_
, scm_to_int (prop
), RIGHT
);
165 context ()->unset_property (ly_symbol2scm ("stemRightBeamCount"));
172 IMPLEMENT_TRANSLATOR_LISTENER (Stem_engraver
, tremolo
);
174 Stem_engraver::listen_tremolo (Stream_event
*ev
)
176 ASSIGN_EVENT_ONCE (tremolo_ev_
, ev
);
179 ADD_ACKNOWLEDGER (Stem_engraver
, rhythmic_head
);
181 ADD_TRANSLATOR (Stem_engraver
,
183 "Create stems and single-stem tremolos. It also works"
184 " together with the beam engraver for overriding beaming.",
193 "stemRightBeamCount ",