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