]> git.donarmstrong.com Git - lilypond.git/blob - lily/metronome-engraver.cc
a1024049d52ef3323349749f5d17d341d92187d5
[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   if (text_
78       && !support_
79       && (g->get_property_data ("break-align-symbol")
80           == text_->get_property_data ("break-align-symbol")))
81     {
82       support_ = g;
83       text_->set_parent (g, X_AXIS);
84     }
85 }
86
87 void
88 Metronome_mark_engraver::acknowledge_grob (Grob_info info)
89 {
90   Grob *g = info.grob ();
91
92   if (text_
93       && !support_
94       && scm_member (g->get_property_data ("break-align-symbol"),
95                      text_->get_property_data ("break-align-symbols"))
96       != SCM_BOOL_F)
97     {
98       text_->set_parent (g, X_AXIS);
99     }
100 }
101
102 void
103 Metronome_mark_engraver::stop_translation_timestep ()
104 {
105   if (text_)
106     {
107       if (!support_)
108         {
109           /*
110             Gardner Read "Music Notation", p.278
111
112             Align the metronome mark over the time signature (or the
113             first notational element of the measure if no time
114             signature is present in that measure).
115           */
116           if (Grob *mc = unsmob_grob (get_property ("currentMusicalColumn")))
117             text_->set_parent (mc, X_AXIS);
118           else if (Grob *cc = unsmob_grob (get_property ("currentCommandColumn")))
119             text_->set_parent (cc, X_AXIS);
120         }
121       text_->set_object ("side-support-elements",
122                          grob_list_to_grob_array (get_property ("stavesFound")));
123       text_ = 0;
124       support_ = 0;
125     }
126 }
127
128 void
129 Metronome_mark_engraver::process_music ()
130 {
131   SCM count = get_property ("tempoUnitCount");
132   SCM duration = get_property ("tempoUnitDuration");
133   SCM text = get_property ("tempoText");
134
135   if ( ( (unsmob_duration (duration) && scm_is_number (count))
136         || Text_interface::is_markup (text) )
137       && !(ly_is_equal (count, last_count_)
138            && ly_is_equal (duration, last_duration_)
139            && ly_is_equal (text, last_text_)))
140     {
141       text_ = make_item ("MetronomeMark", SCM_EOL);
142
143       SCM proc = get_property ("metronomeMarkFormatter");
144       SCM result = scm_call_4 (proc,
145                                text,
146                                duration,
147                                count,
148                                context ()->self_scm ());
149
150       text_->set_property ("text", result);
151     }
152
153   last_duration_ = duration;
154   last_count_ = count;
155   last_text_ = text;
156 }
157
158
159
160 ADD_ACKNOWLEDGER (Metronome_mark_engraver, break_aligned);
161 ADD_ACKNOWLEDGER (Metronome_mark_engraver, grob);
162
163 ADD_TRANSLATOR (Metronome_mark_engraver,
164                 /* doc */
165                 "Engrave metronome marking.  This delegates the formatting"
166                 " work to the function in the @code{metronomeMarkFormatter}"
167                 " property.  The mark is put over all staves.  The staves are"
168                 " taken from the @code{stavesFound} property, which is"
169                 " maintained by @ref{Staff_collecting_engraver}.",
170
171                 /* create */
172                 "MetronomeMark ",
173
174                 /* read */
175                 "stavesFound "
176                 "metronomeMarkFormatter "
177                 "tempoUnitDuration "
178                 "tempoUnitCount "
179                 "tempoText "
180                 "tempoHideNote ",
181
182                 /* write */
183                 ""
184                 );