]> git.donarmstrong.com Git - lilypond.git/blob - lily/multi-measure-rest-engraver.cc
328b9a2d779ffa8729c0fe2df55d6eb074805941
[lilypond.git] / lily / multi-measure-rest-engraver.cc
1 /*
2   multi_measure_rest-engraver.cc -- implement Multi_measure_rest_engraver
3
4   (c) 1998--2001 Jan Nieuwenhuizen <janneke@gnu.org>
5        Han-Wen Nienhuys <hanwen@cs.uu.nl>
6 */
7
8 #include "musical-request.hh"
9 #include "multi-measure-rest.hh"
10 #include "paper-column.hh"
11 #include "engraver-group-engraver.hh"
12 #include "bar.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 FIXME? The MM rest engraver must be able to see bar lines, so it won't
22 work at Voice level. Not a problem in practice, but aesthetically pleasing? 
23
24 */
25 class Multi_measure_rest_engraver : public Engraver
26 {
27 public:
28   VIRTUAL_COPY_CONS(Translator);
29   Multi_measure_rest_engraver ();
30
31 protected:
32   virtual void acknowledge_grob (Grob_info i);
33   virtual bool try_music (Music*);
34   virtual void process_music ();
35   virtual void stop_translation_timestep ();
36   virtual void start_translation_timestep ();
37   virtual void finalize ();
38   virtual void create_grobs ();
39
40 private:
41   Span_req * new_req_l_;
42   Span_req * busy_span_req_l_;
43   Span_req * stop_req_l_;
44   int start_measure_i_;
45   Moment start_moment_;
46   
47   Spanner *mmrest_p_;
48   Spanner *lastrest_p_;
49 };
50
51 ADD_THIS_TRANSLATOR (Multi_measure_rest_engraver);
52
53 Multi_measure_rest_engraver::Multi_measure_rest_engraver ()
54 {
55   start_measure_i_ = 0;
56   mmrest_p_  = lastrest_p_ =0;
57   new_req_l_ = busy_span_req_l_ = stop_req_l_ =0;
58 }
59
60 void
61 Multi_measure_rest_engraver::acknowledge_grob (Grob_info i)
62 {
63   Item * item = dynamic_cast<Item*> (i.elem_l_); 
64   if (item && Bar::has_interface (item))
65     {
66       if (mmrest_p_)
67         Multi_measure_rest::add_column (mmrest_p_,item);
68       if (lastrest_p_)
69         Multi_measure_rest::add_column (lastrest_p_,item);
70     }
71 }
72
73 bool
74 Multi_measure_rest_engraver::try_music (Music* req_l)
75 {
76   if (Span_req * sp = dynamic_cast<Span_req*> (req_l))
77     {
78       
79       if (scm_equal_p (sp->get_mus_property ("span-type"),
80                        ly_str02scm ("rest")) == SCM_BOOL_T)
81         {
82           if (sp->get_span_dir() == STOP)
83             {
84               stop_req_l_ = sp;
85             }
86           else if (sp->get_span_dir() == START && !new_req_l_)
87             {
88               new_req_l_ = sp;
89             }
90           return true;
91         }
92     }
93   return false;
94 }
95
96 void
97 Multi_measure_rest_engraver::process_music ()
98 {
99     if (new_req_l_ && stop_req_l_)
100     stop_req_l_ = 0;
101
102   if (new_req_l_)
103     start_moment_ = now_mom ();
104
105   if (stop_req_l_)
106     {
107       busy_span_req_l_ =0;
108       stop_req_l_ = 0;
109     }
110   
111   if (new_req_l_)
112     {
113       busy_span_req_l_ = new_req_l_;
114       new_req_l_ =0;
115     }
116
117 }
118
119 void
120 Multi_measure_rest_engraver::create_grobs ()
121 {
122
123   if (busy_span_req_l_ && !mmrest_p_)
124     {
125       mmrest_p_ = new Spanner (get_property ("MultiMeasureRest"));
126
127       Multi_measure_rest::set_interface (mmrest_p_);
128       Staff_symbol_referencer::set_interface (mmrest_p_);
129
130       announce_grob (mmrest_p_, busy_span_req_l_);
131       start_measure_i_
132         = gh_scm2int (get_property ("currentBarNumber"));
133     }
134 }
135
136 void
137 Multi_measure_rest_engraver::stop_translation_timestep ()
138 {
139   SCM smp = get_property ("measurePosition");
140   Moment mp =  (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
141
142   if (mmrest_p_ && (now_mom () >= start_moment_) 
143     && !mp
144     && (scm_ilength (mmrest_p_->get_grob_property ("columns")) >= 2))
145     {
146       typeset_grob (mmrest_p_);
147       /*
148         we must keep mmrest_p_ around to set measure-count.
149        */
150     }
151   if (lastrest_p_)
152     {
153       typeset_grob (lastrest_p_);
154       lastrest_p_ = 0;
155     }
156
157   if (new_req_l_)
158     {
159       busy_span_req_l_ = new_req_l_;
160       new_req_l_ =0;
161     }
162   
163 }
164
165 void
166 Multi_measure_rest_engraver::start_translation_timestep ()
167 {
168   SCM smp = get_property ("measurePosition");
169   Moment mp =  (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
170   
171   if (mmrest_p_ && !mp)
172     {
173       lastrest_p_ = mmrest_p_;
174       int cur = gh_scm2int (get_property ("currentBarNumber"));
175       lastrest_p_->set_grob_property ("measure-count",
176                                      gh_int2scm (cur - start_measure_i_));
177       mmrest_p_ = 0;
178     }
179 }
180
181
182 void
183 Multi_measure_rest_engraver::finalize ()
184 {
185   if (mmrest_p_)
186     typeset_grob (mmrest_p_);
187   if (lastrest_p_)
188     typeset_grob (lastrest_p_);
189 }