]> git.donarmstrong.com Git - lilypond.git/blob - lily/quote-iterator.cc
307b860dc9674b504d4b9725bab4ee061b5bf39b
[lilypond.git] / lily / quote-iterator.cc
1 /*   
2   quote-iterator.cc --  implement Quote_iterator
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2004 Han-Wen Nienhuys <hanwen@xs4all.nl>
7
8 */
9
10 #include "context.hh"
11 #include "event.hh"
12 #include "music-sequence.hh"
13 #include "lily-guile.hh"
14 #include "music-iterator.hh"
15 #include "music.hh"
16 #include "input.hh"
17 #include "warn.hh"
18
19
20 class Quote_iterator : public Music_iterator
21 {
22 public:
23   Quote_iterator ();
24   
25   Moment start_moment_;
26   SCM event_vector_;
27   int event_idx_;
28   int end_idx_ ;
29
30   SCM transposed_musics_;
31   
32   DECLARE_SCHEME_CALLBACK (constructor, ()); 
33
34 protected:
35   virtual void derived_mark ();
36   virtual void construct_children ();
37   virtual Moment pending_moment () const;
38   virtual void process (Moment);
39   virtual bool ok () const;
40 };
41
42 void
43 Quote_iterator::derived_mark ()
44 {
45   scm_gc_mark (transposed_musics_ );
46 }
47
48 Quote_iterator::Quote_iterator ()
49 {
50   event_vector_ = SCM_EOL;
51   event_idx_ = 0;
52   end_idx_ = 0;
53 }
54
55 bool
56 moment_less (SCM a, SCM b)
57 {
58   return  *unsmob_moment (a) < *unsmob_moment (b);
59 }
60
61
62 int
63 binsearch_scm_vector (SCM vec, SCM key, bool (*is_less)(SCM a,SCM b))
64 {
65   int lo = 0;
66   int hi = SCM_VECTOR_LENGTH (vec);
67
68   /* binary search */
69   do
70   {
71     int cmp = (lo + hi) / 2;
72
73       SCM when = ly_caar (SCM_VECTOR_REF (vec, cmp));
74       bool result =  (*is_less) (key, when);
75       if (result)
76           hi = cmp;
77       else
78           lo = cmp;
79     }
80   while (hi - lo > 1);
81
82   return lo;
83 }
84
85
86 void
87 Quote_iterator::construct_children ()
88 {
89   SCM dur = get_music ()->get_property ("duration");
90   if (!unsmob_duration (dur))
91     return ;
92
93   set_translator (get_outlet ()->get_default_interpreter ());
94   
95   Moment now = get_outlet ()->now_mom ();
96   Moment stop = now + unsmob_duration (dur)->get_length ();
97
98   start_moment_ = now;
99   event_vector_ = get_music ()->get_property ("quoted-events");
100
101   if (ly_c_vector_p (event_vector_))
102     {
103       event_idx_ = binsearch_scm_vector (event_vector_, now.smobbed_copy (), &moment_less);
104       end_idx_ = binsearch_scm_vector (event_vector_, stop.smobbed_copy (), &moment_less);
105     }
106   else
107     {
108       get_music ()->origin()->warning (_("No events found for \\quote"));
109     }
110 }
111
112
113 bool
114 Quote_iterator::ok () const
115 {
116   return ly_c_vector_p (event_vector_) && (event_idx_ <= end_idx_);
117 }
118
119
120 Moment
121 Quote_iterator::pending_moment () const
122 {
123   SCM entry = SCM_VECTOR_REF (event_vector_, event_idx_);
124   return *unsmob_moment (ly_caar (entry)) - start_moment_;
125 }
126
127
128 void
129 Quote_iterator::process (Moment m)
130 {
131   SCM entry = SCM_EOL;
132
133   m += start_moment_;
134   while (event_idx_ < end_idx_)
135     {
136       entry = SCM_VECTOR_REF (event_vector_, event_idx_);
137
138       Moment em = *unsmob_moment (ly_caar (entry));
139
140       if (em > m)
141         return ;
142
143       if (em == m)
144         break ;
145
146       event_idx_++;
147     }
148
149   if (ly_c_pair_p (entry))
150     {
151       Pitch * quote_pitch = unsmob_pitch (ly_cdar (entry));
152       Pitch * me_pitch = unsmob_pitch (get_outlet ()->get_property ("instrumentTransposition"));
153       
154       for (SCM s = ly_cdr (entry); ly_c_pair_p (s); s = ly_cdr (s))
155         {
156           SCM ev_acc = ly_car (s);
157
158
159           Music * mus = unsmob_music (ly_car (ev_acc));
160           if (mus)
161             {
162               if (quote_pitch || me_pitch)
163                 {
164                   Pitch qp, mp;
165                   if (quote_pitch)
166                     qp = *quote_pitch;
167                   if (me_pitch)
168                     mp = *me_pitch;
169
170                   Pitch diff = interval (mp, qp);
171
172                   SCM copy = ly_deep_mus_copy (mus->self_scm ());
173                   mus = unsmob_music (copy);
174                   transposed_musics_ = scm_cons (copy, transposed_musics_);
175                   
176                   mus->transpose (diff);
177                 }
178
179               
180               bool b = get_outlet ()->try_music (mus);
181       
182               if (!b)
183                 mus->origin ()->warning (_f ("In quotation: junking event %s", mus->name ()));
184             }
185           else
186             programming_error ("need music in quote.");
187         }
188     }
189   event_idx_ ++; 
190 }
191
192 IMPLEMENT_CTOR_CALLBACK (Quote_iterator);