Fixes Issue 1504, allowing feather beam line breaking.
[lilypond/patrick.git] / lily / metronome-engraver.cc
blob09673b7e14a95c9bb5ca8ee42b02c15aeb2bcb71
1 /*
2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1998--2011 Jan Nieuwenhuizen <janneke@gnu.org>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
20 #include <cctype>
21 using namespace std;
23 #include "engraver.hh"
25 #include "context.hh"
26 #include "duration.hh"
27 #include "grob-array.hh"
28 #include "item.hh"
29 #include "music.hh"
30 #include "stream-event.hh"
31 #include "text-interface.hh"
33 #include "translator.icc"
35 class Metronome_mark_engraver : public Engraver
37 Item *text_;
38 Grob *support_;
39 Grob *bar_;
40 Stream_event *tempo_ev_;
42 public:
43 TRANSLATOR_DECLARATIONS (Metronome_mark_engraver);
45 protected:
46 void stop_translation_timestep ();
47 void process_music ();
49 DECLARE_ACKNOWLEDGER (break_aligned);
50 DECLARE_ACKNOWLEDGER (break_alignment);
51 DECLARE_ACKNOWLEDGER (grob);
53 DECLARE_TRANSLATOR_LISTENER (tempo_change);
56 Metronome_mark_engraver::Metronome_mark_engraver ()
58 text_ = 0;
59 support_ = 0;
60 bar_ = 0;
61 tempo_ev_ = 0;
64 IMPLEMENT_TRANSLATOR_LISTENER (Metronome_mark_engraver, tempo_change);
65 void
66 Metronome_mark_engraver::listen_tempo_change (Stream_event *ev)
68 ASSIGN_EVENT_ONCE (tempo_ev_, ev);
71 static bool
72 safe_is_member (SCM scm, SCM lst)
74 return scm_list_p (lst) == SCM_BOOL_T
75 && scm_member (scm, lst) != SCM_BOOL_F;
78 void
79 Metronome_mark_engraver::acknowledge_break_aligned (Grob_info info)
81 Grob *g = info.grob ();
83 if (text_
84 && g->get_property ("break-align-symbol")
85 == ly_symbol2scm ("staff-bar"))
86 bar_ = g;
87 else if (text_
88 && !support_
89 && safe_is_member (g->get_property ("break-align-symbol"),
90 text_->get_property ("break-align-symbols"))
91 && Item::break_visible (g))
93 support_ = g;
94 text_->set_parent (g, X_AXIS);
98 void
99 Metronome_mark_engraver::acknowledge_break_alignment (Grob_info info)
101 Grob *g = info.grob ();
103 if (text_
104 && support_
105 && dynamic_cast<Item *> (g))
106 text_->set_parent (g, X_AXIS);
109 void
110 Metronome_mark_engraver::acknowledge_grob (Grob_info info)
112 Grob *g = info.grob ();
114 if (text_)
115 for (SCM s = text_->get_property ("non-break-align-symbols");
116 scm_is_pair (s);
117 s = scm_cdr (s))
118 if (g->internal_has_interface (scm_car (s)))
119 text_->set_parent (g, X_AXIS);
122 void
123 Metronome_mark_engraver::stop_translation_timestep ()
125 if (text_)
127 if (text_->get_parent (X_AXIS)
128 && text_->get_parent (X_AXIS)->internal_has_interface (ly_symbol2scm ("multi-measure-rest-interface"))
129 && bar_)
130 text_->set_parent (bar_, X_AXIS);
131 else if (!support_)
134 Gardner Read "Music Notation", p.278
136 Align the metronome mark over the time signature (or the
137 first notational element of the measure if no time
138 signature is present in that measure).
140 if (Grob *mc = unsmob_grob (get_property ("currentMusicalColumn")))
141 text_->set_parent (mc, X_AXIS);
142 else if (Grob *cc = unsmob_grob (get_property ("currentCommandColumn")))
143 text_->set_parent (cc, X_AXIS);
145 text_->set_object ("side-support-elements",
146 grob_list_to_grob_array (get_property ("stavesFound")));
147 text_ = 0;
148 support_ = 0;
149 bar_ = 0;
150 tempo_ev_ = 0;
154 void
155 Metronome_mark_engraver::process_music ()
157 if (tempo_ev_)
159 text_ = make_item ("MetronomeMark", tempo_ev_->self_scm ());
161 SCM proc = get_property ("metronomeMarkFormatter");
162 SCM result = scm_call_2 (proc,
163 tempo_ev_->self_scm (),
164 context ()->self_scm ());
166 text_->set_property ("text", result);
170 ADD_ACKNOWLEDGER (Metronome_mark_engraver, break_aligned);
171 ADD_ACKNOWLEDGER (Metronome_mark_engraver, break_alignment);
172 ADD_ACKNOWLEDGER (Metronome_mark_engraver, grob);
174 ADD_TRANSLATOR (Metronome_mark_engraver,
175 /* doc */
176 "Engrave metronome marking. This delegates the formatting"
177 " work to the function in the @code{metronomeMarkFormatter}"
178 " property. The mark is put over all staves. The staves are"
179 " taken from the @code{stavesFound} property, which is"
180 " maintained by @ref{Staff_collecting_engraver}.",
182 /* create */
183 "MetronomeMark ",
185 /* read */
186 "currentCommandColumn "
187 "currentMusicalColumn "
188 "metronomeMarkFormatter "
189 "stavesFound "
190 "tempoHideNote ",
192 /* write */