]> git.donarmstrong.com Git - lilypond.git/blob - lily/piano-pedal-engraver.cc
release: 1.5.13
[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--2001 Jan Nieuwenhuizen <janneke@gnu.org>
7  */
8
9 #include "engraver.hh"
10 #include "musical-request.hh"
11 #include "grob.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 class Piano_pedal_engraver : public Engraver
21 {
22 public:
23   TRANSLATOR_DECLARATIONS(Piano_pedal_engraver);
24   ~Piano_pedal_engraver ();
25 protected:
26   virtual void initialize ();
27   virtual bool try_music (Music*);
28   virtual void stop_translation_timestep ();
29   virtual void start_translation_timestep ();
30   virtual void acknowledge_grob (Grob_info);
31   virtual void create_grobs ();
32
33 private:
34   struct Pedal_info
35   {
36     char const * name_;
37     Span_req* start_req_l_;
38     Drul_array<Span_req*> req_l_drul_;
39     Item* item_p_;
40   };
41
42
43   Pedal_info *info_list_;
44 };
45
46
47
48 Piano_pedal_engraver::Piano_pedal_engraver ()
49 {
50   info_list_ = 0;
51 }
52 void
53 Piano_pedal_engraver::initialize ()
54 {
55   info_list_ = new Pedal_info[4];
56   Pedal_info *p = info_list_;
57
58
59   char * names [] = { "Sostenuto", "Sustain", "UnaCorda", 0  };
60   char **np = names ;
61   do
62     {
63       p->name_ = *np;
64       p->item_p_ = 0;
65       p->req_l_drul_[START] = 0;
66       p->req_l_drul_[STOP] = 0;
67       p->start_req_l_ = 0;
68
69       p++;
70     }
71   while (* (np ++));
72 }
73
74 Piano_pedal_engraver::~Piano_pedal_engraver ()
75 {
76   delete[] info_list_;
77 }
78
79 /*
80    Urg: Code dup
81    I'm a script
82   */
83 void
84 Piano_pedal_engraver::acknowledge_grob (Grob_info info)
85 {
86   for (Pedal_info*p = info_list_; p && p->name_; p ++)
87     {
88       if (p->item_p_)
89         {
90           if (Rhythmic_head::has_interface (info.grob_l_))
91             {
92               Side_position_interface::add_support (p->item_p_, info.grob_l_);
93
94               if (Side_position_interface::get_axis (p->item_p_) == X_AXIS
95                   && !p->item_p_->parent_l (Y_AXIS))
96                 p->item_p_->set_parent (info.grob_l_, Y_AXIS);
97             }
98           if (Stem::has_interface (info.grob_l_))
99             {
100               Side_position_interface::add_support (p->item_p_,info.grob_l_);
101             }
102         }
103     }
104 }
105
106 bool
107 Piano_pedal_engraver::try_music (Music *m)
108 {
109   if (Span_req * s = dynamic_cast<Span_req*> (m))
110     {
111       for (Pedal_info*p = info_list_; p->name_; p ++)
112         {
113           if (scm_equal_p (s->get_mus_property ("span-type"),
114                            ly_str02scm (p->name_))==SCM_BOOL_T)
115             {
116               p->req_l_drul_[s->get_span_dir ()] = s;
117               return true;
118             }
119         }
120     }
121   return false;
122 }
123
124 void
125 Piano_pedal_engraver::create_grobs ()
126 {
127   for (Pedal_info*p = info_list_; p && p->name_; p ++)
128     {
129       if (p->item_p_ || ! (p->req_l_drul_[STOP] || p->req_l_drul_[START]))
130         continue;
131       
132       SCM s = SCM_EOL;
133       SCM strings = get_property (("pedal" + String (p->name_) + "Strings").ch_C ());
134       if (scm_ilength (strings) < 3)
135         continue;
136       
137       if (p->req_l_drul_[STOP] && p->req_l_drul_[START])
138         {
139           if (!p->start_req_l_)
140             {
141               p->req_l_drul_[STOP]->origin ()->warning (_f ("can't find start of piano pedal: `%s'",  p->name_));
142             }
143           else
144             {
145               s = ly_cadr (strings);
146             }
147           p->start_req_l_ = p->req_l_drul_[START];
148         }
149       else if (p->req_l_drul_[STOP])
150         {
151           if (!p->start_req_l_)
152             {
153               p->req_l_drul_[STOP]->origin ()->warning (_f ("can't find start of piano pedal: `%s'", p->name_));
154             }
155           else
156             {
157               s = ly_caddr (strings);
158             }
159           p->start_req_l_ = 0;
160         }
161       else if (p->req_l_drul_[START])
162         {
163           p->start_req_l_ = p->req_l_drul_[START];
164           s = ly_car (strings);
165         }
166
167       if (gh_string_p (s))
168         {
169           String propname = String (p->name_) + "Pedal";
170           p->item_p_ = new Item (get_property (propname.ch_C ()));
171           p->item_p_->set_grob_property ("text", s);
172
173           announce_grob (p->item_p_,
174                             p->req_l_drul_[START]
175                             ? p->req_l_drul_[START]
176                             : p->req_l_drul_[STOP]);
177         }
178       p->req_l_drul_[START] = 0;
179       p->req_l_drul_[STOP] = 0;
180     }
181 }
182
183 void
184 Piano_pedal_engraver::stop_translation_timestep ()
185 {
186   Item * sustain = 0;
187   for (Pedal_info*p = info_list_; p->name_; p ++)
188     {
189       if (p->name_ == String ("Sustain"))
190         sustain = p->item_p_;
191     }
192
193   for (Pedal_info*p = info_list_; p->name_; p ++)
194     {
195       if (p->item_p_)
196         {
197           Side_position_interface::add_staff_support (p->item_p_);
198           
199           /*
200             Hmm.
201           */
202           if (p->name_ != String ("Sustain"))
203             {
204               if (sustain)
205                 {
206                   Side_position_interface::add_support (p->item_p_,sustain);
207                 }
208             }
209           typeset_grob (p->item_p_);
210         }
211       p->item_p_ = 0;
212     }
213 }
214
215 void
216 Piano_pedal_engraver::start_translation_timestep ()
217 {
218   for (Pedal_info*p = info_list_; p->name_; p ++)
219     {
220       p->req_l_drul_[STOP] = 0;
221       p->req_l_drul_[START] = 0;
222     }
223 }
224 ENTER_DESCRIPTION(Piano_pedal_engraver,
225 /* descr */       "Engrave piano pedal symbols.",
226 /* creats*/       "SostenutoPedal SustainPedal UnaCordaPedal",
227 /* acks  */       "rhythmic-head-interface stem-interface",
228 /* reads */       "pedalSostenutoStrings pedalSustainStrings pedalUnaCordaStrings",
229 /* write */       "");