]> git.donarmstrong.com Git - lilypond.git/blob - lily/multi-measure-rest-engraver.cc
release: 1.3.110
[lilypond.git] / lily / multi-measure-rest-engraver.cc
1 /*
2   multi_measure_rest-engraver.cc -- implement Multi_measure_rest_engraver
3
4   (c) 1998--2000 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 stop_translation_timestep ();
35   virtual void start_translation_timestep ();
36   virtual void finalize ();
37   virtual void create_grobs ();
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")))
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::create_grobs ()
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 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_p_ && (now_mom () >= start_moment_) 
136     && !mp
137     && (scm_ilength (mmrest_p_->get_grob_property ("columns")) >= 2))
138     {
139       typeset_grob (mmrest_p_);
140       /*
141         must keep mmrest_p_ around to set measures_i_
142        */
143     }
144   if (lastrest_p_)
145     {
146       typeset_grob (lastrest_p_);
147       lastrest_p_ = 0;
148     }
149
150   if (new_req_l_)
151     {
152       busy_span_req_l_ = new_req_l_;
153       new_req_l_ =0;
154     }
155   
156 }
157
158 void
159 Multi_measure_rest_engraver::start_translation_timestep ()
160 {
161   SCM smp = get_property ("measurePosition");
162   Moment mp =  (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
163   
164   if (mmrest_p_ && !mp)
165     {
166       lastrest_p_ = mmrest_p_;
167       int cur = gh_scm2int (get_property ("currentBarNumber"));
168       lastrest_p_->set_grob_property ("measure-count",
169                                      gh_int2scm (cur - start_measure_i_));
170       mmrest_p_ = 0;
171     }
172 }
173
174
175 void
176 Multi_measure_rest_engraver::finalize ()
177 {
178   if (mmrest_p_)
179     typeset_grob (mmrest_p_);
180   if (lastrest_p_)
181     typeset_grob (lastrest_p_);
182 }