remove the need for action_signalscreenchange().
[Rockbox.git] / apps / action.c
blob826f376dcd23bd9a21aeb6439481e8e1c72c14dd
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 int last_action = ACTION_NONE;
35 static bool repeated = false;
37 #define REPEAT_WINDOW_TICKS HZ/10
38 static int last_action_tick = 0;
40 /* software keylock stuff */
41 #ifndef HAS_BUTTON_HOLD
42 static bool keys_locked = false;
43 static int unlock_combo = BUTTON_NONE;
44 static bool screen_has_lock = false;
45 #endif /* HAVE_SOFTWARE_KEYLOCK */
48 * do_button_check is the worker function for get_default_action.
49 * returns ACTION_UNKNOWN or the requested return value from the list.
51 static inline int do_button_check(const struct button_mapping *items,
52 int button, int last_button, int *start)
54 int i = 0;
55 int ret = ACTION_UNKNOWN;
56 if (items == NULL)
57 return ACTION_UNKNOWN;
59 while (items[i].button_code != BUTTON_NONE)
61 if (items[i].button_code == button)
63 if ((items[i].pre_button_code == BUTTON_NONE)
64 || (items[i].pre_button_code == last_button))
66 ret = items[i].action_code;
67 break;
70 i++;
72 *start = i;
73 return ret;
76 static inline int get_next_context(const struct button_mapping *items, int i)
78 while (items[i].button_code != BUTTON_NONE)
79 i++;
80 return (items[i].action_code == ACTION_NONE ) ?
81 CONTEXT_STD :
82 items[i].action_code;
85 * int get_action_worker(int context, struct button_mapping *user_mappings,
86 int timeout)
87 This function searches the button list for the given context for the just
88 pressed button.
89 If there is a match it returns the value from the list.
90 If there is no match..
91 the last item in the list "points" to the next context in a chain
92 so the "chain" is followed until the button is found.
93 putting ACTION_NONE will get CONTEXT_STD which is always the last list checked.
95 Timeout can be TIMEOUT_NOBLOCK to return immediatly
96 TIMEOUT_BLOCK to wait for a button press
97 Any number >0 to wait that many ticks for a press
100 static int get_action_worker(int context, int timeout,
101 const struct button_mapping* (*get_context_map)(int) )
103 const struct button_mapping *items = NULL;
104 int button;
105 int i=0;
106 int ret = ACTION_UNKNOWN;
107 static int last_context = CONTEXT_STD;
109 if (timeout == TIMEOUT_NOBLOCK)
110 button = button_get(false);
111 else if (timeout == TIMEOUT_BLOCK)
112 button = button_get(true);
113 else
114 button = button_get_w_tmo(timeout);
116 if (button == BUTTON_NONE || button&SYS_EVENT)
118 return button;
121 if ((context != last_context) && ((last_button&BUTTON_REL) == 0))
123 if (button&BUTTON_REL)
125 last_button = button;
126 last_action = ACTION_NONE;
128 /* eat all buttons until the previous button was |BUTTON_REL
129 (also eat the |BUTTON_REL button) */
130 return ACTION_NONE; /* "safest" return value */
132 last_context = context;
134 #ifndef HAS_BUTTON_HOLD
135 screen_has_lock = ((context&ALLOW_SOFTLOCK)==ALLOW_SOFTLOCK);
136 if (screen_has_lock && (keys_locked == true))
138 if (button == unlock_combo)
140 last_button = BUTTON_NONE;
141 keys_locked = false;
142 gui_syncsplash(HZ/2, str(LANG_KEYLOCK_OFF_PLAYER));
143 return ACTION_REDRAW;
145 else
146 #if (BUTTON_REMOTE != 0)
147 if ((button&BUTTON_REMOTE) == 0)
148 #endif
150 if ((button&BUTTON_REL))
151 gui_syncsplash(HZ/2, str(LANG_KEYLOCK_ON_PLAYER));
152 return ACTION_REDRAW;
155 context &= ~ALLOW_SOFTLOCK;
156 #endif /* HAS_BUTTON_HOLD */
158 /* logf("%x,%x",last_button,button); */
161 /* logf("context = %x",context); */
162 #if (BUTTON_REMOTE != 0)
163 if (button&BUTTON_REMOTE)
164 context |= CONTEXT_REMOTE;
165 #endif
166 if ((context&CONTEXT_CUSTOM) && get_context_map)
167 items = get_context_map(context);
168 else
169 items = get_context_mapping(context);
171 ret = do_button_check(items,button,last_button,&i);
173 if ((context ==(int)CONTEXT_STOPSEARCHING) ||
174 items == NULL )
175 break;
177 if (ret == ACTION_UNKNOWN )
179 context = get_next_context(items,i);
180 i = 0;
182 else break;
183 } while (1);
184 /* DEBUGF("ret = %x\n",ret); */
185 #ifndef HAS_BUTTON_HOLD
186 if (screen_has_lock && (ret == ACTION_STD_KEYLOCK))
188 unlock_combo = button;
189 keys_locked = true;
190 gui_syncsplash(HZ/2, str(LANG_KEYLOCK_ON_PLAYER));
192 button_clear_queue();
193 return ACTION_REDRAW;
195 #endif
196 if ((current_tick - last_action_tick < REPEAT_WINDOW_TICKS)
197 && (ret == last_action))
198 repeated = true;
199 else
200 repeated = false;
202 last_button = button;
203 last_action = ret;
204 last_action_tick = current_tick;
205 return ret;
208 int get_action(int context, int timeout)
210 return get_action_worker(context,timeout,NULL);
213 int get_custom_action(int context,int timeout,
214 const struct button_mapping* (*get_context_map)(int))
216 return get_action_worker(context,timeout,get_context_map);
219 bool action_userabort(int timeout)
221 int action = get_action_worker(CONTEXT_STD,timeout,NULL);
222 bool ret = (action == ACTION_STD_CANCEL);
223 return ret;
226 #ifndef HAS_BUTTON_HOLD
227 bool is_keys_locked(void)
229 return (screen_has_lock && (keys_locked == true));
231 #endif
233 int get_action_statuscode(int *button)
235 int ret = 0;
236 if (button)
237 *button = last_button;
239 if (last_button&BUTTON_REMOTE)
240 ret |= ACTION_REMOTE;
241 if (repeated)
242 ret |= ACTION_REPEAT;
243 return ret;