1 //=========================================================
2 // MusE
3 // Linux Music Editor
4 // $Id: key.cpp,v 1.7.2.7 2008/05/21 00:28:52 terminator356 Exp $
5 //
6 // (C) Copyright 1999/2000 Werner Schweer (ws@seh.de)
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License
10 // as published by the Free Software Foundation; version 2 of
11 // the License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 //
22 //=========================================================
23
24 #include <stdio.h>
25 #include <errno.h>
26 #include "muse_math.h"
27
28 #include "key.h"
29 #include "globals.h"
30 #include "gconfig.h"
31 #include "xml.h"
32 #include "keyevent.h"
33
34 namespace MusEGlobal {
35 MusECore::KeyList keymap;
36 }
37
38 namespace MusECore {
39
40 #define DEFAULT_KEY KEY_C
41
42 //---------------------------------------------------------
43 // KeyList
44 //---------------------------------------------------------
45
KeyList()46 KeyList::KeyList()
47 {
48 insert(std::pair<const unsigned, KeyEvent> (MAX_TICK+1, KeyEvent(DEFAULT_KEY, 0, false)));
49 }
50
51 //---------------------------------------------------------
52 // copy
53 //---------------------------------------------------------
54
copy(const KeyList & src)55 void KeyList::copy(const KeyList& src)
56 {
57 // Clear the existing destination list.
58 KEYLIST::clear();
59
60 for (ciKeyEvent i = src.cbegin(); i != src.cend(); ++i)
61 {
62 KeyEvent new_e = KeyEvent(i->second);
63 std::pair<iKeyEvent, bool> res = insert(std::pair<const unsigned, KeyEvent> (i->first, new_e));
64 if(!res.second)
65 {
66 fprintf(stderr, "KeyList::copy insert failed: keylist:%p key:%d tick:%d minor:%d\n",
67 this, new_e.key, new_e.tick, new_e.minor);
68 }
69 }
70 }
71
72 //---------------------------------------------------------
73 // add
74 //---------------------------------------------------------
75
add(unsigned tick,key_enum key,bool isMinor)76 void KeyList::add(unsigned tick, key_enum key, bool isMinor)
77 {
78 if (tick > MAX_TICK)
79 tick = MAX_TICK;
80 iKeyEvent e = upper_bound(tick);
81
82 if (tick == e->second.tick)
83 {
84 e->second.key = key;
85 e->second.minor = isMinor;
86 }
87 else {
88 KeyEvent& ne = e->second;
89 KeyEvent ev = KeyEvent(ne.key, ne.tick, ne.minor);
90 ne.key = key;
91 ne.tick = tick;
92 ne.minor = isMinor;
93 insert(std::pair<const unsigned, KeyEvent> (tick, ev));
94 }
95 }
96
add(KeyEvent e)97 void KeyList::add(KeyEvent e)
98 {
99 int tick = e.tick;
100 key_enum k = e.key;
101 bool is_minor = e.minor;
102 std::pair<iKeyEvent, bool> res = insert(std::pair<const unsigned, KeyEvent> (tick, e));
103 if(!res.second)
104 {
105 fprintf(stderr, "KeyList::add insert failed: keylist:%p key:%d tick:%d minor:%d\n",
106 this, e.key, e.tick, e.minor);
107 }
108 else
109 {
110 iKeyEvent ike = res.first;
111 ++ike; // There is always a 'next' key event - there is always one at index MAX_TICK.
112 KeyEvent& ne = ike->second;
113
114 // Swap the values. (This is how the key list works.)
115 e.key = ne.key;
116 e.tick = ne.tick;
117 e.minor = ne.minor;
118 ne.key = k;
119 ne.tick = tick;
120 ne.minor = is_minor;
121 }
122 }
123
124 //---------------------------------------------------------
125 // KeyList::dump
126 //---------------------------------------------------------
127
dump() const128 void KeyList::dump() const
129 {
130 printf("\nKeyList:\n");
131 for (ciKeyEvent i = begin(); i != end(); ++i) {
132 printf("%6d %06d key %6d minor:%d\n",
133 i->first, i->second.tick, i->second.key, i->second.minor);
134 }
135 }
136
137
138 //---------------------------------------------------------
139 // clear
140 //---------------------------------------------------------
141
clear()142 void KeyList::clear()
143 {
144 KEYLIST::clear();
145 insert(std::pair<const unsigned, KeyEvent> (MAX_TICK+1, KeyEvent(DEFAULT_KEY, 0, false)));
146 }
147
148 //---------------------------------------------------------
149 // keyAtTick
150 //---------------------------------------------------------
151
keyAtTick(unsigned tick) const152 KeyEvent KeyList::keyAtTick(unsigned tick) const
153 {
154 ciKeyEvent i = upper_bound(tick);
155 if (i == end()) {
156 printf("no key at tick %d,0x%x\n", tick, tick);
157 return KeyEvent();
158 }
159 return i->second;
160 }
161
162 //---------------------------------------------------------
163 // del
164 //---------------------------------------------------------
165
del(unsigned tick)166 void KeyList::del(unsigned tick)
167 {
168 iKeyEvent e = find(tick);
169 if (e == end()) {
170 printf("KeyList::del(%d): not found\n", tick);
171 return;
172 }
173 del(e);
174 }
175
del(iKeyEvent e)176 void KeyList::del(iKeyEvent e)
177 {
178 iKeyEvent ne = e;
179 ++ne;
180 if (ne == end()) {
181 printf("KeyList::del() HALLO\n");
182 return;
183 }
184 ne->second.key = e->second.key;
185 ne->second.tick = e->second.tick;
186 ne->second.minor = e->second.minor;
187 erase(e);
188 }
189
190 //---------------------------------------------------------
191 // addKey
192 //---------------------------------------------------------
193
addKey(unsigned t,key_enum key,bool isMinor)194 void KeyList::addKey(unsigned t, key_enum key, bool isMinor)
195 {
196 add(t, key, isMinor);
197 }
198
199 //---------------------------------------------------------
200 // delKey
201 //---------------------------------------------------------
202
delKey(unsigned tick)203 void KeyList::delKey(unsigned tick)
204 {
205 del(tick);
206 }
207
208
209
210 //---------------------------------------------------------
211 // KeyList::write
212 //---------------------------------------------------------
213
write(int level,Xml & xml) const214 void KeyList::write(int level, Xml& xml) const
215 {
216 xml.tag(level, "keylist");
217 for (ciKeyEvent i = begin(); i != end(); ++i)
218 i->second.write(level, xml, i->first);
219 xml.tag(level, "/keylist");
220 }
221
222 //---------------------------------------------------------
223 // KeyList::read
224 //---------------------------------------------------------
225
read(Xml & xml)226 void KeyList::read(Xml& xml)
227 {
228 for (;;) {
229 Xml::Token token = xml.parse();
230 const QString& tag = xml.s1();
231 switch (token) {
232 case Xml::Error:
233 case Xml::End:
234 return;
235 case Xml::TagStart:
236 if (tag == "key") {
237 KeyEvent t;
238 unsigned tick = t.read(xml);
239 iKeyEvent pos = find(tick);
240 if (pos != end())
241 erase(pos);
242 insert(std::pair<const int, KeyEvent> (tick, t));
243 }
244 else
245 xml.unknown("keyList");
246 break;
247 case Xml::Attribut:
248 break;
249 case Xml::TagEnd:
250 if (tag == "keylist") {
251 return;
252 }
253 default:
254 break;
255 }
256 }
257 }
258
KeyEvent()259 KeyEvent::KeyEvent()
260 {
261 key = DEFAULT_KEY;
262 tick = 0;
263 minor = false;
264 }
265
KeyEvent(key_enum k,unsigned tk,bool isMinor)266 KeyEvent::KeyEvent(key_enum k, unsigned tk, bool isMinor)
267 {
268 key = k;
269 tick = tk;
270 minor = isMinor;
271 }
272
273 //---------------------------------------------------------
274 // KeyEvent::write
275 //---------------------------------------------------------
276
write(int level,Xml & xml,int at) const277 void KeyEvent::write(int level, Xml& xml, int at) const
278 {
279 xml.tag(level++, "key at=\"%d\"", at);
280 xml.intTag(level, "tick", tick);
281 xml.intTag(level, "val", key);
282 xml.intTag(level, "minor", minor);
283 xml.tag(level, "/key");
284 }
285
286 //---------------------------------------------------------
287 // KeyEvent::read
288 //---------------------------------------------------------
289
read(Xml & xml)290 int KeyEvent::read(Xml& xml)
291 {
292 int at = 0;
293 for (;;) {
294 Xml::Token token = xml.parse();
295 const QString& tag = xml.s1();
296 switch (token) {
297 case Xml::Error:
298 case Xml::End:
299 return 0;
300 case Xml::TagStart:
301 if (tag == "tick")
302 tick = xml.parseInt();
303 else if (tag == "val")
304 key = key_enum(xml.parseInt());
305 else if (tag == "minor")
306 minor = xml.parseInt();
307 else
308 xml.unknown("KeyEvent");
309 break;
310 case Xml::Attribut:
311 if (tag == "at")
312 at = xml.s2().toInt();
313 break;
314 case Xml::TagEnd:
315 if (tag == "key") {
316 return at;
317 }
318 default:
319 break;
320 }
321 }
322 return 0;
323 }
324
325 //don't remove or insert new elements in keyStrs.
326 //only renaming (keeping the semantic sense) is allowed! (flo)
327 // Static
328 const QStringList KeyEvent::keyStrs = QStringList()
329 << "C (sharps)" << "G" << "D" << "A"<< "E" << "B" << "F#"
330 << "C (flats)" << "F"<< "Bb" << "Eb"<< "Ab"<< "Db"<< "Gb"
331 << "Am (sharps)" << "Em" << "Bm" << "F#m" << "C#m" << "G#m" << "D#m"
332 << "Am (flats)" << "Dm" << "Gm" << "Cm" << "Fm" << "Bbm" << "Ebm";
333
334 //don't change this function (except when renaming stuff)
335 // Static
stringToKey(QString input)336 KeyEvent KeyEvent::stringToKey(QString input) //flo
337 {
338 int index = keyStrs.indexOf(input);
339 KeyEvent map[]={
340 {KEY_C, 0, false}, {KEY_G, 0, false}, {KEY_D, 0, false}, {KEY_A, 0, false},
341 {KEY_E, 0, false}, {KEY_B, 0, false}, {KEY_FIS, 0, false},
342 {KEY_C_B, 0, false}, {KEY_F, 0, false}, {KEY_BES, 0, false}, {KEY_ES, 0, false},
343 {KEY_AS, 0, false}, {KEY_DES, 0, false}, {KEY_GES, 0, false},
344
345 {KEY_C, 0, true}, {KEY_G, 0, true}, {KEY_D, 0, true}, {KEY_A, 0, true},
346 {KEY_E, 0, true}, {KEY_B, 0, true}, {KEY_FIS, 0, true},
347 {KEY_C_B, 0, true}, {KEY_F, 0, true}, {KEY_BES, 0, true}, {KEY_ES, 0, true},
348 {KEY_AS, 0, true}, {KEY_DES, 0, true}, {KEY_GES, 0, true}
349 };
350 return map[index];
351 }
352
353 //don't change the below two functions (except when renaming stuff)
354 // Static
keyToIndex(key_enum key,bool isMinor)355 int KeyEvent::keyToIndex(key_enum key, bool isMinor)
356 {
357 int index=0;
358 switch(key)
359 {
360 case KEY_C: index= isMinor ? 14 : 0; break;
361 case KEY_G: index= isMinor ? 15 : 1; break;
362 case KEY_D: index= isMinor ? 16 : 2; break;
363 case KEY_A: index= isMinor ? 17 : 3; break;
364 case KEY_E: index= isMinor ? 18 : 4; break;
365 case KEY_B: index= isMinor ? 19 : 5; break;
366 case KEY_FIS: index= isMinor ? 20 : 6; break;
367 case KEY_C_B: index= isMinor ? 21 : 7; break;
368 case KEY_F: index= isMinor ? 22 : 8; break;
369 case KEY_BES: index= isMinor ? 23 : 9; break;
370 case KEY_ES: index= isMinor ? 24 : 10; break;
371 case KEY_AS: index= isMinor ? 25 : 11; break;
372 case KEY_DES: index= isMinor ? 26 : 12; break;
373 case KEY_GES: index= isMinor ? 27 : 13; break;
374
375 case KEY_SHARP_BEGIN:
376 case KEY_SHARP_END:
377 case KEY_B_BEGIN:
378 case KEY_B_END:
379 printf("ILLEGAL FUNCTION CALL: keyToIndex called with key_sharp_begin etc.\n");
380 return 0;
381 break;
382
383 default:
384 printf("ILLEGAL FUNCTION CALL: keyToIndex called with illegal key value (not in enum)\n");
385 return 0;
386 }
387 return index;
388 }
389
390 // Static
keyToString(key_enum key,bool isMinor)391 QString KeyEvent::keyToString(key_enum key, bool isMinor)
392 {
393 return keyStrs[keyToIndex(key, isMinor)];
394 }
395
keyIndex() const396 int KeyEvent::keyIndex() const
397 {
398 return keyToIndex(key, minor);
399 }
400
keyString() const401 QString KeyEvent::keyString() const
402 {
403 return keyToString(key, minor);
404 }
405
406
407 } // namespace MusECore
408
409
410