]> git.donarmstrong.com Git - lilypond.git/blob - lily/slur-engraver.cc
(try_music): ignore slurs_. Otherwise we
[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 "note-column.hh"
10 #include "context.hh"
11 #include "directional-element-interface.hh"
12 #include "engraver.hh"
13 #include "spanner.hh"
14 #include "tie.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   Link_array<Grob> slurs_;
27   Link_array<Grob> end_slurs_;
28
29   void set_melisma (bool);
30
31 protected:
32   virtual bool try_music (Music*);
33   virtual void acknowledge_grob (Grob_info);
34   virtual void stop_translation_timestep ();
35   virtual void finalize ();
36   virtual void process_music ();
37
38 public:
39   TRANSLATOR_DECLARATIONS (Slur_engraver);
40 };
41
42 Slur_engraver::Slur_engraver ()
43 {
44   events_[START] =events_[STOP] = 0;
45 }
46
47 bool
48 Slur_engraver::try_music (Music *m)
49 {
50   if (m->is_mus_type ("slur-event"))
51     {
52       Direction d = to_dir (m->get_property ("span-direction"));
53       if (d == START)
54         {
55           events_[START] = m;
56           return true;
57         }
58       else if (d == STOP)
59         {
60           events_[STOP] = m;
61           return true;
62         }
63     }
64   return false;
65 }
66
67 void
68 Slur_engraver::set_melisma (bool m)
69 {
70   context ()->set_property ("slurMelismaBusy", m ? SCM_BOOL_T :SCM_BOOL_F);
71 }
72
73 void
74 Slur_engraver::acknowledge_grob (Grob_info info)
75 {
76   Grob *e =info.grob_;
77   if (Note_column::has_interface (info.grob_))
78     {
79       for (int i = slurs_.size (); i--; )
80         New_slur::add_column (slurs_[i], e);
81       for (int i = end_slurs_.size (); i-- ; )
82         New_slur::add_column (end_slurs_[i], e);
83     }
84   else
85     {
86       SCM inside = e->get_property ("inside-slur");
87       if (Tie::has_interface (e)
88           || to_boolean (inside))
89         {
90           for (int i = slurs_.size (); i--; )
91             New_slur::add_extra_encompass (slurs_[i], e);
92           for (int i = end_slurs_.size (); i--; )
93             New_slur::add_extra_encompass (end_slurs_[i], e);
94         }
95       else if (inside == SCM_BOOL_F)
96         {
97           Grob *slur = slurs_.size()?slurs_[0] : 0;
98           slur =  (end_slurs_.size () && !slur)
99             ? end_slurs_[0] : slur;
100
101           if (slur)
102             {
103               e->add_offset_callback (New_slur::outside_slur_callback_proc, Y_AXIS);
104               e->set_property ("slur", slur->self_scm());
105             }
106         }
107     }
108 }
109
110 void
111 Slur_engraver::finalize ()
112 {
113   if (slurs_.size ())
114     slurs_[0]->warning (_("unterminated slur"));
115 }
116
117 void
118 Slur_engraver::process_music ()
119 {
120   if (events_[STOP])
121     {
122       end_slurs_ = slurs_;
123       slurs_.clear ();
124     }
125   
126   if (events_[START] && slurs_.is_empty ())
127     {
128       Music *ev = events_[START];
129
130       bool double_slurs = to_boolean (get_property ("doubleSlurs"));
131
132       Grob * slur = make_spanner ("Slur", events_[START]->self_scm ());
133       Direction updown = to_dir (ev->get_property ("direction"));
134       if (updown && !double_slurs)
135         set_grob_direction (slur, updown);
136
137       slurs_.push (slur);
138
139       if (double_slurs)
140         {
141           set_grob_direction (slur, DOWN);
142           slur = make_spanner ("Slur", events_[START]->self_scm ());
143           set_grob_direction (slur, UP);
144           slurs_.push (slur); 
145         }
146     }
147   set_melisma (slurs_.size ());
148 }
149
150 void
151 Slur_engraver::stop_translation_timestep ()
152 {
153   end_slurs_.clear ();
154   events_[START] = events_[STOP] = 0;
155 }
156
157 ENTER_DESCRIPTION (Slur_engraver,
158   /* descr */       "Build slurs grobs from slur events",
159   /* creats*/       "Slur",
160   /* accepts */     "slur-event",
161   /* acks  */      "note-column-interface accidental-interface fingering-interface script-interface tie-interface",
162   /* reads */       "slurMelismaBusy doubleSlurs",
163   /* write */       "");