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