summaryrefslogtreecommitdiff
path: root/apps/action.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/action.c')
-rw-r--r--apps/action.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/apps/action.c b/apps/action.c
new file mode 100644
index 0000000000..fc5a8b88a9
--- /dev/null
+++ b/apps/action.c
@@ -0,0 +1,215 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2006 Jonathan Gordon
10 *
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
13 *
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
16 *
17 ****************************************************************************/
18#include <stdio.h>
19#include <string.h>
20#include <stdlib.h>
21
22#include "config.h"
23#include "button.h"
24#include "action.h"
25#include "kernel.h"
26#include "debug.h"
27
28bool ignore_until_release = false;
29int last_button = BUTTON_NONE;
30int soft_unlock_action = ACTION_NONE;
31bool allow_remote_actions = true;
32/*
33 * do_button_check is the worker function for get_default_action.
34 * returns ACTION_UNKNOWN or the requested return value from the list.
35 */
36inline int do_button_check(struct button_mapping *items,
37 int button, int last_button, int *start)
38{
39 int i = 0;
40 int ret = ACTION_UNKNOWN;
41 if (items == NULL)
42 return ACTION_UNKNOWN;
43
44 /* Special case to make the keymaps smaller */
45 if(button & BUTTON_REPEAT)
46 last_button &= ~BUTTON_REPEAT;
47
48 while (items[i].button_code != BUTTON_NONE)
49 {
50 if (items[i].button_code == button)
51 {
52 if (items[i].pre_button_code != BUTTON_NONE)
53 {
54 if ((items[i].pre_button_code == last_button) ||
55 (items[i].button_code == last_button))
56 {
57 ret = items[i].action_code;
58 break;
59 }
60 }
61 else
62 {
63 ret = items[i].action_code;
64 break;
65 }
66 }
67 i++;
68 }
69 *start = i;
70 return ret;
71}
72
73inline int get_next_context(struct button_mapping *items, int i)
74{
75 while (items[i].button_code != BUTTON_NONE)
76 i++;
77 return (items[i].action_code == ACTION_NONE ) ?
78 CONTEXT_STD :
79 items[i].action_code;
80}
81/*
82 * int get_action_worker(int context, struct button_mapping *user_mappings,
83 int timeout)
84 This function searches the button list for the given context for the just
85 pressed button.
86 If there is a match it returns the value from the list.
87 If there is no match..
88 the last item in the list "points" to the next context in a chain
89 so the "chain" is followed until the button is found.
90 putting ACTION_NONE will get CONTEXT_STD which is always the last list checked.
91
92 Timeout can be TIMEOUT_NOBLOCK to return immediatly
93 TIMEOUT_BLOCK to wait for a button press
94 Any number >0 to wait that many ticks for a press
95
96 */
97int get_action_worker(int context, int timeout,
98 struct button_mapping* (*get_context_map)(int) )
99{
100 struct button_mapping *items = NULL;
101 int button;
102 int i=0;
103 int ret = ACTION_UNKNOWN;
104 if (timeout == TIMEOUT_NOBLOCK)
105 button = button_get(false);
106 else if (timeout == TIMEOUT_BLOCK)
107 button = button_get(true);
108 else
109 button = button_get_w_tmo(timeout);
110
111
112 if (button == BUTTON_NONE || button&SYS_EVENT)
113 {
114 return button;
115 }
116
117 if (ignore_until_release == true)
118 {
119 if (button&BUTTON_REL)
120 {
121 ignore_until_release = false;
122 }
123 /*last_button = BUTTON_NONE; this is done by action_signalscreenchange() */
124 return ACTION_UNKNOWN; /* "safest" return value */
125 }
126
127 if (soft_unlock_action != ACTION_NONE)
128 {
129 if ((button&BUTTON_REMOTE) && !allow_remote_actions)
130 return ACTION_NONE;
131 }
132 /* logf("%x,%x",last_button,button); */
133 do
134 {
135 /* logf("context = %x",context); */
136#if (BUTTON_REMOTE != 0)
137 if (button&BUTTON_REMOTE)
138 context |= CONTEXT_REMOTE;
139#endif
140 if ((context&CONTEXT_CUSTOM) && get_context_map)
141 items = get_context_map(context);
142 else
143 items = get_context_mapping(context);
144
145 ret = do_button_check(items,button,last_button,&i);
146
147 if ((context == CONTEXT_STD)
148#if (BUTTON_REMOTE != 0)
149 || ((unsigned)context == (CONTEXT_STD|CONTEXT_REMOTE))
150#endif
151 ) break;
152
153 if (ret == ACTION_UNKNOWN )
154 {
155 context = get_next_context(items,i);
156 i = 0;
157 }
158 else break;
159 } while (1);
160 /* DEBUGF("ret = %x\n",ret); */
161
162 if (soft_unlock_action != ACTION_NONE)
163 {
164 if ((button&BUTTON_REMOTE) == 0)
165 {
166 if (soft_unlock_action == ret)
167 {
168 soft_unlock_action = ACTION_NONE;
169 ret = ACTION_NONE; /* no need to return the code */
170 }
171 }
172 else if (!allow_remote_actions)
173 ret = ACTION_NONE;
174 }
175
176 last_button = button;
177 return ret;
178}
179
180int get_action(int context, int timeout)
181{
182 return get_action_worker(context,timeout,NULL);
183}
184
185int get_custom_action(int context,int timeout,
186 struct button_mapping* (*get_context_map)(int))
187{
188 return get_action_worker(context,timeout,get_context_map);
189}
190
191bool action_userabort(int timeout)
192{
193 action_signalscreenchange();
194 int action = get_action_worker(CONTEXT_STD,timeout,NULL);
195 bool ret = (action == ACTION_STD_CANCEL);
196 action_signalscreenchange();
197 return ret;
198}
199
200void action_signalscreenchange(void)
201{
202 if ((last_button != BUTTON_NONE) &&
203 !(last_button&BUTTON_REL))
204 {
205 ignore_until_release = true;
206 }
207 last_button = BUTTON_NONE;
208}
209
210void action_setsoftwarekeylock(int unlock_action, bool allow_remote)
211{
212 soft_unlock_action = unlock_action;
213 allow_remote_actions = allow_remote;
214 last_button = BUTTON_NONE;
215}