2 dynamic-engraver.cc -- implement Dynamic_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 #include "dimensions.hh"
10 #include "crescendo.hh"
11 #include "musical-request.hh"
13 #include "paper-def.hh"
14 #include "paper-column.hh"
15 #include "staff-symbol.hh"
16 #include "note-column.hh"
17 #include "text-item.hh"
18 #include "side-position-interface.hh"
19 #include "engraver.hh"
21 #include "note-head.hh"
22 #include "group-interface.hh"
23 #include "directional-element-interface.hh"
24 #include "staff-symbol-referencer.hh"
25 #include "translator-group.hh"
27 class Dynamic_line_spanner : public Spanner
30 Dynamic_line_spanner ();
32 void add_column (Note_column*);
33 Direction get_default_dir () const;
35 virtual void do_post_processing ();
38 Dynamic_line_spanner::Dynamic_line_spanner ()
40 set_elt_property ("transparent", SCM_BOOL_T);
41 side_position (this).set_axis (Y_AXIS);
45 Dynamic_line_spanner::add_column (Note_column* n)
47 if (!spanned_drul_[LEFT])
49 set_bounds (RIGHT, n);
55 Dynamic_line_spanner::get_default_dir () const
61 Dynamic_line_spanner::do_post_processing ()
63 Spanner::do_post_processing ();
64 Direction dir = directional_element (this).get ();
66 dir = get_default_dir ();
69 Hier is ook vast iets voor?
71 Staff_symbol_referencer_interface si (this);
72 Real above_staff = si.line_count () + 2;
75 // Aargh, nu snap ik waarom ik het niet snap
76 // zie Staff_symbol_referencer_interface::set_position
78 if (si.position_f () * dir < above_staff)
79 si.set_position (above_staff * (int)dir);
81 SCM s = get_elt_property ("padding");
84 si.set_position (si.position_f () + gh_scm2double (s) * (int) dir);
88 Real pos = si.position_f () * dir;
89 if (pos * dir < above_staff)
92 SCM s = get_elt_property ("padding");
94 dy += gh_scm2double (s);
96 Real half_space = si.staff_space () / 2;
97 translate_axis (dy*half_space*dir, Y_AXIS);
103 print text & hairpin dynamics.
105 class Dynamic_engraver : public Engraver
108 Crescendo * finished_cresc_p_;
109 Crescendo * cresc_p_;
111 Text_script_req* text_req_l_;
112 Span_req * span_start_req_l_;
113 Drul_array<Span_req*> span_req_l_drul_;
115 Dynamic_line_spanner* line_spanner_;
116 Moment last_request_mom_;
121 VIRTUAL_COPY_CONS(Translator);
125 void announce_element (Score_element_info);
127 virtual void do_removal_processing ();
128 virtual void acknowledge_element (Score_element_info);
129 virtual bool do_try_music (Music *req_l);
130 virtual void do_process_requests ();
131 virtual void do_pre_move_processing ();
132 virtual void do_post_move_processing ();
135 ADD_THIS_TRANSLATOR (Dynamic_engraver);
138 Dynamic_engraver::announce_element (Score_element_info i)
140 group (i.elem_l_, "interfaces").add_thing (ly_symbol2scm ("dynamic"));
142 Engraver::announce_element (i);
146 Dynamic_engraver::Dynamic_engraver ()
149 finished_cresc_p_ = 0;
151 span_start_req_l_ = 0;
155 span_req_l_drul_[START] = 0;
156 span_req_l_drul_[STOP] = 0;
160 Dynamic_engraver::do_post_move_processing ()
163 span_req_l_drul_[START] = 0;
164 span_req_l_drul_[STOP] = 0;
168 Dynamic_engraver::do_try_music (Music * m)
170 if (Text_script_req* d = dynamic_cast <Text_script_req*> (m))
172 if (d->style_str_ == "dynamic")
178 else if (Span_req* s = dynamic_cast <Span_req*> (m))
180 if ((s->span_type_str_ == "crescendo"
181 || s->span_type_str_ == "decrescendo"))
183 span_req_l_drul_[s->span_dir_] = s;
191 Dynamic_engraver::do_process_requests ()
193 if ((span_req_l_drul_[START] || text_req_l_) && !line_spanner_)
195 line_spanner_ = new Dynamic_line_spanner;
196 side_position (line_spanner_).set_axis (Y_AXIS);
197 announce_element (Score_element_info
199 text_req_l_ ? text_req_l_ : span_req_l_drul_[START]));
203 if (span_req_l_drul_[START] || text_req_l_)
204 last_request_mom_ = now_mom ();
208 String loud = text_req_l_->text_str_;
210 text_p_ = new Text_item;
211 text_p_->set_elt_property ("text",
212 ly_str02scm (loud.ch_C ()));
213 text_p_->set_elt_property ("style", gh_str02scm ("dynamic"));
214 text_p_->set_elt_property ("script-priority",
217 assert (line_spanner_);
218 text_p_->set_parent (line_spanner_, Y_AXIS);
219 announce_element (Score_element_info (text_p_, text_req_l_));
222 if (span_req_l_drul_[STOP])
226 span_req_l_drul_[STOP]->warning
227 (_ ("can't find start of (de)crescendo"));
231 assert (!finished_cresc_p_);
232 cresc_p_->set_bounds(RIGHT, get_staff_info ().musical_pcol_l ());
233 cresc_p_->add_dependency (get_staff_info ().musical_pcol_l ());
234 finished_cresc_p_ = cresc_p_;
236 span_start_req_l_ = 0;
240 if (span_req_l_drul_[START])
242 if (span_start_req_l_)
244 span_req_l_drul_[START]->warning
245 (span_start_req_l_->span_dir_ == 1
247 _ ("already have a crescendo")
248 : _ ("already have a decrescendo"));
252 span_start_req_l_ = span_req_l_drul_[START];
253 cresc_p_ = new Crescendo;
254 cresc_p_->set_elt_property
256 gh_int2scm ((span_req_l_drul_[START]->span_type_str_ == "crescendo")
257 ? BIGGER : SMALLER));
259 SCM s = get_property (span_req_l_drul_[START]->span_type_str_ + "Text");
262 cresc_p_->set_elt_property ("start-text", s);
263 daddy_trans_l_->set_property (span_req_l_drul_[START]->span_type_str_
264 + "Text", SCM_UNDEFINED);
267 s = get_property (span_req_l_drul_[START]->span_type_str_ + "Spanner");
268 if (gh_string_p (s)) //&& ly_scm2string (s) != "hairpin")
270 cresc_p_->set_elt_property ("spanner", s);
271 daddy_trans_l_->set_property (span_req_l_drul_[START]->span_type_str_
272 + "Spanner", SCM_UNDEFINED);
275 cresc_p_->set_bounds(LEFT, get_staff_info ().musical_pcol_l ());
276 cresc_p_->set_bounds(RIGHT, get_staff_info ().musical_pcol_l ());
277 cresc_p_->add_dependency (get_staff_info ().musical_pcol_l ());
279 // arrragh, brr, urg: we know how wide text is, no?
282 index_set_cell (cresc_p_->get_elt_property ("dynamic-drul"),
284 if (finished_cresc_p_)
285 index_set_cell (finished_cresc_p_->get_elt_property ("dynamic-drul"),
289 assert (line_spanner_);
290 cresc_p_->set_parent (line_spanner_, Y_AXIS);
291 cresc_p_->add_dependency (line_spanner_);
292 announce_element (Score_element_info (cresc_p_, span_req_l_drul_[START]));
298 Dynamic_engraver::do_pre_move_processing ()
304 Dynamic_engraver::do_removal_processing ()
308 typeset_element (cresc_p_ );
309 span_start_req_l_->warning (_ ("unterminated (de)crescendo"));
315 typeset_element (line_spanner_);
322 Dynamic_engraver::typeset_all ()
324 if (finished_cresc_p_)
326 //finished_cresc_p_->set_bounds (RIGHT, get_staff_info ().musical_pcol_l ());
327 typeset_element (finished_cresc_p_);
328 finished_cresc_p_ =0;
333 typeset_element (text_p_);
338 TODO: This should be optionised:
339 * break when group of dynamic requests ends
341 * continue through piece
343 if (line_spanner_ && last_request_mom_ < now_mom ())
345 typeset_element (line_spanner_);
351 Dynamic_engraver::acknowledge_element (Score_element_info i)
355 if (Note_column* n = dynamic_cast<Note_column*> (i.elem_l_))
357 side_position (line_spanner_).add_support (n);
358 line_spanner_->add_column (n);