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