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