]> git.donarmstrong.com Git - lilypond.git/blob - lily/time-scaled-music-iterator.cc
Update source file headers. Fixes using standard GNU package conventions.
[lilypond.git] / lily / time-scaled-music-iterator.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1998--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>,
5                  Erik Sandberg <mandolaerik@gmail.com>
6
7   LilyPond is free software: you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation, either version 3 of the License, or
10   (at your option) any later version.
11
12   LilyPond is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "context.hh"
22 #include "input.hh"
23 #include "international.hh"
24 #include "music.hh"
25 #include "music-wrapper-iterator.hh"
26 #include "stream-event.hh"
27
28 /*
29   Iterates \times, by sending TupletSpanEvents at the start/end of each
30   tuplet bracket. Extra stop/start events are sent at regular
31   intervals if tupletSpannerDuration is set.
32 */
33 class Time_scaled_music_iterator : public Music_wrapper_iterator
34 {
35 public:
36   DECLARE_SCHEME_CALLBACK (constructor, ());
37   /* construction */
38   DECLARE_CLASSNAME (Time_scaled_music_iterator);
39   Time_scaled_music_iterator ();
40 protected:
41   virtual void process (Moment m);
42   virtual void construct_children ();
43   virtual void derived_mark () const;
44   virtual Moment pending_moment () const;
45
46   Music *create_event (Direction d);
47   
48 private:
49
50   /* tupletSpannerDuration */
51   Moment spanner_duration_;
52
53   /* next time to add a stop/start pair */
54   Moment next_split_mom_;
55   
56   /* Recycle start/stop events if tupletSpannerDuration is set. */
57   SCM synthesized_events_;
58   
59   Context_handle tuplet_handler_;
60 };
61
62 Music*
63 Time_scaled_music_iterator::create_event (Direction d)
64 {
65   SCM ev_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"),
66                            ly_symbol2scm ("TupletSpanEvent"),
67                            scm_from_int (d));
68   
69   Music *mus = get_music ();
70
71   Music *ev = unsmob_music (ev_scm);
72   ev->set_spot (*mus->origin ());
73   if (d == START)
74     {
75       ev->set_property ("numerator", mus->get_property ("numerator"));
76       ev->set_property ("denominator", mus->get_property ("denominator"));
77       ev->set_property ("tweaks", mus->get_property ("tweaks"));
78       ev->set_property ("length", spanner_duration_.smobbed_copy ()); 
79     }  
80
81   synthesized_events_ = scm_cons (ev_scm, synthesized_events_);
82   return ev;
83 }
84
85
86 Time_scaled_music_iterator::Time_scaled_music_iterator ()
87 {
88   spanner_duration_ = next_split_mom_ = 0;
89   synthesized_events_ = SCM_EOL;
90 }
91
92
93 Moment
94 Time_scaled_music_iterator::pending_moment () const
95 {
96   Moment next_mom = Music_wrapper_iterator::pending_moment ();
97   next_mom = min (next_mom, next_split_mom_);
98
99   return next_mom;
100 }
101
102
103 void
104 Time_scaled_music_iterator::process (Moment m)
105 {
106   if (spanner_duration_.to_bool () &&
107       m.main_part_ == next_split_mom_)
108     {
109       descend_to_bottom_context ();
110       if (tuplet_handler_.get_outlet ())
111         create_event (STOP)->send_to_context (tuplet_handler_.get_outlet ());
112
113       if (m.main_part_ < music_get_length ().main_part_)
114         {
115           tuplet_handler_.set_context (get_outlet ());
116           report_event (create_event (START));
117       
118           next_split_mom_ += spanner_duration_;
119         }
120       else
121         {
122           tuplet_handler_.set_context (0);
123         }
124     }
125   Music_wrapper_iterator::process (m);
126   if (child_iter_ && child_iter_->ok ())
127     descend_to_child (child_iter_->get_outlet ());
128   
129 }
130
131 void
132 Time_scaled_music_iterator::construct_children ()
133 {
134   spanner_duration_ = music_get_length ();
135
136   Moment *mp = unsmob_moment (get_outlet ()->get_property ("tupletSpannerDuration"));
137   if (mp)
138     spanner_duration_ = min (mp->main_part_, spanner_duration_);
139   
140   Music_wrapper_iterator::construct_children ();
141
142   if (child_iter_ && child_iter_->ok ())
143     descend_to_child (child_iter_->get_outlet ());
144 }
145
146 void
147 Time_scaled_music_iterator::derived_mark () const
148 {
149   scm_gc_mark (synthesized_events_);
150   Music_wrapper_iterator::derived_mark ();
151 }
152
153 IMPLEMENT_CTOR_CALLBACK (Time_scaled_music_iterator);