Fix substitution error in shape noteheads
[lilypond/mpolesky.git] / lily / metronome-engraver.cc
blobd55455f23d36533c6e1131971ed8b0d9a53b9ab7
1 /*
2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1998--2010 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 public:
38 TRANSLATOR_DECLARATIONS (Metronome_mark_engraver);
40 protected:
41 Item *text_;
42 Grob *support_;
43 Grob *bar_;
45 SCM last_duration_;
46 SCM last_count_;
47 SCM last_text_;
49 DECLARE_ACKNOWLEDGER (break_aligned);
50 DECLARE_ACKNOWLEDGER (break_alignment);
51 DECLARE_ACKNOWLEDGER (grob);
53 protected:
54 virtual void derived_mark () const;
55 void stop_translation_timestep ();
56 void process_music ();
59 Metronome_mark_engraver::Metronome_mark_engraver ()
61 text_ = 0;
62 support_ = 0;
63 bar_ = 0;
64 last_duration_ = SCM_EOL;
65 last_count_ = SCM_EOL;
66 last_text_ = SCM_EOL;
69 void
70 Metronome_mark_engraver::derived_mark () const
72 scm_gc_mark (last_count_);
73 scm_gc_mark (last_duration_);
74 scm_gc_mark (last_text_);
77 static bool
78 safe_is_member (SCM scm, SCM lst)
80 return scm_list_p (lst) == SCM_BOOL_T
81 && scm_member (scm, lst) != SCM_BOOL_F;
84 void
85 Metronome_mark_engraver::acknowledge_break_aligned (Grob_info info)
87 Grob *g = info.grob ();
89 if (text_
90 && g->get_property ("break-align-symbol")
91 == ly_symbol2scm ("staff-bar"))
92 bar_ = g;
93 else if (text_
94 && !support_
95 && safe_is_member (g->get_property ("break-align-symbol"),
96 text_->get_property ("break-align-symbols"))
97 && Item::break_visible (g))
98 support_ = g;
101 void
102 Metronome_mark_engraver::acknowledge_break_alignment (Grob_info info)
104 Grob *g = info.grob ();
106 if (text_
107 && support_
108 && dynamic_cast<Item *> (g))
109 text_->set_parent (g, X_AXIS);
112 void
113 Metronome_mark_engraver::acknowledge_grob (Grob_info info)
115 Grob *g = info.grob ();
117 if (text_)
118 for (SCM s = text_->get_property ("non-break-align-symbols");
119 scm_is_pair (s);
120 s = scm_cdr (s))
121 if (g->internal_has_interface (scm_car (s)))
122 text_->set_parent (g, X_AXIS);
125 void
126 Metronome_mark_engraver::stop_translation_timestep ()
128 if (text_)
130 if (text_->get_parent (X_AXIS)
131 && text_->get_parent (X_AXIS)->internal_has_interface (ly_symbol2scm ("multi-measure-rest-interface"))
132 && bar_)
133 text_->set_parent (bar_, X_AXIS);
134 else if (!support_)
137 Gardner Read "Music Notation", p.278
139 Align the metronome mark over the time signature (or the
140 first notational element of the measure if no time
141 signature is present in that measure).
143 if (Grob *mc = unsmob_grob (get_property ("currentMusicalColumn")))
144 text_->set_parent (mc, X_AXIS);
145 else if (Grob *cc = unsmob_grob (get_property ("currentCommandColumn")))
146 text_->set_parent (cc, X_AXIS);
148 text_->set_object ("side-support-elements",
149 grob_list_to_grob_array (get_property ("stavesFound")));
150 text_ = 0;
151 support_ = 0;
152 bar_ = 0;
156 void
157 Metronome_mark_engraver::process_music ()
159 SCM count = get_property ("tempoUnitCount");
160 SCM duration = get_property ("tempoUnitDuration");
161 SCM text = get_property ("tempoText");
163 if ( ( (unsmob_duration (duration) && scm_is_number (count))
164 || Text_interface::is_markup (text) )
165 && !(ly_is_equal (count, last_count_)
166 && ly_is_equal (duration, last_duration_)
167 && ly_is_equal (text, last_text_)))
169 text_ = make_item ("MetronomeMark", SCM_EOL);
171 SCM proc = get_property ("metronomeMarkFormatter");
172 SCM result = scm_call_4 (proc,
173 text,
174 duration,
175 count,
176 context ()->self_scm ());
178 text_->set_property ("text", result);
181 last_duration_ = duration;
182 last_count_ = count;
183 last_text_ = text;
188 ADD_ACKNOWLEDGER (Metronome_mark_engraver, break_aligned);
189 ADD_ACKNOWLEDGER (Metronome_mark_engraver, break_alignment);
190 ADD_ACKNOWLEDGER (Metronome_mark_engraver, grob);
192 ADD_TRANSLATOR (Metronome_mark_engraver,
193 /* doc */
194 "Engrave metronome marking. This delegates the formatting"
195 " work to the function in the @code{metronomeMarkFormatter}"
196 " property. The mark is put over all staves. The staves are"
197 " taken from the @code{stavesFound} property, which is"
198 " maintained by @ref{Staff_collecting_engraver}.",
200 /* create */
201 "MetronomeMark ",
203 /* read */
204 "stavesFound "
205 "metronomeMarkFormatter "
206 "tempoUnitDuration "
207 "tempoUnitCount "
208 "tempoText "
209 "tempoHideNote ",
211 /* write */