2 grob-pq-engraver.cc -- implement Grob_pq_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2001--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
10 #include "engraver.hh"
18 static int compare (Grob_pq_entry const &a,
19 Grob_pq_entry const &b)
21 return Moment::compare (a.end_, b.end_);
25 class Grob_pq_engraver : public Engraver
28 TRANSLATOR_DECLARATIONS (Grob_pq_engraver);
30 virtual void initialize ();
31 virtual void acknowledge_grob (Grob_info);
32 PRECOMPUTED_VIRTUAL void start_translation_timestep ();
33 PRECOMPUTED_VIRTUAL void stop_translation_timestep ();
35 Array<Grob_pq_entry> started_now_;
38 Grob_pq_engraver::Grob_pq_engraver ()
43 Grob_pq_engraver::initialize ()
45 context ()->set_property ("busyGrobs", SCM_EOL);
48 LY_DEFINE (ly_grob_pq_less_p, "ly:grob-pq-less?",
49 2, 0, 0, (SCM a, SCM b),
50 "Compare 2 grob priority queue entries. Internal")
52 if (Moment::compare (*unsmob_moment (scm_car (a)),
53 *unsmob_moment (scm_car (b))) < 0)
60 Grob_pq_engraver::acknowledge_grob (Grob_info gi)
62 Music *m = gi.music_cause ();
65 && !gi.grob ()->internal_has_interface (ly_symbol2scm ("multi-measure-interface")))
67 Moment n = now_mom ();
68 Moment l = m->get_length ();
75 l.grace_part_ = l.main_part_;
85 started_now_.push (e);
90 Grob_pq_engraver::stop_translation_timestep ()
92 Moment now = now_mom ();
93 SCM start_busy = get_property ("busyGrobs");
94 SCM busy = start_busy;
95 while (scm_is_pair (busy) && *unsmob_moment (scm_caar (busy)) == now)
97 busy = scm_cdr (busy);
100 started_now_.sort (Grob_pq_entry::compare);
103 for (int i = 0; i < started_now_.size (); i++)
105 *tail = scm_acons (started_now_[i].end_.smobbed_copy (),
106 started_now_[i].grob_->self_scm (),
108 tail = SCM_CDRLOC(*tail);
111 busy = scm_merge_x (lst, busy, ly_grob_pq_less_p_proc);
112 context ()->set_property ("busyGrobs", busy);
114 started_now_.clear ();
118 Grob_pq_engraver::start_translation_timestep ()
120 Moment now = now_mom ();
122 SCM start_busy = get_property ("busyGrobs");
123 SCM busy = start_busy;
124 while (scm_is_pair (busy) && *unsmob_moment (scm_caar (busy)) < now)
127 The grob-pq-engraver is not water tight, and stuff like
128 tupletSpannerDuration confuses it.
130 busy = scm_cdr (busy);
133 if (start_busy != busy)
134 context ()->set_property ("busyGrobs", busy);
137 #include "translator.icc"
139 ADD_TRANSLATOR (Grob_pq_engraver,
141 /* descr */ "Administrate when certain grobs (eg. note heads) stop playing",
144 /* acks */ "grob-interface",
145 /* reads */ "busyGrobs",
146 /* write */ "busyGrobs");