Fixes Issue 1504, allowing feather beam line breaking.
[lilypond/patrick.git] / lily / piano-pedal-align-engraver.cc
blobf5aa652a4a7ac5d174bd5a9b267c4cecd78e4f10
1 /*
2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2006--2011 Han-Wen Nienhuys <hanwen@lilypond.org>
7 LilyPond is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 LilyPond is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
22 #include "engraver.hh"
24 #include "spanner.hh"
25 #include "item.hh"
26 #include "side-position-interface.hh"
27 #include "stream-event.hh"
28 #include "warn.hh"
29 #include "axis-group-interface.hh"
33 TODO:
36 * Detach from pedal specifics,
38 * Also use this engraver for dynamics.
43 struct Pedal_align_info
45 Spanner *line_spanner_;
46 Grob *carrying_item_;
47 Spanner *carrying_spanner_;
48 Spanner *finished_carrying_spanner_;
50 Pedal_align_info ()
52 clear ();
55 void clear ()
57 line_spanner_ = 0;
58 carrying_spanner_ = 0;
59 carrying_item_ = 0;
60 finished_carrying_spanner_ = 0;
62 bool is_finished ()
64 bool do_continue = carrying_item_;
66 do_continue |= (carrying_spanner_ && !finished_carrying_spanner_);
67 do_continue |= (carrying_spanner_ && finished_carrying_spanner_ != carrying_spanner_);
69 return !do_continue;
73 class Piano_pedal_align_engraver : public Engraver
75 public:
76 TRANSLATOR_DECLARATIONS (Piano_pedal_align_engraver);
78 protected:
79 virtual void finalize ();
81 DECLARE_ACKNOWLEDGER (piano_pedal_script);
82 DECLARE_ACKNOWLEDGER (piano_pedal_bracket);
83 DECLARE_ACKNOWLEDGER (note_column);
85 DECLARE_END_ACKNOWLEDGER (piano_pedal_bracket);
87 void stop_translation_timestep ();
88 void start_translation_timestep ();
90 private:
91 enum Pedal_type {
92 SOSTENUTO,
93 SUSTAIN,
94 UNA_CORDA,
95 NUM_PEDAL_TYPES
97 Pedal_align_info pedal_info_[NUM_PEDAL_TYPES];
98 vector<Grob *> supports_;
100 Pedal_type get_grob_pedal_type (Grob_info g);
101 Spanner *make_line_spanner (Pedal_type t, SCM);
104 Piano_pedal_align_engraver::Piano_pedal_align_engraver ()
108 void
109 Piano_pedal_align_engraver::start_translation_timestep ()
111 supports_.clear ();
114 void
115 Piano_pedal_align_engraver::stop_translation_timestep ()
117 for (int i = 0; i < NUM_PEDAL_TYPES; i ++)
119 if (pedal_info_[i].line_spanner_)
122 if (pedal_info_[i].carrying_item_)
124 if (!pedal_info_[i].line_spanner_->get_bound (LEFT))
125 pedal_info_[i].line_spanner_->set_bound (LEFT,
126 pedal_info_[i].carrying_item_);
128 pedal_info_[i].line_spanner_->set_bound (RIGHT,
129 pedal_info_[i].carrying_item_);
131 else if (pedal_info_[i].carrying_spanner_
132 || pedal_info_[i].finished_carrying_spanner_
135 if (!pedal_info_[i].line_spanner_->get_bound (LEFT)
136 && pedal_info_[i].carrying_spanner_->get_bound (LEFT))
137 pedal_info_[i].line_spanner_->set_bound (LEFT,
138 pedal_info_[i].carrying_spanner_->get_bound (LEFT));
141 if (pedal_info_[i].finished_carrying_spanner_)
142 pedal_info_[i].line_spanner_->set_bound (RIGHT,
143 pedal_info_[i].finished_carrying_spanner_->get_bound (RIGHT));
146 for (vsize j = 0; j < supports_.size (); j++)
148 Side_position_interface::add_support (pedal_info_[i].line_spanner_, supports_[j]);
151 if (pedal_info_[i].is_finished ())
153 announce_end_grob (pedal_info_[i].line_spanner_, SCM_EOL);
154 pedal_info_[i].clear ();
158 pedal_info_[i].carrying_item_ = 0;
162 Piano_pedal_align_engraver::Pedal_type
163 Piano_pedal_align_engraver::get_grob_pedal_type (Grob_info g)
165 if (g.event_cause ()->in_event_class ("sostenuto-event"))
166 return SOSTENUTO;
167 if (g.event_cause ()->in_event_class ("sustain-event"))
168 return SUSTAIN;
169 if (g.event_cause ()->in_event_class ("una-corda-event"))
170 return UNA_CORDA;
172 programming_error ("Unknown piano pedal type. Defaulting to sustain");
173 return SUSTAIN;
177 Spanner *
178 Piano_pedal_align_engraver::make_line_spanner (Pedal_type t, SCM cause)
180 Spanner *sp = pedal_info_[t].line_spanner_;
181 if (!sp)
183 switch (t)
185 case (SOSTENUTO):
186 sp = make_spanner ("SostenutoPedalLineSpanner", cause);
187 break;
188 case (SUSTAIN):
189 sp = make_spanner ("SustainPedalLineSpanner", cause);
190 break;
191 case (UNA_CORDA):
192 sp = make_spanner ("UnaCordaPedalLineSpanner", cause);
193 break;
194 default:
195 programming_error ("No pedal type fonud!") ;
196 return sp;
199 pedal_info_[t].line_spanner_ = sp;
202 return sp;
205 void
206 Piano_pedal_align_engraver::acknowledge_note_column (Grob_info gi)
208 supports_.push_back (gi.grob ());
211 void
212 Piano_pedal_align_engraver::acknowledge_piano_pedal_bracket (Grob_info gi)
214 Pedal_type type = get_grob_pedal_type (gi);
215 Grob *sp = make_line_spanner (type, gi.grob ()->self_scm ());
217 Axis_group_interface::add_element (sp, gi.grob ());
218 pedal_info_[type].carrying_spanner_ = gi.spanner ();
221 void
222 Piano_pedal_align_engraver::acknowledge_end_piano_pedal_bracket (Grob_info gi)
224 Pedal_type type = get_grob_pedal_type (gi);
225 pedal_info_[type].finished_carrying_spanner_ = gi.spanner ();
228 void
229 Piano_pedal_align_engraver::acknowledge_piano_pedal_script (Grob_info gi)
231 Pedal_type type = get_grob_pedal_type (gi);
233 Grob *sp = make_line_spanner (type, gi.grob ()->self_scm ());
234 Axis_group_interface::add_element (sp, gi.grob ());
235 pedal_info_[type].carrying_item_ = gi.grob ();
239 void
240 Piano_pedal_align_engraver::finalize ()
242 for (int i = 0; i < NUM_PEDAL_TYPES; i ++)
244 if (pedal_info_[i].line_spanner_)
246 SCM cc = get_property ("currentCommandColumn");
247 Item *c = unsmob_item (cc);
248 pedal_info_[i].line_spanner_->set_bound (RIGHT, c);
250 pedal_info_[i].clear ();
255 #include "translator.icc"
257 ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, note_column);
258 ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_bracket);
259 ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_script);
261 ADD_END_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_bracket);
264 ADD_TRANSLATOR (Piano_pedal_align_engraver,
265 /* doc */
266 "Align piano pedal symbols and brackets.",
268 /* create */
269 "SostenutoPedalLineSpanner "
270 "SustainPedalLineSpanner "
271 "UnaCordaPedalLineSpanner ",
273 /* read */
274 "currentCommandColumn ",
276 /* write */