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