#include "event.hh"
#include "music-sequence.hh"
#include "lily-guile.hh"
-#include "music-iterator.hh"
-#include "music.hh"
-#include "input.hh"
+#include "music-wrapper-iterator.hh"
#include "warn.hh"
-
-class Quote_iterator : public Music_iterator
+class Quote_iterator : public Music_wrapper_iterator
{
public:
Quote_iterator ();
-
+ Moment vector_moment (int idx) const;
+ Interpretation_context_handle quote_outlet_;
+
Moment start_moment_;
+ Moment stop_moment_;
SCM event_vector_;
int event_idx_;
int end_idx_ ;
SCM transposed_musics_;
DECLARE_SCHEME_CALLBACK (constructor, ());
-
+ bool quote_ok () const;
bool accept_music_type (Music*) const;
protected:
virtual void derived_mark () const;
{
SCM accept = get_outlet()->get_property ("quotedEventTypes");
for (SCM s = mus->get_property ("types");
- ly_c_pair_p (s); s = ly_cdr (s))
+ scm_is_pair (s); s = scm_cdr (s))
{
- if (scm_memq (ly_car (s), accept) != SCM_BOOL_F)
+ if (scm_memq (scm_car (s), accept) != SCM_BOOL_F)
return true;
}
Quote_iterator::Quote_iterator ()
{
+ transposed_musics_ = SCM_EOL;
event_vector_ = SCM_EOL;
event_idx_ = 0;
end_idx_ = 0;
}
-bool
-moment_less (SCM a, SCM b)
-{
- return *unsmob_moment (a) < *unsmob_moment (b);
-}
-
int
binsearch_scm_vector (SCM vec, SCM key, bool (*is_less)(SCM a,SCM b))
{
int cmp = (lo + hi) / 2;
- SCM when = ly_caar (SCM_VECTOR_REF (vec, cmp));
+ SCM when = scm_caar (SCM_VECTOR_REF (vec, cmp));
bool result = (*is_less) (key, when);
if (result)
hi = cmp;
void
Quote_iterator::construct_children ()
{
- SCM dur = get_music ()->get_property ("duration");
- if (!unsmob_duration (dur))
- return ;
+ Music_wrapper_iterator::construct_children ();
- set_translator (get_outlet ()->get_default_interpreter ());
-
- Moment now = get_outlet ()->now_mom ();
- Moment stop = now + unsmob_duration (dur)->get_length ();
+ SCM name = get_music ()->get_property ("quoted-context-type");
+ SCM id = get_music ()->get_property ("quoted-context-id");
- start_moment_ = now;
- event_vector_ = get_music ()->get_property ("quoted-events");
-
- if (ly_c_vector_p (event_vector_))
+ if (scm_is_string (id)
+ && scm_is_symbol (name))
{
- event_idx_ = binsearch_scm_vector (event_vector_, now.smobbed_copy (), &moment_less);
- end_idx_ = binsearch_scm_vector (event_vector_, stop.smobbed_copy (), &moment_less);
+ Context *cue_context = get_outlet()->find_create_context (name,
+ ly_scm2string (id), SCM_EOL);
+ quote_outlet_.set_context (cue_context);
}
else
{
- get_music ()->origin()->warning (_("No events found for \\quote"));
+ quote_outlet_.set_context (get_outlet ());
}
+
+
+ event_vector_ = get_music ()->get_property ("quoted-events");
+
+ /*
+ We have to delay initting event_idx_ , since we have to
+ take starting grace notes into account. Those may offset
+ event_idx_.
+ */
+ event_idx_ = -1;
}
bool
Quote_iterator::ok () const
{
- return ly_c_vector_p (event_vector_) && (event_idx_ <= end_idx_);
+ return
+ Music_wrapper_iterator::ok()
+ || quote_ok ();
+}
+
+bool
+Quote_iterator::quote_ok () const
+{
+ return (event_idx_ >= 0
+ && ly_c_vector_p (event_vector_)
+ && event_idx_ <= end_idx_
+
+ /*
+ Don't quote the grace notes leading to an unquoted note.
+ */
+ && vector_moment (event_idx_).main_part_ < stop_moment_.main_part_
+ );
}
Moment
Quote_iterator::pending_moment () const
{
- SCM entry = SCM_VECTOR_REF (event_vector_, event_idx_);
- return *unsmob_moment (ly_caar (entry)) - start_moment_;
+ Rational infty;
+ infty.set_infinite (1);
+ Moment m (infty);
+
+ if (Music_wrapper_iterator::ok())
+ m = m <? Music_wrapper_iterator::pending_moment();
+
+ /*
+ In case event_idx_ < 0, we're not initted yet, and the wrapped
+ music expression determines the starting moment.
+ */
+ if (quote_ok ())
+ m = m <? vector_moment (event_idx_) - start_moment_;
+
+ return m;
+}
+
+Moment
+Quote_iterator::vector_moment (int idx) const
+{
+ SCM entry = SCM_VECTOR_REF (event_vector_, idx);
+ return *unsmob_moment (scm_caar (entry));
}
void
Quote_iterator::process (Moment m)
{
- SCM entry = SCM_EOL;
+ if (Music_wrapper_iterator::ok())
+ Music_wrapper_iterator::process (m);
+ if (!ly_c_vector_p (event_vector_))
+ return ;
+
+ if (event_idx_ < 0)
+ {
+ event_idx_ = binsearch_scm_vector (event_vector_,
+ get_outlet ()->now_mom ().smobbed_copy (),
+ &moment_less);
+ start_moment_ = get_outlet ()->now_mom () - music_start_mom();
+ stop_moment_ = start_moment_ + get_music()->get_length ();
+
+ end_idx_ = binsearch_scm_vector (event_vector_,
+ stop_moment_.smobbed_copy (),
+ &moment_less);
+ }
+
m += start_moment_;
- while (event_idx_ < end_idx_)
+ while (event_idx_ <= end_idx_)
{
- entry = SCM_VECTOR_REF (event_vector_, event_idx_);
-
- Moment em = *unsmob_moment (ly_caar (entry));
-
+ Moment em = vector_moment (event_idx_);
if (em > m)
return ;
event_idx_++;
}
- if (ly_c_pair_p (entry))
+ if (quote_ok ())
{
- Pitch * quote_pitch = unsmob_pitch (ly_cdar (entry));
+ SCM entry = SCM_VECTOR_REF (event_vector_, event_idx_);
+ Pitch * quote_pitch = unsmob_pitch (scm_cdar (entry));
+
+ /*
+ The pitch that sounds like central C
+ */
Pitch * me_pitch = unsmob_pitch (get_outlet ()->get_property ("instrumentTransposition"));
- for (SCM s = ly_cdr (entry); ly_c_pair_p (s); s = ly_cdr (s))
+ for (SCM s = scm_cdr (entry); scm_is_pair (s); s = scm_cdr (s))
{
- SCM ev_acc = ly_car (s);
+ SCM ev_acc = scm_car (s);
- Music * mus = unsmob_music (ly_car (ev_acc));
+ Music * mus = unsmob_music (scm_car (ev_acc));
if (!mus)
programming_error ("need music in quote.");
else if (accept_music_type (mus))
if (me_pitch)
mp = *me_pitch;
- Pitch diff = interval (mp, qp);
+ Pitch diff = pitch_interval (qp, mp);
- SCM copy = ly_deep_mus_copy (mus->self_scm ());
+ SCM copy = ly_music_deep_copy (mus->self_scm ());
mus = unsmob_music (copy);
- transposed_musics_ = scm_cons (copy, transposed_musics_);
- scm_gc_unprotect_object (copy);
-
+ transposed_musics_ = scm_cons (copy, transposed_musics_);
mus->transpose (diff);
}
-
- bool b = get_outlet ()->try_music (mus);
-
+ bool b = quote_outlet_.get_outlet ()->try_music (mus);
if (!b)
mus->origin ()->warning (_f ("In quotation: junking event %s", mus->name ()));
}
}
+
+ event_idx_ ++;
}
- event_idx_ ++;
}
IMPLEMENT_CTOR_CALLBACK (Quote_iterator);