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