]> git.donarmstrong.com Git - lilypond.git/blob - lily/time-scaled-music-iterator.cc
Made tupletSpannerDuration work again.
[lilypond.git] / lily / time-scaled-music-iterator.cc
1 /*
2   time-scaled-music-iterator.cc -- implement Time_scaled_music_iterator
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1998--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>,
7                  Erik Sandberg <mandolaerik@gmail.com>
8 */
9
10 #include "context.hh"
11 #include "input.hh"
12 #include "international.hh"
13 #include "music.hh"
14 #include "sequential-iterator.hh"
15
16 /*
17   Iterates \times, by sending TupletEvents at the start/end of each
18   tuplet bracket. Extra stop/start events are sent at regular
19   intervals if tupletSpannerDuration is set.
20 */
21 class Time_scaled_music_iterator : public Sequential_iterator
22 {
23 public:
24   DECLARE_SCHEME_CALLBACK (constructor, ());
25   /* construction */
26   DECLARE_CLASSNAME(Time_scaled_music_iterator);
27   Time_scaled_music_iterator ();
28 protected:
29   virtual SCM get_music_list () const;
30   virtual void process (Moment m);
31   virtual void construct_children ();
32   virtual void derived_mark () const;
33   virtual Moment pending_moment () const;
34 private:
35   /* tupletSpannerDuration */
36   Moment spanner_duration_;
37   /* next time to add a stop/start pair */
38   Moment next_split_mom_;
39   /* Recycle start/stop events if tupletSpannerDuration is set. */
40   Music *start_;
41   Music *stop_;
42 };
43
44 Time_scaled_music_iterator::Time_scaled_music_iterator ()
45 {
46   spanner_duration_ = next_split_mom_ = 0;
47 }
48
49
50 Moment
51 Time_scaled_music_iterator::pending_moment () const
52 {
53   Moment next_mom = Sequential_iterator::pending_moment ();
54
55   if (spanner_duration_.to_bool () &&
56       next_mom.main_part_ > next_split_mom_)
57     {
58       next_mom = next_split_mom_;
59     }
60
61   return next_mom;
62 }
63
64
65 void
66 Time_scaled_music_iterator::process (Moment m)
67 {
68   if (spanner_duration_.to_bool () &&
69       m.main_part_ == next_split_mom_)
70     {
71       report_event (stop_);
72       report_event (start_);
73       next_split_mom_ += spanner_duration_;
74       /* avoid sending events twice at the end */
75       if (next_split_mom_ == get_music ()->get_length ().main_part_)
76         next_split_mom_.set_infinite (1);
77     }
78   Sequential_iterator::process(m);
79 }
80
81 void
82 Time_scaled_music_iterator::construct_children ()
83 {
84   /*
85     Inheritance trickery:
86     Time_scaled_music_iterator::construct_children initialises start_
87     and stop_, and calls Sequential_music::construct_children, which
88     in turn calls Time_scaled_music_iterator::get_music which reads
89     start_ and stop_.
90    */
91
92   Music *mus = get_music ();
93   Input *origin = mus->origin ();
94
95   SCM tuplet_symbol = ly_symbol2scm ("TupletEvent");
96   SCM start_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"), tuplet_symbol, scm_from_int (START));
97   start_ = unsmob_music (start_scm);
98   start_->set_spot (*origin);
99   start_->set_property ("numerator", mus->get_property ("numerator"));
100   start_->set_property ("denominator", mus->get_property ("denominator"));
101
102   SCM stop_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"), tuplet_symbol, scm_from_int (STOP));
103   stop_ = unsmob_music (stop_scm);
104   stop_->set_spot (*origin);
105
106   Moment *mp = unsmob_moment (get_outlet ()->get_property ("tupletSpannerDuration"));
107
108   if (mp)
109     {
110       spanner_duration_ = mp->main_part_;
111       next_split_mom_ = spanner_duration_;
112     }
113
114   Sequential_iterator::construct_children ();
115 }
116
117 SCM
118 Time_scaled_music_iterator::get_music_list () const
119 {
120   Music *mus = get_music ();
121   SCM child = mus->get_property ("element");
122
123   return scm_list_3 (start_->self_scm (), child, stop_->self_scm ());
124 }
125
126 void
127 Time_scaled_music_iterator::derived_mark () const
128 {
129   if (start_)
130     scm_gc_mark (start_->self_scm ());
131   if (stop_)
132     scm_gc_mark (stop_->self_scm ());
133
134   Sequential_iterator::derived_mark ();
135 }
136
137 IMPLEMENT_CTOR_CALLBACK (Time_scaled_music_iterator);