2 a2-engraver.cc -- implement A2_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2002 Jan Nieuwenhuizen <janneke@gnu.org>
11 #include "note-head.hh"
14 #include "translator-group.hh"
15 #include "side-position-interface.hh"
16 #include "directional-element-interface.hh"
17 #include "multi-measure-rest.hh"
20 class A2_engraver : public Engraver
22 TRANSLATOR_DECLARATIONS(A2_engraver);
25 virtual void acknowledge_grob (Grob_info);
26 virtual void create_grobs ();
27 virtual void stop_translation_timestep ();
30 enum State { SOLO, SPLIT_INTERVAL, UNIRHYTHM, UNISILENCE, UNISON } state_;
35 A2_engraver::A2_engraver ()
42 A2_engraver::create_grobs ()
44 if (!to_boolean (get_property ("combineParts")))
48 SCM unison = get_property ("unison");
49 SCM solo = get_property ("solo");
50 SCM solo_adue = get_property ("soloADue");
52 if (solo_adue == SCM_BOOL_T
53 && ((solo == SCM_BOOL_T && state_ != SOLO)
54 || (unison == SCM_BOOL_T && state_ != UNISON
55 && daddy_trans_l_->id_str_.left_str (3) == "one")))
57 text_p_ = new Item (get_property ("TextScript"));
58 Side_position_interface::set_axis (text_p_, Y_AXIS);
59 announce_grob(text_p_, SCM_EOL);
63 if (solo == SCM_BOOL_T)
66 if (daddy_trans_l_->id_str_.left_str (3) == "one")
68 text = get_property ("soloText");
72 text = get_property ("soloIIText");
76 else if (unison == SCM_BOOL_T)
79 if (daddy_trans_l_->id_str_.left_str (3) == "one")
80 text = get_property ("aDueText");
83 Side_position_interface::set_direction (text_p_, dir);
84 text_p_->set_grob_property ("text", text);
90 A2_engraver::acknowledge_grob (Grob_info i)
92 if (!to_boolean (get_property ("combineParts")))
97 if (Note_head::has_interface (i.grob_l_))
100 Side_position_interface::add_support (t, i.grob_l_);
101 if (Side_position_interface::get_axis (t) == X_AXIS
102 && !t->get_parent (Y_AXIS))
103 t->set_parent (i.grob_l_, Y_AXIS);
105 if (Stem::has_interface (i.grob_l_))
107 Side_position_interface::add_support (text_p_, i.grob_l_);
111 SCM unisilence = get_property ("unisilence");
112 SCM unison = get_property ("unison");
113 SCM unirhythm = get_property ("unirhythm");
114 SCM solo = get_property ("solo");
115 SCM split_interval = get_property ("split-interval");
116 SCM solo_adue = get_property ("soloADue");
118 State previous_state = state_;
119 if (unisilence == SCM_BOOL_T)
124 else if (solo == SCM_BOOL_T)
126 else if (unison == SCM_BOOL_T)
128 else if (unirhythm == SCM_BOOL_T && split_interval == SCM_BOOL_T)
129 state_ = SPLIT_INTERVAL;
133 Direction d = CENTER;
134 if (daddy_trans_l_->id_str_.left_str (3) == "one")
136 else if (daddy_trans_l_->id_str_.left_str (3) == "two")
139 /* Must only set direction for VoiceCombines, not for StaffCombines:
140 we can't detect that here, so, ugh, yet another property */
141 if (!to_boolean (get_property ("noDirection"))
142 && (Stem::has_interface (i.grob_l_)
143 || Slur::has_interface (i.grob_l_)
144 || Tie::has_interface (i.grob_l_)
146 Usually, dynamics are removed by *_devnull_engravers for the
147 second voice. On the one hand, we don't want all dynamics for
148 the first voice to be placed above the staff. On the other
149 hand, colliding of scripts may be worse.
150 So, we don't set directions for these when we're playing solo.
152 || (i.grob_l_->internal_has_interface (ly_symbol2scm ("dynamic-interface"))
154 || (i.grob_l_->internal_has_interface (ly_symbol2scm ("text-interface"))
159 Hmm. We must set dir when solo, in order to get
160 the rests collided to the right position
162 if ((unirhythm != SCM_BOOL_T) || (solo == SCM_BOOL_T)
163 || ((unisilence == SCM_BOOL_T && previous_state != UNISON))
164 || (unirhythm == SCM_BOOL_T && split_interval == SCM_BOOL_T
165 && (unison != SCM_BOOL_T || solo_adue != SCM_BOOL_T)))
169 Blunt axe method: every grob gets a propertysetting.
171 i.grob_l_->set_grob_property ("direction", gh_int2scm (d));
176 todo: should we have separate state variable for being "rest while
178 if ( Multi_measure_rest::has_interface (i.grob_l_) && d )
179 if (state_ == UNIRHYTHM
180 && unisilence != SCM_BOOL_T)
182 i.grob_l_->set_grob_property ("staff-position", gh_int2scm (d * 6));
187 A2_engraver::stop_translation_timestep ()
191 Side_position_interface::add_staff_support (text_p_);
192 typeset_grob (text_p_);
197 ENTER_DESCRIPTION(A2_engraver,
198 /* descr */ "Part combine engraver for orchestral scores.
200 The markings @emph{a2}, @emph{Solo} and @emph{Solo II}, are
201 created by this engraver. It also acts upon instructions of the part
202 combiner. Another thing that the this engraver, is forcing of stem,
203 slur and tie directions, always when both threads are not identical;
204 up for the musicexpr called @code{one}, down for the musicexpr called
208 /* creats*/ "TextScript",
209 /* acks */ "grob-interface tie-interface note-head-interface ",
210 /* reads */ "combineParts noDirection soloADue soloText soloIIText aDueText split-interval unison solo unisilence unirhythm",