]> git.donarmstrong.com Git - lilypond.git/blob - lily/piano-pedal-engraver.cc
patch::: 1.3.93.jcn2
[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::has_interface (info.elem_l_))
115             {
116               Side_position::add_support (p->item_p_, info.elem_l_);
117
118               if (Side_position::get_axis(p->item_p_) == X_AXIS
119                   && !p->item_p_->parent_l (Y_AXIS))
120                 p->item_p_->set_parent (info.elem_l_, Y_AXIS);
121             }
122           if (Stem::has_interface (info.elem_l_))
123             {
124               Side_position::add_support (p->item_p_,info.elem_l_);
125             }
126         }
127     }
128 }
129
130 bool
131 Piano_pedal_engraver::do_try_music (Music *m)
132 {
133   if (Span_req * s = dynamic_cast<Span_req*>(m))
134     {
135       for (Pedal_info*p = info_list_; p->name_; p ++)
136         {
137           if (s->span_type_str_ == p->name_)
138             {
139               p->req_l_drul_[s->span_dir_] = s;
140               return true;
141             }
142         }
143     }
144   return false;
145 }
146
147 void
148 Piano_pedal_engraver::do_process_music ()
149 {
150   for (Pedal_info*p = info_list_; p->name_; p ++)
151     {
152       SCM s = SCM_UNDEFINED;
153       if (p->req_l_drul_[STOP] && p->req_l_drul_[START])
154         {
155           if (!p->start_req_l_)
156             {
157               p->req_l_drul_[STOP]->origin ()->warning (_f ("can't find start of piano pedal: %s",  p->name_ ));
158             }
159           else
160             {
161               s = get_property (("stopStart" + String (p->name_ )).ch_C());
162             }
163           p->start_req_l_ = p->req_l_drul_[START];
164         }
165       else if (p->req_l_drul_[STOP])
166         {
167           if (!p->start_req_l_)
168             {
169               p->req_l_drul_[STOP]->origin ()->warning (_f ("can't find start of piano pedal: %s", p->name_ ));
170             }
171           else
172             {
173               s = get_property (("stop" + String (p->name_ )).ch_C());
174             }
175           p->start_req_l_ = 0;
176         }
177       else if (p->req_l_drul_[START])
178         {
179           p->start_req_l_ = p->req_l_drul_[START];
180           s = get_property (("start" + String (p->name_ )).ch_C());
181         }
182
183       if (gh_string_p (s))
184         {
185           String propname = String ("basic")+  p->name_ + "PedalProperties";
186           p->item_p_ = new Item (get_property (propname.ch_C()));
187           p->item_p_->set_elt_property ("text", s);
188           // guh
189
190           Side_position::set_axis (p->item_p_,Y_AXIS);
191
192           // todo: init with basic props.
193           p->item_p_->add_offset_callback (Side_position_aligned_on_self_proc, X_AXIS);
194           p->item_p_->add_offset_callback (Side_position_centered_on_parent_proc, X_AXIS);
195           announce_element (p->item_p_,
196                             p->req_l_drul_[START]
197                             ? p->req_l_drul_[START]
198                             : p->req_l_drul_[STOP]);
199         }
200     }
201 }
202
203 void
204 Piano_pedal_engraver::do_pre_move_processing ()
205 {
206   Item * sustain = 0;
207   for (Pedal_info*p = info_list_; p->name_; p ++)
208     {
209       if (p->name_ == String ("Sustain"))
210         sustain = p->item_p_;
211     }
212
213   for (Pedal_info*p = info_list_; p->name_; p ++)
214     {
215       if (p->item_p_)
216         {
217           Side_position::add_staff_support (p->item_p_);
218           /*
219             Hmm.
220           */
221           if (p->name_ != String ("Sustain"))
222             {
223               if (sustain)
224                 {
225                   Side_position::add_support (p->item_p_,sustain);
226                 }
227             }
228           typeset_element (p->item_p_);
229         }
230       p->item_p_ = 0;
231     }
232 }
233
234 void
235 Piano_pedal_engraver::do_post_move_processing ()
236 {
237   for (Pedal_info*p = info_list_; p->name_; p ++)
238     {
239       p->req_l_drul_[STOP] = 0;
240       p->req_l_drul_[START] = 0;
241     }
242 }