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