]> git.donarmstrong.com Git - lilypond.git/blob - lily/time-scaled-music-iterator.cc
56e63ce311bbcdccb35108a4abd845c7c0f90a2b
[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--2007 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 "music-wrapper-iterator.hh"
15 #include "stream-event.hh"
16
17 /*
18   Iterates \times, by sending TupletSpanEvents at the start/end of each
19   tuplet bracket. Extra stop/start events are sent at regular
20   intervals if tupletSpannerDuration is set.
21 */
22 class Time_scaled_music_iterator : public Music_wrapper_iterator
23 {
24 public:
25   DECLARE_SCHEME_CALLBACK (constructor, ());
26   /* construction */
27   DECLARE_CLASSNAME (Time_scaled_music_iterator);
28   Time_scaled_music_iterator ();
29 protected:
30   virtual void process (Moment m);
31   virtual void construct_children ();
32   virtual void derived_mark () const;
33   virtual Moment pending_moment () const;
34
35   Music *create_event (Direction d);
36   
37 private:
38
39   /* tupletSpannerDuration */
40   Moment spanner_duration_;
41
42   /* next time to add a stop/start pair */
43   Moment next_split_mom_;
44   
45   /* Recycle start/stop events if tupletSpannerDuration is set. */
46   SCM synthesized_events_;
47   
48   Context_handle tuplet_handler_;
49 };
50
51 Music*
52 Time_scaled_music_iterator::create_event (Direction d)
53 {
54   SCM ev_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"),
55                            ly_symbol2scm ("TupletSpanEvent"),
56                            scm_from_int (d));
57   
58   Music *mus = get_music ();
59
60   Music *ev = unsmob_music (ev_scm);
61   ev->set_spot (*mus->origin ());
62   if (d == START)
63     {
64       ev->set_property ("numerator", mus->get_property ("numerator"));
65       ev->set_property ("denominator", mus->get_property ("denominator"));
66       ev->set_property ("tweaks", mus->get_property ("tweaks"));
67       ev->set_property ("length", spanner_duration_.smobbed_copy ()); 
68     }  
69
70   synthesized_events_ = scm_cons (ev_scm, synthesized_events_);
71   return ev;
72 }
73
74
75 Time_scaled_music_iterator::Time_scaled_music_iterator ()
76 {
77   spanner_duration_ = next_split_mom_ = 0;
78   synthesized_events_ = SCM_EOL;
79 }
80
81
82 Moment
83 Time_scaled_music_iterator::pending_moment () const
84 {
85   Moment next_mom = Music_wrapper_iterator::pending_moment ();
86   next_mom = min (next_mom, next_split_mom_);
87
88   return next_mom;
89 }
90
91
92 void
93 Time_scaled_music_iterator::process (Moment m)
94 {
95   if (spanner_duration_.to_bool () &&
96       m.main_part_ == next_split_mom_)
97     {
98       descend_to_bottom_context ();
99       if (tuplet_handler_.get_outlet ())
100         create_event (STOP)->send_to_context (tuplet_handler_.get_outlet ());
101
102       if (m.main_part_ < music_get_length ().main_part_)
103         {
104           tuplet_handler_.set_context (get_outlet ());
105           report_event (create_event (START));
106       
107           next_split_mom_ += spanner_duration_;
108         }
109       else
110         {
111           tuplet_handler_.set_context (0);
112         }
113     }
114   Music_wrapper_iterator::process (m);
115   if (child_iter_ && child_iter_->ok ())
116     descend_to_child (child_iter_->get_outlet ());
117   
118 }
119
120 void
121 Time_scaled_music_iterator::construct_children ()
122 {
123   spanner_duration_ = music_get_length ();
124
125   Moment *mp = unsmob_moment (get_outlet ()->get_property ("tupletSpannerDuration"));
126   if (mp)
127     spanner_duration_ = min (mp->main_part_, spanner_duration_);
128   
129   Music_wrapper_iterator::construct_children ();
130
131   if (child_iter_ && child_iter_->ok ())
132     descend_to_child (child_iter_->get_outlet ());
133 }
134
135 void
136 Time_scaled_music_iterator::derived_mark () const
137 {
138   scm_gc_mark (synthesized_events_);
139   Music_wrapper_iterator::derived_mark ();
140 }
141
142 IMPLEMENT_CTOR_CALLBACK (Time_scaled_music_iterator);