]> git.donarmstrong.com Git - lilypond.git/blob - lily/volta-engraver.cc
Web-ja: update introduction
[lilypond.git] / lily / volta-engraver.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 2000--2015 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 "context.hh"
24 #include "grob-array.hh"
25 #include "international.hh"
26 #include "note-column.hh"
27 #include "item.hh"
28 #include "side-position-interface.hh"
29 #include "staff-symbol.hh"
30 #include "text-interface.hh"
31 #include "volta-bracket.hh"
32 #include "warn.hh"
33
34 #include "translator.icc"
35
36 /*
37   Create Volta spanners, by reading repeatCommands  property, usually
38   set by Volta_repeat_iterator.
39 */
40 class Volta_engraver : public Engraver
41 {
42 public:
43   TRANSLATOR_DECLARATIONS (Volta_engraver);
44 protected:
45
46   void acknowledge_bar_line (Grob_info);
47
48   virtual void derived_mark () const;
49   void stop_translation_timestep ();
50   void process_music ();
51
52   Moment started_mom_;
53   Spanner *volta_bracket_;
54   Spanner *end_volta_bracket_;
55   Spanner *volta_spanner_;
56   SCM start_string_;
57 };
58
59 void
60 Volta_engraver::derived_mark () const
61 {
62   scm_gc_mark (start_string_);
63 }
64
65 Volta_engraver::Volta_engraver (Context *c)
66   : Engraver (c)
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_is_eq (scm_car (c), ly_symbol2scm ("volta"))
87           && scm_is_pair (scm_cdr (c)))
88         {
89           if (scm_is_false (scm_cadr (c)))
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 void
194 Volta_engraver::boot ()
195 {
196   ADD_ACKNOWLEDGER (Volta_engraver, bar_line);
197 }
198
199 ADD_TRANSLATOR (Volta_engraver,
200                 /* doc */
201                 "Make volta brackets.",
202
203                 /* create */
204                 "VoltaBracket "
205                 "VoltaBracketSpanner ",
206
207                 /* read */
208                 "repeatCommands "
209                 "voltaSpannerDuration "
210                 "stavesFound ",
211
212                 /* write */
213                 ""
214                );