]> git.donarmstrong.com Git - lilypond.git/blob - lily/chord-tremolo-engraver.cc
release: 1.3.131
[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--2001 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_p_->set_grob_property ("chord-tremolo", SCM_BOOL_T);
111
112
113           SCM smp = get_property ("measurePosition");
114           Moment mp
115             =  (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
116           beam_start_location_ = mp;
117           announce_grob (beam_p_, repeat_);
118         }
119       else if (!sequential_body_b_ && !stem_tremolo_)
120         {
121           int flags = intlog2(note_head_i_ * repeat_->repeat_count ()) -2;
122           if (flags)
123             {
124               stem_tremolo_ = new Item (get_property ("StemTremolo"));
125               Stem_tremolo::set_interface (stem_tremolo_);
126
127               announce_grob (stem_tremolo_, repeat_);
128               stem_tremolo_->set_grob_property ("tremolo-flags",
129                                                 gh_int2scm (flags));
130
131             }
132         }
133     }
134 }
135 void
136 Chord_tremolo_engraver::finalize ()
137 {
138   typeset_beam ();
139   if (beam_p_)
140     {
141       repeat_->origin ()->warning (_ ("unterminated chord tremolo"));
142       beam_p_->suicide ();
143     }
144 }
145
146 void
147 Chord_tremolo_engraver::typeset_beam ()
148 {
149   if (finished_beam_p_)
150     {
151       typeset_grob (finished_beam_p_);
152       finished_beam_p_ = 0;
153     }
154 }
155
156
157 void
158 Chord_tremolo_engraver::acknowledge_grob (Grob_info info)
159 {
160   if (beam_p_)
161     {
162       if (Stem::has_interface (info.elem_l_))
163         {
164           Grob * s = info.elem_l_;
165           int f = Stem::flag_i (s);
166           f = (f > 2) ? f - 2 : 1;
167           Stem::set_beaming (s, f, LEFT);
168           Stem::set_beaming (s, f, RIGHT);
169           
170           /*
171             URG: this sets the direction of the Stem s.
172             It's amazing Mike:
173             
174               Stem:: type_i () ->first_head ()->get_direction () ->
175                       Directional_element_interface::set (me, d);
176
177
178               don't understand this comment.
179                       --hwn.
180            */
181           SCM d = s->get_grob_property ("direction");
182           if (Stem::type_i (s ) != 1)
183             {
184               int gap_i =Stem::flag_i (s ) - ((Stem::type_i (s ) >? 2) - 2);
185               beam_p_->set_grob_property ("beam-gap", gh_int2scm(gap_i));
186             }
187           s->set_grob_property ("direction", d);
188
189           if (dynamic_cast <Rhythmic_req *> (info.req_l_))
190             {
191               Beam::add_stem (beam_p_, s);
192             }
193           else
194             {
195               String s = _ ("stem must have Rhythmic structure");
196               if (info.req_l_)
197                 info.req_l_->origin ()->warning (s);
198               else
199                 ::warning (s);
200             }
201         }
202     }
203   else if (stem_tremolo_ && Stem::has_interface (info.elem_l_))
204     {
205        Stem_tremolo::set_stem (stem_tremolo_, info.elem_l_);
206
207        info.elem_l_->set_grob_property ("duration-log", gh_int2scm (intlog2 (note_head_i_)));
208     }
209
210   
211   if (repeat_ && Note_head::has_interface (info.elem_l_))
212     {
213       info.elem_l_->set_grob_property ("duration-log", gh_int2scm (intlog2 (note_head_i_)));
214     }
215 }
216
217
218 void
219 Chord_tremolo_engraver::start_translation_timestep ()
220 {
221   if (beam_p_ && stop_mom_ == now_mom ())
222     {
223       finished_beam_p_ = beam_p_;
224
225       repeat_ = 0;
226       beam_p_ = 0;
227     }
228 }
229
230
231 void
232 Chord_tremolo_engraver::stop_translation_timestep ()
233 {
234   typeset_beam ();
235
236   if (stem_tremolo_)
237     {
238       typeset_grob (stem_tremolo_);
239       stem_tremolo_ = 0;
240     }
241   
242 }
243
244 ADD_THIS_TRANSLATOR(Chord_tremolo_engraver);
245