]> git.donarmstrong.com Git - lilypond.git/blob - lily/piano-pedal-engraver.cc
release: 1.3.54
[lilypond.git] / lily / piano-pedal-engraver.cc
1 /*   
2   piano-pedal-engraver.cc --  implement Piano_pedal_engraver
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 2000 Jan Nieuwenhuizen <janneke@gnu.org>
7  */
8
9 #include "engraver.hh"
10 #include "musical-request.hh"
11 #include "score-element.hh"
12 #include "item.hh"
13 #include "lookup.hh"
14 #include "lily-guile.hh"
15 #include "note-head.hh"
16 #include "stem.hh"
17 #include "side-position-interface.hh"
18 #include "staff-symbol-referencer.hh"
19 #include "text-item.hh"
20 #include "sustain-pedal.hh"
21
22 /*
23    TODO:
24      * it would be really cool if an engraver could be initialised with a
25        string, ie:
26
27           Piano_pedal_engraver::"sostenuto"
28           Piano_pedal_engraver::"sustain"
29           Piano_pedal_engraver::"una-chorda"
30
31  */
32
33 /*
34   Would it? The semantics are unclear, and real benefits are muddy
35   too.  --hwn
36 */
37
38
39
40 /**
41    engrave Piano pedals symbols.
42  */
43 class Piano_pedal_engraver : public Engraver
44 {
45 public:
46   VIRTUAL_COPY_CONS (Translator);
47   Piano_pedal_engraver ();
48   ~Piano_pedal_engraver ();
49 protected:
50   virtual void do_creation_processing ();
51   virtual bool do_try_music (Music*);
52   virtual void do_process_music ();
53   virtual void do_pre_move_processing ();
54   virtual void do_post_move_processing ();
55   virtual void acknowledge_element (Score_element_info);
56
57 private:
58   struct Pedal_info
59   {
60     char const * name_;
61     Span_req* start_req_l_;
62     Drul_array<Span_req*> req_l_drul_;
63     Item* item_p_;
64   };
65
66
67   Pedal_info *info_list_;
68 };
69
70 ADD_THIS_TRANSLATOR (Piano_pedal_engraver);
71
72 Piano_pedal_engraver::Piano_pedal_engraver ()
73 {
74   info_list_ = 0;
75 }
76 void
77 Piano_pedal_engraver::do_creation_processing()
78 {
79   info_list_ = new Pedal_info[4];
80   Pedal_info *p = info_list_;
81
82
83   char * names [] = { "Sostenuto", "Sustain", "UnaChorda", 0  };
84   char **np = names ;
85   do
86     {
87       p->name_ = *np;
88       p->item_p_ = 0;
89       p->req_l_drul_[START] = 0;
90       p->req_l_drul_[STOP] = 0;
91       p->start_req_l_ = 0;
92
93       p++;
94     }
95   while (*(np ++));
96 }
97
98 Piano_pedal_engraver::~Piano_pedal_engraver()
99 {
100   delete[] info_list_;
101 }
102
103 /*
104   Urg: Code dup
105   I'm a script
106  */
107 void
108 Piano_pedal_engraver::acknowledge_element (Score_element_info info)
109 {
110   for (Pedal_info*p = info_list_; p->name_; p ++)
111     {
112       if (p->item_p_)
113         {
114           if (Note_head* n = dynamic_cast<Note_head*> (info.elem_l_))
115             {
116               Side_position_interface st (p->item_p_);
117               st.add_support (n);
118               if (st.get_axis( ) == X_AXIS
119                   && !p->item_p_->parent_l (Y_AXIS))
120                 p->item_p_->set_parent (n, Y_AXIS);
121             }
122           if (Stem* s = dynamic_cast<Stem*> (info.elem_l_))
123             {
124               Side_position_interface st (p->item_p_);
125               st.add_support (s);
126             }
127         }
128     }
129 }
130
131 bool
132 Piano_pedal_engraver::do_try_music (Music *m)
133 {
134   if (Span_req * s = dynamic_cast<Span_req*>(m))
135     {
136       for (Pedal_info*p = info_list_; p->name_; p ++)
137         {
138           if (s->span_type_str_ == p->name_)
139             {
140               p->req_l_drul_[s->span_dir_] = s;
141               return true;
142             }
143         }
144     }
145   return false;
146 }
147
148 void
149 Piano_pedal_engraver::do_process_music ()
150 {
151   for (Pedal_info*p = info_list_; p->name_; p ++)
152     {
153       SCM s = SCM_UNDEFINED;
154       if (p->req_l_drul_[STOP] && p->req_l_drul_[START])
155         {
156           if (!p->start_req_l_)
157             {
158               p->req_l_drul_[STOP]->warning (_f ("can't find start of piano pedal: %s",  p->name_ ));
159             }
160           else
161             {
162               s = get_property ("stopStart" + String (p->name_ ));
163             }
164           p->start_req_l_ = p->req_l_drul_[START];
165         }
166       else if (p->req_l_drul_[STOP])
167         {
168           if (!p->start_req_l_)
169             {
170               p->req_l_drul_[STOP]->warning (_f ("can't find start of piano pedal: %s", p->name_ ));
171             }
172           else
173             {
174               s = get_property ("stop" + String (p->name_ ));
175             }
176           p->start_req_l_ = 0;
177         }
178       else if (p->req_l_drul_[START])
179         {
180           p->start_req_l_ = p->req_l_drul_[START];
181           s = get_property ("start" + String (p->name_ ));
182         }
183
184       if (s != SCM_UNDEFINED)
185         {
186           if (p->name_ == String ("Sustain"))
187             {
188               p->item_p_ = new Sustain_pedal;
189               p->item_p_->set_elt_property ("text", s);
190             }
191           else
192             {
193               p->item_p_ = new Text_item;
194               p->item_p_->set_elt_property ("text", s);
195               // guh
196               p->item_p_->set_elt_property ("style", ly_str02scm ("italic"));
197             }
198
199           Side_position_interface si (p->item_p_);
200           si.set_axis (Y_AXIS);
201
202           p->item_p_->set_elt_property ("no-spacing-rods"  , SCM_BOOL_T);
203           p->item_p_->set_elt_property ("self-alignment-X", gh_int2scm (0));
204           p->item_p_->add_offset_callback (Side_position_interface::aligned_on_self, X_AXIS);
205           p->item_p_->add_offset_callback (Side_position_interface::centered_on_parent, X_AXIS);
206           announce_element (Score_element_info (p->item_p_,
207                                                 p->req_l_drul_[START]
208                                                 ? p->req_l_drul_[START]
209                                                 : p->req_l_drul_[STOP]));
210         }
211     }
212 }
213
214 void
215 Piano_pedal_engraver::do_pre_move_processing ()
216 {
217   Item * sustain = 0;
218   for (Pedal_info*p = info_list_; p->name_; p ++)
219     {
220       if (p->name_ == String ("Sustain"))
221         sustain = p->item_p_;
222     }
223
224   for (Pedal_info*p = info_list_; p->name_; p ++)
225     {
226       if (p->item_p_)
227         {
228           Side_position_interface (p->item_p_).add_staff_support ();
229           /*
230             Hmm.
231           */
232           if (p->name_ != String ("Sustain"))
233             {
234               if (sustain)
235                 {
236                   Side_position_interface st (p->item_p_);
237                   st.add_support (sustain);
238                 }
239             }
240           typeset_element (p->item_p_);
241         }
242       p->item_p_ = 0;
243     }
244 }
245
246 void
247 Piano_pedal_engraver::do_post_move_processing ()
248 {
249   for (Pedal_info*p = info_list_; p->name_; p ++)
250     {
251       p->req_l_drul_[STOP] = 0;
252       p->req_l_drul_[START] = 0;
253     }
254 }