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