/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id: $ * * Copyright (C) 2002 Philipp Pertermann * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include #include "key_scheme.h" #include "button.h" #include "commands.h" #include "lcd.h" struct key_map key_map_store[KEY_MAP_STORE_SIZE ]; struct key_scheme key_scheme_store[KEY_SCHEME_STORE_SIZE ]; int key_scheme_current = SCHEME_DEFAULT; /** * executes the command stored in the map */ void execute(struct key_map *map) { int value = map->value; char *text = map->text; struct key_command *command = map->command; /* an empty command might have specified in order to only change the current key scheme. In that case we don't do anything */ if (command != NULL){ switch (map->cmd_use) { case CMD_ACTION: if (command->action != NULL) { command->action(); } break; case CMD_VALUE_SET: if (command->set_value != NULL) { command->set_value(value); } break; case CMD_VALUE_INC: if (command->get_value != NULL && command->set_value != NULL) { value = command->get_value(); value ++; command->set_value(value); } break; case CMD_VALUE_DEC: if (command->get_value != NULL && command->set_value != NULL) { value = command->get_value(); value --; command->set_value(value); } break; case CMD_TEXT_SET: if (command->set_text != NULL) { command->set_text(text); } break; case CMD_TEXT_EDIT: /* not available yet */ /* command->set_text(text_editor()); */ break; } } } /** * Use the scheme and execute the command that is mapped * to the given button event. * @param int button - A value as received from button_get * @param int scheme - A valid index for key_scheme_store * @return int - The index of the key scheme that must be * used after the execution of the command. If no command * was assigned to the button scheme is returned. */ int select_and_execute(int button, int scheme){ int retval = scheme; if (scheme != SCHEME_EMPTY && button != BUTTON_NONE) { int i; /* search the current key scheme for the specified button */ bool button_found = false; for (i = key_scheme_store[scheme].start; i < key_scheme_store[scheme].end; i++){ if (button == key_map_store[i].button_event) { retval = key_map_store[i].next_key_scheme; execute(&key_map_store[i]); button_found = true; /* don't return here because servaral commands may have been bound to the same key in order to generate a macro. We only want to consider siblings because otherwise we would execute all inherited assignments instead of overwriting them. */ } } /* nothing found? try inherited */ /* This is a recursion that should be transformed to an iteration in real life. Maybe we want to consider checking for cycles*/ if (!button_found && key_scheme_store[scheme].parent != SCHEME_EMPTY) { select_and_execute(button, key_scheme_store[scheme].parent); } } return retval; } static void clear_map(void) { int i; for (i = 0; i < KEY_MAP_STORE_SIZE; i++) { key_map_store[i].button_event = BUTTON_NONE; key_map_store[i].cmd_use = -1; key_map_store[i].value = -1; key_map_store[i].next_key_scheme = SCHEME_DEFAULT; key_map_store[i].text = NULL; key_map_store[i].command = NULL; } } /** * Here the factory preset is defined */ static void default_scheme(void) { int scheme; int map_idx = 0; button_set_release(ALL_BUTTONS); button_set_repeat(ALL_BUTTONS); init_commands(); clear_map(); for (scheme = 0; scheme < KEY_SCHEME_STORE_SIZE; scheme++){ key_scheme_store[scheme].parent = SCHEME_EMPTY; key_scheme_store[scheme].start = map_idx; key_scheme_store[scheme].end = map_idx; } /* The default key scheme */ scheme = SCHEME_DEFAULT; key_scheme_store[scheme].parent = SCHEME_EMPTY; key_scheme_store[scheme].start = map_idx; /* demonstrate the decrease command */ key_map_store[map_idx].button_event = BUTTON_LEFT; key_map_store[map_idx].cmd_use = CMD_VALUE_DEC; key_map_store[map_idx].value = -1; key_map_store[map_idx].next_key_scheme = SCHEME_DEFAULT; key_map_store[map_idx].text = NULL; key_map_store[map_idx].command = &key_command_table[SPLIT_X]; map_idx++; /* demonstrate repeat. In a config file we might want to have different entries for the button name and its modifiers. That might make the file format more user friendly. We can combine that to one single button event number while parsing */ key_map_store[map_idx].button_event = BUTTON_LEFT | BUTTON_REPEAT; key_map_store[map_idx].cmd_use = CMD_VALUE_DEC; key_map_store[map_idx].value = -1; key_map_store[map_idx].next_key_scheme = SCHEME_DEFAULT; key_map_store[map_idx].text = NULL; key_map_store[map_idx].command = &key_command_table[SPLIT_X]; map_idx++; /* demonstrate the increase command */ key_map_store[map_idx].button_event = BUTTON_RIGHT; key_map_store[map_idx].cmd_use = CMD_VALUE_INC; key_map_store[map_idx].value = -1; key_map_store[map_idx].next_key_scheme = SCHEME_DEFAULT; key_map_store[map_idx].text = NULL; key_map_store[map_idx].command = &key_command_table[SPLIT_X]; map_idx++; key_map_store[map_idx].button_event = BUTTON_RIGHT | BUTTON_REPEAT; key_map_store[map_idx].cmd_use = CMD_VALUE_INC; key_map_store[map_idx].value = -1; key_map_store[map_idx].next_key_scheme = SCHEME_DEFAULT; key_map_store[map_idx].text = NULL; key_map_store[map_idx].command = &key_command_table[SPLIT_X]; map_idx++; /* demonstrate the action command */ key_map_store[map_idx].button_event = BUTTON_UP; key_map_store[map_idx].cmd_use = CMD_ACTION; key_map_store[map_idx].value = -1; key_map_store[map_idx].next_key_scheme = SCHEME_DEFAULT; key_map_store[map_idx].text = NULL; key_map_store[map_idx].command = &key_command_table[SPLIT_ZOOM_IN]; map_idx++; key_map_store[map_idx].button_event = BUTTON_DOWN; key_map_store[map_idx].cmd_use = CMD_ACTION; key_map_store[map_idx].value = -1; key_map_store[map_idx].next_key_scheme = SCHEME_DEFAULT; key_map_store[map_idx].text = NULL; key_map_store[map_idx].command = &key_command_table[SPLIT_ZOOM_OUT]; map_idx++; key_map_store[map_idx].button_event = BUTTON_F2; key_map_store[map_idx].cmd_use = CMD_VALUE_INC; key_map_store[map_idx].value = -1; key_map_store[map_idx].next_key_scheme = SCHEME_DEFAULT; key_map_store[map_idx].text = NULL; key_map_store[map_idx].command = &key_command_table[SPLIT_LOOP_MODE]; map_idx++; /* test scheme change The command itself pauses the engine. We want the pause button to resume playback. But we cannot use the mpeg_pause command for that. Thus we must switch to another key scheme where the pause key is assigned to mpeg_resume */ key_map_store[map_idx].button_event = BUTTON_PLAY | BUTTON_REL; key_map_store[map_idx].cmd_use = CMD_ACTION; key_map_store[map_idx].value = -1; key_map_store[map_idx].next_key_scheme = SCHEME_DEFAULT + 1; /* switch scheme */ key_map_store[map_idx].text = NULL; key_map_store[map_idx].command = &key_command_table[MPEG_PAUSE]; map_idx++; /* test button combinations */ /* test setting a value directly. Note that this feature enables the user to specify the value in the config file */ key_map_store[map_idx].button_event = BUTTON_ON | BUTTON_LEFT; key_map_store[map_idx].cmd_use = CMD_VALUE_SET; key_map_store[map_idx].value = 50; key_map_store[map_idx].next_key_scheme = SCHEME_DEFAULT; key_map_store[map_idx].text = NULL; key_map_store[map_idx].command = &key_command_table[MPEG_SET_PITCH]; map_idx++; key_map_store[map_idx].button_event = BUTTON_ON | BUTTON_RIGHT; key_map_store[map_idx].cmd_use = CMD_VALUE_SET; key_map_store[map_idx].value = 150; key_map_store[map_idx].next_key_scheme = SCHEME_DEFAULT; key_map_store[map_idx].text = NULL; key_map_store[map_idx].command = &key_command_table[MPEG_SET_PITCH]; map_idx++; /* quit the split editor */ key_map_store[map_idx].button_event = BUTTON_OFF; key_map_store[map_idx].cmd_use = CMD_ACTION; key_map_store[map_idx].value = 150; key_map_store[map_idx].next_key_scheme = SCHEME_DEFAULT; key_map_store[map_idx].text = NULL; key_map_store[map_idx].command = &key_command_table[SPLIT_QUIT]; map_idx++; /* demonstrate flexibility: by simply changing the key schemes we can have the play button assigned to three different purposes: 1. pause 2. resume 3. reset pitch (when play is pressed and held) We need a third key scheme for this purpose because we need a key scheme that doesn't pause or resume playback when the play button is released. */ key_map_store[map_idx].button_event = BUTTON_PLAY | BUTTON_REPEAT; key_map_store[map_idx].cmd_use = CMD_VALUE_SET; key_map_store[map_idx].value = 100; key_map_store[map_idx].next_key_scheme = SCHEME_DEFAULT + 2; /* key scheme change */ key_map_store[map_idx].text = NULL; key_map_store[map_idx].command = &key_command_table[MPEG_SET_PITCH]; map_idx++; /* the default key scheme ends */ key_scheme_store[scheme].end = map_idx; scheme++; /* test inheritance This scheme is used when the user has entered pause mode in the split editor. It inherits everything from the default scheme but overwrites the functionality of the play button. Now the play button is assigned to resume. */ key_scheme_store[scheme].parent = SCHEME_DEFAULT; key_scheme_store[scheme].start = map_idx; key_map_store[map_idx].button_event = BUTTON_PLAY | BUTTON_REL; key_map_store[map_idx].cmd_use = CMD_ACTION; key_map_store[map_idx].value = -1; key_map_store[map_idx].next_key_scheme = SCHEME_DEFAULT; /* switch back to default */ key_map_store[map_idx].text = NULL; key_map_store[map_idx].command = &key_command_table[MPEG_RESUME]; map_idx++; key_scheme_store[scheme].end = map_idx; /* End of key scheme 1. Note that it has only one button assignment */ scheme++; /* test bypass This key scheme doesn't inherit anything. It's only purpose is to switch back to the default scheme when the play button is released. */ key_scheme_store[scheme].parent = SCHEME_EMPTY; /* don't inherit */ key_scheme_store[scheme].start = map_idx; key_map_store[map_idx].button_event = BUTTON_PLAY | BUTTON_REL; key_map_store[map_idx].cmd_use = CMD_ACTION; key_map_store[map_idx].value = -1; key_map_store[map_idx].next_key_scheme = SCHEME_DEFAULT; /* change to default */ key_map_store[map_idx].text = NULL; key_map_store[map_idx].command = NULL;//&key_command_table[MPEG_SET_PITCH]; map_idx++; key_scheme_store[scheme].end = map_idx; scheme++; /* enable the default key scheme */ key_scheme_current = SCHEME_DEFAULT; } void load_scheme(char *filename){ (void)filename; default_scheme(); }