Make volume and progresssbar touch regions work with touch timeouts
[maemo-rb.git] / apps / gui / skin_engine / skin_touchsupport.c
bloba0b82dd9dada3252a2a62749064393d67fbc4563
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2009 - 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 ****************************************************************************/
22 #include "config.h"
23 #include <stdio.h>
24 #include "action.h"
25 #include "skin_engine.h"
26 #include "wps_internals.h"
27 #include "misc.h"
28 #include "option_select.h"
29 #include "sound.h"
30 #include "settings_list.h"
31 #include "wps.h"
32 #include "lang.h"
33 #include "splash.h"
34 #include "playlist.h"
35 #include "dsp.h"
37 /** Disarms all touchregions. */
38 void skin_disarm_touchregions(struct wps_data *data)
40 struct skin_token_list *regions = data->touchregions;
41 while (regions)
43 ((struct touchregion *)regions->token->value.data)->armed = false;
44 regions = regions->next;
48 /* Get the touched action.
49 * egde_offset is a percentage value for the position of the touch
50 * inside the bar for regions which arnt WPS_TOUCHREGION_ACTION type.
52 int skin_get_touchaction(struct wps_data *data, int* edge_offset,
53 struct touchregion **retregion)
55 int returncode = ACTION_NONE;
56 short x,y;
57 short vx, vy;
58 int type = action_get_touchscreen_press(&x, &y);
59 struct touchregion *r, *temp = NULL;
60 bool repeated = (type == BUTTON_REPEAT);
61 bool released = (type == BUTTON_REL);
62 bool pressed = (type == BUTTON_TOUCHSCREEN);
63 struct skin_token_list *regions = data->touchregions;
64 bool needs_repeat;
66 while (regions)
68 r = (struct touchregion *)regions->token->value.data;
69 /* make sure this region's viewport is visible */
70 if (r->wvp->hidden_flags&VP_DRAW_HIDDEN)
72 regions = regions->next;
73 continue;
75 needs_repeat = r->press_length != PRESS;
76 /* check if it's inside this viewport */
77 if (viewport_point_within_vp(&(r->wvp->vp), x, y))
78 { /* reposition the touch inside the viewport since touchregions
79 * are relative to a preceding viewport */
80 vx = x - r->wvp->vp.x;
81 vy = y - r->wvp->vp.y;
82 /* now see if the point is inside this region */
83 if (vx >= r->x && vx < r->x+r->width &&
84 vy >= r->y && vy < r->y+r->height)
86 /* reposition the touch within the area */
87 vx -= r->x;
88 vy -= r->y;
91 switch(r->action)
93 case ACTION_TOUCH_SCROLLBAR:
94 case ACTION_TOUCH_VOLUME:
95 if (edge_offset)
97 if(r->width > r->height)
98 *edge_offset = vx*100/r->width;
99 else
100 *edge_offset = vy*100/r->height;
101 if (r->reverse_bar)
102 *edge_offset = 100 - *edge_offset;
104 temp = r;
105 returncode = r->action;
106 r->last_press = current_tick;
107 break;
108 default:
109 if (r->armed && ((repeated && needs_repeat) ||
110 (released && !needs_repeat)))
112 returncode = r->action;
113 temp = r;
115 if (pressed)
117 r->armed = true;
118 r->last_press = current_tick;
120 break;
124 regions = regions->next;
127 /* On release, all regions are disarmed. */
128 if (released)
129 skin_disarm_touchregions(data);
130 if (retregion && temp)
131 *retregion = temp;
132 if (temp && temp->press_length == LONG_PRESS)
133 temp->armed = false;
135 if (returncode != ACTION_NONE)
137 if (global_settings.party_mode)
139 switch (returncode)
141 case ACTION_WPS_PLAY:
142 case ACTION_WPS_SKIPPREV:
143 case ACTION_WPS_SKIPNEXT:
144 case ACTION_WPS_STOP:
145 returncode = ACTION_NONE;
146 break;
147 default:
148 break;
151 switch (returncode)
153 case ACTION_WPS_PLAY:
154 if (!audio_status())
156 if ( global_status.resume_index != -1 )
158 if (playlist_resume() != -1)
160 playlist_start(global_status.resume_index,
161 global_status.resume_offset);
164 else
166 splash(HZ*2, ID2P(LANG_NOTHING_TO_RESUME));
169 else
171 wps_do_playpause(false);
173 returncode = ACTION_REDRAW;
174 break;
175 case ACTION_WPS_SKIPPREV:
176 audio_prev();
177 returncode = ACTION_REDRAW;
178 break;
179 case ACTION_WPS_SKIPNEXT:
180 audio_next();
181 returncode = ACTION_REDRAW;
182 break;
183 case ACTION_WPS_STOP:
184 audio_stop();
185 returncode = ACTION_REDRAW;
186 break;
187 case ACTION_SETTINGS_INC:
188 case ACTION_SETTINGS_DEC:
190 const struct settings_list *setting =
191 temp->setting_data.setting;
192 option_select_next_val(setting,
193 returncode == ACTION_SETTINGS_DEC,
194 true);
195 returncode = ACTION_REDRAW;
197 break;
198 case ACTION_SETTINGS_SET:
200 struct touchsetting *data = &temp->setting_data;
201 const struct settings_list *s = data->setting;
202 void (*f)(int) = NULL;
203 switch (s->flags&F_T_MASK)
205 case F_T_CUSTOM:
206 s->custom_setting
207 ->load_from_cfg(s->setting, data->value.text);
208 break;
209 case F_T_INT:
210 case F_T_UINT:
211 *(int*)s->setting = data->value.number;
212 if (s->flags&F_CHOICE_SETTING)
213 f = s->choice_setting->option_callback;
214 else if (s->flags&F_TABLE_SETTING)
215 f = s->table_setting->option_callback;
216 else
217 f = s->int_setting->option_callback;
219 if (f)
220 f(data->value.number);
221 break;
222 case F_T_BOOL:
223 *(bool*)s->setting = data->value.number ? true : false;
224 if (s->bool_setting->option_callback)
225 s->bool_setting
226 ->option_callback(data->value.number ? true : false);
227 break;
229 returncode = ACTION_REDRAW;
231 break;
232 case ACTION_TOUCH_MUTE:
234 const int min_vol = sound_min(SOUND_VOLUME);
235 if (global_settings.volume == min_vol)
236 global_settings.volume = temp->value;
237 else
239 temp->value = global_settings.volume;
240 global_settings.volume = min_vol;
242 setvol();
243 returncode = ACTION_REDRAW;
245 break;
246 case ACTION_TOUCH_SHUFFLE: /* toggle shuffle mode */
248 global_settings.playlist_shuffle =
249 !global_settings.playlist_shuffle;
250 #if CONFIG_CODEC == SWCODEC
251 dsp_set_replaygain();
252 #endif
253 if (global_settings.playlist_shuffle)
254 playlist_randomise(NULL, current_tick, true);
255 else
256 playlist_sort(NULL, true);
257 returncode = ACTION_REDRAW;
259 break;
260 case ACTION_TOUCH_REPMODE: /* cycle the repeat mode setting */
262 const struct settings_list *rep_setting =
263 find_setting(&global_settings.repeat_mode, NULL);
264 option_select_next_val(rep_setting, false, true);
265 audio_flush_and_reload_tracks();
266 returncode = ACTION_REDRAW;
268 break;
270 return returncode;
273 return ACTION_TOUCHSCREEN;