2 quote-iterator.cc -- implement Quote_iterator
4 source file of the GNU LilyPond music typesetter
6 (c) 2004--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
9 #include "music-wrapper-iterator.hh"
12 #include "dispatcher.hh"
14 #include "international.hh"
15 #include "lily-guile.hh"
16 #include "music-sequence.hh"
18 #include "stream-event.hh"
21 class Quote_iterator : public Music_wrapper_iterator
25 Moment vector_moment (int idx) const;
26 Context_handle quote_outlet_;
34 SCM transposed_musics_;
36 DECLARE_SCHEME_CALLBACK (constructor, ());
37 bool quote_ok () const;
38 bool accept_music_type (Stream_event *) const;
41 virtual void derived_mark () const;
42 virtual void construct_children ();
43 virtual Moment pending_moment () const;
44 virtual void process (Moment);
45 virtual void do_quit ();
46 virtual bool ok () const;
50 Quote_iterator::do_quit ()
52 Music_wrapper_iterator::do_quit ();
53 quote_outlet_.set_context (0);
57 Quote_iterator::accept_music_type (Stream_event *ev) const
59 for (SCM accept = get_outlet ()->get_property ("quotedEventTypes");
60 scm_is_pair (accept); accept = scm_cdr (accept))
62 if (ev->internal_in_event_class (scm_car (accept)))
69 Quote_iterator::derived_mark () const
71 Music_wrapper_iterator::derived_mark ();
72 scm_gc_mark (transposed_musics_);
75 Quote_iterator::Quote_iterator ()
77 transposed_musics_ = SCM_EOL;
78 event_vector_ = SCM_EOL;
84 binsearch_scm_vector (SCM vec, SCM key, bool (*is_less) (SCM a, SCM b))
87 int hi = scm_c_vector_length (vec);
92 int cmp = (lo + hi) / 2;
94 SCM when = scm_caar (scm_c_vector_ref (vec, cmp));
95 bool result = (*is_less) (key, when);
107 Quote_iterator::construct_children ()
109 Music_wrapper_iterator::construct_children ();
111 SCM name = get_music ()->get_property ("quoted-context-type");
112 SCM id = get_music ()->get_property ("quoted-context-id");
114 if (scm_is_string (id)
115 && scm_is_symbol (name))
117 Context *cue_context = get_outlet ()->find_create_context (name,
118 ly_scm2string (id), SCM_EOL);
119 quote_outlet_.set_context (cue_context);
122 quote_outlet_.set_context (get_outlet ());
124 event_vector_ = get_music ()->get_property ("quoted-events");
127 We have to delay initting event_idx_ , since we have to
128 take starting grace notes into account. Those may offset
135 Quote_iterator::ok () const
138 Music_wrapper_iterator::ok ()
143 Quote_iterator::quote_ok () const
145 return (event_idx_ >= 0
146 && scm_is_vector (event_vector_)
147 && event_idx_ <= end_idx_
150 Don't quote the grace notes leading to an unquoted note.
152 && vector_moment (event_idx_).main_part_ < stop_moment_.main_part_);
156 Quote_iterator::pending_moment () const
159 infty.set_infinite (1);
162 if (Music_wrapper_iterator::ok ())
163 m = min (m, Music_wrapper_iterator::pending_moment ());
166 In case event_idx_ < 0, we're not initted yet, and the wrapped
167 music expression determines the starting moment.
170 m = min (m, vector_moment (event_idx_) - start_moment_);
176 Quote_iterator::vector_moment (int idx) const
178 SCM entry = scm_c_vector_ref (event_vector_, idx);
179 return *unsmob_moment (scm_caar (entry));
183 Quote_iterator::process (Moment m)
185 if (Music_wrapper_iterator::ok ())
186 Music_wrapper_iterator::process (m);
188 if (!scm_is_vector (event_vector_))
193 event_idx_ = binsearch_scm_vector (event_vector_,
194 get_outlet ()->now_mom ().smobbed_copy (),
196 start_moment_ = get_outlet ()->now_mom () - music_start_mom ();
197 stop_moment_ = start_moment_ + get_music ()->get_length ();
199 end_idx_ = binsearch_scm_vector (event_vector_,
200 stop_moment_.smobbed_copy (),
205 while (event_idx_ <= end_idx_)
207 Moment em = vector_moment (event_idx_);
219 SCM entry = scm_c_vector_ref (event_vector_, event_idx_);
220 Pitch *quote_pitch = unsmob_pitch (scm_cdar (entry));
223 The pitch that sounds like central C
225 Pitch *me_pitch = unsmob_pitch (get_music ()->get_property ("quoted-transposition"));
227 me_pitch = unsmob_pitch (get_outlet ()->get_property ("instrumentTransposition"));
229 for (SCM s = scm_cdr (entry); scm_is_pair (s); s = scm_cdr (s))
231 SCM ev_acc = scm_car (s);
233 Stream_event *ev = unsmob_stream_event (scm_car (ev_acc));
235 programming_error ("no music found in quote");
236 else if (accept_music_type (ev))
238 /* create a transposed copy if necessary */
239 if (quote_pitch || me_pitch)
247 Pitch diff = pitch_interval (qp, mp);
249 SCM props = transpose_mutable (ev->get_property_alist (true), diff);
250 ev = new Stream_event (ev->get_property ("class"), props);
251 transposed_musics_ = scm_cons (ev->unprotect (), transposed_musics_);
253 quote_outlet_.get_outlet ()->event_source ()->broadcast (ev);
261 IMPLEMENT_CTOR_CALLBACK (Quote_iterator);