]> git.donarmstrong.com Git - lilypond.git/blob - lily/grob-pq-engraver.cc
* lily/text-item.cc (interpret_string): new file, select font with
[lilypond.git] / lily / grob-pq-engraver.cc
1 /*   
2   grob-pq-engraver.cc --  implement Grob_pq_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2001--2004  Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "context.hh"
10 #include "engraver.hh"
11 #include "grob.hh"
12 #include "warn.hh"
13
14 class Grob_pq_engraver: public Engraver
15 {
16 public:
17   TRANSLATOR_DECLARATIONS (Grob_pq_engraver);
18 protected:
19   virtual void initialize ();
20   virtual void acknowledge_grob (Grob_info);
21   virtual void start_translation_timestep ();
22   virtual void stop_translation_timestep ();
23 };
24
25
26 Grob_pq_engraver::Grob_pq_engraver ()
27 {
28 }
29
30 void
31 Grob_pq_engraver::initialize ()
32 {
33   daddy_context_->set_property ("busyGrobs", SCM_EOL); 
34 }
35
36 LY_DEFINE (ly_grob_pq_less_p, "ly:grob-pq-less?",
37           2, 0 ,0, (SCM a, SCM b), 
38           "Compare 2 grob priority queue entries. Internal")
39 {
40   if (Moment::compare (*unsmob_moment (ly_car (a)),
41                        *unsmob_moment (ly_car (b))) < 0)
42     return SCM_BOOL_T;
43   else
44     return SCM_BOOL_F;
45 }
46           
47 void
48 Grob_pq_engraver::acknowledge_grob (Grob_info gi)
49 {
50   Music  * m = gi.music_cause ();
51
52   if (m
53       && !gi.grob_->internal_has_interface (ly_symbol2scm ("multi-measure-interface")))
54     {
55       Moment n = now_mom ();
56       Moment l = m->get_length ();
57
58       if (!l.to_bool ())
59         return ;
60       
61       if (n.grace_part_)
62         {
63           l.grace_part_ = l.main_part_;
64           l.main_part_ = 0;
65         }
66
67       Moment end = n + l;
68       SCM lst = scm_acons (end.smobbed_copy (),
69                          gi.grob_->self_scm (),
70                          SCM_EOL);
71
72       SCM busy= get_property ("busyGrobs");
73       busy = scm_merge_x (lst, busy, ly_grob_pq_less_p_proc);
74       daddy_context_->set_property ("busyGrobs", busy);
75     }
76 }
77
78
79 void
80 Grob_pq_engraver::stop_translation_timestep ()
81 {
82   Moment now = now_mom ();
83   SCM start_busy = get_property ("busyGrobs");
84   SCM busy = start_busy;
85   while (is_pair (busy) && *unsmob_moment (ly_caar (busy)) == now)
86     {
87       busy = ly_cdr (busy);
88     }
89
90   if (start_busy != busy)
91     daddy_context_->set_property ("busyGrobs", busy);
92 }
93
94 void
95 Grob_pq_engraver::start_translation_timestep ()
96 {
97   Moment now = now_mom ();
98
99   SCM start_busy = get_property ("busyGrobs");
100   SCM busy = start_busy;
101   while (is_pair (busy) && *unsmob_moment (ly_caar (busy)) < now)
102     {
103       /*
104         The grob-pq-engraver is not water tight, and stuff like
105         tupletSpannerDuration confuses it.
106        */
107       busy = ly_cdr (busy);
108     }
109
110   if (start_busy != busy)
111     daddy_context_->set_property ("busyGrobs", busy);
112 }
113
114
115 ENTER_DESCRIPTION (Grob_pq_engraver,
116
117 /* descr */       "Administrate when certain grobs (eg. note heads) stop playing; this \
118 engraver is a sort-of a failure, since it doesn't handle all sorts of \
119 borderline cases very well. \
120 ",                                                                                                \
121                   
122 /* creats*/       "",                                                                             \
123 /* accepts */     "",                                                                             \
124 /* acks  */      "grob-interface",                                                                \
125 /* reads */       "busyGrobs",                                                                    \
126 /* write */       "busyGrobs");