]> git.donarmstrong.com Git - lilypond.git/blob - lily/beam-engraver.cc
5ba4ed9306dc1fc0e05d7bf7d7ce9fe5f8b733e7
[lilypond.git] / lily / beam-engraver.cc
1 /*   
2   beam-engraver.cc --  implement Beam_engraver
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 1998--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9 #include "timing-engraver.hh"
10 #include "engraver-group-engraver.hh"
11 #include "beam-engraver.hh"
12 #include "musical-request.hh"
13 #include "beam.hh"
14 #include "stem.hh"
15 #include "warn.hh"
16 #include "time-description.hh"
17 #include "beaming.hh"
18 #include "score-engraver.hh"
19
20 Beam_engraver::Beam_engraver ()
21 {
22   beam_p_ = 0;
23   finished_beam_p_ =0;
24   finished_beam_info_p_=0;
25   beam_info_p_ =0;
26   reqs_drul_[LEFT] = reqs_drul_[RIGHT] =0;
27   prev_start_req_ =0;
28 }
29
30 bool
31 Beam_engraver::do_try_music (Music *m)
32 {
33   if (Span_req * c = dynamic_cast<Span_req*>(m))
34     {
35       if (c->span_type_str_ != "beam")
36         return false;
37       
38       Direction d =c->span_dir_;
39
40       if (d == STOP && !beam_p_)
41         {
42           m->warning (_ ("no beam to end"));
43           return false;
44         }
45       reqs_drul_[d ] = c;
46       return true;
47     }
48   return false;
49 }
50
51
52 void
53 Beam_engraver::do_process_requests ()
54 {
55   if (reqs_drul_[STOP])
56     {
57       if (!beam_p_)
58         reqs_drul_[STOP]->warning (_("no beam to end"));
59       prev_start_req_ =0;
60       finished_beam_p_ = beam_p_;
61       finished_beam_info_p_ = beam_info_p_;
62
63       beam_info_p_ =0;
64       beam_p_ = 0;
65     }
66
67
68   if (beam_p_)
69     {
70       Score_engraver * e = 0;
71       Translator * t  =  daddy_grav_l ();
72       for (; !e && t;  t = t->daddy_trans_l_)
73         {
74           e = dynamic_cast<Score_engraver*> (t);
75         }
76       
77       if (!e)
78         programming_error ("No score engraver!");
79       else
80         e->forbid_breaks ();
81     }
82   
83   if (reqs_drul_[START])
84     {
85       if (beam_p_)
86         {
87           reqs_drul_[START]->warning (_ ("Already have a Beam"));
88           return;
89         }
90
91       prev_start_req_ = reqs_drul_[START];
92       beam_p_ = new Beam;
93
94       Translator * t  = daddy_grav_l  ()->get_simple_translator ("Timing_engraver");
95       Timing_engraver *timer = dynamic_cast<Timing_engraver*> (t);
96       beam_start_location_ = (t) ?  timer->time_.whole_in_measure_ : Moment (0);
97       beam_start_mom_ = now_mom();
98       beam_info_p_ = new Beaming_info_list;
99       
100       
101       /* urg, must copy to Auto_beam_engraver too */
102       Scalar prop = get_property ("beamslopedamping", 0);
103       if (prop.isnum_b ()) 
104         beam_p_->set_elt_property (damping_scm_sym, gh_int2scm( prop));
105       
106       prop = get_property ("autoKneeGap", 0);
107       if (prop.isnum_b ()) 
108         beam_p_->set_elt_property (auto_knee_gap_scm_sym, gh_int2scm( prop));
109       
110       prop = get_property ("autoInterstaffKneeGap", 0);
111       if (prop.isnum_b ()) 
112         beam_p_->set_elt_property (auto_interstaff_knee_gap_scm_sym, gh_int2scm( prop));
113
114       prop = get_property ("beamquantisation", 0);
115       if (prop.isnum_b ()) 
116         beam_p_->quantisation_ = (Beam::Quantisation)(int)prop;
117  
118       announce_element (Score_element_info (beam_p_, reqs_drul_[START]));
119     }
120 }
121
122 void
123 Beam_engraver::typeset_beam ()
124 {
125   if (finished_beam_p_)
126     {
127       finished_beam_info_p_->beamify ();
128       
129       finished_beam_p_->set_beaming (finished_beam_info_p_);
130       typeset_element (finished_beam_p_);
131       delete finished_beam_info_p_;
132       finished_beam_info_p_ =0;
133       finished_beam_p_ = 0;
134     
135       reqs_drul_[STOP] = 0;
136     }
137 }
138
139 void
140 Beam_engraver::do_post_move_processing ()
141 {
142   reqs_drul_ [START] =0;
143 }
144
145 void
146 Beam_engraver::do_pre_move_processing ()
147 {
148   typeset_beam ();
149 }
150
151 void
152 Beam_engraver::do_removal_processing ()
153 {
154   typeset_beam ();
155   if (beam_p_)
156     {
157       prev_start_req_->warning (_ ("unfinished beam"));
158       finished_beam_p_ = beam_p_;
159       finished_beam_info_p_ = beam_info_p_;
160       typeset_beam ();
161     }
162 }
163
164 void
165 Beam_engraver::acknowledge_element (Score_element_info info)
166 {
167   if (beam_p_)
168     {
169       Stem* stem_l = dynamic_cast<Stem *> (info.elem_l_);
170       if (!stem_l || stem_l->beam_l_)
171         return;
172
173
174       bool stem_grace = stem_l->get_elt_property (grace_scm_sym) != SCM_BOOL_F;
175
176       if (get_property ("weAreGraceContext",0).to_bool () != stem_grace)
177         return;
178
179       Rhythmic_req *rhythmic_req = dynamic_cast <Rhythmic_req *> (info.req_l_);
180       if (!rhythmic_req)
181         {
182           String s = _ ("Stem must have Rhythmic structure");
183           if (info.req_l_)
184             info.req_l_->warning (s);
185           else
186             ::warning (s);
187           
188           return;
189         }
190       
191       if (rhythmic_req->duration_.durlog_i_<= 2)
192         {
193           rhythmic_req->warning (_ ("Stem doesn't fit in beam"));
194           prev_start_req_->warning (_ ("Beam was started here"));
195           return;
196         }
197
198       stem_l->flag_i_ = rhythmic_req->duration_.durlog_i_;
199       Moment stem_location = now_mom () - beam_start_mom_ + beam_start_location_;
200       beam_info_p_->add_stem (stem_location, rhythmic_req->duration_.durlog_i_ - 2);
201       beam_p_->add_stem (stem_l);
202     }
203 }
204
205
206
207 ADD_THIS_TRANSLATOR(Beam_engraver);