]> git.donarmstrong.com Git - lilypond.git/blob - lily/timing-translator.cc
patch::: 1.3.18.jcn1
[lilypond.git] / lily / timing-translator.cc
1 /*
2   timing-translator.cc -- implement Timing_translator
3
4
5   source file of the GNU LilyPond music typesetter
6
7   (c)  1997--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 */
9
10 #include "debug.hh"
11 #include "timing-translator.hh"
12 #include "command-request.hh"
13 #include "translator-group.hh"
14 #include "global-translator.hh"
15 #include "multi-measure-rest.hh"
16
17 ADD_THIS_TRANSLATOR (Timing_translator);
18
19 bool
20 Timing_translator::do_try_music (Music*r)
21 {
22   if (Timing_req *t =  dynamic_cast <Timing_req *> (r))
23     {
24       for (int i=0; i < timing_req_l_arr_.size (); i++)
25         {
26           if (timing_req_l_arr_[i]->equal_b(t))
27             return true;
28           if (String (classname (timing_req_l_arr_[i])) == classname (r))
29             {
30               r->warning (_ ("conflicting timing request"));
31               return false;
32             }
33         }
34     
35       timing_req_l_arr_.push(t);
36       return true;
37     }
38   return false;
39 }
40
41 /*ugh.
42  */
43 Time_signature_change_req*
44 Timing_translator::time_signature_req_l() const
45 {
46   Time_signature_change_req *m_l=0;
47   for (int i=0; !m_l && i < timing_req_l_arr_.size (); i++)
48     {
49       m_l=dynamic_cast<Time_signature_change_req*> (timing_req_l_arr_[i]);
50     }
51   return m_l;
52 }
53
54 void
55 Timing_translator::do_process_requests()
56 {
57   for (int i=0; i < timing_req_l_arr_.size (); i++)
58     {
59       Timing_req * tr_l = timing_req_l_arr_[i];
60
61       if (Time_signature_change_req *m_l = dynamic_cast <Time_signature_change_req *> (tr_l))
62         {
63           int b_i= m_l->beats_i_;
64           int o_i = m_l->one_beat_i_;
65           set_time_signature (b_i, o_i);
66         }
67       else if (dynamic_cast <Barcheck_req *> (tr_l))
68         {
69           if (measure_position ())
70             {
71               tr_l ->warning (_f ("barcheck failed at: %s", 
72                                   measure_position ().str ()));
73               // resync
74               daddy_trans_l_->set_property("measurePosition",
75                                            (new Moment)->smobify_self ());
76
77             }
78         }
79     }
80 }
81
82
83 void
84 Timing_translator::do_pre_move_processing()
85 {
86   timing_req_l_arr_.set_size (0);
87   Translator *t = this;
88   Global_translator *global_l =0;
89   do
90     {
91       t = t->daddy_trans_l_ ;
92       global_l = dynamic_cast<Global_translator*> (t);
93     }
94   while (!global_l);
95
96   /* allbars == ! skipbars */
97   SCM sb = get_property ("skipBars", 0);
98   bool allbars = !(gh_boolean_p (sb)&&gh_scm2bool (sb));
99
100   // urg: multi bar rests: should always process whole of first bar?
101   SCM tim = get_property ("timing", 0);
102   bool timb = to_boolean (tim);
103   if (timb && allbars)
104     {
105       Moment barleft = (measure_length () - measure_position ());
106
107       if (barleft > Moment (0))
108         global_l->add_moment_to_process (now_mom () + barleft);
109     }
110 }
111
112 void
113 Timing_translator::do_creation_processing()
114 {
115   daddy_trans_l_->set_property ("timing" , SCM_BOOL_T);  
116   daddy_trans_l_->set_property ("currentBarNumber" , gh_int2scm (1));
117   daddy_trans_l_->set_property("measurePosition",
118                                (new Moment)->smobify_self());
119   daddy_trans_l_->set_property ("oneBeat",
120                                 (new Moment (1,4))->smobify_self ());
121   daddy_trans_l_->set_property("measureLength",
122                                (new Moment (1))->smobify_self());
123 }
124
125 Moment
126 Timing_translator::measure_length () const
127 {
128   SCM l = get_property("measureLength",0);
129   if (SMOB_IS_TYPE_B(Moment, l))
130     return *SMOB_TO_TYPE (Moment, l);
131   else
132     return Moment (1);
133 }
134
135
136 void
137 Timing_translator::get_time_signature (int *n, int *d) const
138 {
139   Moment one_beat (1,4);
140   SCM one = get_property ("beatLength",0);
141   if (SMOB_IS_TYPE_B (Moment, one))
142     one_beat = *SMOB_TO_TYPE (Moment, one);
143   *n = measure_length () / one_beat;
144   *d = one_beat.den_i ();
145 }
146
147
148 void
149 Timing_translator::set_time_signature (int l, int o)
150 {
151   Moment one_beat = Moment (1)/Moment (o);
152   Moment len = Moment (l) * one_beat;
153   daddy_trans_l_->set_property ("measureLength",
154                                 (new Moment (len))->smobify_self ());
155   daddy_trans_l_->set_property ("beatength",
156                                 (new Moment (one_beat))->smobify_self ());
157 }
158
159 Timing_translator::Timing_translator()
160 {
161 }
162
163
164 Moment
165 Timing_translator::measure_position () const
166 {
167   SCM sm = get_property ("measurePosition",0);
168   
169   Moment m   =0;
170   if (SMOB_IS_TYPE_B (Moment, sm))
171     {
172       m = *SMOB_TO_TYPE (Moment, sm);
173       while (m < Moment (0))
174         m += measure_length ();
175     }
176   
177   return m;
178 }
179
180 void
181 Timing_translator::do_post_move_processing()
182 {
183   Translator *t = this;
184   Global_translator *global_l =0;
185   do
186     {
187       t = t->daddy_trans_l_ ;
188       global_l = dynamic_cast<Global_translator*> (t);
189     }
190   while (!global_l);
191
192   Moment dt = global_l->now_mom_  - global_l -> prev_mom_;
193   if (dt < Moment (0))
194     {
195       programming_error ("Moving backwards in time");
196       dt = 0;
197     }
198   
199   if (!dt)
200     return;
201
202   Moment * measposp =0;
203
204   SCM s = get_property ("measurePosition", 0);
205   if (SMOB_IS_TYPE_B (Moment, s))
206     {
207       measposp = SMOB_TO_TYPE (Moment,s);
208     }
209   else
210     {
211       measposp = new Moment;
212       daddy_trans_l_->set_property ("measurePosition", measposp->smobify_self ());
213     }
214   
215   *measposp += dt;
216   // don't need to set_property
217   
218   Translator_group * tr =daddy_trans_l_; 
219   SCM barn = get_property ("currentBarNumber", &tr);
220   int b = 0;
221   if (gh_number_p(barn))
222     {
223       b = gh_scm2int (barn);
224     }
225
226   SCM cad = get_property ("timing", 0);
227   bool c= to_boolean (cad );
228
229   Moment len = measure_length ();
230   while (c && *measposp >= len)
231       {
232         *measposp -= len;
233         b ++;
234       }
235
236   tr->set_property ("currentBarNumber", gh_int2scm (b));
237 }
238