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 "international.hh"
13 #include "note-column.hh"
14 #include "pointer-group-interface.hh"
15 #include "self-alignment-interface.hh"
17 #include "stream-event.hh"
18 #include "text-interface.hh"
20 #include "translator.icc"
22 class New_dynamic_engraver
: public Engraver
24 TRANSLATOR_DECLARATIONS (New_dynamic_engraver
);
25 DECLARE_ACKNOWLEDGER (note_column
);
26 DECLARE_TRANSLATOR_LISTENER (absolute_dynamic
);
27 DECLARE_TRANSLATOR_LISTENER (span_dynamic
);
30 virtual void process_music ();
31 virtual void stop_translation_timestep ();
32 virtual void finalize ();
35 SCM
get_property_setting (Stream_event
*evt
, char const *evprop
,
37 string
get_spanner_type (Stream_event
*ev
);
39 Drul_array
<Stream_event
*> accepted_spanevents_drul_
;
40 Spanner
*current_spanner_
;
41 Spanner
*finished_spanner_
;
44 Stream_event
*script_event_
;
45 Stream_event
*current_span_event_
;
48 New_dynamic_engraver::New_dynamic_engraver ()
51 current_span_event_
= 0;
53 finished_spanner_
= 0;
55 accepted_spanevents_drul_
.set (0, 0);
58 IMPLEMENT_TRANSLATOR_LISTENER (New_dynamic_engraver
, absolute_dynamic
);
60 New_dynamic_engraver::listen_absolute_dynamic (Stream_event
*ev
)
62 ASSIGN_EVENT_ONCE (script_event_
, ev
);
65 IMPLEMENT_TRANSLATOR_LISTENER (New_dynamic_engraver
, span_dynamic
);
67 New_dynamic_engraver::listen_span_dynamic (Stream_event
*ev
)
69 Direction d
= to_dir (ev
->get_property ("span-direction"));
71 ASSIGN_EVENT_ONCE (accepted_spanevents_drul_
[d
], ev
);
75 New_dynamic_engraver::get_property_setting (Stream_event
*evt
,
79 SCM spanner_type
= evt
->get_property (evprop
);
80 if (spanner_type
== SCM_EOL
)
81 spanner_type
= get_property (ctxprop
);
86 New_dynamic_engraver::process_music ()
89 && (accepted_spanevents_drul_
[STOP
]
91 || accepted_spanevents_drul_
[START
]))
93 Stream_event
*ender
= accepted_spanevents_drul_
[STOP
];
95 ender
= script_event_
;
98 ender
= accepted_spanevents_drul_
[START
];
100 finished_spanner_
= current_spanner_
;
101 announce_end_grob (finished_spanner_
, ender
->self_scm ());
102 current_spanner_
= 0;
103 current_span_event_
= 0;
106 if (accepted_spanevents_drul_
[START
])
108 current_span_event_
= accepted_spanevents_drul_
[START
];
110 string start_type
= get_spanner_type (current_span_event_
);
111 SCM cresc_type
= get_property_setting (current_span_event_
, "span-type",
112 (start_type
+ "Spanner").c_str ());
114 if (cresc_type
== ly_symbol2scm ("text"))
117 = make_spanner ("DynamicTextSpanner",
118 accepted_spanevents_drul_
[START
]->self_scm ());
120 SCM text
= get_property_setting (current_span_event_
, "span-text",
121 (start_type
+ "Text").c_str ());
122 if (Text_interface::is_markup (text
))
123 current_spanner_
->set_property ("text", text
);
127 if (cresc_type
!= ly_symbol2scm ("hairpin"))
129 string as_string
= ly_scm_write_string (cresc_type
);
131 ->origin()->warning (_f ("unknown crescendo style: %s\ndefaulting to hairpin.", as_string
.c_str()));
133 current_spanner_
= make_spanner ("Hairpin",
134 current_span_event_
->self_scm ());
136 if (finished_spanner_
)
138 if (Hairpin::has_interface (finished_spanner_
))
139 Pointer_group_interface::add_grob (finished_spanner_
,
140 ly_symbol2scm ("adjacent-spanners"),
142 if (Hairpin::has_interface (current_spanner_
))
143 Pointer_group_interface::add_grob (current_spanner_
,
144 ly_symbol2scm ("adjacent-spanners"),
151 script_
= make_item ("DynamicText", script_event_
->self_scm ());
152 script_
->set_property ("text",
153 script_event_
->get_property ("text"));
155 if (finished_spanner_
)
156 finished_spanner_
->set_bound (RIGHT
, script_
);
157 if (current_spanner_
)
159 current_spanner_
->set_bound (LEFT
, script_
);
161 if (!Hairpin::has_interface (current_spanner_
))
162 set_nested_property (current_spanner_
,
163 scm_list_3 (ly_symbol2scm ("bound-details"),
164 ly_symbol2scm ("left"),
165 ly_symbol2scm ("attach-dir")),
166 scm_from_int (RIGHT
));
172 New_dynamic_engraver::stop_translation_timestep ()
174 if (finished_spanner_
&& !finished_spanner_
->get_bound (RIGHT
))
177 unsmob_grob (get_property ("currentMusicalColumn")));
179 if (current_spanner_
&& !current_spanner_
->get_bound (LEFT
))
182 unsmob_grob (get_property ("currentMusicalColumn")));
185 accepted_spanevents_drul_
.set (0, 0);
186 finished_spanner_
= 0;
190 New_dynamic_engraver::finalize ()
193 && !current_spanner_
->is_live ())
194 current_spanner_
= 0;
195 if (current_spanner_
)
198 ->origin ()->warning (_f ("unterminated %s",
199 get_spanner_type (current_span_event_
)
201 current_spanner_
->suicide ();
202 current_spanner_
= 0;
207 New_dynamic_engraver::get_spanner_type (Stream_event
*ev
)
210 SCM start_sym
= ev
->get_property ("class");
212 if (start_sym
== ly_symbol2scm ("decrescendo-event"))
213 type
= "decrescendo";
214 else if (start_sym
== ly_symbol2scm ("crescendo-event"))
217 programming_error ("unknown dynamic spanner type");
223 New_dynamic_engraver::acknowledge_note_column (Grob_info info
)
225 if (script_
&& !script_
->get_parent (X_AXIS
))
227 extract_grob_set (info
.grob (), "note-heads", heads
);
230 Grob
*head
= heads
[0];
231 script_
->set_parent (head
, X_AXIS
);
232 Self_alignment_interface::set_center_parent (script_
, X_AXIS
);
236 if (current_spanner_
&& !current_spanner_
->get_bound (LEFT
))
237 current_spanner_
->set_bound (LEFT
, info
.grob ());
238 if (finished_spanner_
&& !finished_spanner_
->get_bound (RIGHT
))
239 finished_spanner_
->set_bound (RIGHT
, info
.grob ());
242 ADD_ACKNOWLEDGER (New_dynamic_engraver
, note_column
);
243 ADD_TRANSLATOR (New_dynamic_engraver
,
245 "Create hairpins, dynamic texts, and their vertical"
246 " alignments. The symbols are collected onto a"
247 " @code{DynamicLineSpanner} grob which takes care of vertical"
251 "DynamicTextSpanner "
258 "currentMusicalColumn "
259 "decrescendoSpanner "