]> git.donarmstrong.com Git - lilypond.git/blob - lily/multi-measure-rest-engraver.cc
* scm/engraver-documentation-lib.scm
[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 "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   Music * new_req_;
36   Music * busy_span_req_;
37   Music * 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 (req->is_mus_type ("multi-measure-rest-event"))
59     {
60       Direction d = to_dir (req->get_mus_property ("span-direction"));
61       if (d == STOP)
62         {
63           stop_req_ = req;
64         }
65       else if (d == START&& !new_req_)
66         {
67           new_req_ = req;
68         }
69       return true;
70     }
71   return false;
72 }
73
74 void
75 Multi_measure_rest_engraver::process_music ()
76 {
77   if (new_req_ && stop_req_)
78     stop_req_ = 0;
79
80   if (new_req_)
81     start_moment_ = now_mom ();
82
83   if (stop_req_)
84     {
85       busy_span_req_ =0;
86       stop_req_ = 0;
87     }
88   
89   if (new_req_)
90     {
91       busy_span_req_ = new_req_;
92       new_req_ =0;
93     }
94
95   if (busy_span_req_ && !mmrest_)
96     {
97       mmrest_ = new Spanner (get_property ("MultiMeasureRest"));
98
99       announce_grob(mmrest_, busy_span_req_->self_scm());
100       start_measure_
101         = gh_scm2int (get_property ("currentBarNumber"));
102     }
103
104   if (gh_string_p (get_property ("whichBar")))
105     {
106       Grob *cmc = unsmob_grob (get_property( "currentCommandColumn"));
107       Item *it = dynamic_cast<Item*> (cmc);
108       if (mmrest_)
109         add_bound_item (mmrest_, it);
110       if (lastrest_)
111         add_bound_item (lastrest_,it);
112     }
113 }
114
115 void
116 Multi_measure_rest_engraver::stop_translation_timestep ()
117 {
118   SCM smp = get_property ("measurePosition");
119   Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
120
121   if (mmrest_ && (now_mom () >= start_moment_) 
122       && !mp.to_bool ()
123       && mmrest_->get_bound (LEFT) && mmrest_->get_bound (RIGHT))
124     {
125       typeset_grob (mmrest_);
126       /*
127         we must keep mmrest_ around to set measure-count, so
128         no mmrest_ = 0 here. 
129        */
130     }
131
132   if (lastrest_)
133     {
134       /* sanity check */
135       if (lastrest_->get_bound (LEFT) && lastrest_->get_bound (RIGHT)
136           && lastrest_->get_bound (LEFT) != lastrest_->get_bound (RIGHT))
137         typeset_grob (lastrest_);
138       lastrest_ = 0;
139     }
140
141   if (new_req_)
142     {
143       busy_span_req_ = new_req_;
144       new_req_ =0;
145     }
146   
147 }
148
149 void
150 Multi_measure_rest_engraver::start_translation_timestep ()
151 {
152   SCM smp = get_property ("measurePosition");
153   Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
154   
155   if (mmrest_ && !mp.to_bool ())
156     {
157       lastrest_ = mmrest_;
158       int cur = gh_scm2int (get_property ("currentBarNumber"));
159       lastrest_->set_grob_property ("measure-count",
160                                      gh_int2scm (cur - start_measure_));
161       mmrest_ = 0;
162     }
163 }
164
165
166 void
167 Multi_measure_rest_engraver::finalize ()
168 {
169   if (mmrest_)
170     typeset_grob (mmrest_);
171   if (lastrest_)
172     typeset_grob (lastrest_);
173 }
174
175 ENTER_DESCRIPTION(Multi_measure_rest_engraver,
176 /* descr */       "Engraves multi-measure rests that are produced with @code{R}.  Reads
177 measurePosition and currentBarNumber to determine what number to print over the MultiMeasureRest
178 ",
179 /* creats*/       "MultiMeasureRest",
180 /* accepts */     "multi-measure-rest-event",
181 /* acks  */      "",
182 /* reads */       "currentBarNumber currentCommandColumn measurePosition",
183 /* write */       "");