]> git.donarmstrong.com Git - lilypond.git/blob - lily/multi-measure-rest-engraver.cc
*** empty log message ***
[lilypond.git] / lily / multi-measure-rest-engraver.cc
1 /*
2   multi_measure_rest-engraver.cc -- implement Multi_measure_rest_engraver
3
4   (c) 1998--2003 Jan Nieuwenhuizen <janneke@gnu.org>
5        Han-Wen Nienhuys <hanwen@cs.uu.nl>
6 */
7
8 #include "event.hh"
9 #include "multi-measure-rest.hh"
10 #include "paper-column.hh"
11 #include "engraver-group-engraver.hh"
12 #include "side-position-interface.hh"
13 #include "staff-symbol-referencer.hh"
14 #include "engraver.hh"
15 #include "moment.hh"
16 #include "spanner.hh"
17
18 /**
19    The name says it all: make multi measure rests 
20
21 */
22 class Multi_measure_rest_engraver : public Engraver
23 {
24 public:
25   TRANSLATOR_DECLARATIONS(Multi_measure_rest_engraver);
26
27 protected:
28   virtual bool try_music (Music*);
29   virtual void process_music ();
30   virtual void stop_translation_timestep ();
31   virtual void start_translation_timestep ();
32   virtual void finalize ();
33
34 private:
35   Music * new_req_;
36   Music * busy_span_req_;
37   Music * stop_req_;
38   int start_measure_;
39   Moment start_moment_;
40   
41
42   Spanner *mmrest_;
43   Spanner *number_;
44
45   Spanner *last_number_;
46   Spanner *last_rest_;
47 };
48
49 Multi_measure_rest_engraver::Multi_measure_rest_engraver ()
50 {
51   start_measure_ = 0;
52   mmrest_ = 0;
53   last_rest_ =0;
54   number_ = 0;
55   new_req_ = busy_span_req_ = stop_req_ =0;
56 }
57
58 bool
59 Multi_measure_rest_engraver::try_music (Music* req)
60 {
61   if (req->is_mus_type ("multi-measure-rest-event"))
62     {
63       Direction d = to_dir (req->get_mus_property ("span-direction"));
64       if (d == STOP)
65         {
66           stop_req_ = req;
67         }
68       else if (d == START&& !new_req_)
69         {
70           new_req_ = req;
71         }
72       return true;
73     }
74   return false;
75 }
76
77 void
78 Multi_measure_rest_engraver::process_music ()
79 {
80   if (new_req_ && stop_req_)
81     stop_req_ = 0;
82
83   if (new_req_)
84     start_moment_ = now_mom ();
85
86   if (stop_req_)
87     {
88       busy_span_req_ =0;
89       stop_req_ = 0;
90     }
91   
92   if (new_req_)
93     {
94       busy_span_req_ = new_req_;
95       new_req_ =0;
96     }
97
98   if (busy_span_req_ && !mmrest_)
99     {
100       mmrest_ = new Spanner (get_property ("MultiMeasureRest"));
101       number_ = new Spanner (get_property ("MultiMeasureRestNumber"));
102
103       Side_position_interface::add_support (number_, mmrest_);
104       number_->set_parent (mmrest_, Y_AXIS);
105
106       announce_grob (mmrest_, busy_span_req_->self_scm());
107       announce_grob (number_, busy_span_req_->self_scm());
108       start_measure_
109         = gh_scm2int (get_property ("currentBarNumber"));
110     }
111
112   if (gh_string_p (get_property ("whichBar")))
113     {
114       Grob *cmc = unsmob_grob (get_property( "currentCommandColumn"));
115       Item *it = dynamic_cast<Item*> (cmc);
116       if (mmrest_)
117         {
118           add_bound_item (mmrest_, it);
119           add_bound_item (number_, it);
120         }
121       if (last_rest_)
122         {
123           add_bound_item (last_rest_,it);
124           add_bound_item (last_number_, it);
125         }      
126     }
127 }
128
129 void
130 Multi_measure_rest_engraver::stop_translation_timestep ()
131 {
132   SCM smp = get_property ("measurePosition");
133   Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
134
135   if (mmrest_ && (now_mom () >= start_moment_) 
136       && !mp.to_bool ()
137       && mmrest_->get_bound (LEFT) && mmrest_->get_bound (RIGHT))
138     {
139       typeset_grob (mmrest_);
140       typeset_grob (number_);
141       Side_position_interface::add_staff_support (number_);
142       /*
143         we must keep mmrest_ around to set measure-count, so
144         no mmrest_ = 0 here. 
145        */
146
147       
148     }
149
150   if (last_rest_)
151     {
152       /* sanity check */
153       if (last_rest_->get_bound (LEFT) && last_rest_->get_bound (RIGHT)
154           && last_rest_->get_bound (LEFT) != last_rest_->get_bound (RIGHT))
155         {
156           typeset_grob (last_rest_);
157           typeset_grob (last_number_);
158         }
159       last_rest_ = 0;
160       last_number_ = 0;
161     }
162
163   if (new_req_)
164     {
165       busy_span_req_ = new_req_;
166       new_req_ =0;
167     }
168   
169 }
170
171 void
172 Multi_measure_rest_engraver::start_translation_timestep ()
173 {
174   SCM smp = get_property ("measurePosition");
175   Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
176   
177   if (mmrest_ && !mp.to_bool ())
178     {
179       last_rest_ = mmrest_;
180       last_number_ = number_;
181
182       int cur = gh_scm2int (get_property ("currentBarNumber"));
183       int num = cur - start_measure_;
184       last_rest_->set_grob_property ("measure-count", gh_int2scm (num));
185
186       SCM sml = get_property ("measureLength");
187       Rational ml = (unsmob_moment (sml)) ? unsmob_moment (sml)->main_part_ : Rational (1);
188       if (ml >= Rational (2))
189         {
190           last_rest_->set_grob_property ("use-breve-rest", SCM_BOOL_T);
191         }
192
193       mmrest_ = 0;
194
195       SCM text =last_number_->get_grob_property ("text");
196       SCM thres = get_property ("restNumberThreshold");
197       int t = 1;
198       if (gh_number_p (thres))
199         t = gh_scm2int (thres);
200       
201       if (text == SCM_EOL && num <= t)
202         last_number_->suicide();
203       else if (text == SCM_EOL)
204         {
205           text = scm_number_to_string (gh_int2scm (num), SCM_MAKINUM (10));
206           last_number_->set_grob_property ("text", text);
207         }
208     }
209 }
210
211
212 void
213 Multi_measure_rest_engraver::finalize ()
214 {
215   if (mmrest_)
216     {
217       typeset_grob (mmrest_);
218       typeset_grob (number_);
219     }
220   if (last_rest_)
221     {
222       typeset_grob (last_rest_);
223       typeset_grob (last_number_);
224     }
225 }
226
227 ENTER_DESCRIPTION(Multi_measure_rest_engraver,
228 /* descr */
229                   "Engraves multi-measure rests that are produced with @code{R}.  Reads "
230 "measurePosition and currentBarNumber to determine what number to print "
231 "over the MultiMeasureRest.  Reads measureLength to determine if it "
232 "should use a whole rest or a breve rest to represent 1 measure "
233                   ,
234 /* creats*/       "MultiMeasureRest MultiMeasureRestNumber",
235 /* accepts */     "multi-measure-rest-event",
236 /* acks  */      "",
237 /* reads */       "currentBarNumber restNumberThreshold currentCommandColumn measurePosition measureLength",
238 /* write */       "");