2 new-dynamic-engraver.cc -- implement New_dynamic_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2008--2009 Han-Wen Nienhuys <hanwen@lilypond.org>
11 #include "engraver.hh"
14 #include "international.hh"
16 #include "note-column.hh"
17 #include "pointer-group-interface.hh"
18 #include "self-alignment-interface.hh"
20 #include "stream-event.hh"
21 #include "text-interface.hh"
23 #include "translator.icc"
25 class New_dynamic_engraver : public Engraver
27 TRANSLATOR_DECLARATIONS (New_dynamic_engraver);
28 DECLARE_ACKNOWLEDGER (note_column);
29 DECLARE_TRANSLATOR_LISTENER (absolute_dynamic);
30 DECLARE_TRANSLATOR_LISTENER (span_dynamic);
33 virtual void process_music ();
34 virtual void stop_translation_timestep ();
36 SCM get_property_setting (Stream_event *evt, char const *evprop, char const *ctxprop);
38 Drul_array<Stream_event *> accepted_spanevents_drul_;
39 Spanner *current_spanner_;
40 Spanner *finished_spanner_;
43 Stream_event *script_event_;
44 Stream_event *current_span_event_;
47 New_dynamic_engraver::New_dynamic_engraver ()
50 current_span_event_ = 0;
52 finished_spanner_ = 0;
54 accepted_spanevents_drul_.set (0, 0);
57 IMPLEMENT_TRANSLATOR_LISTENER (New_dynamic_engraver, absolute_dynamic);
59 New_dynamic_engraver::listen_absolute_dynamic (Stream_event *ev)
61 ASSIGN_EVENT_ONCE (script_event_, ev);
64 IMPLEMENT_TRANSLATOR_LISTENER (New_dynamic_engraver, span_dynamic);
66 New_dynamic_engraver::listen_span_dynamic (Stream_event *ev)
68 Direction d = to_dir (ev->get_property ("span-direction"));
70 ASSIGN_EVENT_ONCE (accepted_spanevents_drul_[d], ev);
74 New_dynamic_engraver::get_property_setting (Stream_event *evt, char const *evprop, char const *ctxprop)
76 SCM spanner_type = evt->get_property (evprop);
77 if (spanner_type == SCM_EOL)
78 spanner_type = get_property (ctxprop);
83 New_dynamic_engraver::process_music ()
86 && (accepted_spanevents_drul_[STOP] || script_event_ || accepted_spanevents_drul_[START]))
88 Stream_event* ender = accepted_spanevents_drul_[STOP];
90 ender = script_event_;
93 ender = accepted_spanevents_drul_[START];
95 finished_spanner_ = current_spanner_;
96 announce_end_grob (finished_spanner_, ender->self_scm ());
98 current_span_event_ = 0;
101 if (accepted_spanevents_drul_[START])
103 current_span_event_ = accepted_spanevents_drul_[START];
105 SCM start_sym = current_span_event_->get_property ("class");
108 if (start_sym == ly_symbol2scm ("decrescendo-event"))
109 start_type = "decrescendo";
110 else if (start_sym == ly_symbol2scm ("crescendo-event"))
111 start_type = "crescendo";
114 programming_error ("unknown dynamic spanner type");
118 SCM cresc_type = get_property_setting (current_span_event_, "span-type",
119 (start_type + "Spanner").c_str ());
121 if (cresc_type == ly_symbol2scm ("text"))
124 = make_spanner ("DynamicTextSpanner",
125 accepted_spanevents_drul_[START]->self_scm ());
127 SCM text = get_property_setting (current_span_event_, "span-text",
128 (start_type + "Text").c_str ());
129 if (Text_interface::is_markup (text))
131 current_spanner_->set_property ("text", text);
136 if (cresc_type != ly_symbol2scm ("hairpin"))
138 // Fixme: should put value in error message.
139 string as_string = ly_scm_write_string (cresc_type);
141 ->origin()->warning (_f ("unknown crescendo style: %s\ndefaulting to hairpin.", as_string.c_str()));
143 current_spanner_ = make_spanner ("Hairpin",
144 current_span_event_->self_scm ());
145 if (finished_spanner_)
147 Pointer_group_interface::add_grob (finished_spanner_,
148 ly_symbol2scm ("adjacent-hairpins"),
151 Pointer_group_interface::add_grob (current_spanner_,
152 ly_symbol2scm ("adjacent-hairpins"),
160 script_ = make_item ("DynamicText", script_event_->self_scm ());
161 script_->set_property ("text",
162 script_event_->get_property ("text"));
164 if (finished_spanner_)
165 finished_spanner_->set_bound (RIGHT, script_);
166 if (current_spanner_)
168 current_spanner_->set_bound (LEFT, script_);
170 if (!Hairpin::has_interface (current_spanner_))
171 set_nested_property (current_spanner_,
172 scm_list_3 (ly_symbol2scm ("bound-details"),
173 ly_symbol2scm ("left"),
174 ly_symbol2scm ("attach-dir")
176 scm_from_int (RIGHT));
185 New_dynamic_engraver::stop_translation_timestep ()
187 if (finished_spanner_ && !finished_spanner_->get_bound (RIGHT))
188 finished_spanner_->set_bound (RIGHT,
189 unsmob_grob (get_property ("currentMusicalColumn")));
191 if (current_spanner_ && !current_spanner_->get_bound (LEFT))
192 current_spanner_->set_bound (LEFT,
193 unsmob_grob (get_property ("currentMusicalColumn")));
196 accepted_spanevents_drul_.set (0, 0);
197 finished_spanner_ = 0;
201 New_dynamic_engraver::acknowledge_note_column (Grob_info info)
203 if (script_ && !script_->get_parent (X_AXIS))
205 extract_grob_set (info.grob (), "note-heads", heads);
208 Grob *head = heads[0];
209 script_->set_parent (head, X_AXIS);
210 Self_alignment_interface::set_center_parent (script_, X_AXIS);
214 if (current_spanner_ && !current_spanner_->get_bound (LEFT))
215 current_spanner_->set_bound (LEFT, info.grob ());
216 if (finished_spanner_ && !finished_spanner_->get_bound (RIGHT))
217 finished_spanner_->set_bound (RIGHT, info.grob ());
220 ADD_ACKNOWLEDGER (New_dynamic_engraver, note_column);
221 ADD_TRANSLATOR (New_dynamic_engraver,
223 "Create hairpins, dynamic texts, and their vertical"
224 " alignments. The symbols are collected onto a"
225 " @code{DynamicLineSpanner} grob which takes care of vertical"
229 "DynamicTextSpanner "
236 "currentMusicalColumn "
237 "decrescendoSpanner "