simplify my last commit. Thanks to obo for the hint.
[Rockbox.git] / apps / action.c
blob5aeab25e1dd9e0b420946534cc0734633ff45907
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006 Jonathan Gordon
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
23 #include "config.h"
24 #include "lang.h"
26 #include "button.h"
27 #include "action.h"
28 #include "kernel.h"
29 #include "debug.h"
30 #include "splash.h"
32 static int last_button = BUTTON_NONE|BUTTON_REL; /* allow the ipod wheel to
33 work on startup */
34 static intptr_t last_data = 0;
35 static int last_action = ACTION_NONE;
36 static bool repeated = false;
38 #define REPEAT_WINDOW_TICKS HZ/10
39 static int last_action_tick = 0;
41 /* software keylock stuff */
42 #ifndef HAS_BUTTON_HOLD
43 static bool keys_locked = false;
44 static int unlock_combo = BUTTON_NONE;
45 static bool screen_has_lock = false;
46 #endif /* HAVE_SOFTWARE_KEYLOCK */
49 * do_button_check is the worker function for get_default_action.
50 * returns ACTION_UNKNOWN or the requested return value from the list.
52 static inline int do_button_check(const struct button_mapping *items,
53 int button, int last_button, int *start)
55 int i = 0;
56 int ret = ACTION_UNKNOWN;
57 if (items == NULL)
58 return ACTION_UNKNOWN;
60 while (items[i].button_code != BUTTON_NONE)
62 if (items[i].button_code == button)
64 if ((items[i].pre_button_code == BUTTON_NONE)
65 || (items[i].pre_button_code == last_button))
67 ret = items[i].action_code;
68 break;
71 i++;
73 *start = i;
74 return ret;
77 static inline int get_next_context(const struct button_mapping *items, int i)
79 while (items[i].button_code != BUTTON_NONE)
80 i++;
81 return (items[i].action_code == ACTION_NONE ) ?
82 CONTEXT_STD :
83 items[i].action_code;
86 * int get_action_worker(int context, struct button_mapping *user_mappings,
87 int timeout)
88 This function searches the button list for the given context for the just
89 pressed button.
90 If there is a match it returns the value from the list.
91 If there is no match..
92 the last item in the list "points" to the next context in a chain
93 so the "chain" is followed until the button is found.
94 putting ACTION_NONE will get CONTEXT_STD which is always the last list checked.
96 Timeout can be TIMEOUT_NOBLOCK to return immediatly
97 TIMEOUT_BLOCK to wait for a button press
98 Any number >0 to wait that many ticks for a press
101 static int get_action_worker(int context, int timeout,
102 const struct button_mapping* (*get_context_map)(int) )
104 const struct button_mapping *items = NULL;
105 int button;
106 int i=0;
107 int ret = ACTION_UNKNOWN;
108 static int last_context = CONTEXT_STD;
110 if (timeout == TIMEOUT_NOBLOCK)
111 button = button_get(false);
112 else if (timeout == TIMEOUT_BLOCK)
113 button = button_get(true);
114 else
115 button = button_get_w_tmo(timeout);
117 /* Data from sys events can be pulled with button_get_data */
118 if (button == BUTTON_NONE || button&SYS_EVENT)
120 return button;
123 if ((context != last_context) && ((last_button&BUTTON_REL) == 0))
125 if (button&BUTTON_REL)
127 last_button = button;
128 last_action = ACTION_NONE;
130 /* eat all buttons until the previous button was |BUTTON_REL
131 (also eat the |BUTTON_REL button) */
132 return ACTION_NONE; /* "safest" return value */
134 last_context = context;
136 #ifndef HAS_BUTTON_HOLD
137 screen_has_lock = ((context&ALLOW_SOFTLOCK)==ALLOW_SOFTLOCK);
138 if (screen_has_lock && (keys_locked == true))
140 if (button == unlock_combo)
142 last_button = BUTTON_NONE;
143 keys_locked = false;
144 gui_syncsplash(HZ/2, str(LANG_KEYLOCK_OFF));
145 return ACTION_REDRAW;
147 else
148 #if (BUTTON_REMOTE != 0)
149 if ((button&BUTTON_REMOTE) == 0)
150 #endif
152 if ((button&BUTTON_REL))
153 gui_syncsplash(HZ/2, str(LANG_KEYLOCK_ON));
154 return ACTION_REDRAW;
157 context &= ~ALLOW_SOFTLOCK;
158 #endif /* HAS_BUTTON_HOLD */
160 /* logf("%x,%x",last_button,button); */
163 /* logf("context = %x",context); */
164 #if (BUTTON_REMOTE != 0)
165 if (button&BUTTON_REMOTE)
166 context |= CONTEXT_REMOTE;
167 #endif
168 if ((context&CONTEXT_CUSTOM) && get_context_map)
169 items = get_context_map(context);
170 else
171 items = get_context_mapping(context);
173 ret = do_button_check(items,button,last_button,&i);
175 if ((context ==(int)CONTEXT_STOPSEARCHING) ||
176 items == NULL )
177 break;
179 if (ret == ACTION_UNKNOWN )
181 context = get_next_context(items,i);
182 i = 0;
184 else break;
185 } while (1);
186 /* DEBUGF("ret = %x\n",ret); */
187 #ifndef HAS_BUTTON_HOLD
188 if (screen_has_lock && (ret == ACTION_STD_KEYLOCK))
190 unlock_combo = button;
191 keys_locked = true;
192 gui_syncsplash(HZ/2, str(LANG_KEYLOCK_ON));
194 button_clear_queue();
195 return ACTION_REDRAW;
197 #endif
198 if ((current_tick - last_action_tick < REPEAT_WINDOW_TICKS)
199 && (ret == last_action))
200 repeated = true;
201 else
202 repeated = false;
204 last_button = button;
205 last_action = ret;
206 last_data = button_get_data();
207 last_action_tick = current_tick;
208 return ret;
211 int get_action(int context, int timeout)
213 return get_action_worker(context,timeout,NULL);
216 int get_custom_action(int context,int timeout,
217 const struct button_mapping* (*get_context_map)(int))
219 return get_action_worker(context,timeout,get_context_map);
222 bool action_userabort(int timeout)
224 int action = get_action_worker(CONTEXT_STD,timeout,NULL);
225 bool ret = (action == ACTION_STD_CANCEL);
226 return ret;
229 #ifndef HAS_BUTTON_HOLD
230 bool is_keys_locked(void)
232 return (screen_has_lock && (keys_locked == true));
234 #endif
236 intptr_t get_action_data(void)
238 return last_data;
241 int get_action_statuscode(int *button)
243 int ret = 0;
244 if (button)
245 *button = last_button;
247 if (last_button&BUTTON_REMOTE)
248 ret |= ACTION_REMOTE;
249 if (repeated)
250 ret |= ACTION_REPEAT;
251 return ret;