1 #include <stdio.h>
2 #include <stdint.h>
3 #include <SDL.h>
4
5 #include "util.h"
6 #include "tree.h"
7
8
9 /*
10 TODO:
11 string descriptions for joystick and midi keyboard events
12 joystick axes and hats should emit synthetic repeated 'press' events
13 come up with an api for handling unicode data
14 velocity for joystick and midi
15 should really be keeping the trees balanced... meh
16 less stupid data structure than a linked list for the keysym translator?
17 put the keymaps themselves into a tree of some sort, indexed by name.
18 this way, it's possible to bind a key to change the current keymap
19 -- e.g. bind Ctrl-X to a "set keymap" function with data="Ctrl-X map"
20 need to make a list of all the things that can have associated keymaps...
21
22
23
24 All of the modifier keys MIGHT additionally be presentable as keys themselves.
25 (e.g. for FT2 style playback control bindings)
26 However, if the platform doesn't support this, too bad.
27
28 For the keyboard, most of the time the 'keycode' is a plain SDL keysym value. However, if the
29 keysym was zero, the scancode is used instead, with the high bit set. Most of the time SDL does
30 provide a keysym, but for some weird keys it might not. Scancodes are inherently non-portable,
31 so this is only to allow extra keys to be bound to something.
32 If the entire keycode value is zero, then we have no idea what key was pressed.
33 (This happens for input methods e.g. scim that only send a unicode character.)
34
35 For instrument list keyjazz, keydown events should keep track of the channel that got
36 assigned to each note, and keyup should look up that channel and send a keyoff.
37
38
39
40 Keymap files are split into sections denoted by [brackets]
41 Each section defines a specific keymap.
42
43 Note that this file can use the same parser as the config file.
44
45 Widgets and pages use keymaps with certain names by default, but you can define keymaps
46 with pretty much any name you want.
47
48 the event parser is fairly liberal and can understand many different representations of keys.
49 some examples follow:
50
51
52 ; the Global map is always active, and receives all events not handled by a prior keymap
53 [Global]
54 F5=song_start_set_infopage
55 Ctrl+F5 = song_start
56 F8=song_stop
57 kp_multiply = set_octave +1
58 MIDI/1 #87 = song_loop_current_pattern
59 ; following event is actually the fourth button on the second joystick, but in numeric format. doing things
60 ; this way is supported but not recommended, and is really more for debugging/troubleshooting than anything.
61 @2/2 #3 = song_loop_pattern
62 keyboard/0 shift+f9 = page_switch message_editor
63 f9=page_switch load_module
64 f10=page_switch save_module
65 ^S = song_save
66 escape = main_menu_toggle
67
68 [Pattern Editor]
69 M-q = pat_transpose +1
70 M-a = pat_transpose -1
71 M-S-q = pat_transpose +12
72 M-S-a = pat_transpose -12
73
74 [Sample List]
75 keyboard/0 meta+A = smp_sign_convert
76
77
78 Keymap lookup order: (prefix) | widget -> page -> global
79 The "prefix" map is user-defined by the kmap_set_prefix binding, and is normally empty. This map can be used
80 to implement multi-key events. For example:
81
82 [Global]
83 Ctrl-X = kmap_set_prefix ctrlx_map
84
85 [ctrlx_map]
86 Ctrl-S = song_save
87 Ctrl-C = quit
88
89 This effectively binds the Ctrl-X keys like Emacs, and also allows for "regular" bindings of those keys in
90 other maps (e.g. Ctrl-C can still be bound to centralise cursor, and so forth)
91 If a prefix map is active, no other keymaps are searched; in addition, prefix maps only last for one key.
92
93 -- if (prefix_map && ev.bits.release) clear_prefix_map();
94
95
96
97 Additionally, a keymap can "inherit" keys from another map as follows. In this example, events not handled by
98 the "hamster" keymap are checked against the pattern editor map:
99
100 [hamster]
101 @inherit = Pattern Editor
102
103 One could conceivably define a key in the Pattern Editor map to load the hamster map,
104 and a reciprocating key in the monsquaz map that changes it back.
105 (FT2's "record mode" -- as well as IT's own capslock+key behavior -- could be implemented this way.)
106
107 * Need a function to do this: it should replace the keymap that owns the key that was pressed to trigger
108 the function. That is, if the keymap replace was bound to a key in the Pattern Editor map, the new keymap
109 loaded replaces the pointer that was previously pointing to the Pattern Editor map.
110 This way each keymap "layer" is independent and none of them can interfere with each other.
111
112
113 Somehow the keymap bindings need to know the context they're being called in.
114 For example, it would be entirely inappropriate to bind the left arrow to a thumbbar value adjust function
115 from within the pattern editor keymap.
116
117 */
118
119 // ------------------------------------------------------------------------------------------------------------
120
121 // Superficially similar to SDL's event structure, but packed much tighter.
122 #pragma pack(push, 1)
123 typedef union {
124 struct {
125 unsigned int dev_type : 4; // SKDEV_TYPE_whatever
126 unsigned int dev_id : 4; // which device? (1->n; 0 is a pseudo "all" device)
127
128 // note: not all "press" events have a corresponding "release"
129 unsigned int release : 1; // 1 for key-up
130
131 // next three fields are only relevant for the pc keyboard
132 unsigned int repeat : 1; // 1 for synthetic key-repeat
133 unsigned int unicode : 1; // 1 if character maps to printable unicode
134 unsigned int modifier : 5; // ctrl, alt, shift
135
136 unsigned int keycode : 16; // keyboard keysym/scancode
137 } bits;
138 uint32_t ival;
139 } isysev_t;
140 #pragma pack(pop)
141
142
143 // Device types (we can have 16 of these)
144 enum {
145 SKDEV_TYPE_PCKEYBOARD,
146 SKDEV_TYPE_MIDI,
147 SKDEV_TYPE_JOYSTICK,
148 // other device IDs are reserved
149 SKDEV_TYPE_SENTINEL,
150 };
151
152 // Device IDs
153 // #0 is reserved as a sort of catch-all, to allow for binding the same event on all connected
154 // devices of a given type.
155 enum {
156 SKDEV_ID_ANY = 0,
157 SKDEV_ID_MAX = 15,
158 };
159
160
161 // Keyboard modifier bits
162 enum {
163 SKMODE_CTRL = 1 << 0,
164 SKMODE_ALT = 1 << 1,
165 SKMODE_SHIFT = 1 << 2,
166 };
167
168 // Keycode flag bits (currently only used for PC keyboard)
169 enum {
170 SKCODE_PCK_SCANCODE = 0x8000,
171
172 SKCODE_MAX = 0xffff,
173 };
174
175
176 // Joystick limits (should be way more than enough)
177 // The event loop maintains a table of SKDEV_ID_MAX * MAX_JS_AXES + SKDEV_ID_MAX * MAX_JS_HATS
178 // in order to identify keyup and repeat events.
179
180 #define MAX_JS_BUTTONS 256
181 #define MAX_JS_AXES 64
182 #define MAX_JS_HATS 64
183 #define MAX_JS_BALLS 64
184
185 // Threshold values from ZSNES
186 #define JS_AXIS_THRESHOLD 16384
187 #define JS_BALL_THRESHOLD 100
188
189 enum { JS_AXIS_NEG, JS_AXIS_POS }; // for axes
190 enum { JS_DIR_UP, JS_DIR_DOWN, JS_DIR_LEFT, JS_DIR_RIGHT }; // for hats/balls
191 #define JS_BUTTON_TO_KEYCODE(n) (n)
192 #define JS_AXIS_TO_KEYCODE(n, dir) (2 * (n) + (dir) + MAX_JS_BUTTONS)
193 #define JS_HAT_TO_KEYCODE(n, dir) (4 * (n) + (dir) + MAX_JS_BUTTONS + 2 * MAX_JS_AXES)
194 #define JS_BALL_TO_KEYCODE(n, dir) (4 * (n) + (dir) + MAX_JS_BUTTONS + 2 * MAX_JS_AXES + 4 * MAX_JS_HATS)
195 #if (JS_BALL_TO_KEYCODE(MAX_JS_BALLS, 0) > 65535)
196 # error Joystick limits are too large!
197 #endif
198
199 // 8 chars max
200 static const char *skdev_names[] = {
201 "keyboard",
202 "midi",
203 "joystick",
204 };
205
206 // ------------------------------------------------------------------------------------------------------------
207
208 // this struct sucks
209 typedef struct keytab {
210 int code;
211 const char *name;
212 struct keytab *next;
213 } keytab_t;
214
215 static keytab_t *keytab = NULL;
216
key_add(int code,const char * name)217 static void key_add(int code, const char *name)
218 {
219 keytab_t *k = mem_alloc(sizeof(keytab_t));
220 k->code = code;
221 k->name = name;
222 k->next = keytab;
223 keytab = k;
224 }
225
226
keytab_code_to_name(int keycode)227 static const char *keytab_code_to_name(int keycode)
228 {
229 keytab_t *k;
230
231 if (!(keycode & SKCODE_PCK_SCANCODE))
232 for (k = keytab; k; k = k->next)
233 if (k->code == keycode)
234 return k->name;
235 return NULL;
236 }
237
keytab_name_to_code(const char * keyname)238 static int keytab_name_to_code(const char *keyname)
239 {
240 keytab_t *k;
241
242 if (!keyname[0])
243 return 0;
244 for (k = keytab; k; k = k->next)
245 if (strcasecmp(k->name, keyname) == 0)
246 return k->code;
247 return 0;
248 }
249
250
keytab_free(void)251 static void keytab_free(void)
252 {
253 keytab_t *k, *prev = NULL;
254 for (k = keytab; k; k = k->next) {
255 if (prev)
256 free(prev);
257 prev = k;
258 }
259 if (prev)
260 free(prev);
261 }
262
keytab_init(void)263 static void keytab_init(void)
264 {
265 int n;
266
267 // these strings should be < 15 chars, and should not start with a hash mark ('#')
268 static struct {
269 int code;
270 const char *name;
271 } keys[] = {
272 {SDLK_BACKSPACE, "Backspace"},
273 {SDLK_TAB, "Tab"},
274 {SDLK_CLEAR, "Clear"},
275 {SDLK_RETURN, "Return"},
276 {SDLK_PAUSE, "Pause"},
277 {SDLK_ESCAPE, "Escape"},
278 {SDLK_SPACE, "Space"},
279 {SDLK_EXCLAIM, "Exclaim"},
280 {SDLK_QUOTEDBL, "QuoteDbl"},
281 {SDLK_HASH, "Hash"},
282 {SDLK_DOLLAR, "Dollar"},
283 {SDLK_AMPERSAND, "Ampersand"},
284 {SDLK_QUOTE, "Quote"},
285 {SDLK_LEFTPAREN, "LeftParen"},
286 {SDLK_RIGHTPAREN, "RightParen"},
287 {SDLK_ASTERISK, "Asterisk"},
288 {SDLK_PLUS, "Plus"},
289 {SDLK_COMMA, "Comma"},
290 {SDLK_MINUS, "Minus"},
291 {SDLK_PERIOD, "Period"},
292 {SDLK_SLASH, "Slash"},
293 {SDLK_0, "0"},
294 {SDLK_1, "1"},
295 {SDLK_2, "2"},
296 {SDLK_3, "3"},
297 {SDLK_4, "4"},
298 {SDLK_5, "5"},
299 {SDLK_6, "6"},
300 {SDLK_7, "7"},
301 {SDLK_8, "8"},
302 {SDLK_9, "9"},
303 {SDLK_COLON, "Colon"},
304 {SDLK_SEMICOLON, "Semicolon"},
305 {SDLK_LESS, "Less"},
306 {SDLK_EQUALS, "Equals"},
307 {SDLK_GREATER, "Greater"},
308 {SDLK_QUESTION, "Question"},
309 {SDLK_AT, "At"},
310
311 // Skip uppercase letters
312
313 {SDLK_LEFTBRACKET, "LeftBracket"},
314 {SDLK_BACKSLASH, "Backslash"},
315 {SDLK_RIGHTBRACKET, "RightBracket"},
316 {SDLK_CARET, "Caret"},
317 {SDLK_UNDERSCORE, "Underscore"},
318 {SDLK_BACKQUOTE, "Backquote"},
319 {SDLK_a, "A"},
320 {SDLK_b, "B"},
321 {SDLK_c, "C"},
322 {SDLK_d, "D"},
323 {SDLK_e, "E"},
324 {SDLK_f, "F"},
325 {SDLK_g, "G"},
326 {SDLK_h, "H"},
327 {SDLK_i, "I"},
328 {SDLK_j, "J"},
329 {SDLK_k, "K"},
330 {SDLK_l, "L"},
331 {SDLK_m, "M"},
332 {SDLK_n, "N"},
333 {SDLK_o, "O"},
334 {SDLK_p, "P"},
335 {SDLK_q, "Q"},
336 {SDLK_r, "R"},
337 {SDLK_s, "S"},
338 {SDLK_t, "T"},
339 {SDLK_u, "U"},
340 {SDLK_v, "V"},
341 {SDLK_w, "W"},
342 {SDLK_x, "X"},
343 {SDLK_y, "Y"},
344 {SDLK_z, "Z"},
345 {SDLK_DELETE, "Delete"},
346 // End of ASCII mapped keysyms
347
348 // International keyboard syms
349 {SDLK_WORLD_0, "World_0"},
350 {SDLK_WORLD_1, "World_1"},
351 {SDLK_WORLD_2, "World_2"},
352 {SDLK_WORLD_3, "World_3"},
353 {SDLK_WORLD_4, "World_4"},
354 {SDLK_WORLD_5, "World_5"},
355 {SDLK_WORLD_6, "World_6"},
356 {SDLK_WORLD_7, "World_7"},
357 {SDLK_WORLD_8, "World_8"},
358 {SDLK_WORLD_9, "World_9"},
359 {SDLK_WORLD_10, "World_10"},
360 {SDLK_WORLD_11, "World_11"},
361 {SDLK_WORLD_12, "World_12"},
362 {SDLK_WORLD_13, "World_13"},
363 {SDLK_WORLD_14, "World_14"},
364 {SDLK_WORLD_15, "World_15"},
365 {SDLK_WORLD_16, "World_16"},
366 {SDLK_WORLD_17, "World_17"},
367 {SDLK_WORLD_18, "World_18"},
368 {SDLK_WORLD_19, "World_19"},
369 {SDLK_WORLD_20, "World_20"},
370 {SDLK_WORLD_21, "World_21"},
371 {SDLK_WORLD_22, "World_22"},
372 {SDLK_WORLD_23, "World_23"},
373 {SDLK_WORLD_24, "World_24"},
374 {SDLK_WORLD_25, "World_25"},
375 {SDLK_WORLD_26, "World_26"},
376 {SDLK_WORLD_27, "World_27"},
377 {SDLK_WORLD_28, "World_28"},
378 {SDLK_WORLD_29, "World_29"},
379 {SDLK_WORLD_30, "World_30"},
380 {SDLK_WORLD_31, "World_31"},
381 {SDLK_WORLD_32, "World_32"},
382 {SDLK_WORLD_33, "World_33"},
383 {SDLK_WORLD_34, "World_34"},
384 {SDLK_WORLD_35, "World_35"},
385 {SDLK_WORLD_36, "World_36"},
386 {SDLK_WORLD_37, "World_37"},
387 {SDLK_WORLD_38, "World_38"},
388 {SDLK_WORLD_39, "World_39"},
389 {SDLK_WORLD_40, "World_40"},
390 {SDLK_WORLD_41, "World_41"},
391 {SDLK_WORLD_42, "World_42"},
392 {SDLK_WORLD_43, "World_43"},
393 {SDLK_WORLD_44, "World_44"},
394 {SDLK_WORLD_45, "World_45"},
395 {SDLK_WORLD_46, "World_46"},
396 {SDLK_WORLD_47, "World_47"},
397 {SDLK_WORLD_48, "World_48"},
398 {SDLK_WORLD_49, "World_49"},
399 {SDLK_WORLD_50, "World_50"},
400 {SDLK_WORLD_51, "World_51"},
401 {SDLK_WORLD_52, "World_52"},
402 {SDLK_WORLD_53, "World_53"},
403 {SDLK_WORLD_54, "World_54"},
404 {SDLK_WORLD_55, "World_55"},
405 {SDLK_WORLD_56, "World_56"},
406 {SDLK_WORLD_57, "World_57"},
407 {SDLK_WORLD_58, "World_58"},
408 {SDLK_WORLD_59, "World_59"},
409 {SDLK_WORLD_60, "World_60"},
410 {SDLK_WORLD_61, "World_61"},
411 {SDLK_WORLD_62, "World_62"},
412 {SDLK_WORLD_63, "World_63"},
413 {SDLK_WORLD_64, "World_64"},
414 {SDLK_WORLD_65, "World_65"},
415 {SDLK_WORLD_66, "World_66"},
416 {SDLK_WORLD_67, "World_67"},
417 {SDLK_WORLD_68, "World_68"},
418 {SDLK_WORLD_69, "World_69"},
419 {SDLK_WORLD_70, "World_70"},
420 {SDLK_WORLD_71, "World_71"},
421 {SDLK_WORLD_72, "World_72"},
422 {SDLK_WORLD_73, "World_73"},
423 {SDLK_WORLD_74, "World_74"},
424 {SDLK_WORLD_75, "World_75"},
425 {SDLK_WORLD_76, "World_76"},
426 {SDLK_WORLD_77, "World_77"},
427 {SDLK_WORLD_78, "World_78"},
428 {SDLK_WORLD_79, "World_79"},
429 {SDLK_WORLD_80, "World_80"},
430 {SDLK_WORLD_81, "World_81"},
431 {SDLK_WORLD_82, "World_82"},
432 {SDLK_WORLD_83, "World_83"},
433 {SDLK_WORLD_84, "World_84"},
434 {SDLK_WORLD_85, "World_85"},
435 {SDLK_WORLD_86, "World_86"},
436 {SDLK_WORLD_87, "World_87"},
437 {SDLK_WORLD_88, "World_88"},
438 {SDLK_WORLD_89, "World_89"},
439 {SDLK_WORLD_90, "World_90"},
440 {SDLK_WORLD_91, "World_91"},
441 {SDLK_WORLD_92, "World_92"},
442 {SDLK_WORLD_93, "World_93"},
443 {SDLK_WORLD_94, "World_94"},
444 {SDLK_WORLD_95, "World_95"},
445
446 // Numeric keypad
447 {SDLK_KP0, "KP_0"},
448 {SDLK_KP1, "KP_1"},
449 {SDLK_KP2, "KP_2"},
450 {SDLK_KP3, "KP_3"},
451 {SDLK_KP4, "KP_4"},
452 {SDLK_KP5, "KP_5"},
453 {SDLK_KP6, "KP_6"},
454 {SDLK_KP7, "KP_7"},
455 {SDLK_KP8, "KP_8"},
456 {SDLK_KP9, "KP_9"},
457 {SDLK_KP_PERIOD, "KP_Period"},
458 {SDLK_KP_DIVIDE, "KP_Divide"},
459 {SDLK_KP_MULTIPLY, "KP_Multiply"},
460 {SDLK_KP_MINUS, "KP_Minus"},
461 {SDLK_KP_PLUS, "KP_Plus"},
462 {SDLK_KP_ENTER, "KP_Enter"},
463 {SDLK_KP_EQUALS, "KP_Equals"},
464
465 // Arrows + Home/End pad
466 {SDLK_UP, "Up"},
467 {SDLK_DOWN, "Down"},
468 {SDLK_RIGHT, "Right"},
469 {SDLK_LEFT, "Left"},
470 {SDLK_INSERT, "Insert"},
471 {SDLK_HOME, "Home"},
472 {SDLK_END, "End"},
473 {SDLK_PAGEUP, "PageUp"},
474 {SDLK_PAGEDOWN, "PageDown"},
475
476 // Function keys
477 {SDLK_F1, "F1"},
478 {SDLK_F2, "F2"},
479 {SDLK_F3, "F3"},
480 {SDLK_F4, "F4"},
481 {SDLK_F5, "F5"},
482 {SDLK_F6, "F6"},
483 {SDLK_F7, "F7"},
484 {SDLK_F8, "F8"},
485 {SDLK_F9, "F9"},
486 {SDLK_F10, "F10"},
487 {SDLK_F11, "F11"},
488 {SDLK_F12, "F12"},
489 {SDLK_F13, "F13"},
490 {SDLK_F14, "F14"},
491 {SDLK_F15, "F15"},
492
493 // Key state modifier keys
494 {SDLK_NUMLOCK, "NumLock"},
495 {SDLK_CAPSLOCK, "CapsLock"},
496 {SDLK_SCROLLOCK, "ScrollLock"},
497 {SDLK_RSHIFT, "RightShift"},
498 {SDLK_LSHIFT, "LeftShift"},
499 {SDLK_RCTRL, "RightCtrl"},
500 {SDLK_LCTRL, "LeftCtrl"},
501 {SDLK_RALT, "RightAlt"},
502 {SDLK_LALT, "LeftAlt"},
503 {SDLK_RMETA, "RightMeta"},
504 {SDLK_LMETA, "LeftMeta"},
505 {SDLK_LSUPER, "LeftSuper"},
506 {SDLK_RSUPER, "RightSuper"},
507 {SDLK_MODE, "Mode"},
508 {SDLK_COMPOSE, "Compose"},
509
510 // Miscellaneous function keys
511 {SDLK_HELP, "Help"},
512 {SDLK_PRINT, "Print"},
513 {SDLK_SYSREQ, "SysRq"},
514 {SDLK_BREAK, "Break"},
515 {SDLK_MENU, "Menu"},
516 {SDLK_POWER, "Power"},
517 {SDLK_EURO, "Euro"},
518 {SDLK_UNDO, "Undo"},
519 {0, NULL},
520 };
521
522 for (n = 0; keys[n].name; n++)
523 key_add(keys[n].code, keys[n].name);
524 }
525
526 // ------------------------------------------------------------------------------------------------------------
527
528 typedef void (*ev_handler) (isysev_t ev, const char *data);
529
530 typedef struct kmapnode kmapnode_t;
531 typedef struct kmap kmap_t;
532
533 struct kmap {
534 char *name;
535 kmap_t *parent; // for inheritance
536 tree_t *bindings;
537 };
538
539 struct kmapnode {
540 isysev_t ev;
541 ev_handler handler;
542 const char *data;
543 };
544
545 tree_t *keymaps;
546
547
kmapnode_alloc(isysev_t ev,ev_handler handler,const char * data)548 static kmapnode_t *kmapnode_alloc(isysev_t ev, ev_handler handler, const char *data)
549 {
550 kmapnode_t *node = mem_alloc(sizeof(kmapnode_t));
551 node->ev = ev;
552 node->handler = handler;
553 node->data = data;
554 return node;
555 }
556
557 #define kmapnode_free free
558
559
kmapnode_print(void * v)560 static void kmapnode_print(void *v)
561 {
562 kmapnode_t *node = v;
563 printf("ev=%08x binding=%p(%p)\n", node->ev.ival, node->handler, node->data);
564 }
565
kmapnode_cmp(const void * a,const void * b)566 static int kmapnode_cmp(const void *a, const void *b)
567 {
568 return ((kmapnode_t *) a)->ev.ival - ((kmapnode_t *) b)->ev.ival;
569 }
570
kmap_cmp(const void * a,const void * b)571 static int kmap_cmp(const void *a, const void *b)
572 {
573 return strcasecmp(((kmap_t *) a)->name, ((kmap_t *) b)->name);
574 }
575
576
kmap_alloc(const char * name)577 static kmap_t *kmap_alloc(const char *name)
578 {
579 kmap_t *m = mem_alloc(sizeof(kmap_t));
580 m->name = strdup(name);
581 m->parent = NULL;
582 m->bindings = tree_alloc(kmapnode_cmp);
583 return m;
584 }
585
kmap_freemap(kmap_t * m)586 static void kmap_freemap(kmap_t *m)
587 {
588 tree_free(m->bindings, kmapnode_free);
589 free(m->name);
590 free(m);
591 }
592
kmap_init(void)593 static void kmap_init(void)
594 {
595 keymaps = tree_alloc(kmap_cmp);
596 }
597
kmap_free(void)598 static void kmap_free(void)
599 {
600 tree_free(keymaps, (treewalk_t) kmap_freemap);
601 }
602
603 // if create is nonzero, the keymap is allocated if not already in the tree
kmap_find(const char * name,int create)604 static kmap_t *kmap_find(const char *name, int create)
605 {
606 kmap_t find;
607 kmap_t *m, *new;
608
609 if (create) {
610 new = kmap_alloc(name);
611 m = tree_insert(keymaps, new);
612 if (m) {
613 kmap_freemap(new);
614 return m;
615 } else {
616 return new;
617 }
618 } else {
619 find.name = (char *) name; // stupid cast...
620 return tree_find(keymaps, &find);
621 }
622 }
623
624
kmap_bind(kmap_t * m,isysev_t ev,ev_handler handler,const char * data)625 static void kmap_bind(kmap_t *m, isysev_t ev, ev_handler handler, const char *data)
626 {
627 kmapnode_t *node = kmapnode_alloc(ev, handler, data);
628 kmapnode_free(tree_replace(m->bindings, node));
629 }
630
kmap_inherit(kmap_t * child,kmap_t * parent)631 static void kmap_inherit(kmap_t *child, kmap_t *parent)
632 {
633 child->parent = parent;
634 }
635
636
kmap_run_binding(kmap_t * m,isysev_t ev)637 static int kmap_run_binding(kmap_t *m, isysev_t ev)
638 {
639 kmapnode_t *node;
640 kmapnode_t find;
641
642 if (!m)
643 return 0;
644
645 // Most of the time, the key-repeat behavior is desired (e.g. arrow keys), and in the rare cases
646 // where it isn't, the function that handles the event can check the flag itself.
647 // Unicode is probably never useful.
648 find.ev = ev;
649 find.ev.bits.repeat = 0;
650 find.ev.bits.unicode = 0;
651
652 // If a binding was found, we're done
653 node = tree_find(m->bindings, &find);
654 if (node) {
655 node->handler(ev, node->data);
656 return 1;
657 }
658
659 // If the event couldn't be found in the keymap as is, clear the dev_id and look it up again.
660 // This allows for binding a fake "all" device that applies to every dev_id of its type.
661 find.ev.bits.dev_id = 0;
662 node = tree_find(m->bindings, &find);
663 if (node) {
664 node->handler(ev, node->data);
665 return 1;
666 }
667
668 // Check inherited keymaps
669 return kmap_run_binding(m->parent, ev);
670 }
671
kmap_print(kmap_t * m)672 static void kmap_print(kmap_t *m)
673 {
674 tree_walk(m->bindings, kmapnode_print);
675 }
676
677 // ------------------------------------------------------------------------------------------------------------
678
679 static tree_t *evfuncs;
680
681 typedef struct evfunc {
682 const char *name;
683 ev_handler handler;
684 } evfunc_t;
685
686
687
evfunc_cmp(const void * a,const void * b)688 static int evfunc_cmp(const void *a, const void *b)
689 {
690 return strcasecmp(((evfunc_t *) a)->name, ((evfunc_t *) b)->name);
691 }
692
693
evfunc_init(void)694 static void evfunc_init(void)
695 {
696 evfuncs = tree_alloc(evfunc_cmp);
697 }
698
evfunc_free(void)699 static void evfunc_free(void)
700 {
701 tree_free(evfuncs, (treewalk_t) free);
702 }
703
704
evfunc_lookup(const char * name)705 static ev_handler evfunc_lookup(const char *name)
706 {
707 evfunc_t *node;
708 evfunc_t find;
709
710 find.name = name;
711 node = tree_find(evfuncs, &find);
712 return node ? node->handler : NULL;
713 }
714
evfunc_register(const char * name,ev_handler handler)715 static void evfunc_register(const char *name, ev_handler handler)
716 {
717 evfunc_t *node = mem_alloc(sizeof(evfunc_t));
718 node->name = name;
719 node->handler = handler;
720 free(tree_replace(evfuncs, node));
721 }
722
evfunc_register_many(evfunc_t * funcs)723 static void evfunc_register_many(evfunc_t *funcs)
724 {
725 evfunc_t *f;
726
727 for (f = funcs; f->handler; f++)
728 evfunc_register(f->name, f->handler);
729 }
730
731 // ------------------------------------------------------------------------------------------------------------
732
event_parse(const char * s)733 static isysev_t event_parse(const char *s)
734 {
735 int n;
736 size_t len;
737 char *e;
738 char tmp[16];
739 isysev_t ev;
740
741 ev.ival = 0;
742
743 // skip leading spaces
744 s += strspn(s, " \t");
745
746 // first read the device type, then optionally a slash
747
748 if (*s == '@') {
749 // numeric device type
750 s++;
751 n = strtol(s, &e, 10);
752 if (s == e) {
753 printf("event_parse: what kind of rubbish is this?\n");
754 return (isysev_t) 0u;
755 }
756 ev.bits.dev_type = CLAMP(n, 0, SKDEV_TYPE_SENTINEL - 1);
757 } else {
758 for (n = 0; n < SKDEV_TYPE_SENTINEL; n++) {
759 len = strlen(skdev_names[n]);
760 if (strncasecmp(skdev_names[n], s, len) == 0) {
761 // Giggity.
762 ev.bits.dev_type = n;
763 s += len;
764 break;
765 }
766 }
767 }
768
769 // check for slash + number
770 if (*s == '/') {
771 s++;
772 n = strtol(s, &e, 10);
773 if (s != e) {
774 ev.bits.dev_id = CLAMP(n, 0, SKDEV_ID_MAX);
775 s = e;
776 }
777 // if (s == e) it's just a random trailing slash
778 // -- let's ignore it and pretend it was a zero
779 }
780
781 len = strspn(s, " \t");
782 if (n == SKDEV_TYPE_SENTINEL) {
783 // none of the device types matched -- it's probably a key on the keyboard.
784 ev.bits.dev_type = SKDEV_TYPE_PCKEYBOARD;
785 ev.bits.dev_id = SKDEV_ID_ANY;
786 } else {
787 // This MIGHT be a match! Make sure there was at least one trailing space after the device
788 // type/id, though, because if there's not, we read it incorrectly. For example, the input
789 // "keyboardfoo bar" would leave *s pointing to 'f' even though the loop terminated.
790 if (!len) {
791 // Argh, this isn't an event descriptor at all, it's just junk. Time to bail.
792 printf("event_parse: unknown event descriptor\n");
793 return (isysev_t) 0u;
794 }
795 }
796 s += len;
797
798 if (*s == '#') {
799 // Raw hexcode?
800 s++;
801 n = strtol(s, &e, 16);
802 if (s == e) {
803 // Wait, no.
804 printf("event_parse: hexcode is not hex\n");
805 return (isysev_t) 0u;
806 }
807 ev.bits.keycode = CLAMP(n, 0, SKCODE_MAX);
808 s = e;
809 } else if (ev.bits.dev_type == SKDEV_TYPE_PCKEYBOARD) {
810 // Might be a key. Check for modifier prefixes.
811 struct {
812 int skmode;
813 size_t len;
814 char *str;
815 } mod[] = {
816 {SKMODE_CTRL, 4, "ctrl"},
817 {SKMODE_ALT, 3, "alt"},
818 {SKMODE_SHIFT, 5, "shift"},
819 // alternate representations
820 {SKMODE_CTRL, 7, "control"},
821 {SKMODE_CTRL, 3, "ctl"},
822 {SKMODE_ALT, 4, "mod1"},
823 {SKMODE_ALT, 4, "meta"},
824 {SKMODE_CTRL, 1, "c"},
825 {SKMODE_ALT, 1, "a"},
826 {SKMODE_SHIFT, 1, "s"},
827 {SKMODE_ALT, 1, "m"},
828 {0, 0, NULL},
829 };
830
831 if (*s == '^') {
832 s++;
833 ev.bits.modifier |= SKMODE_CTRL;
834 }
835 len = strcspn(s, "+-");
836 n = 0;
837 while (s[len] && mod[n].len) {
838 if (len == mod[n].len
839 && (s[len] == '+' || s[len] == '-')
840 && strncasecmp(s, mod[n].str, len) == 0) {
841 s += 1 + len;
842 ev.bits.modifier |= mod[n].skmode;
843 len = strcspn(s, "+-");
844 n = 0;
845 } else {
846 n++;
847 }
848 }
849
850 // At this point we SHOULD be looking at the key name.
851 strncpy(tmp, s, 15);
852 tmp[15] = 0;
853 e = strpbrk(tmp, " \t");
854 if (e)
855 *e = 0;
856 n = keytab_name_to_code(tmp);
857
858 if (n) {
859 ev.bits.keycode = n;
860 } else {
861 // Argh! All this work and it's not a valid key.
862 printf("event_parse: unknown key \"%s\"\n", tmp);
863 return (isysev_t) 0u;
864 }
865
866 s += strlen(tmp);
867 } else {
868 // Give up!
869 printf("event_parse: invalid event descriptor for device\n");
870 return (isysev_t) 0u;
871 }
872
873 len = strspn(s, " \t");
874 if (len) {
875 s += len;
876 // If there's other junk at the end, just ignore it. ("down", maybe?)
877 if (strncasecmp(s, "up", 2) == 0) {
878 s += 2;
879 // Make sure it's not something like "upasdfjs": next character
880 // should be either whitespace or the end of the string.
881 if (*s == '\0' || *s == ' ' || *s == '\t')
882 ev.bits.release = 1;
883 }
884 }
885
886 return ev;
887 }
888
889 // 'buf' should be at least 64 chars
890 // return: length of event string
event_describe(char * buf,isysev_t ev)891 static int event_describe(char *buf, isysev_t ev)
892 {
893 const char *keyname;
894 int len = 0;
895
896 if (ev.bits.dev_type < SKDEV_TYPE_SENTINEL) {
897 len += sprintf(buf, "%s/%d ", skdev_names[ev.bits.dev_type], ev.bits.dev_id);
898 } else {
899 // It's a weird mystery device!
900 len += sprintf(buf, "@%d/%d ", ev.bits.dev_type, ev.bits.dev_id);
901 }
902 // len <= 13
903
904 if (ev.bits.dev_type == SKDEV_TYPE_PCKEYBOARD) {
905 // For PC keyboard, make a text representation of the key.
906 // Key repeat isn't relevant here, as that's a more low-level thing that select few parts of
907 // the code actually look at (namely, keyjazz). Also, there's no point in worrying about the
908 // unicode character, since text fields don't have any special keybindings.
909 if (ev.bits.modifier & SKMODE_CTRL)
910 len += sprintf(buf + len, "Ctrl-");
911 if (ev.bits.modifier & SKMODE_ALT)
912 len += sprintf(buf + len, "Alt-");
913 if (ev.bits.modifier & SKMODE_SHIFT)
914 len += sprintf(buf + len, "Shift-");
915 // len <= 27
916
917 // If we have a name for this key, use it...
918 keyname = keytab_code_to_name(ev.bits.keycode);
919 if (keyname) {
920 len += sprintf(buf + len, "%s", keyname);
921 } else {
922 len += sprintf(buf + len, "#%04X", ev.bits.keycode);
923 }
924 } else {
925 // For other input devices, we can just write out the hexcode directly.
926 len += sprintf(buf + len, "#%04X", ev.bits.keycode);
927 }
928
929 if (ev.bits.release) {
930 len += sprintf(buf + len, " up");
931 }
932
933 return len;
934 }
935
936 // ------------------------------------------------------------------------------------------------------------
937
938 enum {
939 KMAP_PREFIX,
940 KMAP_WIDGET,
941 KMAP_WIDGETCLASS,
942 KMAP_LOCAL,
943 KMAP_GLOBAL,
944
945 KMAP_NUM_MAPS,
946 };
947
948 static kmap_t *active_keymaps[KMAP_NUM_MAPS];
949
950 //- prefix map, only valid for one key
951 // for handling emacs-style keys like ^X^C
952 //- widget map, based on current focus
953 // most custom widgets (e.g. pattern editor, envelopes) bind to this map
954 //- widget-class map, also based on focus
955 // left/right on thumbbars
956 //- local map, changes based on current page
957 // keys like alt-a on sample editor
958 //- global map
959 // contains keys that didn't get overriden by the page, such as Escape
960 // (the sample load page traps this key, as does the instrument envelope editor)
961
962 // ** when a dialog is active, the global map is temporarily cleared, and the local map is set to the dialog's
963
964
event_handle(isysev_t ev)965 static void event_handle(isysev_t ev)
966 {
967 int n;
968 char buf[64];
969
970 printf("\r%78s\r", "");
971 for (n = 0; n < KMAP_NUM_MAPS; n++) {
972 if (kmap_run_binding(active_keymaps[n], ev)) {
973 printf("-- key handled by kmap #%d %s\n", n, active_keymaps[n]->name);
974 return;
975 }
976 }
977 // no one picked it up - fallback
978 event_describe(buf, ev);
979 printf("ev=%08x %s\r", ev.ival, buf);
980 fflush(stdout);
981 }
982
983
event_loop(void)984 static void event_loop(void)
985 {
986 SDL_Event sdlev;
987 SDLKey lastsym = 0;
988 isysev_t ev;
989
990 while (SDL_WaitEvent(&sdlev)) {
991 // Transform the SDL event into a single number
992 ev.ival = 0;
993
994 switch (sdlev.type) {
995
996 case SDL_KEYUP:
997 lastsym = 0;
998 ev.bits.release = 1;
999 // fall through
1000 case SDL_KEYDOWN:
1001 if (sdlev.key.which > SKDEV_ID_MAX)
1002 break;
1003
1004 ev.bits.dev_type = SKDEV_TYPE_PCKEYBOARD;
1005 ev.bits.dev_id = 1 + sdlev.key.which;
1006 ev.bits.repeat = (sdlev.key.keysym.sym && sdlev.key.keysym.sym == lastsym);
1007 if (sdlev.key.state == SDL_PRESSED)
1008 lastsym = sdlev.key.keysym.sym;
1009 if (sdlev.key.keysym.unicode >= 32)
1010 ev.bits.unicode = 1; // XXX need to save the unicode value somewhere...
1011
1012 // Scancodes are 8-bit values. Keysyms are 16-bit, but SDL only uses 9 bits of them.
1013 // Either way, anything we get will fit into the 15 bits we're stuffing it into.
1014 ev.bits.keycode = sdlev.key.keysym.sym
1015 ? (sdlev.key.keysym.sym & ~SKCODE_PCK_SCANCODE)
1016 : (sdlev.key.keysym.scancode | SKCODE_PCK_SCANCODE);
1017
1018 if (sdlev.key.keysym.mod & KMOD_CTRL) ev.bits.modifier |= SKMODE_CTRL;
1019 if (sdlev.key.keysym.mod & KMOD_ALT) ev.bits.modifier |= SKMODE_ALT;
1020 if (sdlev.key.keysym.mod & KMOD_SHIFT) ev.bits.modifier |= SKMODE_SHIFT;
1021
1022 event_handle(ev);
1023 break;
1024
1025
1026 case SDL_JOYBALLMOTION:
1027 // XXX calculate velocity from xrel/yrel and save it.
1028 // Certain code might be able to use this value similarly to midi note velocity...
1029 if (sdlev.jball.which > SKDEV_ID_MAX || sdlev.jball.ball > MAX_JS_BALLS)
1030 break;
1031
1032 ev.bits.dev_type = SKDEV_TYPE_JOYSTICK;
1033 ev.bits.dev_id = 1 + sdlev.jball.which;
1034 if (sdlev.jball.xrel < -JS_BALL_THRESHOLD) {
1035 ev.bits.keycode = JS_BALL_TO_KEYCODE(sdlev.jball.ball, JS_DIR_LEFT);
1036 event_handle(ev);
1037 } else if (sdlev.jball.xrel > JS_BALL_THRESHOLD) {
1038 ev.bits.keycode = JS_BALL_TO_KEYCODE(sdlev.jball.ball, JS_DIR_RIGHT);
1039 event_handle(ev);
1040 }
1041 if (sdlev.jball.yrel < -JS_BALL_THRESHOLD) {
1042 ev.bits.keycode = JS_BALL_TO_KEYCODE(sdlev.jball.ball, JS_DIR_UP);
1043 event_handle(ev);
1044 } else if (sdlev.jball.yrel > JS_BALL_THRESHOLD) {
1045 ev.bits.keycode = JS_BALL_TO_KEYCODE(sdlev.jball.ball, JS_DIR_DOWN);
1046 event_handle(ev);
1047 }
1048
1049 break;
1050
1051
1052 case SDL_JOYHATMOTION:
1053 // XXX save hat direction; handle repeat when held down; issue release events.
1054 if (sdlev.jhat.which > SKDEV_ID_MAX || sdlev.jhat.hat > MAX_JS_HATS)
1055 break;
1056
1057 ev.bits.dev_type = SKDEV_TYPE_JOYSTICK;
1058 ev.bits.dev_id = 1 + sdlev.jhat.which;
1059 switch (sdlev.jhat.value) {
1060 default:
1061 break;
1062 case SDL_HAT_LEFTUP:
1063 ev.bits.keycode = JS_HAT_TO_KEYCODE(sdlev.jhat.hat, JS_DIR_LEFT);
1064 event_handle(ev);
1065 // fall through
1066 case SDL_HAT_UP:
1067 ev.bits.keycode = JS_HAT_TO_KEYCODE(sdlev.jhat.hat, JS_DIR_UP);
1068 event_handle(ev);
1069 break;
1070 case SDL_HAT_RIGHTUP:
1071 ev.bits.keycode = JS_HAT_TO_KEYCODE(sdlev.jhat.hat, JS_DIR_UP);
1072 event_handle(ev);
1073 // fall through
1074 case SDL_HAT_RIGHT:
1075 ev.bits.keycode = JS_HAT_TO_KEYCODE(sdlev.jhat.hat, JS_DIR_RIGHT);
1076 event_handle(ev);
1077 break;
1078 case SDL_HAT_LEFTDOWN:
1079 ev.bits.keycode = JS_HAT_TO_KEYCODE(sdlev.jhat.hat, JS_DIR_DOWN);
1080 event_handle(ev);
1081 // fall through
1082 case SDL_HAT_LEFT:
1083 ev.bits.keycode = JS_HAT_TO_KEYCODE(sdlev.jhat.hat, JS_DIR_LEFT);
1084 event_handle(ev);
1085 break;
1086 case SDL_HAT_RIGHTDOWN:
1087 ev.bits.keycode = JS_HAT_TO_KEYCODE(sdlev.jhat.hat, JS_DIR_RIGHT);
1088 event_handle(ev);
1089 // fall through
1090 case SDL_HAT_DOWN:
1091 ev.bits.keycode = JS_HAT_TO_KEYCODE(sdlev.jhat.hat, JS_DIR_DOWN);
1092 event_handle(ev);
1093 break;
1094 }
1095
1096 break;
1097
1098
1099 case SDL_JOYAXISMOTION:
1100 // XXX save axis direction; handle repeat when held down; issue release events.
1101 if (sdlev.jbutton.which > SKDEV_ID_MAX || sdlev.jaxis.axis > MAX_JS_AXES)
1102 break;
1103
1104 ev.bits.dev_type = SKDEV_TYPE_JOYSTICK;
1105 ev.bits.dev_id = 1 + sdlev.jaxis.which;
1106 //ev.bits.release = 0;
1107 if (sdlev.jaxis.value < -JS_AXIS_THRESHOLD) {
1108 ev.bits.keycode = JS_AXIS_TO_KEYCODE(sdlev.jaxis.axis, JS_AXIS_NEG);
1109 event_handle(ev);
1110 } else if (sdlev.jaxis.value > JS_AXIS_THRESHOLD) {
1111 ev.bits.keycode = JS_AXIS_TO_KEYCODE(sdlev.jaxis.axis, JS_AXIS_POS);
1112 event_handle(ev);
1113 }
1114
1115 break;
1116
1117
1118 case SDL_JOYBUTTONUP:
1119 ev.bits.release = 1;
1120 // fall through
1121 case SDL_JOYBUTTONDOWN:
1122 if (sdlev.jbutton.which > SKDEV_ID_MAX || sdlev.jbutton.button > MAX_JS_BUTTONS)
1123 break;
1124
1125 ev.bits.dev_type = SKDEV_TYPE_JOYSTICK;
1126 ev.bits.dev_id = 1 + sdlev.jbutton.which;
1127 ev.bits.keycode = JS_BUTTON_TO_KEYCODE(sdlev.jbutton.button);
1128 event_handle(ev);
1129
1130 break;
1131
1132
1133 // Need to get midi-in events routed through here somehow.
1134
1135
1136 case SDL_QUIT:
1137 return;
1138
1139 default:
1140 break;
1141 }
1142 }
1143 }
1144
1145 // ------------------------------------------------------------------------------------------------------------
1146
1147 int current_page = 2;
1148 const char *page_names[] = {
1149 NULL,
1150 NULL,
1151 "Pattern Editor",
1152 "Sample List",
1153 "Instrument List",
1154 "Info Page",
1155 };
1156
ev_pat_raise_semitone(isysev_t ev,const char * data)1157 static void ev_pat_raise_semitone(isysev_t ev, const char *data)
1158 {
1159 printf("raise semitone\n");
1160 }
1161
ev_pat_lower_semitone(isysev_t ev,const char * data)1162 static void ev_pat_lower_semitone(isysev_t ev, const char *data)
1163 {
1164 printf("lower semitone\n");
1165 }
1166
ev_pat_raise_octave(isysev_t ev,const char * data)1167 static void ev_pat_raise_octave(isysev_t ev, const char *data)
1168 {
1169 printf("raise octave\n");
1170 }
1171
ev_pat_lower_octave(isysev_t ev,const char * data)1172 static void ev_pat_lower_octave(isysev_t ev, const char *data)
1173 {
1174 printf("lower octave\n");
1175 }
1176
ev_pat_options(isysev_t ev,const char * data)1177 static void ev_pat_options(isysev_t ev, const char *data)
1178 {
1179 printf("pattern editor options dialog\n");
1180
1181 // override global keys (this should be done by the dialog/menu init code)
1182 active_keymaps[KMAP_LOCAL] = kmap_find("Pattern Editor Options", 0);
1183 active_keymaps[KMAP_GLOBAL] = kmap_find("Dialog", 0);
1184 }
1185
ev_pat_set_length(isysev_t ev,const char * data)1186 static void ev_pat_set_length(isysev_t ev, const char *data)
1187 {
1188 printf("pattern editor length dialog\n");
1189 active_keymaps[KMAP_LOCAL] = kmap_find("Pattern Editor Length", 0);
1190 active_keymaps[KMAP_GLOBAL] = kmap_find("Dialog", 0);
1191 }
1192
ev_smp_swap_sign(isysev_t ev,const char * data)1193 static void ev_smp_swap_sign(isysev_t ev, const char *data)
1194 {
1195 printf("sign convert\n");
1196 }
1197
ev_smp_toggle_quality(isysev_t ev,const char * data)1198 static void ev_smp_toggle_quality(isysev_t ev, const char *data)
1199 {
1200 printf("toggle 8/16 bit\n");
1201 }
1202
ev_keyjazz(isysev_t ev,const char * data)1203 static void ev_keyjazz(isysev_t ev, const char *data)
1204 {
1205 printf("keyjazz - %s\n", data);
1206 }
1207
ev_quit(isysev_t ev,const char * data)1208 static void ev_quit(isysev_t ev, const char *data)
1209 {
1210 printf("quit\n");
1211 }
1212
ev_page_switch(isysev_t ev,const char * data)1213 static void ev_page_switch(isysev_t ev, const char *data)
1214 {
1215 int n;
1216
1217 for (n = 2; n <= 5; n++) {
1218 if (strcasecmp(page_names[n], data) == 0) {
1219 current_page = n;
1220 active_keymaps[KMAP_LOCAL] = kmap_find(data, 0);
1221 printf("switched to page %d (%s)\n", n, data);
1222 return;
1223 }
1224 }
1225 printf("unknown page name \"%s\"\n", data);
1226 }
1227
ev_song_play_infopage(isysev_t ev,const char * data)1228 static void ev_song_play_infopage(isysev_t ev, const char *data)
1229 {
1230 printf("play song and show infopage!\n");
1231 active_keymaps[KMAP_LOCAL] = kmap_find("Info Page", 0);
1232 }
1233
ev_song_play(isysev_t ev,const char * data)1234 static void ev_song_play(isysev_t ev, const char *data)
1235 {
1236 printf("play song and stay put!\n");
1237 }
1238
ev_song_stop(isysev_t ev,const char * data)1239 static void ev_song_stop(isysev_t ev, const char *data)
1240 {
1241 printf("stop playing!\n");
1242 }
1243
ev_main_menu(isysev_t ev,const char * data)1244 static void ev_main_menu(isysev_t ev, const char *data)
1245 {
1246 printf("pop up menu\n");
1247 active_keymaps[KMAP_LOCAL] = kmap_find("Menu", 0);
1248 active_keymaps[KMAP_GLOBAL] = kmap_find("Dialog", 0);
1249 }
1250
ev_dlg_cancel(isysev_t ev,const char * data)1251 static void ev_dlg_cancel(isysev_t ev, const char *data)
1252 {
1253 active_keymaps[KMAP_LOCAL] = kmap_find(page_names[current_page], 0);
1254 active_keymaps[KMAP_GLOBAL] = kmap_find("Global", 0);
1255 }
1256
1257 // ------------------------------------------------------------------------------------------------------------
1258
1259 typedef struct dbg {
1260 const char *m, *k, *f, *d;
1261 } dbg_t;
1262
main(int argc,char ** argv)1263 int main(int argc, char **argv)
1264 {
1265 int n, jn;
1266 kmap_t *m;
1267 ev_handler f;
1268
1269 SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
1270 SDL_EnableUNICODE(1);
1271 SDL_EnableKeyRepeat(125, 25);
1272
1273 n = SDL_NumJoysticks();
1274 if (n > SKDEV_ID_MAX) {
1275 printf("warning: %d of your %d joysticks will be ignored\n", SKDEV_ID_MAX - n, n);
1276 n = SKDEV_ID_MAX;
1277 }
1278 for (jn = 0; jn < n; jn++) {
1279 SDL_Joystick *js = SDL_JoystickOpen(jn);
1280 printf("Joystick #%d [%s]\n\taxes:%d buttons:%d hats:%d balls:%d\n",
1281 jn, SDL_JoystickName(jn),
1282 SDL_JoystickNumAxes(js), SDL_JoystickNumButtons(js),
1283 SDL_JoystickNumHats(js), SDL_JoystickNumBalls(js));
1284 }
1285
1286 keytab_init();
1287 kmap_init();
1288 evfunc_init();
1289
1290 // prefix local widget widgetclass global
1291 active_keymaps[KMAP_GLOBAL] = kmap_find("Global", 1);
1292 m = active_keymaps[KMAP_LOCAL] = kmap_find("Pattern Editor", 1);
1293 kmap_inherit(m, kmap_find("Keyjazz", 1));
1294
1295 evfunc_t evs[] = {
1296 {"pat_raise_semitone", ev_pat_raise_semitone},
1297 {"pat_lower_semitone", ev_pat_lower_semitone},
1298 {"pat_raise_octave", ev_pat_raise_octave},
1299 {"pat_lower_octave", ev_pat_lower_octave},
1300 {"pat_options", ev_pat_options},
1301 {"pat_set_length", ev_pat_set_length},
1302 {"smp_swap_sign", ev_smp_swap_sign},
1303 {"smp_toggle_quality", ev_smp_toggle_quality},
1304 {"keyjazz", ev_keyjazz},
1305 {"quit", ev_quit},
1306 {"page_switch", ev_page_switch},
1307 {"song_play_infopage", ev_song_play_infopage},
1308 {"song_play", ev_song_play},
1309 {"song_stop", ev_song_stop},
1310 {"main_menu", ev_main_menu},
1311 {"dlg_cancel", ev_dlg_cancel},
1312 {NULL, NULL},
1313 };
1314 evfunc_register_many(evs);
1315
1316 dbg_t debug[] = {
1317 {"Pattern Editor", "Alt-Q", "pat_raise_semitone", NULL},
1318 {"Pattern Editor", "Alt-A", "pat_lower_semitone", NULL},
1319 {"Pattern Editor", "Alt-Shift-Q", "pat_raise_octave", NULL},
1320 {"Pattern Editor", "Alt-Shift-A", "pat_lower_octave", NULL},
1321 {"Pattern Editor", "F2", "pat_options", NULL},
1322 {"Pattern Editor", "Ctrl-F2", "pat_set_length", NULL},
1323 {"Pattern Editor Options", "F2", "page_switch", "Pattern Editor"},
1324 {"Sample List", "Alt-Q", "smp_toggle_quality", NULL},
1325 {"Sample List", "Alt-A", "smp_swap_sign", NULL},
1326 {"Keyjazz", "q", "keyjazz", "C-1"},
1327 {"Keyjazz", "2", "keyjazz", "C#1"},
1328 {"Keyjazz", "w", "keyjazz", "D-1"},
1329 {"Keyjazz", "3", "keyjazz", "D#1"},
1330 {"Keyjazz", "e", "keyjazz", "E-1"},
1331 {"Keyjazz", "r", "keyjazz", "F-1"},
1332 {"Keyjazz", "5", "keyjazz", "F#1"},
1333 {"Keyjazz", "t", "keyjazz", "G-1"},
1334 {"Keyjazz", "6", "keyjazz", "G#1"},
1335 {"Keyjazz", "y", "keyjazz", "A-1"},
1336 {"Keyjazz", "7", "keyjazz", "A#1"},
1337 {"Keyjazz", "u", "keyjazz", "B-1"},
1338 {"Keyjazz", "i", "keyjazz", "C-2"},
1339 {"Global", "Ctrl-Q", "quit", NULL},
1340 {"Global", "F2", "page_switch", "Pattern Editor"},
1341 {"Global", "F3", "page_switch", "Sample List"},
1342 {"Global", "F4", "page_switch", "Instrument List"},
1343 {"Global", "F5", "song_play_infopage", NULL},
1344 {"Global", "Ctrl-F5", "song_play", NULL},
1345 {"Global", "F8", "song_stop", NULL},
1346 {"Global", "Escape", "main_menu", NULL},
1347 {"Dialog", "Escape", "dlg_cancel", NULL},
1348 {NULL, NULL, NULL, NULL},
1349 };
1350 for (n = 0; debug[n].k; n++) {
1351 if (strcasecmp(m->name, debug[n].m) != 0)
1352 m = kmap_find(debug[n].m, 1);
1353 f = evfunc_lookup(debug[n].f);
1354 if (!f) {
1355 printf("warning: unknown function \"%s\"\n", debug[n].f);
1356 continue;
1357 }
1358 kmap_bind(m, event_parse(debug[n].k), f, debug[n].d);
1359 }
1360
1361 kmap_print(kmap_find("Pattern Editor", 0));
1362
1363 SDL_JoystickEventState(SDL_ENABLE);
1364 SDL_SetVideoMode(200, 200, 0, 0);
1365 event_loop();
1366
1367 evfunc_free();
1368 kmap_free();
1369 keytab_free();
1370
1371 SDL_Quit();
1372
1373 return 0;
1374 }
1375
1376