]> git.donarmstrong.com Git - lilypond.git/blob - lily/phrasing-slur-engraver.cc
* scm/engraver-documentation-lib.scm
[lilypond.git] / lily / phrasing-slur-engraver.cc
1 /*
2   phrasing-slur-engraver.cc -- implement Phrasing_slur_engraver
3
4   (c)  1997--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
5 */
6
7 #include "request.hh"
8 #include "slur.hh"
9 #include "warn.hh"
10 #include "note-column.hh"
11 #include "translator-group.hh"
12 #include "engraver.hh"
13 #include "spanner.hh"
14
15 class Phrasing_slur_engraver : public Engraver
16 {
17   Link_array<Music> requestses_;
18   Link_array<Music> new_phrasing_slur_reqs_;
19   Link_array<Grob> phrasing_slur_l_stack_;
20   Link_array<Grob> end_phrasing_slurs_;
21   Moment last_start_;
22
23 protected:
24   virtual bool try_music (Music*);
25   virtual void acknowledge_grob (Grob_info);
26   virtual void stop_translation_timestep ();
27   virtual void start_translation_timestep ();
28   virtual void finalize ();
29   virtual void process_acknowledged_grobs ();
30
31 public:
32   TRANSLATOR_DECLARATIONS(Phrasing_slur_engraver);
33   
34 };
35
36 Phrasing_slur_engraver::Phrasing_slur_engraver ()
37 {
38   last_start_ = Moment (-1);
39 }
40
41 bool
42 Phrasing_slur_engraver::try_music (Music *req)
43 {
44   if (req->is_mus_type ("abort-event"))
45     {
46           for (int i = 0; i < phrasing_slur_l_stack_.size (); i++)
47             {
48               phrasing_slur_l_stack_[i]->suicide ();
49             }
50           phrasing_slur_l_stack_.clear ();
51           for (int i = 0; i < end_phrasing_slurs_.size (); i++)
52             {
53               end_phrasing_slurs_[i]->suicide ();
54             }
55           end_phrasing_slurs_.clear ();
56           requestses_.clear ();
57           new_phrasing_slur_reqs_.clear ();
58     }
59   else if (req->is_mus_type ("phrasing-slur-event"))
60     {
61       /*
62         Let's not start more than one phrasing slur per moment.
63       */
64       
65     Direction d = to_dir (req->get_mus_property ("span-direction"));
66           
67       if (d == START)
68         {
69           if (now_mom () > last_start_)
70             {
71               new_phrasing_slur_reqs_.push (req);
72               last_start_ = now_mom ();
73               return true;
74             }
75         }
76       else
77         {
78           new_phrasing_slur_reqs_.push (req);
79           return true;
80         }
81     }
82   return false;
83 }
84
85 void
86 Phrasing_slur_engraver::acknowledge_grob (Grob_info info)
87 {
88   if (Note_column::has_interface (info.grob_))
89     {
90       Grob *e =info.grob_;
91       for (int i = 0; i < phrasing_slur_l_stack_.size (); i++)
92         Slur::add_column (phrasing_slur_l_stack_[i], e);
93       for (int i = 0; i < end_phrasing_slurs_.size (); i++)
94         Slur::add_column (end_phrasing_slurs_[i], e);
95     }
96 }
97
98 void
99 Phrasing_slur_engraver::finalize ()
100 {
101   for (int i = 0; i < phrasing_slur_l_stack_.size (); i++)
102     {
103 #if 0
104       typeset_grob (phrasing_slur_l_stack_[i]);
105 #else
106       /*
107         Let's not typeset unterminated stuff
108        */
109       phrasing_slur_l_stack_[i]->suicide ();
110 #endif     
111     }
112   phrasing_slur_l_stack_.clear ();
113
114     for (int i=0; i < requestses_.size (); i++)
115       {
116         requestses_[i]->origin ()->warning (_ ("unterminated phrasing slur"));
117       }
118 }
119
120 void
121 Phrasing_slur_engraver::process_acknowledged_grobs ()
122 {
123   Link_array<Grob> start_phrasing_slurs;
124   for (int i=0; i< new_phrasing_slur_reqs_.size (); i++)
125     {
126       Music* phrasing_slur_req = new_phrasing_slur_reqs_[i];
127       // end phrasing slur: move the phrasing slur to other array
128
129       Direction d = to_dir (phrasing_slur_req->get_mus_property ("span-direction"));
130       
131       if (d == STOP)
132         {
133           if (phrasing_slur_l_stack_.empty ())
134             phrasing_slur_req->origin ()->warning (_f ("can't find start of phrasing slur"));
135           else
136             {
137               Grob* phrasing_slur = phrasing_slur_l_stack_.pop ();
138               end_phrasing_slurs_.push (phrasing_slur);
139               requestses_.pop ();
140             }
141         }
142       else if (d == START)
143         {
144           // push a new phrasing_slur onto stack.
145           // (use temp. array to wait for all phrasing_slur STOPs)
146           Grob* phrasing_slur = new Spanner (get_property ("PhrasingSlur"));
147           Slur::set_interface (phrasing_slur); // can't remove.
148           start_phrasing_slurs.push (phrasing_slur);
149           requestses_.push (phrasing_slur_req);
150           announce_grob(phrasing_slur, phrasing_slur_req->self_scm());
151         }
152     }
153   for (int i=0; i < start_phrasing_slurs.size (); i++)
154     phrasing_slur_l_stack_.push (start_phrasing_slurs[i]);
155   new_phrasing_slur_reqs_.clear ();
156 }
157
158 void
159 Phrasing_slur_engraver::stop_translation_timestep ()
160 {
161   for (int i = 0; i < end_phrasing_slurs_.size (); i++)
162     {
163       typeset_grob (end_phrasing_slurs_[i]);
164     }
165   end_phrasing_slurs_.clear ();
166 }
167
168 void
169 Phrasing_slur_engraver::start_translation_timestep ()
170 {
171   new_phrasing_slur_reqs_.clear ();
172 }
173
174
175
176 ENTER_DESCRIPTION(Phrasing_slur_engraver,
177 /* descr */       "Print phrasing slurs. Similar to Slur_engraver",
178 /* creats*/       "PhrasingSlur",
179 /* accepts */     "phrasing-slur-event",
180 /* acks  */       "note-column-interface",
181 /* reads */       "slurMelismaBusy",
182 /* write */       "");