]> git.donarmstrong.com Git - lilypond.git/blob - lily/metronome-engraver.cc
Metronome-mark: align on key-signature too.
[lilypond.git] / lily / metronome-engraver.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1998--2010 Jan Nieuwenhuizen <janneke@gnu.org>
5
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.
10
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.
15
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/>.
18 */
19
20 #include <cctype>
21 using namespace std;
22
23 #include "engraver.hh"
24
25 #include "context.hh"
26 #include "duration.hh"
27 #include "grob-array.hh"
28 #include "item.hh"
29 #include "stream-event.hh"
30 #include "text-interface.hh"
31
32 #include "translator.icc"
33
34 class Metronome_mark_engraver : public Engraver
35 {
36 public:
37   TRANSLATOR_DECLARATIONS (Metronome_mark_engraver);
38
39 protected:
40   Item *text_;
41   Grob *support_;
42
43   SCM last_duration_;
44   SCM last_count_;
45   SCM last_text_;
46
47   DECLARE_ACKNOWLEDGER (break_aligned);
48   DECLARE_ACKNOWLEDGER (grob);
49
50 protected:
51   virtual void derived_mark () const;
52   void stop_translation_timestep ();
53   void process_music ();
54 };
55
56 Metronome_mark_engraver::Metronome_mark_engraver ()
57 {
58   text_ = 0;
59   support_ = 0;
60   last_duration_ = SCM_EOL;
61   last_count_ = SCM_EOL;
62   last_text_ = SCM_EOL;
63 }
64
65 void
66 Metronome_mark_engraver::derived_mark () const
67 {
68   scm_gc_mark (last_count_);
69   scm_gc_mark (last_duration_);
70   scm_gc_mark (last_text_);
71 }
72
73 void
74 Metronome_mark_engraver::acknowledge_break_aligned (Grob_info info)
75 {
76   Grob *g = info.grob ();
77
78   if (text_
79       && !support_
80       && scm_member (g->get_property_data ("break-align-symbol"),
81                      text_->get_property_data ("break-align-symbols"))
82       != SCM_BOOL_F)
83     {
84       support_ = g;
85       text_->set_parent (g, X_AXIS);
86     }
87 }
88
89 SCM
90 grob_name_scm (Grob *g)
91 {
92   SCM name_pair = scm_assq (ly_symbol2scm ("name"), g->get_property ("meta"));
93   return scm_is_pair (name_pair) ? scm_cdr (name_pair) : SCM_EOL;
94 }
95
96 void
97 Metronome_mark_engraver::acknowledge_grob (Grob_info info)
98 {
99   Grob *g = info.grob ();
100
101   if (text_
102       && !support_
103       && scm_member (grob_name_scm (g),
104                      text_->get_property_data ("non-break-align-symbols"))
105       != SCM_BOOL_F)
106     {
107       text_->set_parent (g, X_AXIS);
108     }
109 }
110
111 void
112 Metronome_mark_engraver::stop_translation_timestep ()
113 {
114   if (text_)
115     {
116       if (!support_)
117         {
118           /*
119             Gardner Read "Music Notation", p.278
120
121             Align the metronome mark over the time signature (or the
122             first notational element of the measure if no time
123             signature is present in that measure).
124           */
125           if (Grob *mc = unsmob_grob (get_property ("currentMusicalColumn")))
126             text_->set_parent (mc, X_AXIS);
127           else if (Grob *cc = unsmob_grob (get_property ("currentCommandColumn")))
128             text_->set_parent (cc, X_AXIS);
129         }
130       text_->set_object ("side-support-elements",
131                          grob_list_to_grob_array (get_property ("stavesFound")));
132       text_ = 0;
133       support_ = 0;
134     }
135 }
136
137 void
138 Metronome_mark_engraver::process_music ()
139 {
140   SCM count = get_property ("tempoUnitCount");
141   SCM duration = get_property ("tempoUnitDuration");
142   SCM text = get_property ("tempoText");
143
144   if ( ( (unsmob_duration (duration) && scm_is_number (count))
145         || Text_interface::is_markup (text) )
146       && !(ly_is_equal (count, last_count_)
147            && ly_is_equal (duration, last_duration_)
148            && ly_is_equal (text, last_text_)))
149     {
150       text_ = make_item ("MetronomeMark", SCM_EOL);
151
152       SCM proc = get_property ("metronomeMarkFormatter");
153       SCM result = scm_call_4 (proc,
154                                text,
155                                duration,
156                                count,
157                                context ()->self_scm ());
158
159       text_->set_property ("text", result);
160     }
161
162   last_duration_ = duration;
163   last_count_ = count;
164   last_text_ = text;
165 }
166
167
168
169 ADD_ACKNOWLEDGER (Metronome_mark_engraver, break_aligned);
170 ADD_ACKNOWLEDGER (Metronome_mark_engraver, grob);
171
172 ADD_TRANSLATOR (Metronome_mark_engraver,
173                 /* doc */
174                 "Engrave metronome marking.  This delegates the formatting"
175                 " work to the function in the @code{metronomeMarkFormatter}"
176                 " property.  The mark is put over all staves.  The staves are"
177                 " taken from the @code{stavesFound} property, which is"
178                 " maintained by @ref{Staff_collecting_engraver}.",
179
180                 /* create */
181                 "MetronomeMark ",
182
183                 /* read */
184                 "stavesFound "
185                 "metronomeMarkFormatter "
186                 "tempoUnitDuration "
187                 "tempoUnitCount "
188                 "tempoText "
189                 "tempoHideNote ",
190
191                 /* write */
192                 ""
193                 );