]> git.donarmstrong.com Git - lilypond.git/blob - lily/timing-engraver.cc
* flower
[lilypond.git] / lily / timing-engraver.cc
1 /*
2   timing-engraver.cc -- implement Timing_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "context.hh"
10 #include "multi-measure-rest.hh"
11 #include "timing-translator.hh"
12 #include "engraver.hh"
13 #include "grob.hh"
14
15 /**
16    Do time bookkeeping
17 */
18 class Timing_engraver : public Timing_translator, public Engraver
19 {
20 protected:
21   /* Needed to know whether we're advancing in grace notes, or not. */
22   Moment last_moment_;
23
24   virtual void start_translation_timestep ();
25   virtual void initialize ();
26   virtual void process_music ();
27   virtual void stop_translation_timestep ();
28
29 public:
30   TRANSLATOR_DECLARATIONS (Timing_engraver);
31 };
32
33 Timing_engraver::Timing_engraver ()
34 {
35   last_moment_.main_part_ = Rational (-1);
36 }
37
38 void
39 Timing_engraver::initialize ()
40 {
41   Timing_translator::initialize ();
42
43   SCM which = get_property ("whichBar");
44   Moment now = now_mom ();
45
46   /* Set the first bar of the score? */
47   if (!scm_is_string (which))
48     which = (now.main_part_ || now.main_part_ == last_moment_.main_part_)
49       ? SCM_EOL : scm_makfrom0str ("|");
50
51   context ()->set_property ("whichBar", which);
52 }
53
54 void
55 Timing_engraver::process_music ()
56 {
57   Timing_translator::process_music ();
58
59   bool start_of_measure = (last_moment_.main_part_ != now_mom ().main_part_
60                            && !measure_position ().main_part_);
61
62   /*
63     We can't do this in start_translation_timestep(), since time sig
64     changes won't have happened by then.
65   */
66   if (start_of_measure)
67     {
68       Moment mlen = Moment (measure_length ());
69       unsmob_grob (get_property ("currentCommandColumn"))
70         ->set_property ("measure-length", mlen.smobbed_copy ());
71     }
72 }
73
74 void
75 Timing_engraver::start_translation_timestep ()
76 {
77   Timing_translator::start_translation_timestep ();
78
79   SCM automatic_bars = get_property ("automaticBars");
80   Moment now = now_mom ();
81   SCM which = get_property ("whichBar");
82
83   /* Set the first bar of the score? */
84   if (!scm_is_string (which))
85     which = SCM_EOL;
86
87   Moment mp = measure_position ();
88   bool start_of_measure = (last_moment_.main_part_ != now.main_part_
89                            && !mp.main_part_);
90
91   if (!scm_is_string (which) && to_boolean (automatic_bars))
92     {
93       SCM always = get_property ("barAlways");
94
95       if (start_of_measure || (to_boolean (always)))
96         {
97           /* should this work, or be junked?  See input/bugs/no-bars.ly */
98           which = get_property ("defaultBarType");
99         }
100     }
101
102   context ()->set_property ("whichBar", which);
103 }
104
105 void
106 Timing_engraver::stop_translation_timestep ()
107 {
108   Timing_translator::stop_translation_timestep ();
109   context ()->set_property ("whichBar", SCM_EOL);
110   last_moment_ = now_mom ();
111 }
112
113 ADD_TRANSLATOR (Timing_engraver,
114                 /* descr */ " Responsible for synchronizing timing information from staves.  "
115                 "Normally in @code{Score}.  In order to create polyrhythmic music, "
116                 "this engraver should be removed from @code{Score} and placed in "
117                 "@code{Staff}. "
118                 "\n\nThis engraver adds the alias @code{Timing} to its containing context.",
119                 /* creats*/ "",
120                 /* accepts */ "",
121                 /* acks  */ "",
122                 /* reads */ "automaticBars whichBar barAlways defaultBarType skipBars timing measureLength measurePosition currentBarNumber",
123                 /* write */ "");