]> git.donarmstrong.com Git - lilypond.git/blob - lily/key-engraver.cc
* lily/parser.yy (Music_list): add error-found to music with errors.
[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--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   */
8
9
10
11 #include "event.hh"
12 #include "item.hh"
13 #include "bar-line.hh"
14 #include "staff-symbol-referencer.hh"
15 #include "context.hh"
16 #include "engraver.hh"
17 #include "pitch.hh"
18 #include "protected-scm.hh"
19 #include "clef.hh"
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_ev (Music const * r);
32
33   Music *key_ev_;
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   virtual bool try_music (Music *ev);
43   virtual void stop_translation_timestep ();
44   virtual void start_translation_timestep ();
45   virtual void process_music ();
46   virtual void acknowledge_grob (Grob_info);
47 };
48
49
50 void
51 Key_engraver::finalize ()
52 {
53 }
54
55
56 Key_engraver::Key_engraver ()
57 {
58   key_ev_ = 0;
59   item_ = 0;
60   cancellation_ = 0;
61 }
62
63
64 void
65 Key_engraver::create_key (bool def)
66 {
67   if (!item_) 
68     {
69       item_ = make_item ("KeySignature", key_ev_ ? key_ev_->self_scm () : SCM_EOL);
70
71       item_->set_property ("c0-position",
72                            get_property ("middleCPosition"));
73
74       SCM last = get_property ("lastKeySignature");
75       SCM key = get_property ("keySignature");
76       if (to_boolean (get_property ("printKeyCancellation"))
77           && !scm_is_eq (last, key))
78         {
79           cancellation_ = make_item ("KeyCancellation", key_ev_ ? key_ev_->self_scm () : SCM_EOL);
80           cancellation_->set_property ("old-accidentals",last);
81           cancellation_->set_property ("c0-position",
82                            get_property ("middleCPosition"));
83       
84         }
85       item_->set_property ("new-accidentals", key);
86     }
87
88   if (!def)
89     {
90       SCM vis = get_property ("explicitKeySignatureVisibility"); 
91       if (ly_c_procedure_p (vis))
92         item_->set_property ("break-visibility",vis);
93     }
94 }      
95
96
97 bool
98 Key_engraver::try_music (Music * ev)
99 {
100   if (ev->is_mus_type ("key-change-event"))
101     {
102       /* do this only once, just to be on the safe side.  */
103       if (!key_ev_)
104         {
105           key_ev_ = ev;
106           read_ev (key_ev_);
107         }
108       return true;
109     }   
110   return  false;
111 }
112
113
114 void
115 Key_engraver::acknowledge_grob (Grob_info info)
116 {
117   if (Clef::has_interface (info.grob_))
118     {
119       SCM c =  get_property ("createKeyOnClefChange");
120       if (to_boolean (c))
121         {
122           create_key (false);
123         }
124     }
125   else if (Bar_line::has_interface (info.grob_)
126            && scm_is_pair (get_property ("keySignature")))
127     {
128       create_key (true);
129     }
130 }
131
132
133 void
134 Key_engraver::process_music ()
135 {
136   if (key_ev_ ||
137       get_property ("lastKeySignature") != get_property ("keySignature"))
138     create_key (false);
139 }
140
141
142 void
143 Key_engraver::stop_translation_timestep ()
144 {
145   item_ = 0;
146   context ()->set_property ("lastKeySignature", get_property ("keySignature"));
147   cancellation_ = 0; 
148 }
149
150
151 void
152 Key_engraver::read_ev (Music const * r)
153 {
154   SCM p = r->get_property ("pitch-alist");
155   if (!scm_is_pair (p))
156     return;
157
158   SCM n = scm_list_copy (p);
159   SCM accs = SCM_EOL;
160   for (SCM s = get_property ("keyAccidentalOrder");
161        scm_is_pair (s); s = scm_cdr (s))
162     {
163       if (scm_is_pair (scm_member (scm_car (s), n)))
164         {
165           accs = scm_cons (scm_car (s), accs);
166           n = scm_delete_x (scm_car (s), n);
167         }
168     }
169   
170   for (SCM s = n ; scm_is_pair (s); s = scm_cdr (s))
171     if (scm_to_int (scm_cdar (s)))
172       accs = scm_cons (scm_car (s), accs);
173
174   context ()->set_property ("keySignature", accs);
175   context ()->set_property ("tonic" ,
176                             r->get_property ("tonic"));
177 }
178
179
180 void
181 Key_engraver::start_translation_timestep ()
182 {
183   key_ev_ = 0;
184 }
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
198
199 ENTER_DESCRIPTION (Key_engraver,
200 /* descr */       "",
201 /* creats*/       "KeySignature",
202 /* accepts */     "key-change-event",
203 /* acks  */      "bar-line-interface clef-interface",
204 /* reads */       "keySignature printKeyCancellation lastKeySignature explicitKeySignatureVisibility createKeyOnClefChange keyAccidentalOrder keySignature",
205 /* write */       "lastKeySignature tonic keySignature");