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