]> git.donarmstrong.com Git - lilypond.git/blob - lily/slur-engraver.cc
* lily/part-combine-engraver.cc: rename soloADue ->
[lilypond.git] / lily / slur-engraver.cc
1 /*
2   slur-engraver.cc -- implement Slur_engraver
3
4   (c) 1997--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
5 */
6
7 #include "event.hh"
8 #include "new-slur.hh"
9 #include "warn.hh"
10 #include "note-column.hh"
11 #include "context.hh"
12
13 #include "engraver.hh"
14 #include "spanner.hh"
15
16 /*
17   It is possible that a slur starts and ends on the same note.  At
18   least, it is for phrasing slurs: a note can be both beginning and
19   ending of a phrase.
20  */
21
22 class Slur_engraver : public Engraver
23 {
24   Drul_array<Music *> events_;
25   Music * running_slur_start_;
26   Grob * slur_;
27   Grob * end_slur_;
28
29   Moment last_start_;
30
31   void set_melisma (bool);
32
33 protected:
34   virtual bool try_music (Music*);
35   virtual void acknowledge_grob (Grob_info);
36   virtual void stop_translation_timestep ();
37   virtual void finalize ();
38   virtual void process_music ();
39
40 public:
41   TRANSLATOR_DECLARATIONS (Slur_engraver);
42 };
43
44 Slur_engraver::Slur_engraver ()
45 {
46   events_[START] =events_[STOP] = 0;
47   end_slur_ = slur_ = 0;
48   last_start_ = Moment (-1);
49 }
50
51 bool
52 Slur_engraver::try_music (Music *m)
53 {
54   if (m->is_mus_type ("slur-event"))
55     {
56       /*
57         Let's not start more than one slur per moment.
58       */
59       Direction d = to_dir (m->get_property ("span-direction"));
60       if (d == START)
61         {
62           if (slur_)
63             return false;
64           
65           events_[START] = m;
66           return true;
67         }
68       else if (d == STOP)
69         {
70           if (!slur_)
71             return false;
72           
73           events_[STOP] = m;
74           return true;
75         }
76     }
77   return false;
78 }
79
80 void
81 Slur_engraver::set_melisma (bool m)
82 {
83   context ()->set_property ("slurMelismaBusy", m ? SCM_BOOL_T :SCM_BOOL_F);
84 }
85
86 void
87 Slur_engraver::acknowledge_grob (Grob_info info)
88 {
89   Grob *e =info.grob_;
90   if (Note_column::has_interface (info.grob_))
91     {
92       if (slur_)
93         New_slur::add_column (slur_, e);
94       if (end_slur_)
95         New_slur::add_column (end_slur_, e);
96     }
97   else
98     {
99       if (slur_)
100         New_slur::add_extra_encompass (slur_, e);
101       if (end_slur_)
102         New_slur::add_extra_encompass (end_slur_, e);
103     }
104 }
105
106 void
107 Slur_engraver::finalize ()
108 {
109   if (slur_)
110     slur_->warning (_("unterminated slur"));
111 }
112
113 void
114 Slur_engraver::process_music ()
115 {
116   if (events_[STOP])
117     {
118       end_slur_ = slur_;
119       slur_ = 0;
120     }
121   
122   if (events_[START] && !slur_)
123     {
124       Music *ev = events_[START];
125       slur_ = make_spanner ("Slur", events_[START]->self_scm ());
126       if (Direction updown = to_dir (ev->get_property ("direction")))
127         slur_->set_property ("direction", scm_int2num (updown));
128     }
129
130   set_melisma (slur_);
131 }
132
133 void
134 Slur_engraver::stop_translation_timestep ()
135 {
136   end_slur_ = 0;
137   events_[START] = events_[STOP] = 0;
138 }
139
140 ENTER_DESCRIPTION (Slur_engraver,
141 /* descr */       "Build slurs grobs from slur events",
142 /* creats*/       "Slur",
143 /* accepts */     "slur-event",
144 /* acks  */      "note-column-interface accidental-interface fingering-interface script-interface",
145 /* reads */       "slurMelismaBusy",
146 /* write */       "");