]> git.donarmstrong.com Git - lilypond.git/blob - lily/beam-engraver.cc
patch::: 1.3.18.jcn1
[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
10 #include "timing-engraver.hh"
11 #include "engraver-group-engraver.hh"
12 #include "beam-engraver.hh"
13 #include "musical-request.hh"
14 #include "beam.hh"
15 #include "stem.hh"
16 #include "warn.hh"
17 #include "timing-translator.hh"
18 #include "beaming.hh"
19 #include "score-engraver.hh"
20
21 ADD_THIS_TRANSLATOR (Beam_engraver);
22
23 Beam_engraver::Beam_engraver ()
24 {
25   beam_p_ = 0;
26   finished_beam_p_ =0;
27   finished_beam_info_p_=0;
28   beam_info_p_ =0;
29   reqs_drul_[LEFT] = reqs_drul_[RIGHT] =0;
30   prev_start_req_ =0;
31 }
32
33 bool
34 Beam_engraver::do_try_music (Music *m)
35 {
36   if (Span_req * c = dynamic_cast<Span_req*>(m))
37     {
38       if (c->span_type_str_ != "beam")
39         return false;
40       
41       Direction d =c->span_dir_;
42
43       if (d == STOP && !beam_p_)
44         {
45           m->warning (_ ("no beam to end"));
46           return false;
47         }
48       reqs_drul_[d ] = c;
49       return true;
50     }
51   return false;
52 }
53
54
55 void
56 Beam_engraver::do_process_requests ()
57 {
58   if (reqs_drul_[STOP])
59     {
60       if (!beam_p_)
61         reqs_drul_[STOP]->warning (_("no beam to end"));
62       prev_start_req_ =0;
63       finished_beam_p_ = beam_p_;
64       finished_beam_info_p_ = beam_info_p_;
65
66       beam_info_p_ =0;
67       beam_p_ = 0;
68     }
69
70
71   if (beam_p_)
72     {
73       Score_engraver * e = 0;
74       Translator * t  =  daddy_grav_l ();
75       for (; !e && t;  t = t->daddy_trans_l_)
76         {
77           e = dynamic_cast<Score_engraver*> (t);
78         }
79       
80       if (!e)
81         programming_error ("No score engraver!");
82       else
83         e->forbid_breaks ();
84     }
85   
86   if (reqs_drul_[START])
87     {
88       if (beam_p_)
89         {
90           reqs_drul_[START]->warning (_ ("Already have a beam"));
91           return;
92         }
93
94       prev_start_req_ = reqs_drul_[START];
95       beam_p_ = new Beam;
96
97       Translator * t  = daddy_grav_l  ()->get_simple_translator ("Timing_engraver");
98       Timing_engraver *timer = dynamic_cast<Timing_engraver*> (t);
99       beam_start_location_ = (t) ?  timer->measure_position () : Moment (0);
100       beam_start_mom_ = now_mom();
101       beam_info_p_ = new Beaming_info_list;
102       
103       
104       /* urg, must copy to Auto_beam_engraver too */
105  
106       announce_element (Score_element_info (beam_p_, reqs_drul_[START]));
107     }
108 }
109
110 void
111 Beam_engraver::typeset_beam ()
112 {
113   if (finished_beam_p_)
114     {
115       finished_beam_info_p_->beamify ();
116       
117       finished_beam_p_->set_beaming (finished_beam_info_p_);
118       typeset_element (finished_beam_p_);
119       delete finished_beam_info_p_;
120       finished_beam_info_p_ =0;
121       finished_beam_p_ = 0;
122     
123       reqs_drul_[STOP] = 0;
124     }
125 }
126
127 void
128 Beam_engraver::do_post_move_processing ()
129 {
130   reqs_drul_ [START] =0;
131 }
132
133 void
134 Beam_engraver::do_pre_move_processing ()
135 {
136   typeset_beam ();
137 }
138
139 void
140 Beam_engraver::do_removal_processing ()
141 {
142   typeset_beam ();
143   if (beam_p_)
144     {
145       prev_start_req_->warning (_ ("unfinished beam"));
146       finished_beam_p_ = beam_p_;
147       finished_beam_info_p_ = beam_info_p_;
148       typeset_beam ();
149     }
150 }
151
152 void
153 Beam_engraver::acknowledge_element (Score_element_info info)
154 {
155   if (beam_p_)
156     {
157       Stem* stem_l = dynamic_cast<Stem *> (info.elem_l_);
158       if (!stem_l || stem_l->beam_l ())
159         return;
160
161
162       bool stem_grace = stem_l->get_elt_property ("grace") == SCM_BOOL_T;
163
164       SCM wg =get_property ("weAreGraceContext",0);
165       bool wgb= to_boolean (wg);
166
167       if (wgb!= stem_grace)
168         return;
169
170       Rhythmic_req *rhythmic_req = dynamic_cast <Rhythmic_req *> (info.req_l_);
171       if (!rhythmic_req)
172         {
173           String s = _ ("Stem must have Rhythmic structure");
174           if (info.req_l_)
175             info.req_l_->warning (s);
176           else
177             ::warning (s);
178           
179           return;
180         }
181       
182       if (rhythmic_req->duration_.durlog_i_<= 2)
183         {
184           rhythmic_req->warning (_ ("Stem doesn't fit in beam"));
185           prev_start_req_->warning (_ ("Beam was started here"));
186           return;
187         }
188
189       stem_l->set_elt_property ("duration-log",
190                                 gh_int2scm (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