]> git.donarmstrong.com Git - lilypond.git/blob - lily/metronome-engraver.cc
Align metronome mark at time signature or first musical element.
[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 #include "time-signature.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
44   SCM last_duration_;
45   SCM last_count_;
46   SCM last_text_;
47
48   DECLARE_ACKNOWLEDGER (break_aligned);
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 inf)
75 {
76   Grob *s = inf.grob ();
77   if (text_ && Time_signature::has_interface (s))
78     support_ = s;
79 }
80
81 void
82 Metronome_mark_engraver::stop_translation_timestep ()
83 {
84   if (text_)
85     {
86       if (!support_)
87         {
88           /*
89             Gardner Read "Music Notation", p.278
90
91             Align the metronome mark over the time signature (or the
92             first notational element of the measure if no time
93             signature is present in that measure).
94           */
95           Grob *mc = unsmob_grob (get_property ("currentMusicalColumn"));
96           text_->set_parent (mc, X_AXIS);
97         }
98       text_->set_object ("side-support-elements",
99                          grob_list_to_grob_array (get_property ("stavesFound")));
100       text_ = 0;
101       support_ = 0;
102     }
103 }
104
105 void
106 Metronome_mark_engraver::process_music ()
107 {
108   SCM count = get_property ("tempoUnitCount");
109   SCM duration = get_property ("tempoUnitDuration");
110   SCM text = get_property ("tempoText");
111
112   if ( ( (unsmob_duration (duration) && scm_is_number (count))
113         || Text_interface::is_markup (text) )
114       && !(ly_is_equal (count, last_count_)
115            && ly_is_equal (duration, last_duration_)
116            && ly_is_equal (text, last_text_)))
117     {
118       text_ = make_item ("MetronomeMark", SCM_EOL);
119
120       SCM proc = get_property ("metronomeMarkFormatter");
121       SCM result = scm_call_4 (proc,
122                                text,
123                                duration,
124                                count,
125                                context ()->self_scm ());
126
127       text_->set_property ("text", result);
128     }
129
130   last_duration_ = duration;
131   last_count_ = count;
132   last_text_ = text;
133 }
134
135
136
137 ADD_ACKNOWLEDGER (Metronome_mark_engraver, break_aligned);
138
139 ADD_TRANSLATOR (Metronome_mark_engraver,
140                 /* doc */
141                 "Engrave metronome marking.  This delegates the formatting"
142                 " work to the function in the @code{metronomeMarkFormatter}"
143                 " property.  The mark is put over all staves.  The staves are"
144                 " taken from the @code{stavesFound} property, which is"
145                 " maintained by @ref{Staff_collecting_engraver}.",
146
147                 /* create */
148                 "MetronomeMark ",
149
150                 /* read */
151                 "stavesFound "
152                 "metronomeMarkFormatter "
153                 "tempoUnitDuration "
154                 "tempoUnitCount "
155                 "tempoText "
156                 "tempoHideNote ",
157
158                 /* write */
159                 ""
160                 );