]> git.donarmstrong.com Git - lilypond.git/blob - lily/piano-pedal-engraver.cc
release: 1.3.67
[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 "rhythmic-head.hh"
16 #include "stem.hh"
17 #include "side-position-interface.hh"
18 #include "staff-symbol-referencer.hh"
19 #include "item.hh"
20
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 (Rhythmic_head* n = dynamic_cast<Rhythmic_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_ )).ch_C());
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_ )).ch_C());
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_ )).ch_C());
182         }
183
184       if (gh_string_p (s))
185         {
186           if (p->name_ == String ("Sustain"))
187             {
188               // fixme: Item should be sufficient.
189               p->item_p_ = new Item (get_property ("basicSustainPedalProperties"));
190             }
191           else
192             {
193               p->item_p_ = new Item (get_property ("basicPedalProperties"));
194             }
195           p->item_p_->set_elt_property ("text", s);
196           // guh
197
198           Side_position_interface si (p->item_p_);
199           si.set_axis (Y_AXIS);
200
201           // todo: init with basic props.
202           p->item_p_->add_offset_callback (Side_position_interface::aligned_on_self, X_AXIS);
203           p->item_p_->add_offset_callback (Side_position_interface::centered_on_parent, X_AXIS);
204           announce_element (Score_element_info (p->item_p_,
205                                                 p->req_l_drul_[START]
206                                                 ? p->req_l_drul_[START]
207                                                 : p->req_l_drul_[STOP]));
208         }
209     }
210 }
211
212 void
213 Piano_pedal_engraver::do_pre_move_processing ()
214 {
215   Item * sustain = 0;
216   for (Pedal_info*p = info_list_; p->name_; p ++)
217     {
218       if (p->name_ == String ("Sustain"))
219         sustain = p->item_p_;
220     }
221
222   for (Pedal_info*p = info_list_; p->name_; p ++)
223     {
224       if (p->item_p_)
225         {
226           Side_position_interface (p->item_p_).add_staff_support ();
227           /*
228             Hmm.
229           */
230           if (p->name_ != String ("Sustain"))
231             {
232               if (sustain)
233                 {
234                   Side_position_interface st (p->item_p_);
235                   st.add_support (sustain);
236                 }
237             }
238           typeset_element (p->item_p_);
239         }
240       p->item_p_ = 0;
241     }
242 }
243
244 void
245 Piano_pedal_engraver::do_post_move_processing ()
246 {
247   for (Pedal_info*p = info_list_; p->name_; p ++)
248     {
249       p->req_l_drul_[STOP] = 0;
250       p->req_l_drul_[START] = 0;
251     }
252 }