]> git.donarmstrong.com Git - lilypond.git/blob - lily/multi-measure-rest-engraver.cc
0a0ec83780d920ce1a018ad66c13333bd53e7fb1
[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
39 private:
40   Span_req * new_req_l_;
41   Span_req * busy_span_req_l_;
42   Span_req * stop_req_l_;
43   int start_measure_i_;
44   Moment start_moment_;
45   
46   Spanner *mmrest_p_;
47   Spanner *lastrest_p_;
48 };
49
50 ADD_THIS_TRANSLATOR (Multi_measure_rest_engraver);
51
52 Multi_measure_rest_engraver::Multi_measure_rest_engraver ()
53 {
54   start_measure_i_ = 0;
55   mmrest_p_  = lastrest_p_ =0;
56   new_req_l_ = busy_span_req_l_ = stop_req_l_ =0;
57 }
58
59 void
60 Multi_measure_rest_engraver::acknowledge_grob (Grob_info i)
61 {
62   Item * item = dynamic_cast<Item*> (i.elem_l_); 
63   if (item && Bar::has_interface (item))
64     {
65       if (mmrest_p_)
66         Multi_measure_rest::add_column (mmrest_p_,item);
67       if (lastrest_p_)
68         Multi_measure_rest::add_column (lastrest_p_,item);
69     }
70 }
71
72 bool
73 Multi_measure_rest_engraver::try_music (Music* req_l)
74 {
75   if (Span_req * sp = dynamic_cast<Span_req*> (req_l))
76     {
77       
78       if (scm_equal_p (sp->get_mus_property ("span-type"),
79                        ly_str02scm ("rest")) == SCM_BOOL_T)
80         {
81           if (sp->get_span_dir () == STOP)
82             {
83               stop_req_l_ = sp;
84             }
85           else if (sp->get_span_dir () == START && !new_req_l_)
86             {
87               new_req_l_ = sp;
88             }
89           return true;
90         }
91     }
92   return false;
93 }
94
95 void
96 Multi_measure_rest_engraver::process_music ()
97 {
98   if (new_req_l_ && stop_req_l_)
99     stop_req_l_ = 0;
100
101   if (new_req_l_)
102     start_moment_ = now_mom ();
103
104   if (stop_req_l_)
105     {
106       busy_span_req_l_ =0;
107       stop_req_l_ = 0;
108     }
109   
110   if (new_req_l_)
111     {
112       busy_span_req_l_ = new_req_l_;
113       new_req_l_ =0;
114     }
115
116   if (busy_span_req_l_ && !mmrest_p_)
117     {
118       mmrest_p_ = new Spanner (get_property ("MultiMeasureRest"));
119
120       Multi_measure_rest::set_interface (mmrest_p_);
121       Staff_symbol_referencer::set_interface (mmrest_p_);
122
123       announce_grob (mmrest_p_, busy_span_req_l_);
124       start_measure_i_
125         = gh_scm2int (get_property ("currentBarNumber"));
126     }
127
128
129 }
130
131 void
132 Multi_measure_rest_engraver::stop_translation_timestep ()
133 {
134   SCM smp = get_property ("measurePosition");
135   Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
136
137   if (mmrest_p_ && (now_mom () >= start_moment_) 
138       && !mp
139       && (scm_ilength (mmrest_p_->get_grob_property ("columns")) >= 2))
140     {
141       typeset_grob (mmrest_p_);
142       /*
143         we must keep mmrest_p_ around to set measure-count, so
144         no mmrest_p_ = 0 here. 
145        */
146     }
147
148   if (lastrest_p_)
149     {
150       /* sanity check */
151       if (scm_ilength (lastrest_p_->get_grob_property ("columns")) >= 2
152           && lastrest_p_->get_bound (LEFT) && lastrest_p_->get_bound (RIGHT)
153           && lastrest_p_->get_bound (LEFT) != lastrest_p_->get_bound (RIGHT))
154         typeset_grob (lastrest_p_);
155       lastrest_p_ = 0;
156     }
157
158   if (new_req_l_)
159     {
160       busy_span_req_l_ = new_req_l_;
161       new_req_l_ =0;
162     }
163   
164 }
165
166 void
167 Multi_measure_rest_engraver::start_translation_timestep ()
168 {
169   SCM smp = get_property ("measurePosition");
170   Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
171   
172   if (mmrest_p_ && !mp)
173     {
174       lastrest_p_ = mmrest_p_;
175       int cur = gh_scm2int (get_property ("currentBarNumber"));
176       lastrest_p_->set_grob_property ("measure-count",
177                                      gh_int2scm (cur - start_measure_i_));
178       mmrest_p_ = 0;
179     }
180 }
181
182
183 void
184 Multi_measure_rest_engraver::finalize ()
185 {
186   if (mmrest_p_)
187     typeset_grob (mmrest_p_);
188   if (lastrest_p_)
189     typeset_grob (lastrest_p_);
190 }