]> git.donarmstrong.com Git - lilypond.git/blob - lily/percent-repeat-engraver.cc
update for the lily-wins.py script.
[lilypond.git] / lily / percent-repeat-engraver.cc
1 /*   
2   new-chord-tremolo-engraver.cc --  implement Chord_tremolo_engraver
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 2000--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9
10 #include "engraver.hh"
11 #include "repeated-music.hh"
12 #include "engraver-group-engraver.hh"
13 #include "global-context.hh"
14 #include "warn.hh"
15 #include "misc.hh"
16 #include "spanner.hh"
17 #include "item.hh"
18 #include "percent-repeat-iterator.hh"
19 #include "bar-line.hh"
20
21 #include "score-engraver.hh"
22 #include "context.hh"
23
24
25 /**
26   This acknowledges repeated music with "percent" style.  It typesets
27   a % sign.  
28
29   TODO:
30
31   - BEAT case: Create items for single beat repeats, i.e. c4 / / /
32
33   - DOUBLE_MEASURE case: attach a % to an appropriate barline.
34   
35 */
36 class Percent_repeat_engraver : public Engraver
37 {
38   void typeset_perc ();
39 public:
40   TRANSLATOR_DECLARATIONS (Percent_repeat_engraver);
41 protected:
42   Repeated_music * repeat_;
43
44   /// moment (global time) where beam started.
45   Moment start_mom_;
46   Moment stop_mom_;
47
48   /// location  within measure where beam started.
49   Moment beam_start_location_;
50   Moment next_moment_;
51   Moment body_length_;
52
53   enum {
54     UNKNOWN,
55     MEASURE,
56     DOUBLE_MEASURE,
57   } repeat_sign_type_ ;
58
59   Item * double_percent_;
60   Spanner * perc_;
61   Spanner * finished_perc_;
62 protected:
63   virtual void finalize ();
64   virtual bool try_music (Music*);
65   virtual void stop_translation_timestep ();
66   virtual void start_translation_timestep ();
67   virtual void process_music ();
68 };
69
70 Percent_repeat_engraver::Percent_repeat_engraver ()
71 {
72   perc_  = 0;
73   finished_perc_ = 0;
74   repeat_ =0;
75
76   double_percent_ = 0;
77 }
78
79 bool
80 Percent_repeat_engraver::try_music (Music * m)
81 {
82   Repeated_music * rp = dynamic_cast<Repeated_music*> (m);
83   if (rp
84       && rp->get_property ("iterator-ctor")
85          == Percent_repeat_iterator::constructor_proc
86       && !repeat_)
87     {
88       body_length_ = rp->body_get_length ();
89       int count =   rp->repeat_count ();
90       
91       Moment now = now_mom ();
92       start_mom_ = now;
93       stop_mom_ = start_mom_ + Moment (count) * body_length_;
94       next_moment_ = start_mom_ + body_length_;
95
96       SCM m = get_property ("measureLength");
97       Moment meas_len;
98       if (unsmob_moment (m))
99         meas_len = *unsmob_moment (m);
100
101       if (meas_len == body_length_)
102         repeat_sign_type_ = MEASURE;
103       else if (Moment (2)* meas_len == body_length_)
104         {
105           repeat_sign_type_ = DOUBLE_MEASURE;
106           next_moment_ += meas_len ;
107         }
108       else
109         {
110           warning (_ ("Don't know how to handle a percent repeat of this length."));
111           return false;
112         }
113
114       repeat_ = rp;
115
116       
117       Global_context *global = get_global_context ();
118       for (int i = 0; i < count; i++)  
119         global->add_moment_to_process (next_moment_ + Moment (i) * body_length_);
120   
121       return true;
122     }
123
124   return false;
125 }
126
127 void
128 Percent_repeat_engraver::process_music ()
129 {
130   if (repeat_ && now_mom () == next_moment_)
131     {
132       if (repeat_sign_type_ == MEASURE)
133         {
134           finished_perc_ = perc_;
135           typeset_perc ();
136           perc_ = make_spanner ("PercentRepeat", repeat_->self_scm ());
137           SCM col =get_property ("currentCommandColumn");
138           perc_->set_bound (LEFT, unsmob_grob (col));
139         }
140       else if (repeat_sign_type_ == DOUBLE_MEASURE)
141         {
142           double_percent_ = make_item ("DoublePercentRepeat", repeat_->self_scm ());
143       /*
144         forbid breaks on a % line. Should forbid all breaks, really.
145        */
146
147           get_score_engraver ()->forbid_breaks ();      // guh. Use properties!      
148         }
149       next_moment_ = next_moment_ + body_length_;
150
151       get_global_context ()->add_moment_to_process (next_moment_);
152     }
153 }
154
155 void
156 Percent_repeat_engraver::finalize ()
157 {
158   typeset_perc ();
159   if (perc_)
160     {
161       repeat_->origin ()->warning (_ ("unterminated percent repeat"));
162       perc_->suicide ();
163     }
164 }
165
166 void
167 Percent_repeat_engraver::typeset_perc ()
168 {
169   if (finished_perc_)
170     {
171       SCM col =get_property ("currentCommandColumn");
172       finished_perc_->set_bound (RIGHT, unsmob_grob (col));
173       typeset_grob (finished_perc_);
174       finished_perc_ = 0;
175     }
176
177   if (double_percent_)
178     {
179       typeset_grob (double_percent_);
180       double_percent_ = 0;
181     }
182 }
183
184
185
186
187 void
188 Percent_repeat_engraver::start_translation_timestep ()
189 {
190   if (stop_mom_ == now_mom ())
191     {
192       if (perc_)
193         {
194           finished_perc_ = perc_;
195           typeset_perc ();
196         }
197       repeat_ = 0;
198       perc_ = 0;
199       repeat_sign_type_ = UNKNOWN;
200     }
201 }
202
203
204 void
205 Percent_repeat_engraver::stop_translation_timestep ()
206 {
207   typeset_perc ();
208 }
209
210
211
212
213 ENTER_DESCRIPTION (Percent_repeat_engraver,
214 /* descr */       "Make whole bar and double bar repeats.",
215 /* creats*/       "PercentRepeat DoublePercentRepeat",
216 /* accepts */     "repeated-music",
217 /* acks  */      "",
218 /* reads */       "measureLength currentCommandColumn",
219 /* write */       "");