2 local-key-engraver.cc -- implement Local_key_engraver
4 (c) 1997--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 #include "musical-request.hh"
8 #include "command-request.hh"
9 #include "local-key-item.hh"
10 #include "key-item.hh"
12 #include "rhythmic-head.hh"
13 #include "timing-translator.hh"
14 #include "engraver-group-engraver.hh"
15 #include "grace-align-item.hh"
16 #include "staff-symbol-referencer.hh"
17 #include "side-position-interface.hh"
18 #include "engraver.hh"
22 Make accidentals. Catches note heads, ties and notices key-change
23 events. Due to interaction with ties (which don't come together
24 with note heads), this needs to be in a context higher than Tie_engraver.
27 struct Local_key_engraver
: Engraver
{
28 Local_key_item
*key_item_p_
;
30 VIRTUAL_COPY_CONS(Translator
);
31 virtual void do_process_music();
32 virtual void acknowledge_element (Score_element_info
);
33 virtual void do_pre_move_processing();
34 virtual void do_creation_processing ();
35 virtual void process_acknowledged ();
36 virtual void do_removal_processing ();
42 Link_array
<Note_req
> mel_l_arr_
;
43 Link_array
<Item
> support_l_arr_
;
44 Link_array
<Item
> forced_l_arr_
;
45 Link_array
<Item
> tied_l_arr_
;
48 Grace_align_item
* grace_align_l_
;
51 Local_key_engraver::Local_key_engraver()
55 last_keysig_
= SCM_EOL
;
59 Local_key_engraver::do_creation_processing ()
61 last_keysig_
= get_property ("keySignature");
62 daddy_trans_l_
->set_property ("localKeySignature", last_keysig_
);
66 Local_key_engraver::process_acknowledged ()
68 if (!key_item_p_
&& mel_l_arr_
.size())
70 SCM localsig
= get_property ("localKeySignature");
72 SCM f
= get_property ("forgetAccidentals");
73 bool forget
= to_boolean (f
);
74 for (int i
=0; i
< mel_l_arr_
.size(); i
++)
76 Item
* support_l
= support_l_arr_
[i
];
77 Note_req
* note_l
= mel_l_arr_
[i
];
79 int n
= note_l
->pitch_
.notename_i_
;
80 int o
= note_l
->pitch_
.octave_i_
;
81 int a
= note_l
->pitch_
.accidental_i_
;
83 /* see if there's a tie that "changes" the accidental */
84 /* works because if there's a tie, the note to the left
85 is of the same pitch as the actual note */
87 SCM prev
= scm_assoc (gh_cons (gh_int2scm (o
), gh_int2scm (n
)), localsig
);
88 if (prev
== SCM_BOOL_F
)
89 prev
= scm_assoc (gh_int2scm (n
), localsig
);
90 int prev_acc
= (prev
== SCM_BOOL_F
) ? 0 : gh_scm2int (gh_cdr (prev
));
91 bool different
= prev_acc
!= a
;
93 bool tie_changes
= tied_l_arr_
.find_l (support_l
) && different
;
95 && (note_l
->forceacc_b_
|| different
)
100 key_item_p_
= new Local_key_item (get_property ("basicLocalKeyProperties"));
101 Side_position_interface (key_item_p_
).set_axis (X_AXIS
);
102 Side_position_interface (key_item_p_
).set_direction (LEFT
);
103 Staff_symbol_referencer_interface::set_interface (key_item_p_
);
105 announce_element (Score_element_info (key_item_p_
, 0));
110 sign (prev_acc
) * (prev_acc
- a
) == 1
111 && abs(prev_acc
) == 2;
113 key_item_p_
->add_pitch (note_l
->pitch_
,
114 note_l
->cautionary_b_
,
116 Side_position_interface (key_item_p_
).add_support (support_l
);
121 localsig
= scm_assoc_set_x (localsig
, gh_cons (gh_int2scm (o
),
129 if (!tied_l_arr_
.find_l (support_l
))
131 local_key_
.clear_internal_forceacc (note_l
->pitch_
);
133 else if (tie_changes
)
135 local_key_
.set_internal_forceacc (note_l
->pitch_
);
144 daddy_trans_l_
->set_property ("localKeySignature", localsig
);
149 if (key_item_p_
&& grace_align_l_
)
151 Side_position_interface (grace_align_l_
).add_support (key_item_p_
);
158 Local_key_engraver::do_removal_processing ()
160 // TODO: if grace ? signal accidentals to Local_key_engraver the
164 Local_key_engraver::do_pre_move_processing()
168 for (int i
=0; i
< support_l_arr_
.size(); i
++)
169 Side_position_interface (key_item_p_
).add_support (support_l_arr_
[i
]);
171 typeset_element (key_item_p_
);
178 support_l_arr_
.clear();
179 forced_l_arr_
.clear();
183 Local_key_engraver::acknowledge_element (Score_element_info info
)
185 SCM wg
= get_property ("weAreGraceContext");
187 bool selfgr
= gh_boolean_p (wg
) &&gh_scm2bool (wg
);
188 bool he_gr
= to_boolean (info
.elem_l_
->get_elt_property ("grace"));
190 Grace_align_item
* gai
= dynamic_cast<Grace_align_item
*> (info
.elem_l_
);
191 if (he_gr
&& !selfgr
&& gai
)
193 grace_align_l_
= gai
;
198 Note_req
* note_l
= dynamic_cast <Note_req
*> (info
.req_l_
);
199 Rhythmic_head
* note_head
= dynamic_cast<Rhythmic_head
*> (info
.elem_l_
);
201 if (note_l
&& note_head
)
203 mel_l_arr_
.push (note_l
);
204 support_l_arr_
.push (note_head
);
206 else if (Tie
* tie_l
= dynamic_cast<Tie
*> (info
.elem_l_
))
208 tied_l_arr_
.push (Tie::head (tie_l
, RIGHT
));
213 ugh. repeated deep_copy generates lots of garbage.
216 Local_key_engraver::do_process_music()
218 SCM smp
= get_property ("measurePosition");
219 Moment mp
= (unsmob_moment (smp
)) ? *unsmob_moment (smp
) : Moment (0);
221 SCM sig
= get_property ("keySignature");
224 if (!to_boolean (get_property ("noResetKey")))
225 daddy_trans_l_
->set_property ("localKeySignature", ly_deep_copy (sig
));
227 else if (last_keysig_
!= sig
)
229 daddy_trans_l_
->set_property ("localKeySignature", ly_deep_copy (sig
));
236 ADD_THIS_TRANSLATOR(Local_key_engraver
);