Fix type predicates/docstrings for two music properties.
[lilypond/mpolesky.git] / lily / extender-engraver.cc
blob097b47912ba0daa1d7375cc416ee89bec8382317
1 /*
2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1999--2010 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/>.
21 #include "context.hh"
22 #include "engraver.hh"
23 #include "international.hh"
24 #include "item.hh"
25 #include "lyric-extender.hh"
26 #include "note-head.hh"
27 #include "pointer-group-interface.hh"
28 #include "stream-event.hh"
29 #include "warn.hh"
30 #include "spanner.hh"
31 #include "paper-column.hh"
33 #include "translator.icc"
35 void completize_extender (Spanner *sp);
37 class Extender_engraver : public Engraver
39 Stream_event *ev_;
40 Spanner *extender_;
41 Spanner *pending_extender_;
42 bool current_lyric_is_skip_;
44 public:
45 TRANSLATOR_DECLARATIONS (Extender_engraver);
47 protected:
48 DECLARE_TRANSLATOR_LISTENER (extender);
49 DECLARE_ACKNOWLEDGER (lyric_syllable);
51 virtual void finalize ();
53 void stop_translation_timestep ();
54 void process_music ();
57 Extender_engraver::Extender_engraver ()
59 current_lyric_is_skip_ = false;
60 extender_ = 0;
61 pending_extender_ = 0;
62 ev_ = 0;
65 IMPLEMENT_TRANSLATOR_LISTENER (Extender_engraver, extender);
66 void
67 Extender_engraver::listen_extender (Stream_event *ev)
69 ASSIGN_EVENT_ONCE (ev_, ev);
72 void
73 Extender_engraver::process_music ()
75 if (ev_)
76 extender_ = make_spanner ("LyricExtender", ev_->self_scm ());
79 void
80 Extender_engraver::acknowledge_lyric_syllable (Grob_info i)
82 Item *item = i.item ();
83 if (extender_)
84 extender_->set_bound (LEFT, item);
86 SCM text = item->get_property ("text");
87 current_lyric_is_skip_ = ly_is_equal (text, scm_from_locale_string (" "));
89 if (pending_extender_ && !current_lyric_is_skip_)
91 pending_extender_->set_object ("next", item->self_scm ());
92 completize_extender (pending_extender_);
93 pending_extender_ = 0;
97 void
98 Extender_engraver::stop_translation_timestep ()
100 if (extender_ || pending_extender_)
102 Context *voice = get_voice_to_lyrics (context ());
103 Grob *h = voice ? get_current_note_head (voice) : 0;
105 if (h)
107 if (extender_)
109 Pointer_group_interface::add_grob (extender_,
110 ly_symbol2scm ("heads"), h);
113 if (pending_extender_)
115 Pointer_group_interface::add_grob (pending_extender_,
116 ly_symbol2scm ("heads"), h);
118 The following check addresses the case where the lyrics end before
119 the associated voice. The current_lyric_is_skip_ check is
120 necessary to handle manual melismata, which should not result in
121 extenders being completized. We also need to make sure that we're not
122 in the middle of a note (happens when this function is called because
123 of an event in a voice other than our associated one).
125 if (!melisma_busy (voice) && !current_lyric_is_skip_)
127 Moment now = voice->now_mom ();
128 Paper_column *column = (dynamic_cast<Item *> (h))->get_column ();
129 Moment *start_mom = column ? unsmob_moment (column->get_property ("when")) : 0;
130 if (!column || (start_mom->main_part_ == now.main_part_))
132 completize_extender (pending_extender_);
133 pending_extender_ = 0;
138 else
140 if (pending_extender_
141 && !get_property ("extendersOverRests"))
143 completize_extender (pending_extender_);
144 pending_extender_ = 0;
148 if (extender_)
150 pending_extender_ = extender_;
151 extender_ = 0;
155 ev_ = 0;
158 void
159 completize_extender (Spanner *sp)
161 if (!sp->get_bound (RIGHT))
163 extract_item_set (sp, "heads", heads);
164 if (heads.size ())
165 sp->set_bound (RIGHT, heads.back ());
169 void
170 Extender_engraver::finalize ()
172 if (extender_)
174 completize_extender (extender_);
176 if (!extender_->get_bound (RIGHT))
177 extender_->warning (_ ("unterminated extender"));
178 extender_ = 0;
181 if (pending_extender_)
183 completize_extender (pending_extender_);
185 if (!pending_extender_->get_bound (RIGHT))
186 pending_extender_->warning (_ ("unterminated extender"));
187 pending_extender_ = 0;
191 ADD_ACKNOWLEDGER (Extender_engraver, lyric_syllable);
192 ADD_TRANSLATOR (Extender_engraver,
193 /* doc */
194 "Create lyric extenders.",
196 /* create */
197 "LyricExtender ",
199 /* read */
200 "extendersOverRests ",
202 /* write */