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