]> git.donarmstrong.com Git - lilypond.git/blob - lily/chord-tremolo-engraver.cc
291133c50e60aecb86bc4b87da793b646b1cc59d
[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 "note-head.hh"
15 #include "engraver-group-engraver.hh"
16 #include "musical-request.hh"
17 #include "warn.hh"
18 #include "misc.hh"
19
20 /**
21   This acknowledges repeated music with "tremolo" style.  It typesets
22   a beam.
23
24   TODO:
25
26   - perhaps use engraver this to steer other engravers? That would
27   create dependencies between engravers, which is bad.
28
29   - create dots if appropriate.
30
31  */
32
33 class Chord_tremolo_engraver : public Engraver
34 {
35   void typeset_beam ();
36 public:
37   VIRTUAL_COPY_CONS(Translator);
38   Chord_tremolo_engraver();
39 protected:
40   Repeated_music * repeat_;
41
42   /// moment (global time) where beam started.
43   Moment start_mom_;
44   Moment stop_mom_;
45
46   /// location  within measure where beam started.
47   Moment beam_start_location_;
48
49   int note_head_i_;
50   
51   Beam * beam_p_;
52   Beam * finished_beam_p_;
53   
54 protected:
55   virtual void do_removal_processing();
56   virtual void do_process_music();
57   virtual bool do_try_music (Music*);
58   virtual void acknowledge_element (Score_element_info);
59   virtual void do_pre_move_processing();
60   virtual void do_post_move_processing();
61 };
62
63 Chord_tremolo_engraver::Chord_tremolo_engraver()
64 {
65   beam_p_  = finished_beam_p_ = 0;
66   repeat_ =0;
67   note_head_i_ = 0;
68 }
69
70 bool
71 Chord_tremolo_engraver::do_try_music (Music * m)
72 {
73   Repeated_music * rp = dynamic_cast<Repeated_music*> (m);
74   if (rp && rp->type_ == "tremolo" && !repeat_) 
75     {
76       Moment l = rp->body_length_mom ();
77       repeat_ = rp;
78       start_mom_ = now_mom ();
79       stop_mom_ = start_mom_ + l;
80
81       // ugh. should generate dots, triplet beams.      
82       note_head_i_ = l.den () <? 4; 
83       return true;
84     }
85   return false;
86 }
87
88 void
89 Chord_tremolo_engraver::do_process_music ()
90 {
91   if (repeat_ && !beam_p_)
92     {
93       beam_p_ = new Beam;
94       beam_p_->set_elt_property ("chord-tremolo", SCM_BOOL_T);
95
96
97       SCM smp = get_property ("measurePosition");
98       Moment mp =  (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
99       beam_start_location_ = mp;
100       announce_element (Score_element_info (beam_p_, repeat_));
101     }
102 }
103
104
105 void
106 Chord_tremolo_engraver::do_removal_processing ()
107 {
108   typeset_beam ();
109   if (beam_p_)
110     {
111       repeat_->warning (_ ("unterminated chord tremolo"));
112       finished_beam_p_ = beam_p_;
113       typeset_beam ();
114     }
115 }
116
117 void
118 Chord_tremolo_engraver::typeset_beam ()
119 {
120   if (finished_beam_p_)
121     {
122       typeset_element (finished_beam_p_);
123       finished_beam_p_ = 0;
124     }
125 }
126
127
128 void
129 Chord_tremolo_engraver::acknowledge_element (Score_element_info info)
130 {
131   if (beam_p_)
132     {
133       if (Stem* s = dynamic_cast<Stem *> (info.elem_l_))
134         {
135           int f = s->flag_i ();
136           f = (f > 2) ? f - 2 : 1;
137           s->set_beaming (f, LEFT);
138           s->set_beaming (f, RIGHT);
139           
140           /*
141             URG: this sets the direction of the Stem s.
142             It's amazing Mike:
143             
144               Stem:: type_i () ->first_head ()->get_direction () ->
145                       directional_element (me).set (d);
146
147
148               don't understand this comment.
149                       --hwn.
150            */
151           SCM d = s->get_elt_property ("direction");
152           if (s->type_i () != 1)
153             {
154               int gap_i =s->flag_i () - ((s->type_i () >? 2) - 2);
155               beam_p_->set_elt_property ("beam-gap", gh_int2scm(gap_i));
156             }
157           s->set_elt_property ("direction", d);
158
159           if (Rhythmic_req* r = dynamic_cast <Rhythmic_req *> (info.req_l_))
160             {
161               beam_p_->add_stem (s);
162               Moment stem_location = now_mom () -
163                 start_mom_ + beam_start_location_;
164             }
165           else
166             {
167               String s = _ ("stem must have Rhythmic structure");
168               if (info.req_l_)
169                 info.req_l_->warning (s);
170               else
171                 ::warning (s);
172             }
173         }
174       if (Note_head *nh = dynamic_cast<Note_head*> (info.elem_l_))
175         {
176           nh->set_elt_property ("duration-log", gh_int2scm (intlog2 (note_head_i_)));
177         }
178     }
179 }
180
181
182 void
183 Chord_tremolo_engraver::do_post_move_processing ()
184 {
185   if (beam_p_ && stop_mom_ == now_mom ())
186     {
187       finished_beam_p_ = beam_p_;
188
189       repeat_ = 0;
190       beam_p_ = 0;
191     }
192 }
193
194
195 void
196 Chord_tremolo_engraver::do_pre_move_processing ()
197 {
198   typeset_beam ();
199 }
200
201 ADD_THIS_TRANSLATOR(Chord_tremolo_engraver);
202