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