A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Copyright (C) 2008 by Maurus Cuelenaere
11* Copyright (C) 2009 by Karl Kurbjun
12*
13* This program is free software; you can redistribute it and/or
14* modify it under the terms of the GNU General Public License
15* as published by the Free Software Foundation; either version 2
16* of the License, or (at your option) any later version.
17*
18* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19* KIND, either express or implied.
20*
21****************************************************************************/
22
23#include "plugin.h"
24
25#include "pluginlib_touchscreen.h"
26#include "pluginlib_exit.h"
27
28/*******************************************************************************
29 * Touchbutton functions: These functions allow the plugin to specify a button
30 * location that, in turn gets mapped to a button press return value.
31 ******************************************************************************/
32
33/* touchbutton_check_button:
34 * This function checks the touchbutton structure passed to it for hits. When
35 * one is found it returns action. It doesn't block because it doesn't actually
36 * call button_get. You need to call it before and pass its result.
37 * inputs:
38 * struct touchbutton *data: This is intended to be an array of
39 * touchbuttons of size num_buttons. Each element in the array defines
40 * one button.
41 * int button: This is the button return value from a button_get() call.
42 * It is used to determine REPEAT/RELEASE events. This way
43 * this function can be mixed with other buttons
44 * int num_buttons: This tells touchbutton_get how many elements are in
45 * data.
46 * return:
47 * If a touch occured over one of the defined buttons, return action, else
48 * return 0.
49 */
50int touchbutton_check_button(int button, struct touchbutton *data, int num_buttons) {
51 short x,y;
52
53 /* Get the x/y location of the button press, this is set by button_get when
54 * a button is pulled from the queue.
55 */
56 x = rb->button_get_data() >> 16;
57 y = (short) rb->button_get_data();
58 struct viewport *v;
59
60 int i;
61
62 /* Loop over the data array to check if any of the buttons were pressed */
63 for (i=0; i<num_buttons; i++) {
64 v=&data[i].vp;
65 /* See if the point is inside the button viewport */
66 if( x >= v->x && x < (v->x + v->width) &&
67 y >= v->y && y < (v->y + v->height) ) {
68 if( ((button & BUTTON_REPEAT) && data[i].repeat) ||
69 ((button & BUTTON_REL) && !data[i].repeat) ) {
70 return data[i].action;
71 }
72 }
73 }
74 return 0;
75}
76
77/* touchbutton_get_w_tmo:
78 * This function checks the touchbutton structure passed to it for hits. When
79 * one is found it returns the corresponding action.
80 * inputs:
81 * struct touchbutton *data: This is intended to be an array of
82 * touchbuttons of size num_buttons. Each element in the array defines
83 * one button.
84 * int tmo: Timeout when waiting for input.
85 * int num_buttons: This tells touchbutton_get how many elements are in
86 * data.
87 * return:
88 * If a touch occured over one of the defined buttons, return action, else
89 * return 0.
90 */
91int touchbutton_get_w_tmo(int tmo, struct touchbutton *data, int num_buttons)
92{
93 int btn = rb->button_get_w_tmo(tmo);
94 int result = touchbutton_check_button(btn, data, num_buttons);
95 exit_on_usb(result);
96 return result;
97}
98
99/* touchbutton_get:
100 * This function checks the touchbutton structure passed to it for hits. When
101 * one is found it returns the corresponding action.
102 * inputs:
103 * struct touchbutton *data: This is intended to be an array of
104 * touchbuttons of size num_buttons. Each element in the array defines
105 * one button.
106 * int num_buttons: This tells touchbutton_get how many elements are in
107 * data.
108 * return:
109 * If a touch occured over one of the defined buttons, return action, else
110 * return 0.
111 */
112int touchbutton_get(struct touchbutton *data, int num_buttons)
113{
114 return touchbutton_get_w_tmo(TIMEOUT_BLOCK, data, num_buttons);
115}
116
117/* touchbutton_draw:
118 * This function draws the button with the associated text as long as the
119 * invisible flag is not set. Support for pixmaps needs to be added.
120 * inputs:
121 * struct touchbutton *data: This is intended to be an array of
122 * touchbuttons of size num_buttons. Each element in the array defines
123 * one button.
124 * int num_buttons: This tells touchbutton_get how many elements are in
125 * data.
126 * return:
127 * If a touch occured over one of the defined buttons, return action, else
128 * return 0.
129 */
130void touchbutton_draw(struct touchbutton *data, int num_buttons) {
131 int i;
132 struct screen *lcd = rb->screens[SCREEN_MAIN];
133
134 /* Loop over all the elements in data */
135 for(i=0; i<num_buttons; i++) {
136 /* Is this a visible button? */
137 if(!data[i].invisible) {
138 /* Set the current viewport to the button so that all drawing
139 * operations are within the button location.
140 */
141 lcd->set_viewport(&data[i].vp);
142
143 /* TODO: Center text vert*/
144 data[i].vp.flags |= VP_FLAG_ALIGN_CENTER;
145
146 /* If the width offset was 0, use a scrolling puts, else center and
147 * print the title.
148 */
149 lcd->puts_scroll(0, 0, data[i].title);
150 /* Draw bounding box around the button location. */
151 lcd->draw_border_viewport();
152 }
153 }
154 lcd->set_viewport(NULL); /* Go back to the default viewport */
155}
156
157/*******************************************************************************
158 * Touchmap functions: Not sure how exactly these functions are used, comments
159 * needed!!!
160 ******************************************************************************/
161unsigned int touchscreen_map(struct ts_mappings *map, int x, int y)
162{
163 int i;
164 for(i=0; i < map->amount; i++)
165 {
166 #define _MAP(x) (map->mappings[x])
167 if(x > _MAP(i).tl_x && x < (_MAP(i).tl_x+_MAP(i).width)
168 && y > _MAP(i).tl_y && y < (_MAP(i).tl_y+_MAP(i).height))
169 return i;
170 }
171
172 return -1;
173}
174
175unsigned int touchscreen_map_raster(struct ts_raster *map, int x, int y, struct ts_raster_result *result)
176{
177 int res1_x, res2_x, res1_y, res2_y;
178
179 if((x - map->tl_x) < 0 ||
180 (x - map->tl_x) > map->width)
181 return -1;
182 res1_x = (x - map->tl_x)/(map->raster_width);
183 res2_x = (x - map->tl_x)%(map->raster_width);
184
185 if((y - map->tl_y) < 0 ||
186 (y - map->tl_y) > map->height)
187 return -1;
188 res1_y = (y - map->tl_y)/(map->raster_height);
189 res2_y = (y - map->tl_y)%(map->raster_height);
190
191 if(res2_x == 0 || res2_y == 0) /* pen hit a raster boundary */
192 return -2;
193 else
194 {
195 (*result).x = res1_x;
196 (*result).y = res1_y;
197 return 1;
198 }
199}
200
201struct ts_raster_button_result touchscreen_raster_map_button(struct ts_raster_button_mapping *map, int x, int y, int button)
202{
203 struct ts_raster_button_result ret = {0, {0, 0}, {0, 0}};
204 struct ts_raster_result tmp;
205
206 ret.action = TS_ACTION_NONE;
207 if(touchscreen_map_raster(map->raster, x, y, &tmp) != 1)
208 return ret;
209
210 #define NOT_HANDLED (ret.action == TS_ACTION_NONE)
211 if((button == BUTTON_REPEAT) && (map->_prev_btn_state != BUTTON_REPEAT) && map->drag_drop_enable)
212 {
213 map->_prev_x = tmp.x;
214 map->_prev_y = tmp.y;
215 }
216 if((button == BUTTON_REL) && (map->_prev_btn_state == BUTTON_REPEAT) && map->drag_drop_enable)
217 {
218 ret.action = TS_ACTION_DRAG_DROP;
219 ret.from.x = map->_prev_x;
220 ret.from.y = map->_prev_y;
221 ret.to.x = tmp.x;
222 ret.to.y = tmp.y;
223 }
224 if((button == BUTTON_REL) && map->double_click_enable && NOT_HANDLED)
225 {
226 if(map->_prev_x == tmp.x && map->_prev_y == tmp.y)
227 {
228 ret.action = TS_ACTION_DOUBLE_CLICK;
229 ret.from.x = ret.to.x = tmp.x;
230 ret.from.y = ret.to.y = tmp.y;
231 }
232 else
233 {
234 map->_prev_x = tmp.x;
235 map->_prev_y = tmp.y;
236 }
237 }
238 if((button & BUTTON_REL || button & BUTTON_REPEAT) && map->two_d_movement_enable && NOT_HANDLED)
239 {
240 if((map->two_d_from.x == tmp.x) ^ (map->two_d_from.y == tmp.y))
241 {
242 ret.action = TS_ACTION_TWO_D_MOVEMENT;
243 ret.from.x = map->two_d_from.x;
244 ret.from.y = map->two_d_from.y;
245 ret.to.x = map->two_d_from.x + (map->two_d_from.x == tmp.x ? 0 : (tmp.x > map->two_d_from.x ? 1 : -1));
246 ret.to.y = map->two_d_from.y + (map->two_d_from.y == tmp.y ? 0 : (tmp.y > map->two_d_from.y ? 1 : -1));
247 }
248 else
249 ret.action = TS_ACTION_NONE;
250 }
251 if(map->click_enable && (button & BUTTON_REL) && NOT_HANDLED)
252 {
253 ret.action = TS_ACTION_CLICK;
254 ret.from.x = ret.to.x = tmp.x;
255 ret.from.y = ret.to.y = tmp.y;
256 }
257 if(map->move_progress_enable && NOT_HANDLED)
258 {
259 ret.action = TS_ACTION_MOVE;
260 ret.from.x = ret.to.x = tmp.x;
261 ret.from.y = ret.to.y = tmp.y;
262 }
263
264 map->_prev_btn_state = button;
265 return ret;
266}