]> git.donarmstrong.com Git - lilypond.git/blob - lily/beam-engraver.cc
7568a7f700de906bb5ff532773ca5cdf6da5987b
[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
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 ("beamquantisation", 0);
107       if (prop.isnum_b ()) 
108         beam_p_->quantisation_ = (Beam::Quantisation)(int)prop;
109  
110       announce_element (Score_element_info (beam_p_, reqs_drul_[START]));
111     }
112 }
113
114 void
115 Beam_engraver::typeset_beam ()
116 {
117   if (finished_beam_p_)
118     {
119       finished_beam_info_p_->beamify ();
120       
121       finished_beam_p_->set_beaming (finished_beam_info_p_);
122       typeset_element (finished_beam_p_);
123       delete finished_beam_info_p_;
124       finished_beam_info_p_ =0;
125       finished_beam_p_ = 0;
126     
127       reqs_drul_[STOP] = 0;
128     }
129 }
130
131 void
132 Beam_engraver::do_post_move_processing ()
133 {
134   reqs_drul_ [START] =0;
135 }
136
137 void
138 Beam_engraver::do_pre_move_processing ()
139 {
140   typeset_beam ();
141 }
142
143 void
144 Beam_engraver::do_removal_processing ()
145 {
146   typeset_beam ();
147   if (beam_p_)
148     {
149       prev_start_req_->warning (_ ("Unfinished beam"));
150       finished_beam_p_ = beam_p_;
151       finished_beam_info_p_ = beam_info_p_;
152       typeset_beam ();
153     }
154 }
155
156 void
157 Beam_engraver::acknowledge_element (Score_element_info info)
158 {
159   if (beam_p_)
160     {
161       Stem* stem_l = dynamic_cast<Stem *> (info.elem_l_);
162       if (!stem_l || stem_l->beam_l_)
163         return;
164
165
166       bool stem_grace = stem_l->get_elt_property (grace_scm_sym) != SCM_BOOL_F;
167
168       if (get_property ("weAreGraceContext",0).to_bool () != stem_grace)
169         return;
170
171       Rhythmic_req *rhythmic_req = dynamic_cast <Rhythmic_req *> (info.req_l_);
172       if (!rhythmic_req)
173         {
174           String s = _ ("Stem must have Rhythmic structure.");
175           if (info.req_l_)
176             info.req_l_->warning (s);
177           else
178             ::warning (s);
179           
180           return;
181         }
182       
183       if (rhythmic_req->duration_.durlog_i_<= 2)
184         {
185           rhythmic_req->warning (_ ("stem doesn't fit in beam"));
186           prev_start_req_->warning (_ ("beam was started here"));
187           return;
188         }
189
190       stem_l->flag_i_ = rhythmic_req->duration_.durlog_i_;
191       Moment stem_location = now_mom () - beam_start_mom_ + beam_start_location_;
192       beam_info_p_->add_stem (stem_location, rhythmic_req->duration_.durlog_i_ - 2);
193       beam_p_->add_stem (stem_l);
194     }
195 }
196
197
198
199 ADD_THIS_TRANSLATOR(Beam_engraver);