Also build database.c using SIM settings, in an attempt to fix the red on b32-roolku
[kugel-rb.git] / apps / action.c
blobf65ef39bf0295bb7aaf4acdec5fe436c784fb5d5
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006 Jonathan Gordon
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
25 #include "config.h"
26 #include "lang.h"
28 #include "appevents.h"
29 #include "button.h"
30 #include "action.h"
31 #include "kernel.h"
32 #include "debug.h"
33 #include "splash.h"
34 #include "settings.h"
35 #include "pcmbuf.h"
36 #include "misc.h"
37 #if defined(HAVE_LCD_BITMAP) && !defined(BOOTLOADER)
38 #include "language.h"
39 #endif
41 static int last_button = BUTTON_NONE|BUTTON_REL; /* allow the ipod wheel to
42 work on startup */
43 static intptr_t last_data = 0;
44 static int last_action = ACTION_NONE;
45 static bool repeated = false;
46 static bool wait_for_release = false;
48 #ifdef HAVE_TOUCHSCREEN
49 static bool short_press = false;
50 #endif
52 #define REPEAT_WINDOW_TICKS HZ/10
53 static int last_action_tick = 0;
55 /* software keylock stuff */
56 #ifndef HAS_BUTTON_HOLD
57 static bool keys_locked = false;
58 static int unlock_combo = BUTTON_NONE;
59 static bool screen_has_lock = false;
60 #endif /* HAVE_SOFTWARE_KEYLOCK */
63 * do_button_check is the worker function for get_default_action.
64 * returns ACTION_UNKNOWN or the requested return value from the list.
66 static inline int do_button_check(const struct button_mapping *items,
67 int button, int last_button, int *start)
69 int i = 0;
70 int ret = ACTION_UNKNOWN;
72 while (items[i].button_code != BUTTON_NONE)
74 if (items[i].button_code == button)
76 if ((items[i].pre_button_code == BUTTON_NONE)
77 || (items[i].pre_button_code == last_button))
79 ret = items[i].action_code;
80 break;
83 i++;
85 *start = i;
86 return ret;
89 #if defined(HAVE_LCD_BITMAP) && !defined(BOOTLOADER)
91 * button is horizontally inverted to support RTL language if the given language
92 * and context combination require that
94 static int button_flip_horizontally(int context, int button)
96 int newbutton;
98 if (!(lang_is_rtl() && ((context == CONTEXT_STD) ||
99 (context & CONTEXT_TREE) || (context & CONTEXT_MAINMENU))))
101 return button;
104 newbutton = button &
105 ~(BUTTON_LEFT | BUTTON_RIGHT
106 #if defined(BUTTON_SCROLL_BACK) && defined(BUTTON_SCROLL_FWD) && \
107 !defined(SIMULATOR)
108 | BUTTON_SCROLL_BACK | BUTTON_SCROLL_FWD
109 #endif
112 if (button & BUTTON_LEFT)
113 newbutton |= BUTTON_RIGHT;
114 if (button & BUTTON_RIGHT)
115 newbutton |= BUTTON_LEFT;
116 #if defined(BUTTON_SCROLL_BACK) && defined(BUTTON_SCROLL_FWD) && \
117 !defined(SIMULATOR)
118 if (button & BUTTON_SCROLL_BACK)
119 newbutton |= BUTTON_SCROLL_FWD;
120 if (button & BUTTON_SCROLL_FWD)
121 newbutton |= BUTTON_SCROLL_BACK;
122 #endif
124 return newbutton;
126 #endif
128 static inline int get_next_context(const struct button_mapping *items, int i)
130 while (items[i].button_code != BUTTON_NONE)
131 i++;
132 return (items[i].action_code == ACTION_NONE ) ?
133 CONTEXT_STD :
134 items[i].action_code;
137 * int get_action_worker(int context, struct button_mapping *user_mappings,
138 int timeout)
139 This function searches the button list for the given context for the just
140 pressed button.
141 If there is a match it returns the value from the list.
142 If there is no match..
143 the last item in the list "points" to the next context in a chain
144 so the "chain" is followed until the button is found.
145 putting ACTION_NONE will get CONTEXT_STD which is always the last list checked.
147 Timeout can be TIMEOUT_NOBLOCK to return immediatly
148 TIMEOUT_BLOCK to wait for a button press
149 Any number >0 to wait that many ticks for a press
151 static int get_action_worker(int context, int timeout,
152 const struct button_mapping* (*get_context_map)(int) )
154 const struct button_mapping *items = NULL;
155 int button;
156 int i=0;
157 int ret = ACTION_UNKNOWN;
158 static int last_context = CONTEXT_STD;
161 send_event(GUI_EVENT_ACTIONUPDATE, NULL);
163 if (timeout == TIMEOUT_NOBLOCK)
164 button = button_get(false);
165 else if (timeout == TIMEOUT_BLOCK)
166 button = button_get(true);
167 else
168 button = button_get_w_tmo(timeout);
170 /* Data from sys events can be pulled with button_get_data */
171 if (button == BUTTON_NONE || button & SYS_EVENT)
172 return button;
173 /* Don't send any buttons through untill we see the release event */
174 if (wait_for_release)
176 if (button&BUTTON_REL)
178 wait_for_release = false;
180 return ACTION_NONE;
184 #if CONFIG_CODEC == SWCODEC
185 /* Produce keyclick */
186 if (global_settings.keyclick && !(button & BUTTON_REL))
187 if (!(button & BUTTON_REPEAT) || global_settings.keyclick_repeats)
188 pcmbuf_beep(4000, KEYCLICK_DURATION, 2500*global_settings.keyclick);
189 #endif
191 if ((context != last_context) && ((last_button & BUTTON_REL) == 0))
193 if (button & BUTTON_REL)
195 last_button = button;
196 last_action = ACTION_NONE;
198 /* eat all buttons until the previous button was |BUTTON_REL
199 (also eat the |BUTTON_REL button) */
200 return ACTION_NONE; /* "safest" return value */
202 last_context = context;
203 #ifdef HAVE_TOUCHSCREEN
204 if (button & BUTTON_TOUCHSCREEN)
206 repeated = false;
207 short_press = false;
208 if (last_button & BUTTON_TOUCHSCREEN)
210 if ((button & BUTTON_REL) &&
211 ((last_button & BUTTON_REPEAT)==0))
213 short_press = true;
215 else if (button & BUTTON_REPEAT)
216 repeated = true;
218 last_button = button;
219 return ACTION_TOUCHSCREEN;
221 #endif
222 #ifndef HAS_BUTTON_HOLD
223 screen_has_lock = ((context & ALLOW_SOFTLOCK) == ALLOW_SOFTLOCK);
224 if (screen_has_lock && keys_locked)
226 if (button == unlock_combo)
228 last_button = BUTTON_NONE;
229 keys_locked = false;
230 splash(HZ/2, str(LANG_KEYLOCK_OFF));
231 return ACTION_REDRAW;
233 else
234 #if (BUTTON_REMOTE != 0)
235 if ((button & BUTTON_REMOTE) == 0)
236 #endif
238 if ((button & BUTTON_REL))
239 splash(HZ/2, str(LANG_KEYLOCK_ON));
240 return ACTION_REDRAW;
243 context &= ~ALLOW_SOFTLOCK;
244 #endif /* HAS_BUTTON_HOLD */
246 #if defined(HAVE_LCD_BITMAP) && !defined(BOOTLOADER)
247 button = button_flip_horizontally(context, button);
248 #endif
250 /* logf("%x,%x",last_button,button); */
251 while (1)
253 /* logf("context = %x",context); */
254 #if (BUTTON_REMOTE != 0)
255 if (button & BUTTON_REMOTE)
256 context |= CONTEXT_REMOTE;
257 #endif
258 if ((context & CONTEXT_PLUGIN) && get_context_map)
259 items = get_context_map(context);
260 else
261 items = get_context_mapping(context);
263 if (items == NULL)
264 break;
266 ret = do_button_check(items,button,last_button,&i);
268 if (ret == ACTION_UNKNOWN)
270 context = get_next_context(items,i);
272 if (context != (int)CONTEXT_STOPSEARCHING)
274 i = 0;
275 continue;
279 /* Action was found or STOPSEARCHING was specified */
280 break;
282 /* DEBUGF("ret = %x\n",ret); */
283 #ifndef HAS_BUTTON_HOLD
284 if (screen_has_lock && (ret == ACTION_STD_KEYLOCK))
286 unlock_combo = button;
287 keys_locked = true;
288 splash(HZ/2, str(LANG_KEYLOCK_ON));
290 button_clear_queue();
291 return ACTION_REDRAW;
293 #endif
294 if ((current_tick - last_action_tick < REPEAT_WINDOW_TICKS)
295 && (ret == last_action))
296 repeated = true;
297 else
298 repeated = false;
300 last_button = button;
301 last_action = ret;
302 last_data = button_get_data();
303 last_action_tick = current_tick;
304 return ret;
307 int get_action(int context, int timeout)
309 return get_action_worker(context,timeout,NULL);
312 int get_custom_action(int context,int timeout,
313 const struct button_mapping* (*get_context_map)(int))
315 return get_action_worker(context,timeout,get_context_map);
318 bool action_userabort(int timeout)
320 int action = get_action_worker(CONTEXT_STD,timeout,NULL);
321 bool ret = (action == ACTION_STD_CANCEL);
322 if(!ret)
324 default_event_handler(action);
326 return ret;
329 #ifndef HAS_BUTTON_HOLD
330 bool is_keys_locked(void)
332 return (screen_has_lock && keys_locked);
334 #endif
336 intptr_t get_action_data(void)
338 return last_data;
341 int get_action_statuscode(int *button)
343 int ret = 0;
344 if (button)
345 *button = last_button;
347 if (last_button & BUTTON_REMOTE)
348 ret |= ACTION_REMOTE;
349 if (repeated)
350 ret |= ACTION_REPEAT;
351 return ret;
354 #ifdef HAVE_TOUCHSCREEN
355 /* return BUTTON_NONE on error
356 * BUTTON_REPEAT if repeated press
357 * BUTTON_REPEAT|BUTTON_REL if release after repeated press
358 * BUTTON_REL if its a short press = release after press
359 * BUTTON_TOUCHSCREEN if press
361 int action_get_touchscreen_press(short *x, short *y)
363 static int last_data = 0;
364 int data;
365 if ((last_button & BUTTON_TOUCHSCREEN) == 0)
366 return BUTTON_NONE;
367 data = button_get_data();
368 if (last_button & BUTTON_REL)
370 *x = (last_data&0xffff0000)>>16;
371 *y = (last_data&0xffff);
373 else
375 *x = (data&0xffff0000)>>16;
376 *y = (data&0xffff);
378 last_data = data;
379 if (repeated)
380 return BUTTON_REPEAT;
381 if (short_press)
382 return BUTTON_REL;
383 /* This is to return a BUTTON_REL after a BUTTON_REPEAT. */
384 if (last_button & BUTTON_REL)
385 return BUTTON_REPEAT|BUTTON_REL;
386 return BUTTON_TOUCHSCREEN;
388 #endif
390 /* Don't let get_action*() return any ACTION_* values untill the current buttons
391 * have ben release. SYS_* and BUTTON_NONE will go through.
392 * Any actions relying on _RELEASE won't get seen
394 void action_wait_for_release(void)
396 wait_for_release = true;