]> git.donarmstrong.com Git - lilypond.git/blob - lily/piano-pedal-align-engraver.cc
Run `make grand-replace'.
[lilypond.git] / lily / piano-pedal-align-engraver.cc
1 /* 
2   piano-pedal-align-engraver.cc -- implement  Piano_pedal_align_engraver
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 2006--2008 Han-Wen Nienhuys <hanwen@lilypond.org>
7   
8 */
9
10
11 #include "engraver.hh"
12
13 #include "spanner.hh"
14 #include "item.hh"
15 #include "side-position-interface.hh"
16 #include "stream-event.hh"
17 #include "warn.hh"
18 #include "axis-group-interface.hh"
19
20
21 /*
22   TODO:
23
24
25   * Detach from pedal specifics,
26   
27   * Also use this engraver for dynamics.
28   
29 */
30
31
32 struct Pedal_align_info
33 {
34   Spanner *line_spanner_;
35   Grob *carrying_item_;
36   Spanner *carrying_spanner_;
37   Spanner *finished_carrying_spanner_;
38
39   Pedal_align_info ()
40   {
41     clear ();
42
43   }
44   void clear ()
45   {
46     line_spanner_ = 0;
47     carrying_spanner_ = 0;
48     carrying_item_ = 0;
49     finished_carrying_spanner_ = 0;
50   }
51   bool is_finished ()
52   {
53     bool do_continue = carrying_item_;
54
55     do_continue |= (carrying_spanner_ && !finished_carrying_spanner_);
56     do_continue |= (carrying_spanner_ && finished_carrying_spanner_ != carrying_spanner_);
57
58     return !do_continue;
59   }
60 };
61
62 class Piano_pedal_align_engraver : public Engraver
63 {
64 public:
65   TRANSLATOR_DECLARATIONS (Piano_pedal_align_engraver);
66
67 protected:
68   virtual void finalize ();
69   
70   DECLARE_ACKNOWLEDGER (piano_pedal_script);
71   DECLARE_ACKNOWLEDGER (piano_pedal_bracket);
72   DECLARE_ACKNOWLEDGER (note_column);
73
74   DECLARE_END_ACKNOWLEDGER (piano_pedal_bracket);
75
76   void stop_translation_timestep ();
77   void start_translation_timestep ();
78   
79 private:
80   enum Pedal_type {
81     SOSTENUTO,
82     SUSTAIN,
83     UNA_CORDA,
84     NUM_PEDAL_TYPES
85   };
86   Pedal_align_info pedal_info_[NUM_PEDAL_TYPES];
87   vector<Grob *> supports_;
88
89   Pedal_type get_grob_pedal_type (Grob_info g);
90   Spanner *make_line_spanner (Pedal_type t, SCM);
91 };
92
93 Piano_pedal_align_engraver::Piano_pedal_align_engraver ()
94 {
95 }
96
97 void
98 Piano_pedal_align_engraver::start_translation_timestep ()
99 {
100   supports_.clear ();
101 }
102
103 void
104 Piano_pedal_align_engraver::stop_translation_timestep ()
105 {
106   for (int i = 0; i < NUM_PEDAL_TYPES; i ++)
107     {
108       if (pedal_info_[i].line_spanner_)
109         {
110           
111           if (pedal_info_[i].carrying_item_)
112             {
113               if (!pedal_info_[i].line_spanner_->get_bound (LEFT))
114                 pedal_info_[i].line_spanner_->set_bound (LEFT,
115                                                          pedal_info_[i].carrying_item_);
116
117               pedal_info_[i].line_spanner_->set_bound (RIGHT,
118                                                        pedal_info_[i].carrying_item_);
119             }
120           else if (pedal_info_[i].carrying_spanner_
121                    || pedal_info_[i].finished_carrying_spanner_
122                    )
123             {
124               if (!pedal_info_[i].line_spanner_->get_bound (LEFT)
125                   && pedal_info_[i].carrying_spanner_->get_bound (LEFT))
126                 pedal_info_[i].line_spanner_->set_bound (LEFT,
127                                                          pedal_info_[i].carrying_spanner_->get_bound (LEFT));
128               
129
130               if (pedal_info_[i].finished_carrying_spanner_)
131                 pedal_info_[i].line_spanner_->set_bound (RIGHT,
132                                                          pedal_info_[i].finished_carrying_spanner_->get_bound (RIGHT));
133             }
134           
135           for (vsize j = 0; j < supports_.size (); j++)
136             {
137               Side_position_interface::add_support (pedal_info_[i].line_spanner_, supports_[j]);
138             }
139
140           if (pedal_info_[i].is_finished ())
141             {
142               announce_end_grob (pedal_info_[i].line_spanner_, SCM_EOL);
143               pedal_info_[i].clear ();
144             }
145         }
146
147       pedal_info_[i].carrying_item_ = 0;
148     }
149 }
150
151 Piano_pedal_align_engraver::Pedal_type
152 Piano_pedal_align_engraver::get_grob_pedal_type (Grob_info g)
153 {
154   if (g.event_cause ()->in_event_class ("sostenuto-event"))
155     return SOSTENUTO;
156   if (g.event_cause ()->in_event_class ("sustain-event"))
157     return SUSTAIN;
158   if (g.event_cause ()->in_event_class ("una-corda-event"))
159     return UNA_CORDA;
160
161   programming_error ("Unknown piano pedal type. Defaulting to sustain");
162   return SUSTAIN;
163 }
164
165
166 Spanner *
167 Piano_pedal_align_engraver::make_line_spanner (Pedal_type t, SCM cause)
168 {
169   Spanner *sp = pedal_info_[t].line_spanner_;
170   if (!sp)
171     {
172       switch (t)
173         {
174         case (SOSTENUTO):
175           sp = make_spanner ("SostenutoPedalLineSpanner", cause);
176           break;
177         case (SUSTAIN):
178           sp = make_spanner ("SustainPedalLineSpanner", cause);
179           break;
180         case (UNA_CORDA):
181           sp = make_spanner ("UnaCordaPedalLineSpanner", cause);
182           break;
183         default:
184           programming_error ("No pedal type fonud!") ;
185           return sp;
186         }
187   
188       pedal_info_[t].line_spanner_ = sp;
189     }
190   
191   return sp;
192 }
193
194 void
195 Piano_pedal_align_engraver::acknowledge_note_column (Grob_info gi)
196 {
197   supports_.push_back (gi.grob ());
198 }
199
200 void
201 Piano_pedal_align_engraver::acknowledge_piano_pedal_bracket (Grob_info gi)
202 {
203   Pedal_type type = get_grob_pedal_type (gi);
204   Grob *sp = make_line_spanner (type, gi.grob ()->self_scm ());
205
206   Axis_group_interface::add_element (sp, gi.grob ());
207   pedal_info_[type].carrying_spanner_ = gi.spanner ();
208 }
209
210 void
211 Piano_pedal_align_engraver::acknowledge_end_piano_pedal_bracket (Grob_info gi)
212 {
213   Pedal_type type = get_grob_pedal_type (gi);
214   pedal_info_[type].finished_carrying_spanner_ = gi.spanner ();
215 }
216
217 void
218 Piano_pedal_align_engraver::acknowledge_piano_pedal_script (Grob_info gi)
219 {
220   Pedal_type type = get_grob_pedal_type (gi);
221   
222   Grob *sp = make_line_spanner (type, gi.grob ()->self_scm ());
223   Axis_group_interface::add_element (sp, gi.grob ());
224   pedal_info_[type].carrying_item_ = gi.grob ();
225 }
226
227
228 void
229 Piano_pedal_align_engraver::finalize ()
230 {
231  for (int i = 0; i < NUM_PEDAL_TYPES; i ++)
232     {
233       if (pedal_info_[i].line_spanner_)
234         {
235           SCM cc = get_property ("currentCommandColumn");
236           Item *c = unsmob_item (cc);
237           pedal_info_[i].line_spanner_->set_bound (RIGHT, c);
238
239           pedal_info_[i].clear ();
240         }
241     }
242 }
243
244 #include "translator.icc"
245
246 ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, note_column);
247 ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_bracket);
248 ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_script);
249
250 ADD_END_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_bracket);
251
252
253 ADD_TRANSLATOR (Piano_pedal_align_engraver,
254                 /* doc */
255                 "Align piano pedal symbols and brackets.",
256
257                 /* create */
258                 "SostenutoPedalLineSpanner "
259                 "SustainPedalLineSpanner "
260                 "UnaCordaPedalLineSpanner ",
261
262                 /* read */
263                 "currentCommandColumn ",
264
265                 /* write */
266                 ""
267                 );