]> git.donarmstrong.com Git - lilypond.git/blob - lily/timing-translator.cc
Merge branch 'master' into lilypond/translation
[lilypond.git] / lily / timing-translator.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
5
6   LilyPond is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
11   LilyPond is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "timing-translator.hh"
21
22 #include "warn.hh"
23 #include "translator-group.hh"
24 #include "global-context.hh"
25
26 void
27 Timing_translator::stop_translation_timestep ()
28 {
29   Global_context *global = get_global_context ();
30
31   if (to_boolean (get_property ("timing"))
32       && !to_boolean (get_property ("skipBars")))
33     {
34       Moment barleft = (measure_length () - measure_position (context ()));
35       Moment now = now_mom ();
36
37       if (barleft > Moment (0))
38         {
39           Moment nextmom = now + barleft;
40           nextmom.grace_part_ = Rational (0);
41           global->add_moment_to_process (nextmom);
42         }
43     }
44 }
45
46 void
47 Timing_translator::initialize ()
48 {
49   Context *timing = unsmob_context (scm_call_2 (ly_lily_module_constant ("ly:context-find"),
50                                                 context ()->self_scm (),
51                                                 ly_symbol2scm ("Timing")));
52   if (timing != context ())
53     {
54       context ()->add_alias (ly_symbol2scm ("Timing"));
55
56       if (!timing)
57         {
58           programming_error ("Can't find Timing context template");
59           timing = context ();
60         }
61     }
62
63   SCM barnumber = timing->get_property ("currentBarNumber");
64   if (!scm_is_integer (barnumber))
65     barnumber = scm_from_int (1);
66   context ()->set_property ("currentBarNumber", barnumber);
67   context ()->set_property ("internalBarNumber", barnumber);
68
69   context ()->set_property ("timeSignatureFraction",
70                             timing->get_property ("timeSignatureFraction"));
71   /*
72     Do not init measurePosition; this should be done from global
73     context.
74   */
75   context ()->set_property ("measureLength",
76                             timing->get_property ("measureLength"));
77   context ()->set_property ("baseMoment",
78                             timing->get_property ("baseMoment"));
79 }
80
81 Rational
82 Timing_translator::measure_length () const
83 {
84   SCM l = get_property ("measureLength");
85   if (unsmob_moment (l))
86     return unsmob_moment (l)->main_part_;
87   else
88     return Rational (1);
89 }
90
91 Timing_translator::Timing_translator ()
92 {
93 }
94
95 void
96 Timing_translator::start_translation_timestep ()
97 {
98   Global_context *global = get_global_context ();
99
100   Moment now = global->now_mom ();
101   Moment dt = now - global->previous_moment ();
102   if (dt < Moment (0))
103     {
104       programming_error ("moving backwards in time");
105       dt = 0;
106     }
107   else if (dt.main_part_.is_infinity ())
108     {
109       programming_error ("moving infinitely to future");
110       dt = 0;
111     }
112
113   if (!dt.to_bool ())
114     return;
115
116   Moment measposp;
117
118   SCM s = get_property ("measurePosition");
119   if (unsmob_moment (s))
120     measposp = *unsmob_moment (s);
121   else
122     {
123       measposp = now;
124       context ()->set_property ("measurePosition",
125                                 measposp.smobbed_copy ());
126     }
127
128   measposp += dt;
129
130   int current_barnumber = robust_scm2int (get_property ("currentBarNumber"), 0);
131   int internal_barnumber = robust_scm2int (get_property ("internalBarNumber"), 0);
132
133   SCM cad = get_property ("timing");
134   bool c = to_boolean (cad);
135
136   Rational len = measure_length ();
137   while (c && measposp.main_part_ >= len)
138     {
139       measposp.main_part_ -= len;
140       current_barnumber++;
141       internal_barnumber++;
142     }
143
144   context ()->set_property ("currentBarNumber", scm_from_int (current_barnumber));
145   context ()->set_property ("internalBarNumber", scm_from_int (internal_barnumber));
146   context ()->set_property ("measurePosition", measposp.smobbed_copy ());
147 }
148
149 #include "translator.icc"
150
151 ADD_TRANSLATOR (Timing_translator,
152                 /* doc */
153                 "This engraver adds the alias @code{Timing} to its containing"
154                 " context.  Responsible for synchronizing timing information"
155                 " from staves.  Normally in @code{Score}.  In order to create"
156                 " polyrhythmic music, this engraver should be removed from"
157                 " @code{Score} and placed in @code{Staff}.",
158
159                 /* create */
160                 "",
161
162                 /* read */
163                 "baseMoment "
164                 "currentBarNumber "
165                 "internalBarNumber "
166                 "measureLength "
167                 "measurePosition "
168                 "timeSignatureFraction ",
169
170                 /* write */
171                 "baseMoment "
172                 "currentBarNumber "
173                 "internalBarNumber "
174                 "measureLength "
175                 "measurePosition "
176                 "timeSignatureFraction "
177                );