]> git.donarmstrong.com Git - lilypond.git/blob - lily/time-scaled-music-iterator.cc
9ab2673eeb86a23a7694700e886f5b0a13242086
[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 TupletSpanEvents 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
36   /* tupletSpannerDuration */
37   Moment spanner_duration_;
38
39   /* next time to add a stop/start pair */
40   Moment next_split_mom_;
41   
42   /* Recycle start/stop events if tupletSpannerDuration is set. */
43   Music *start_;
44   Music *stop_;
45 };
46
47 Time_scaled_music_iterator::Time_scaled_music_iterator ()
48 {
49   spanner_duration_ = next_split_mom_ = 0;
50 }
51
52
53 Moment
54 Time_scaled_music_iterator::pending_moment () const
55 {
56   Moment next_mom = Sequential_iterator::pending_moment ();
57
58   if (spanner_duration_.to_bool () &&
59       next_mom.main_part_ > next_split_mom_)
60     {
61       next_mom = next_split_mom_;
62     }
63
64   return next_mom;
65 }
66
67
68 void
69 Time_scaled_music_iterator::process (Moment m)
70 {
71   if (spanner_duration_.to_bool () &&
72       m.main_part_ == next_split_mom_)
73     {
74       report_event (stop_);
75       report_event (start_);
76       
77       next_split_mom_ += spanner_duration_;
78       /* avoid sending events twice at the end */
79       if (next_split_mom_ == get_music ()->get_length ().main_part_)
80         next_split_mom_.set_infinite (1);
81     }
82   Sequential_iterator::process(m);
83 }
84
85 void
86 Time_scaled_music_iterator::construct_children ()
87 {
88   /*
89     Inheritance trickery:
90     Time_scaled_music_iterator::construct_children initialises start_
91     and stop_, and calls Sequential_music::construct_children, which
92     in turn calls Time_scaled_music_iterator::get_music which reads
93     start_ and stop_.
94    */
95
96   Music *mus = get_music ();
97   Input *origin = mus->origin ();
98
99   SCM tuplet_symbol = ly_symbol2scm ("TupletSpanEvent");
100   SCM start_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"), tuplet_symbol, scm_from_int (START));
101   start_ = unsmob_music (start_scm);
102   start_->set_spot (*origin);
103   start_->set_property ("numerator", mus->get_property ("numerator"));
104   start_->set_property ("denominator", mus->get_property ("denominator"));
105   start_->set_property ("tweaks", mus->get_property ("tweaks"));
106   
107
108   SCM stop_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"), tuplet_symbol, scm_from_int (STOP));
109   stop_ = unsmob_music (stop_scm);
110   stop_->set_spot (*origin);
111
112   Moment *mp = unsmob_moment (get_outlet ()->get_property ("tupletSpannerDuration"));
113
114   if (mp)
115     {
116       spanner_duration_ = mp->main_part_;
117       next_split_mom_ = spanner_duration_;
118     }
119
120   Sequential_iterator::construct_children ();
121 }
122
123 SCM
124 Time_scaled_music_iterator::get_music_list () const
125 {
126   Music *mus = get_music ();
127   SCM child = mus->get_property ("element");
128
129   return scm_list_3 (start_->self_scm (), child, stop_->self_scm ());
130 }
131
132 void
133 Time_scaled_music_iterator::derived_mark () const
134 {
135   if (start_)
136     scm_gc_mark (start_->self_scm ());
137   if (stop_)
138     scm_gc_mark (stop_->self_scm ());
139
140   Sequential_iterator::derived_mark ();
141 }
142
143 IMPLEMENT_CTOR_CALLBACK (Time_scaled_music_iterator);