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