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>
11 #include "music-sequence.hh"
12 #include "lily-guile.hh"
13 #include "music-wrapper-iterator.hh"
17 class Quote_iterator : public Music_wrapper_iterator
21 Moment vector_moment (int idx) const;
22 Context_handle quote_outlet_;
30 SCM transposed_musics_;
32 DECLARE_SCHEME_CALLBACK (constructor, ());
33 bool quote_ok () const;
34 bool accept_music_type (Music *) const;
37 virtual void derived_mark () const;
38 virtual void construct_children ();
39 virtual Moment pending_moment () const;
40 virtual void process (Moment);
41 virtual void do_quit ();
42 virtual bool ok () const;
46 Quote_iterator::do_quit ()
48 Music_wrapper_iterator::do_quit ();
49 quote_outlet_.set_context (0);
53 Quote_iterator::accept_music_type (Music *mus) const
55 SCM accept = get_outlet ()->get_property ("quotedEventTypes");
56 for (SCM s = mus->get_property ("types");
57 scm_is_pair (s); s = scm_cdr (s))
59 if (scm_memq (scm_car (s), accept) != SCM_BOOL_F)
67 Quote_iterator::derived_mark () const
69 Music_wrapper_iterator::derived_mark ();
70 scm_gc_mark (transposed_musics_);
73 Quote_iterator::Quote_iterator ()
75 transposed_musics_ = SCM_EOL;
76 event_vector_ = SCM_EOL;
82 binsearch_scm_vector (SCM vec, SCM key, bool (*is_less) (SCM a, SCM b))
85 int hi = scm_c_vector_length (vec);
90 int cmp = (lo + hi) / 2;
92 SCM when = scm_caar (scm_c_vector_ref (vec, cmp));
93 bool result = (*is_less) (key, when);
105 Quote_iterator::construct_children ()
107 Music_wrapper_iterator::construct_children ();
109 SCM name = get_music ()->get_property ("quoted-context-type");
110 SCM id = get_music ()->get_property ("quoted-context-id");
112 if (scm_is_string (id)
113 && scm_is_symbol (name))
115 Context *cue_context = get_outlet ()->find_create_context (name,
116 ly_scm2string (id), SCM_EOL);
117 quote_outlet_.set_context (cue_context);
120 quote_outlet_.set_context (get_outlet ());
122 event_vector_ = get_music ()->get_property ("quoted-events");
125 We have to delay initting event_idx_ , since we have to
126 take starting grace notes into account. Those may offset
133 Quote_iterator::ok () const
136 Music_wrapper_iterator::ok ()
141 Quote_iterator::quote_ok () const
143 return (event_idx_ >= 0
144 && scm_is_vector (event_vector_)
145 && event_idx_ <= end_idx_
148 Don't quote the grace notes leading to an unquoted note.
150 && vector_moment (event_idx_).main_part_ < stop_moment_.main_part_);
154 Quote_iterator::pending_moment () const
157 infty.set_infinite (1);
160 if (Music_wrapper_iterator::ok ())
161 m = min (m, Music_wrapper_iterator::pending_moment ());
164 In case event_idx_ < 0, we're not initted yet, and the wrapped
165 music expression determines the starting moment.
168 m = min (m, vector_moment (event_idx_) - start_moment_);
174 Quote_iterator::vector_moment (int idx) const
176 SCM entry = scm_c_vector_ref (event_vector_, idx);
177 return *unsmob_moment (scm_caar (entry));
181 Quote_iterator::process (Moment m)
183 if (Music_wrapper_iterator::ok ())
184 Music_wrapper_iterator::process (m);
186 if (!scm_is_vector (event_vector_))
191 event_idx_ = binsearch_scm_vector (event_vector_,
192 get_outlet ()->now_mom ().smobbed_copy (),
194 start_moment_ = get_outlet ()->now_mom () - music_start_mom ();
195 stop_moment_ = start_moment_ + get_music ()->get_length ();
197 end_idx_ = binsearch_scm_vector (event_vector_,
198 stop_moment_.smobbed_copy (),
203 while (event_idx_ <= end_idx_)
205 Moment em = vector_moment (event_idx_);
217 SCM entry = scm_c_vector_ref (event_vector_, event_idx_);
218 Pitch *quote_pitch = unsmob_pitch (scm_cdar (entry));
221 The pitch that sounds like central C
223 Pitch *me_pitch = unsmob_pitch (get_outlet ()->get_property ("instrumentTransposition"));
225 for (SCM s = scm_cdr (entry); scm_is_pair (s); s = scm_cdr (s))
227 SCM ev_acc = scm_car (s);
229 Music *mus = unsmob_music (scm_car (ev_acc));
231 programming_error ("no music found in quote");
232 else if (accept_music_type (mus))
234 if (quote_pitch || me_pitch)
242 Pitch diff = pitch_interval (qp, mp);
244 SCM copy = ly_music_deep_copy (mus->self_scm ());
245 mus = unsmob_music (copy);
247 transposed_musics_ = scm_cons (copy, transposed_musics_);
248 mus->transpose (diff);
251 bool b = quote_outlet_.get_outlet ()->try_music (mus);
253 mus->origin ()->warning (_f ("in quotation: junking event %s",
262 IMPLEMENT_CTOR_CALLBACK (Quote_iterator);