]> git.donarmstrong.com Git - lilypond.git/blob - lily/key-engraver.cc
f9362832339230217a89a107459c3d6967eb64ab
[lilypond.git] / lily / key-engraver.cc
1 /*
2   key-engraver.cc -- implement Key_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "bar-line.hh"
10 #include "clef.hh"
11 #include "context.hh"
12 #include "engraver.hh"
13 #include "item.hh"
14 #include "pitch.hh"
15 #include "protected-scm.hh"
16 #include "staff-symbol-referencer.hh"
17 #include "stream-event.hh"
18
19 #include "translator.icc"
20
21 /*
22   TODO: The representation  of key sigs is all fucked.
23 */
24
25 /**
26    Make the key signature.
27 */
28 class Key_engraver : public Engraver
29 {
30   void create_key (bool);
31   void read_event (Stream_event const *r);
32
33   Stream_event *key_event_;
34   Item *item_;
35   Item *cancellation_;
36 public:
37   TRANSLATOR_DECLARATIONS (Key_engraver);
38
39 protected:
40   virtual void initialize ();
41   virtual void finalize ();
42   void stop_translation_timestep ();
43   void process_music ();
44
45   DECLARE_TRANSLATOR_LISTENER (key_change);
46   DECLARE_ACKNOWLEDGER (clef);
47   DECLARE_ACKNOWLEDGER (bar_line);
48 };
49
50 void
51 Key_engraver::finalize ()
52 {
53 }
54
55 Key_engraver::Key_engraver ()
56 {
57   key_event_ = 0;
58   item_ = 0;
59   cancellation_ = 0;
60 }
61
62 void
63 Key_engraver::create_key (bool is_default)
64 {
65   if (!item_)
66     {
67       item_ = make_item ("KeySignature",
68                          key_event_ ? key_event_->self_scm () : SCM_EOL);
69
70       item_->set_property ("c0-position",
71                            get_property ("middleCPosition"));
72
73       SCM last = get_property ("lastKeySignature");
74       SCM key = get_property ("keySignature");
75
76       if ((to_boolean (get_property ("printKeyCancellation"))
77            || key == SCM_EOL)
78           && !scm_is_eq (last, key))
79         {
80           SCM restore = SCM_EOL;
81           SCM *tail = &restore;
82           for (SCM s = last; scm_is_pair (s); s = scm_cdr (s))
83             {
84               if (scm_assoc (scm_caar (s), key) == SCM_BOOL_F)
85                 {
86                   *tail = scm_acons (scm_caar (s),
87                                      scm_from_int (0), *tail);
88                   tail = SCM_CDRLOC (*tail);
89                 }
90             }
91
92           if (scm_is_pair (restore))
93             {
94               cancellation_ = make_item ("KeyCancellation",
95                                          key_event_
96                                          ? key_event_->self_scm () : SCM_EOL);
97           
98               cancellation_->set_property ("alteration-alist", restore);
99               cancellation_->set_property ("c0-position",
100                                            get_property ("middleCPosition"));
101             }
102         }
103       item_->set_property ("alteration-alist", key);
104     }
105
106   if (!is_default)
107     {
108       SCM visibility = get_property ("explicitKeySignatureVisibility");
109       item_->set_property ("break-visibility", visibility);
110       if (cancellation_)
111         cancellation_->set_property ("break-visibility", visibility);
112     }
113 }
114
115 IMPLEMENT_TRANSLATOR_LISTENER (Key_engraver, key_change);
116 void
117 Key_engraver::listen_key_change (Stream_event *ev)
118 {
119   /* do this only once, just to be on the safe side.  */
120   if (ASSIGN_EVENT_ONCE (key_event_, ev))
121     read_event (key_event_);
122 }
123
124 void
125 Key_engraver::acknowledge_clef (Grob_info info)
126 {
127   (void)info;
128   SCM c = get_property ("createKeyOnClefChange");
129   if (to_boolean (c))
130     create_key (false);
131 }
132
133 void
134 Key_engraver::acknowledge_bar_line (Grob_info info)
135 {
136   (void)info;
137   if (scm_is_pair (get_property ("keySignature")))
138     create_key (true);
139 }
140
141 void
142 Key_engraver::process_music ()
143 {
144   if (key_event_
145       || get_property ("lastKeySignature") != get_property ("keySignature"))
146     create_key (false);
147 }
148
149 void
150 Key_engraver::stop_translation_timestep ()
151 {
152   item_ = 0;
153   context ()->set_property ("lastKeySignature", get_property ("keySignature"));
154   cancellation_ = 0;
155   key_event_ = 0;
156 }
157
158 void
159 Key_engraver::read_event (Stream_event const *r)
160 {
161   SCM p = r->get_property ("pitch-alist");
162   if (!scm_is_pair (p))
163     return;
164
165   SCM n = scm_list_copy (p);
166   SCM accs = SCM_EOL;
167   for (SCM s = get_property ("keyAlterationOrder");
168        scm_is_pair (s); s = scm_cdr (s))
169     {
170       if (scm_is_pair (scm_member (scm_car (s), n)))
171         {
172           accs = scm_cons (scm_car (s), accs);
173           n = scm_delete_x (scm_car (s), n);
174         }
175     }
176
177   for (SCM s = n; scm_is_pair (s); s = scm_cdr (s))
178     if (scm_to_int (scm_cdar (s)))
179       accs = scm_cons (scm_car (s), accs);
180
181   context ()->set_property ("keySignature", accs);
182   context ()->set_property ("tonic",
183                             r->get_property ("tonic"));
184 }
185
186 void
187 Key_engraver::initialize ()
188 {
189   context ()->set_property ("keySignature", SCM_EOL);
190   context ()->set_property ("lastKeySignature", SCM_EOL);
191
192   Pitch p (0, 0, 0);
193   context ()->set_property ("tonic", p.smobbed_copy ());
194 }
195
196 ADD_ACKNOWLEDGER (Key_engraver, clef);
197 ADD_ACKNOWLEDGER (Key_engraver, bar_line);
198
199 ADD_TRANSLATOR (Key_engraver,
200                 /* doc */ "",
201                 /* create */ "KeySignature",
202                 /* accept */ "key-change-event",
203                 
204                 /* read */
205                 "createKeyOnClefChange "
206                 "explicitKeySignatureVisibility "
207                 "keyAlterationOrder "
208                 "keySignature "
209                 "keySignature "
210                 "lastKeySignature "
211                 "printKeyCancellation "
212                 ,
213                 
214                 /* write */
215                 "keySignature "
216                 "lastKeySignature "
217                 "tonic ")