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