]> git.donarmstrong.com Git - lilypond.git/blob - lily/grob-pq-engraver.cc
release: 1.5.29
[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--2002  Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "translator-group.hh"
10 #include "engraver.hh"
11 #include "grob.hh"
12 #include "warn.hh"
13
14 struct Grob_mom
15 {
16   Grob * grob_ ;
17   Moment end_;
18   Grob_mom () {}
19   Grob_mom (Grob*gr, Moment e)
20   {
21     grob_ = gr;
22     end_ = e;
23   }
24 };
25
26 int compare  (Grob_mom const &a, Grob_mom const &b)
27 {
28   return Moment::compare (a.end_, b.end_);
29 }
30
31 class Grob_pq_engraver: public Engraver
32 {
33 public:
34   TRANSLATOR_DECLARATIONS(Grob_pq_engraver);
35
36   Array<Grob_mom> current_grobs_;
37 protected:
38   virtual void initialize ();
39   virtual void acknowledge_grob (Grob_info);
40   virtual void start_translation_timestep ();
41   virtual void stop_translation_timestep ();
42 };
43
44
45 Grob_pq_engraver::Grob_pq_engraver()
46 {
47 }
48
49
50 void
51 Grob_pq_engraver::initialize ()
52 {
53   daddy_trans_l_->set_property ("busyGrobs", SCM_EOL); 
54 }
55
56 void
57 Grob_pq_engraver::acknowledge_grob (Grob_info gi)
58 {
59   Music  * m = gi.music_cause ();
60
61   if (m)
62     {
63       Moment n = now_mom ();
64       Moment l = m->length_mom ();
65
66       if (!l.to_bool ())
67         return ;
68       
69       if (n.grace_part_)
70         {
71           l.grace_part_ = l.main_part_;
72           l.main_part_ = 0;
73         }
74
75       current_grobs_.push (Grob_mom (gi.grob_l_, n + l));
76     }
77 }
78
79 void
80 Grob_pq_engraver::stop_translation_timestep ()
81 {
82   Moment now = now_mom();
83
84   current_grobs_.sort (&compare);
85
86   SCM busy = get_property ("busyGrobs");
87   while (gh_pair_p (busy) && *unsmob_moment (gh_caar (busy)) == now)
88     {
89       busy = gh_cdr (busy);
90     }
91   
92   SCM start = busy;
93   SCM * current_cell = &start;
94
95   int  i = 0; 
96   while (i  < current_grobs_.size ())
97     {
98       Moment stop;
99       stop.set_infinite (1);
100       
101       if (gh_pair_p (busy))
102         {
103           SCM h = gh_car (busy);
104           stop = *unsmob_moment (gh_car (h));
105         }
106
107       Moment current_stop = current_grobs_[i].end_;
108       if (current_stop <= stop)
109         {
110           SCM new_entry = gh_cons (current_stop.smobbed_copy(),
111                                    current_grobs_[i].grob_->self_scm ());
112
113           /*
114             Insert before BUSY.
115            */
116           i ++;
117           *current_cell = gh_cons (new_entry, busy);
118           current_cell = SCM_CDRLOC(*current_cell);
119         }
120       else
121         {
122           /*
123             if current_stop > stop, then stop != infty, and we
124             apparently have a next entry */
125           busy = gh_cdr (busy);
126           current_cell = SCM_CDRLOC(*current_cell);
127         }
128     }
129
130   current_grobs_.clear ();
131   daddy_trans_l_->set_property ("busyGrobs", start);
132 }
133
134 void
135 Grob_pq_engraver::start_translation_timestep ()
136 {
137  Moment now = now_mom();
138
139   SCM start_busy = get_property ("busyGrobs");
140   SCM busy = start_busy;
141   while (gh_pair_p (busy) && *unsmob_moment (gh_caar (busy)) < now)
142     {
143       programming_error ("Skipped something ?!");
144       
145       busy = gh_cdr (busy);
146     }
147
148   if (start_busy != busy)
149     daddy_trans_l_->set_property ("busyGrobs", busy);
150 }
151
152
153 ENTER_DESCRIPTION(Grob_pq_engraver,
154 /* descr */       "Administrate when certain grobs (eg. note heads) stop playing.
155 ",
156 /* creats*/       "",
157 /* acks  */       "grob-interface",
158 /* reads */       "busyGrobs",
159 /* write */       "busyGrobs");