]> git.donarmstrong.com Git - lilypond.git/blob - lily/chord-tremolo-engraver.cc
release: 1.3.128
[lilypond.git] / lily / chord-tremolo-engraver.cc
1 /*   
2   new-chord-tremolo-engraver.cc --  implement Chord_tremolo_engraver
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9
10 #include "engraver.hh"
11 #include "beam.hh"
12 #include "repeated-music.hh"
13 #include "stem.hh"
14 #include "rhythmic-head.hh"
15 #include "engraver-group-engraver.hh"
16 #include "musical-request.hh"
17 #include "warn.hh"
18 #include "misc.hh"
19 #include "note-head.hh"
20 #include "spanner.hh"
21 #include "item.hh"
22 #include "chord-tremolo-iterator.hh"
23 #include "stem-tremolo.hh"
24 #include "music-list.hh"
25
26 /**
27   This acknowledges repeated music with "tremolo" style.  It typesets
28   a beam.
29
30   TODO:
31
32   - perhaps use engraver this to steer other engravers? That would
33   create dependencies between engravers, which is bad.
34
35   - create dots if appropriate.
36
37   - create  TremoloBeam iso Beam?
38  */
39
40 class Chord_tremolo_engraver : public Engraver
41 {
42   void typeset_beam ();
43 public:
44   VIRTUAL_COPY_CONS(Translator);
45   Chord_tremolo_engraver();
46 protected:
47   Repeated_music * repeat_;
48
49   /// moment (global time) where beam started.
50   Moment start_mom_;
51   Moment stop_mom_;
52
53   /// location  within measure where beam started.
54   Moment beam_start_location_;
55
56   int note_head_i_;
57
58   bool sequential_body_b_;
59   Spanner * beam_p_;
60   Spanner * finished_beam_p_;
61   Item * stem_tremolo_;
62 protected:
63   virtual void finalize();
64   virtual bool try_music (Music*);
65   virtual void acknowledge_grob (Grob_info);
66   virtual void stop_translation_timestep();
67   virtual void start_translation_timestep();
68   virtual void process_music ();
69 };
70
71 Chord_tremolo_engraver::Chord_tremolo_engraver()
72 {
73   beam_p_  = finished_beam_p_ = 0;
74   repeat_ =0;
75   note_head_i_ = 0;
76   stem_tremolo_ = 0;
77   sequential_body_b_ = false;
78 }
79
80 bool
81 Chord_tremolo_engraver::try_music (Music * m)
82 {
83   Repeated_music * rp = dynamic_cast<Repeated_music*> (m);
84   if (rp
85       && rp->get_mus_property ("iterator-ctor") == Chord_tremolo_iterator::constructor_cxx_function
86       && !repeat_) 
87     {
88       Moment l = rp->length_mom ();
89       repeat_ = rp;
90       start_mom_ = now_mom ();
91       stop_mom_ = start_mom_ + l;
92       sequential_body_b_ = dynamic_cast<Sequential_music*> (rp->body ());
93
94       // ugh. should generate dots, triplet beams.      
95       note_head_i_ = l.den () <? 4; 
96       return true;
97     }
98
99   return false;
100 }
101
102 void
103 Chord_tremolo_engraver::process_music ()
104 {
105   if (repeat_)
106     {
107       if (sequential_body_b_ && !beam_p_)
108         {
109           beam_p_ = new Spanner (get_property ("Beam"));
110           Beam::set_interface (beam_p_);
111           beam_p_->set_grob_property ("chord-tremolo", SCM_BOOL_T);
112
113
114           SCM smp = get_property ("measurePosition");
115           Moment mp
116             =  (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
117           beam_start_location_ = mp;
118           announce_grob (beam_p_, repeat_);
119         }
120       else if (!sequential_body_b_ && !stem_tremolo_)
121         {
122           int flags = intlog2(note_head_i_ * repeat_->repeat_count ()) -2;
123           if (flags)
124             {
125               stem_tremolo_ = new Item (get_property ("StemTremolo"));
126               Stem_tremolo::set_interface (stem_tremolo_);
127
128               announce_grob (stem_tremolo_, repeat_);
129               stem_tremolo_->set_grob_property ("tremolo-flags",
130                                                 gh_int2scm (flags));
131
132             }
133         }
134     }
135 }
136 void
137 Chord_tremolo_engraver::finalize ()
138 {
139   typeset_beam ();
140   if (beam_p_)
141     {
142       repeat_->origin ()->warning (_ ("unterminated chord tremolo"));
143       beam_p_->suicide ();
144     }
145 }
146
147 void
148 Chord_tremolo_engraver::typeset_beam ()
149 {
150   if (finished_beam_p_)
151     {
152       typeset_grob (finished_beam_p_);
153       finished_beam_p_ = 0;
154     }
155 }
156
157
158 void
159 Chord_tremolo_engraver::acknowledge_grob (Grob_info info)
160 {
161   if (beam_p_)
162     {
163       if (Stem::has_interface (info.elem_l_))
164         {
165           Grob * s = info.elem_l_;
166           int f = Stem::flag_i (s);
167           f = (f > 2) ? f - 2 : 1;
168           Stem::set_beaming (s, f, LEFT);
169           Stem::set_beaming (s, f, RIGHT);
170           
171           /*
172             URG: this sets the direction of the Stem s.
173             It's amazing Mike:
174             
175               Stem:: type_i () ->first_head ()->get_direction () ->
176                       Directional_element_interface::set (me, d);
177
178
179               don't understand this comment.
180                       --hwn.
181            */
182           SCM d = s->get_grob_property ("direction");
183           if (Stem::type_i (s ) != 1)
184             {
185               int gap_i =Stem::flag_i (s ) - ((Stem::type_i (s ) >? 2) - 2);
186               beam_p_->set_grob_property ("beam-gap", gh_int2scm(gap_i));
187             }
188           s->set_grob_property ("direction", d);
189
190           if (dynamic_cast <Rhythmic_req *> (info.req_l_))
191             {
192               Beam::add_stem (beam_p_, s);
193             }
194           else
195             {
196               String s = _ ("stem must have Rhythmic structure");
197               if (info.req_l_)
198                 info.req_l_->origin ()->warning (s);
199               else
200                 ::warning (s);
201             }
202         }
203     }
204   else if (stem_tremolo_ && Stem::has_interface (info.elem_l_))
205     {
206        Stem_tremolo::set_stem (stem_tremolo_, info.elem_l_);
207
208        info.elem_l_->set_grob_property ("duration-log", gh_int2scm (intlog2 (note_head_i_)));
209     }
210
211   
212   if (repeat_ && Note_head::has_interface (info.elem_l_))
213     {
214       info.elem_l_->set_grob_property ("duration-log", gh_int2scm (intlog2 (note_head_i_)));
215     }
216 }
217
218
219 void
220 Chord_tremolo_engraver::start_translation_timestep ()
221 {
222   if (beam_p_ && stop_mom_ == now_mom ())
223     {
224       finished_beam_p_ = beam_p_;
225
226       repeat_ = 0;
227       beam_p_ = 0;
228     }
229 }
230
231
232 void
233 Chord_tremolo_engraver::stop_translation_timestep ()
234 {
235   typeset_beam ();
236
237   if (stem_tremolo_)
238     {
239       typeset_grob (stem_tremolo_);
240       stem_tremolo_ = 0;
241     }
242   
243 }
244
245 ADD_THIS_TRANSLATOR(Chord_tremolo_engraver);
246