2 quote-iterator.cc -- implement Quote_iterator
4 source file of the GNU LilyPond music typesetter
6 (c) 2004--2009 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"
20 class Quote_iterator
: public Music_wrapper_iterator
24 Moment
vector_moment (int idx
) const;
25 Context_handle quote_outlet_
;
33 SCM transposed_musics_
;
35 DECLARE_SCHEME_CALLBACK (constructor
, ());
36 bool quote_ok () const;
37 bool accept_music_type (Stream_event
*) const;
40 virtual void derived_mark () const;
41 virtual void construct_children ();
42 virtual Moment
pending_moment () const;
43 virtual void process (Moment
);
44 virtual void do_quit ();
45 virtual bool ok () const;
49 Quote_iterator::do_quit ()
51 Music_wrapper_iterator::do_quit ();
52 quote_outlet_
.set_context (0);
56 Quote_iterator::accept_music_type (Stream_event
*ev
) const
58 for (SCM accept
= get_outlet ()->get_property ("quotedEventTypes");
59 scm_is_pair (accept
); accept
= scm_cdr (accept
))
61 if (ev
->internal_in_event_class (scm_car (accept
)))
68 Quote_iterator::derived_mark () const
70 Music_wrapper_iterator::derived_mark ();
71 scm_gc_mark (transposed_musics_
);
74 Quote_iterator::Quote_iterator ()
76 transposed_musics_
= SCM_EOL
;
77 event_vector_
= SCM_EOL
;
83 binsearch_scm_vector (SCM vec
, SCM key
, bool (*is_less
) (SCM a
, SCM b
))
86 int hi
= scm_c_vector_length (vec
);
91 int cmp
= (lo
+ hi
) / 2;
93 SCM when
= scm_caar (scm_c_vector_ref (vec
, cmp
));
94 bool result
= (*is_less
) (key
, when
);
106 Quote_iterator::construct_children ()
108 Music_wrapper_iterator::construct_children ();
110 SCM name
= get_music ()->get_property ("quoted-context-type");
111 SCM id
= get_music ()->get_property ("quoted-context-id");
113 if (scm_is_string (id
)
114 && scm_is_symbol (name
))
116 Context
*cue_context
= get_outlet ()->find_create_context (name
,
117 ly_scm2string (id
), SCM_EOL
);
118 quote_outlet_
.set_context (cue_context
);
121 quote_outlet_
.set_context (get_outlet ());
123 event_vector_
= get_music ()->get_property ("quoted-events");
126 We have to delay initting event_idx_ , since we have to
127 take starting grace notes into account. Those may offset
134 Quote_iterator::ok () const
137 Music_wrapper_iterator::ok ()
142 Quote_iterator::quote_ok () const
144 return (event_idx_
>= 0
145 && scm_is_vector (event_vector_
)
146 && event_idx_
<= end_idx_
149 Don't quote the grace notes leading to an unquoted note.
151 && vector_moment (event_idx_
).main_part_
< stop_moment_
.main_part_
);
155 Quote_iterator::pending_moment () const
158 infty
.set_infinite (1);
161 if (Music_wrapper_iterator::ok ())
162 m
= min (m
, Music_wrapper_iterator::pending_moment ());
165 In case event_idx_ < 0, we're not initted yet, and the wrapped
166 music expression determines the starting moment.
169 m
= min (m
, vector_moment (event_idx_
) - start_moment_
);
175 Quote_iterator::vector_moment (int idx
) const
177 SCM entry
= scm_c_vector_ref (event_vector_
, idx
);
178 return *unsmob_moment (scm_caar (entry
));
182 Quote_iterator::process (Moment m
)
184 if (Music_wrapper_iterator::ok ())
185 Music_wrapper_iterator::process (m
);
187 if (!scm_is_vector (event_vector_
))
192 event_idx_
= binsearch_scm_vector (event_vector_
,
193 get_outlet ()->now_mom ().smobbed_copy (),
195 start_moment_
= get_outlet ()->now_mom () - music_start_mom ();
196 stop_moment_
= start_moment_
+ get_music ()->get_length ();
198 end_idx_
= binsearch_scm_vector (event_vector_
,
199 stop_moment_
.smobbed_copy (),
204 while (event_idx_
<= end_idx_
)
206 Moment em
= vector_moment (event_idx_
);
218 SCM entry
= scm_c_vector_ref (event_vector_
, event_idx_
);
219 Pitch
*quote_pitch
= unsmob_pitch (scm_cdar (entry
));
222 The pitch that sounds like central C
224 Pitch
*me_pitch
= unsmob_pitch (get_music ()->get_property ("quoted-transposition"));
226 me_pitch
= unsmob_pitch (get_outlet ()->get_property ("instrumentTransposition"));
228 for (SCM s
= scm_cdr (entry
); scm_is_pair (s
); s
= scm_cdr (s
))
230 SCM ev_acc
= scm_car (s
);
232 Stream_event
*ev
= unsmob_stream_event (scm_car (ev_acc
));
234 programming_error ("no music found in quote");
235 else if (accept_music_type (ev
))
237 /* create a transposed copy if necessary */
238 if (quote_pitch
|| me_pitch
)
246 Pitch diff
= pitch_interval (qp
, mp
);
249 transpose_mutable (ev
->get_property_alist (true), diff
);
250 transposed_musics_
= scm_cons (ev
->unprotect (), transposed_musics_
);
252 quote_outlet_
.get_outlet ()->event_source ()->broadcast (ev
);
260 IMPLEMENT_CTOR_CALLBACK (Quote_iterator
);