]> git.donarmstrong.com Git - lilypond.git/blob - lily/key-engraver.cc
*** empty log message ***
[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
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", 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       if (to_boolean (get_property ("printKeyCancellation"))
75           && !scm_is_eq (last, key))
76         {
77           cancellation_ = make_item ("KeyCancellation", key_event_ ? key_event_->self_scm () : SCM_EOL);
78           cancellation_->set_property ("accidentals", last);
79           cancellation_->set_property ("c0-position",
80                                        get_property ("middleCPosition"));
81         }
82       item_->set_property ("accidentals", key);
83     }
84
85   if (!is_default)
86     {
87       SCM visibility = get_property ("explicitKeySignatureVisibility");
88       item_->set_property ("break-visibility", visibility);
89     }
90 }
91
92 bool
93 Key_engraver::try_music (Music *event)
94 {
95   if (event->is_mus_type ("key-change-event"))
96     {
97       /* do this only once, just to be on the safe side.  */
98       if (!key_event_)
99         {
100           key_event_ = event;
101           read_event (key_event_);
102         }
103       return true;
104     }
105   return false;
106 }
107
108 void
109 Key_engraver::acknowledge_clef (Grob_info info)
110 {
111   (void)info;
112   SCM c = get_property ("createKeyOnClefChange");
113   if (to_boolean (c))
114     {
115       create_key (false);
116     }
117 }
118
119 void
120 Key_engraver::acknowledge_bar_line (Grob_info info)
121 {
122   (void)info;
123   if (scm_is_pair (get_property ("keySignature")))
124     {
125       create_key (true);
126     }
127 }
128
129 void
130 Key_engraver::process_music ()
131 {
132   if (key_event_
133       || get_property ("lastKeySignature") != get_property ("keySignature"))
134     create_key (false);
135 }
136
137 void
138 Key_engraver::stop_translation_timestep ()
139 {
140   item_ = 0;
141   context ()->set_property ("lastKeySignature", get_property ("keySignature"));
142   cancellation_ = 0;
143   key_event_ = 0;
144 }
145
146 void
147 Key_engraver::read_event (Music const *r)
148 {
149   SCM p = r->get_property ("pitch-alist");
150   if (!scm_is_pair (p))
151     return;
152
153   SCM n = scm_list_copy (p);
154   SCM accs = SCM_EOL;
155   for (SCM s = get_property ("keyAccidentalOrder");
156        scm_is_pair (s); s = scm_cdr (s))
157     {
158       if (scm_is_pair (scm_member (scm_car (s), n)))
159         {
160           accs = scm_cons (scm_car (s), accs);
161           n = scm_delete_x (scm_car (s), n);
162         }
163     }
164
165   for (SCM s = n; scm_is_pair (s); s = scm_cdr (s))
166     if (scm_to_int (scm_cdar (s)))
167       accs = scm_cons (scm_car (s), accs);
168
169   context ()->set_property ("keySignature", accs);
170   context ()->set_property ("tonic",
171                             r->get_property ("tonic"));
172 }
173
174 void
175 Key_engraver::initialize ()
176 {
177   context ()->set_property ("keySignature", SCM_EOL);
178   context ()->set_property ("lastKeySignature", SCM_EOL);
179
180   Pitch p (0, 0, 0);
181   context ()->set_property ("tonic", p.smobbed_copy ());
182 }
183
184
185 ADD_ACKNOWLEDGER (Key_engraver,clef);
186 ADD_ACKNOWLEDGER (Key_engraver,bar_line);
187
188 ADD_TRANSLATOR (Key_engraver,
189                 /* descr */ "",
190                 /* creats*/ "KeySignature",
191                 /* accepts */ "key-change-event",
192                 /* reads */ "keySignature printKeyCancellation lastKeySignature explicitKeySignatureVisibility createKeyOnClefChange keyAccidentalOrder keySignature",
193                 /* write */ "lastKeySignature tonic keySignature");