]> git.donarmstrong.com Git - lilypond.git/blob - lily/volta-engraver.cc
Merge branch 'lilypond/translation' of ssh://git.sv.gnu.org/srv/git/lilypond into...
[lilypond.git] / lily / volta-engraver.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 2000--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
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 "engraver.hh"
21
22 #include "axis-group-interface.hh"
23 #include "bar-line.hh"
24 #include "context.hh"
25 #include "grob-array.hh"
26 #include "international.hh"
27 #include "note-column.hh"
28 #include "item.hh"
29 #include "side-position-interface.hh"
30 #include "staff-symbol.hh"
31 #include "text-interface.hh"
32 #include "volta-bracket.hh"
33 #include "warn.hh"
34
35 #include "translator.icc"
36
37 /*
38   Create Volta spanners, by reading repeatCommands  property, usually
39   set by Volta_repeat_iterator.
40 */
41 class Volta_engraver : public Engraver
42 {
43 public:
44   TRANSLATOR_DECLARATIONS (Volta_engraver);
45 protected:
46
47   DECLARE_ACKNOWLEDGER (bar_line);
48
49   virtual void derived_mark () const;
50   void stop_translation_timestep ();
51   void process_music ();
52
53   Moment started_mom_;
54   Spanner *volta_bracket_;
55   Spanner *end_volta_bracket_;
56   Spanner *volta_spanner_;
57   SCM start_string_;
58 };
59
60 void
61 Volta_engraver::derived_mark () const
62 {
63   scm_gc_mark (start_string_);
64 }
65
66 Volta_engraver::Volta_engraver ()
67 {
68   start_string_ = SCM_EOL;
69   volta_bracket_ = 0;
70   end_volta_bracket_ = 0;
71   volta_spanner_ = 0;
72 }
73
74 void
75 Volta_engraver::process_music ()
76 {
77   SCM cs = get_property ("repeatCommands");
78
79   bool end = false;
80   start_string_ = SCM_EOL;
81   while (scm_is_pair (cs))
82     {
83       SCM c = scm_car (cs);
84
85       if (scm_is_pair (c)
86           && scm_car (c) == ly_symbol2scm ("volta")
87           && scm_is_pair (scm_cdr (c)))
88         {
89           if (scm_cadr (c) == SCM_BOOL_F)
90             end = true;
91           else
92             start_string_ = scm_cadr (c);
93         }
94
95       cs = scm_cdr (cs);
96     }
97
98   if (volta_bracket_)
99     {
100       SCM l (get_property ("voltaSpannerDuration"));
101       Moment now = now_mom ();
102
103       bool early_stop = unsmob_moment (l)
104                         && *unsmob_moment (l) <= now - started_mom_;
105
106       end = end || early_stop;
107     }
108
109   if (end && !volta_bracket_)
110     /* fixme: be more verbose.  */
111     warning (_ ("cannot end volta spanner"));
112   else if (end)
113     {
114       end_volta_bracket_ = volta_bracket_;
115       volta_bracket_ = 0;
116     }
117
118   if (volta_bracket_
119       && (scm_is_string (start_string_) || scm_is_pair (start_string_)))
120     {
121       warning (_ ("already have a volta spanner, ending that one prematurely"));
122
123       if (end_volta_bracket_)
124         {
125           warning (_ ("also already have an ended spanner"));
126           warning (_ ("giving up"));
127           return;
128         }
129
130       end_volta_bracket_ = volta_bracket_;
131       volta_bracket_ = 0;
132     }
133
134   if (!volta_bracket_
135       && Text_interface::is_markup (start_string_))
136     {
137       started_mom_ = now_mom ();
138
139       volta_bracket_ = make_spanner ("VoltaBracket", SCM_EOL);
140
141       volta_bracket_->set_property ("text", start_string_);
142
143       if (!volta_spanner_)
144         volta_spanner_ = make_spanner ("VoltaBracketSpanner", SCM_EOL);
145
146       Axis_group_interface::add_element (volta_spanner_, volta_bracket_);
147     }
148 }
149
150 void
151 Volta_engraver::acknowledge_bar_line (Grob_info i)
152 {
153   if (volta_bracket_)
154     Volta_bracket_interface::add_bar (volta_bracket_, i.item ());
155   if (end_volta_bracket_)
156     Volta_bracket_interface::add_bar (end_volta_bracket_, i.item ());
157
158   if (volta_spanner_)
159     Side_position_interface::add_support (volta_spanner_, i.grob ());
160 }
161
162 void
163 Volta_engraver::stop_translation_timestep ()
164 {
165   Grob *cc = unsmob_grob (get_property ("currentCommandColumn"));
166   Item *ci = dynamic_cast<Item *> (cc);
167
168   if (end_volta_bracket_ && !end_volta_bracket_->get_bound (RIGHT))
169     end_volta_bracket_->set_bound (RIGHT, ci);
170
171   if (volta_spanner_ && end_volta_bracket_)
172     volta_spanner_->set_bound (RIGHT, end_volta_bracket_->get_bound (RIGHT));
173
174   if (end_volta_bracket_ && !volta_bracket_)
175     {
176       for (SCM s = get_property ("stavesFound"); scm_is_pair (s); s = scm_cdr (s))
177         Side_position_interface::add_support (volta_spanner_, unsmob_grob (scm_car (s)));
178       volta_spanner_ = 0;
179     }
180
181   end_volta_bracket_ = 0;
182
183   if (volta_bracket_ && !volta_bracket_->get_bound (LEFT))
184     volta_bracket_->set_bound (LEFT, ci);
185
186   if (volta_spanner_ && volta_bracket_ && !volta_spanner_->get_bound (LEFT))
187     volta_spanner_->set_bound (LEFT, volta_bracket_->get_bound (LEFT));
188 }
189
190 /*
191   TODO: should attach volta to paper-column if no bar is found.
192 */
193 ADD_ACKNOWLEDGER (Volta_engraver, bar_line);
194 ADD_TRANSLATOR (Volta_engraver,
195                 /* doc */
196                 "Make volta brackets.",
197
198                 /* create */
199                 "VoltaBracket "
200                 "VoltaBracketSpanner ",
201
202                 /* read */
203                 "repeatCommands "
204                 "voltaSpannerDuration "
205                 "stavesFound ",
206
207                 /* write */
208                 ""
209                );