2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2008--2011 Han-Wen Nienhuys <hanwen@lilypond.org>
7 LilyPond is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 LilyPond is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
23 #include "engraver.hh"
25 #include "axis-group-interface.hh"
26 #include "directional-element-interface.hh"
28 #include "side-position-interface.hh"
30 #include "stream-event.hh"
32 #include "translator.icc"
34 class Dynamic_align_engraver
: public Engraver
36 TRANSLATOR_DECLARATIONS (Dynamic_align_engraver
);
37 DECLARE_TRANSLATOR_LISTENER (break_span
);
38 DECLARE_ACKNOWLEDGER (note_column
);
39 DECLARE_ACKNOWLEDGER (dynamic
);
40 DECLARE_END_ACKNOWLEDGER (dynamic
);
43 virtual void stop_translation_timestep ();
46 void create_line_spanner (Stream_event
*cause
);
48 vector
<Spanner
*> ended_
;
49 vector
<Spanner
*> started_
;
50 vector
<Grob
*> scripts_
;
51 vector
<Grob
*> support_
;
53 set
<Spanner
*> running_
;
58 Dynamic_align_engraver::Dynamic_align_engraver ()
64 ADD_ACKNOWLEDGER (Dynamic_align_engraver
, dynamic
);
65 ADD_ACKNOWLEDGER (Dynamic_align_engraver
, note_column
);
66 ADD_END_ACKNOWLEDGER (Dynamic_align_engraver
, dynamic
);
69 Dynamic_align_engraver::create_line_spanner (Stream_event
*event
)
72 line_
= make_spanner ("DynamicLineSpanner",
73 event
? event
->self_scm () : SCM_EOL
);
77 Dynamic_align_engraver::acknowledge_end_dynamic (Grob_info info
)
79 if (Spanner::has_interface (info
.grob ()))
80 ended_
.push_back (info
.spanner ());
84 Dynamic_align_engraver::acknowledge_note_column (Grob_info info
)
86 support_
.push_back (info
.grob ());
89 IMPLEMENT_TRANSLATOR_LISTENER (Dynamic_align_engraver
, break_span
);
91 Dynamic_align_engraver::listen_break_span (Stream_event
*event
)
93 if (event
->in_event_class ("break-dynamic-span-event"))
98 Dynamic_align_engraver::acknowledge_dynamic (Grob_info info
)
100 Stream_event
*cause
= info
.event_cause ();
101 create_line_spanner (cause
);
102 if (Spanner::has_interface (info
.grob ()))
104 started_
.push_back (info
.spanner ());
106 If we are using text spans instead of hairpins and the line
107 is hidden, end the alignment spanner early: this allows dynamics
108 to be spaced individually instead of being linked together.
110 if (info
.grob ()->internal_has_interface (ly_symbol2scm ("dynamic-text-spanner-interface"))
111 && (info
.grob ()->get_property ("style") == ly_symbol2scm ("none")))
114 else if (info
.item ())
115 scripts_
.push_back (info
.item ());
117 info
.grob ()->programming_error ("unknown dynamic grob");
119 Axis_group_interface::add_element (line_
, info
.grob ());
123 if (Direction d
= to_dir (cause
->get_property ("direction")))
124 set_grob_direction (line_
, d
);
129 Dynamic_align_engraver::stop_translation_timestep ()
131 for (vsize i
= 0; i
< started_
.size (); i
++)
132 running_
.insert (started_
[i
]);
133 for (vsize i
= 0; i
< ended_
.size (); i
++)
135 Spanner
*sp
= ended_
[i
];
137 set
<Spanner
*>::iterator it
= running_
.find (sp
);
138 if (it
!= running_
.end ())
141 started_
[i
]->programming_error ("lost track of this dynamic spanner");
144 bool end
= line_
&& (running_
.empty ()
150 && ((d
== LEFT
&& !line_
->get_bound (LEFT
))
151 || (end
&& d
== RIGHT
&& !line_
->get_bound (RIGHT
))))
153 vector
<Spanner
*> const &spanners
154 = (d
== LEFT
) ? started_
: ended_
;
157 if (scripts_
.size ())
159 else if (spanners
.size ())
160 bound
= spanners
[0]->get_bound (d
);
163 bound
= unsmob_grob (get_property ("currentMusicalColumn"));
165 programming_error ("started DynamicLineSpanner but have no left bound");
168 line_
->set_bound (d
, bound
);
171 while (flip (&d
) != LEFT
);
173 for (vsize i
= 0; line_
&& i
< support_
.size (); i
++)
174 Side_position_interface::add_support (line_
, support_
[i
]);
188 ADD_TRANSLATOR (Dynamic_align_engraver
,
190 "Align hairpins and dynamic texts on a horizontal line.",
193 "DynamicLineSpanner ",
196 "currentMusicalColumn ",