diff options
Diffstat (limited to 'apps/action.c')
-rw-r--r-- | apps/action.c | 215 |
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 | |||
28 | bool ignore_until_release = false; | ||
29 | int last_button = BUTTON_NONE; | ||
30 | int soft_unlock_action = ACTION_NONE; | ||
31 | bool 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 | */ | ||
36 | inline 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 | |||
73 | inline 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 | */ | ||
97 | int 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 | |||
180 | int get_action(int context, int timeout) | ||
181 | { | ||
182 | return get_action_worker(context,timeout,NULL); | ||
183 | } | ||
184 | |||
185 | int 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 | |||
191 | bool 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 | |||
200 | void 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 | |||
210 | void 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 | } | ||