]> git.donarmstrong.com Git - lilypond.git/blob - lily/new-dynamic-engraver.cc
Merge branch 'lilypond/translation' of /home/lilycvs/git/lily/ into lilypond/translation
[lilypond.git] / lily / new-dynamic-engraver.cc
1 /* 
2   new-dynamic-engraver.cc -- implement New_dynamic_engraver
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 2008 Han-Wen Nienhuys <hanwen@lilypond.org>
7   
8 */
9
10
11 #include "engraver.hh"
12
13 #include "item.hh"
14 #include "pointer-group-interface.hh"
15 #include "text-interface.hh"
16 #include "note-column.hh"
17 #include "self-alignment-interface.hh"
18 #include "spanner.hh"
19 #include "stream-event.hh"
20
21 #include "translator.icc"
22
23 class New_dynamic_engraver : public Engraver
24 {
25   TRANSLATOR_DECLARATIONS (New_dynamic_engraver);
26   DECLARE_ACKNOWLEDGER (note_column);
27   DECLARE_TRANSLATOR_LISTENER (absolute_dynamic);
28   DECLARE_TRANSLATOR_LISTENER (span_dynamic);
29
30 protected:
31   virtual void process_music ();
32   virtual void stop_translation_timestep ();
33 private:
34   Drul_array<Stream_event *> accepted_spanevents_drul_;
35   Spanner *current_spanner_;
36   Spanner *finished_spanner_;
37   
38   Item *script_;
39   Stream_event *script_event_;
40   Stream_event *current_span_event_;
41 };
42
43 New_dynamic_engraver::New_dynamic_engraver ()
44 {
45   script_event_ = 0;
46   current_span_event_ = 0;
47   script_ = 0;
48   finished_spanner_ = 0;
49   current_spanner_ = 0;
50   accepted_spanevents_drul_.set (0, 0);
51 }
52
53 IMPLEMENT_TRANSLATOR_LISTENER (New_dynamic_engraver, absolute_dynamic);
54 void
55 New_dynamic_engraver::listen_absolute_dynamic (Stream_event *ev)
56 {
57   ASSIGN_EVENT_ONCE (script_event_, ev);
58 }
59
60 IMPLEMENT_TRANSLATOR_LISTENER (New_dynamic_engraver, span_dynamic);
61 void
62 New_dynamic_engraver::listen_span_dynamic (Stream_event *ev)
63 {
64   Direction d = to_dir (ev->get_property ("span-direction"));
65
66   ASSIGN_EVENT_ONCE (accepted_spanevents_drul_[d], ev);
67 }
68
69
70 void
71 New_dynamic_engraver::process_music ()
72 {
73   if (current_spanner_
74       && (accepted_spanevents_drul_[STOP] || script_event_ || accepted_spanevents_drul_[START]))
75     {
76       Stream_event* ender = accepted_spanevents_drul_[STOP];
77       if (!ender)
78         ender = script_event_;
79
80       if (!ender)
81         ender = accepted_spanevents_drul_[START];
82       
83       finished_spanner_ = current_spanner_;
84       announce_end_grob (finished_spanner_, ender->self_scm ());
85       current_spanner_ = 0;
86       current_span_event_ = 0;
87     }
88
89   if (accepted_spanevents_drul_[START])
90     {
91       current_span_event_ = accepted_spanevents_drul_[START];
92       
93       SCM start_sym = current_span_event_->get_property ("class");
94       string start_type;
95           
96       if (start_sym == ly_symbol2scm ("decrescendo-event"))
97         start_type = "decrescendo";
98       else if (start_sym == ly_symbol2scm ("crescendo-event"))
99         start_type = "crescendo";
100       else
101         {
102           programming_error ("unknown dynamic spanner type");
103           return;
104         }
105       
106       SCM cresc_type = get_property ((start_type + "Spanner").c_str ());
107
108       if (cresc_type == ly_symbol2scm ("text"))
109         {
110           current_spanner_
111             = make_spanner ("DynamicTextSpanner",
112                             accepted_spanevents_drul_[START]->self_scm ());
113
114           SCM text = get_property ((start_type + "Text").c_str ());
115           if (Text_interface::is_markup (text))
116             {
117               current_spanner_->set_property ("text", text);
118             }
119         }
120       else
121         {
122           if (cresc_type != ly_symbol2scm ("hairpin"))
123             {
124               // Fixme: should put value in error message.
125               ly_display_scm (cresc_type);
126               current_span_event_
127                 ->origin()->warning ("unknown crescendo style; defaulting to hairpin.");
128             }
129           current_spanner_ = make_spanner ("Hairpin",
130                                            current_span_event_->self_scm ());
131           if (finished_spanner_)
132             {
133               Pointer_group_interface::add_grob (finished_spanner_,
134                                                  ly_symbol2scm ("adjacent-hairpins"),
135                                                  current_spanner_);
136
137               Pointer_group_interface::add_grob (current_spanner_,
138                                                  ly_symbol2scm ("adjacent-hairpins"),
139                                                  finished_spanner_);
140             }
141         }
142     }
143
144   if (script_event_)
145     {
146       script_ = make_item ("DynamicText", script_event_->self_scm ());
147       script_->set_property ("text",
148                              script_event_->get_property ("text"));
149
150       if (finished_spanner_)
151         finished_spanner_->set_bound (RIGHT, script_);
152       if (current_spanner_)
153         {
154           current_spanner_->set_bound (LEFT, script_);
155           set_nested_property (current_spanner_,
156                                scm_list_3 (ly_symbol2scm ("bound-details"),
157                                            ly_symbol2scm ("left"),
158                                            ly_symbol2scm ("attach-dir")
159                                            ),
160                                scm_from_int (RIGHT));
161
162         }
163     }
164 }
165
166
167
168 void
169 New_dynamic_engraver::stop_translation_timestep ()
170 {
171   if (finished_spanner_ && !finished_spanner_->get_bound (RIGHT))
172     finished_spanner_->set_bound (RIGHT,
173                                   unsmob_grob (get_property ("currentMusicalColumn")));
174
175   if (current_spanner_ && !current_spanner_->get_bound (LEFT))
176     current_spanner_->set_bound (LEFT,
177                                  unsmob_grob (get_property ("currentMusicalColumn")));
178   script_ = 0;
179   script_event_ = 0;
180   accepted_spanevents_drul_.set (0, 0);
181   finished_spanner_ = 0;
182 }
183
184 void
185 New_dynamic_engraver::acknowledge_note_column (Grob_info info)
186 {
187   if (script_ && !script_->get_parent (X_AXIS))
188     {
189       extract_grob_set (info.grob (), "note-heads", heads);
190       if (heads.size ())
191         {
192           Grob *head = heads[0];
193           script_->set_parent (head, X_AXIS);
194           Self_alignment_interface::set_center_parent (script_, X_AXIS);
195         }
196     }
197
198   if (current_spanner_ && !current_spanner_->get_bound (LEFT))
199     current_spanner_->set_bound (LEFT, info.grob ());
200   if (finished_spanner_ && !finished_spanner_->get_bound (RIGHT))
201     finished_spanner_->set_bound (RIGHT, info.grob ());
202 }
203
204 ADD_ACKNOWLEDGER (New_dynamic_engraver, note_column);
205 ADD_TRANSLATOR (New_dynamic_engraver,
206                 /* doc */
207                 "Create hairpins, dynamic texts, and their vertical"
208                 " alignments.  The symbols are collected onto a"
209                 " @code{DynamicLineSpanner} grob which takes care of vertical"
210                 " positioning.",
211
212                 /* create */
213                 "DynamicTextSpanner "
214                 "DynamicText "
215                 "Hairpin "
216                 "TextSpanner ",
217
218                 /* read */
219                 "currentMusicalColumn ",
220
221                 /* write */
222                 ""
223                 );