2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1999--2012 Glen Prideaux <glenprideaux@iname.com>,
5 Han-Wen Nienhuys <hanwen@xs4all.nl>,
6 Jan Nieuwenhuizen <janneke@gnu.org>
8 LilyPond is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 LilyPond is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
23 #include "engraver.hh"
24 #include "international.hh"
26 #include "lyric-extender.hh"
27 #include "note-head.hh"
28 #include "pointer-group-interface.hh"
29 #include "stream-event.hh"
32 #include "translator.icc"
34 void completize_extender (Spanner *sp);
36 class Extender_engraver : public Engraver
40 Spanner *pending_extender_;
43 TRANSLATOR_DECLARATIONS (Extender_engraver);
46 DECLARE_TRANSLATOR_LISTENER (extender);
47 DECLARE_TRANSLATOR_LISTENER (completize_extender);
48 DECLARE_ACKNOWLEDGER (lyric_syllable);
50 virtual void finalize ();
52 void stop_translation_timestep ();
53 void process_music ();
56 Extender_engraver::Extender_engraver ()
59 pending_extender_ = 0;
63 IMPLEMENT_TRANSLATOR_LISTENER (Extender_engraver, extender);
65 Extender_engraver::listen_extender (Stream_event *ev)
67 ASSIGN_EVENT_ONCE (ev_, ev);
71 A CompletizeExtenderEvent is sent at the end of each lyrics block
72 to ensure any pending extender can be correctly terminated if the lyrics
73 end before the associated voice (this prevents the right bound being extended
74 to the next note-column if no lyric follows the extender)
76 IMPLEMENT_TRANSLATOR_LISTENER (Extender_engraver, completize_extender);
78 Extender_engraver::listen_completize_extender (Stream_event * /* ev */)
80 if (pending_extender_)
82 completize_extender (pending_extender_);
83 pending_extender_ = 0;
88 Extender_engraver::process_music ()
91 extender_ = make_spanner ("LyricExtender", ev_->self_scm ());
95 Extender_engraver::acknowledge_lyric_syllable (Grob_info i)
97 Item *item = i.item ();
99 extender_->set_bound (LEFT, item);
101 if (pending_extender_)
103 pending_extender_->set_object ("next", item->self_scm ());
104 completize_extender (pending_extender_);
105 pending_extender_ = 0;
110 Extender_engraver::stop_translation_timestep ()
112 if (extender_ || pending_extender_)
114 Context *voice = get_voice_to_lyrics (context ());
115 Grob *h = voice ? get_current_note_head (voice, to_boolean (get_property ("includeGraceNotes"))) : 0;
121 Pointer_group_interface::add_grob (extender_,
122 ly_symbol2scm ("heads"), h);
125 if (pending_extender_)
127 Pointer_group_interface::add_grob (pending_extender_,
128 ly_symbol2scm ("heads"), h);
133 if (pending_extender_
134 && !get_property ("extendersOverRests"))
136 completize_extender (pending_extender_);
137 pending_extender_ = 0;
142 pending_extender_ = extender_;
151 completize_extender (Spanner *sp)
153 if (!sp->get_bound (RIGHT))
155 extract_item_set (sp, "heads", heads);
157 sp->set_bound (RIGHT, heads.back ());
162 Extender_engraver::finalize ()
166 completize_extender (extender_);
168 if (!extender_->get_bound (RIGHT))
169 extender_->warning (_ ("unterminated extender"));
173 if (pending_extender_)
175 completize_extender (pending_extender_);
177 if (!pending_extender_->get_bound (RIGHT))
178 pending_extender_->warning (_ ("unterminated extender"));
179 pending_extender_ = 0;
183 ADD_ACKNOWLEDGER (Extender_engraver, lyric_syllable);
184 ADD_TRANSLATOR (Extender_engraver,
186 "Create lyric extenders.",
192 "extendersOverRests "
193 "includeGraceNotes ",