diff options
Diffstat (limited to 'apps/plugins/pdbox/pdbox-gui.c')
-rw-r--r-- | apps/plugins/pdbox/pdbox-gui.c | 809 |
1 files changed, 809 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/pdbox-gui.c b/apps/plugins/pdbox/pdbox-gui.c new file mode 100644 index 0000000000..a03e97c361 --- /dev/null +++ b/apps/plugins/pdbox/pdbox-gui.c | |||
@@ -0,0 +1,809 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2009 Wincent Balin | ||
11 | * | ||
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. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "plugin.h" | ||
23 | #include "pdbox.h" | ||
24 | |||
25 | #include "lib/xlcd.h" | ||
26 | |||
27 | /* Declare back- and foreground colors. */ | ||
28 | #define BGCOLOR (LCD_BLACK) | ||
29 | #define FGCOLOR (LCD_WHITE) | ||
30 | /* Button colors. */ | ||
31 | #define BTNCOLOR_DARK (LCD_DARKGRAY) | ||
32 | #define BTNCOLOR_LIGHT (LCD_LIGHTGRAY) | ||
33 | |||
34 | /* Variables in the main code. */ | ||
35 | extern char* filename; | ||
36 | extern bool quit; | ||
37 | |||
38 | /* Screen multiplier. */ | ||
39 | static float screen_multiplier; | ||
40 | |||
41 | /* Displacement of the slanted corner in the contour of the number widget. */ | ||
42 | static int number_corner; | ||
43 | |||
44 | /* Button flags. */ | ||
45 | static bool play_on; | ||
46 | static bool previous_on; | ||
47 | static bool next_on; | ||
48 | static bool menu_on; | ||
49 | static bool action_on; | ||
50 | |||
51 | /* Pause flag. */ | ||
52 | static bool paused; | ||
53 | |||
54 | |||
55 | /* Draw circle using midpoint circle algorithm. | ||
56 | Adapted from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm. */ | ||
57 | void drawcircle(int x, int y, int r) | ||
58 | { | ||
59 | int f = 1 - r; | ||
60 | int ddfx = 1; | ||
61 | int ddfy = -2 * r; | ||
62 | int xp = 0; | ||
63 | int yp = r; | ||
64 | |||
65 | /* Draw outer points. */ | ||
66 | rb->lcd_drawpixel(x, y + r); | ||
67 | rb->lcd_drawpixel(x, y + r); | ||
68 | rb->lcd_drawpixel(x + r, y); | ||
69 | rb->lcd_drawpixel(x - r, y); | ||
70 | |||
71 | /* Calculate coordinates of points in one octant. */ | ||
72 | while(xp < yp) | ||
73 | { | ||
74 | /* ddfx == 2 * xp + 1; | ||
75 | ddfy == -2 * yp; | ||
76 | f == xp*xp + yp*yp - r*r + 2*xp - yp + 1; */ | ||
77 | if(f >= 0) | ||
78 | { | ||
79 | yp--; | ||
80 | ddfy += 2; | ||
81 | f += ddfy; | ||
82 | } | ||
83 | |||
84 | xp++; | ||
85 | ddfx += 2; | ||
86 | f += ddfx; | ||
87 | |||
88 | /* Draw pixels in all octants. */ | ||
89 | rb->lcd_drawpixel(x + xp, y + yp); | ||
90 | rb->lcd_drawpixel(x + xp, y - yp); | ||
91 | rb->lcd_drawpixel(x - xp, y + yp); | ||
92 | rb->lcd_drawpixel(x - xp, y - yp); | ||
93 | rb->lcd_drawpixel(x + yp, y + xp); | ||
94 | rb->lcd_drawpixel(x + yp, y - xp); | ||
95 | rb->lcd_drawpixel(x - yp, y + xp); | ||
96 | rb->lcd_drawpixel(x - yp, y - xp); | ||
97 | } | ||
98 | } | ||
99 | |||
100 | /* Fill circle. */ | ||
101 | void fillcircle(int x, int y, int r) | ||
102 | { | ||
103 | int f = 1 - r; | ||
104 | int ddfx = 1; | ||
105 | int ddfy = -2 * r; | ||
106 | int xp = 0; | ||
107 | int yp = r; | ||
108 | |||
109 | /* Draw outer points. */ | ||
110 | rb->lcd_drawpixel(x, y + r); | ||
111 | rb->lcd_drawpixel(x, y + r); | ||
112 | rb->lcd_drawpixel(x + r, y); | ||
113 | rb->lcd_drawpixel(x - r, y); | ||
114 | |||
115 | /* Calculate coordinates of points in one octant. */ | ||
116 | while(xp < yp) | ||
117 | { | ||
118 | /* ddfx == 2 * xp + 1; | ||
119 | ddfy == -2 * yp; | ||
120 | f == xp*xp + yp*yp - r*r + 2*xp - yp + 1; */ | ||
121 | if(f >= 0) | ||
122 | { | ||
123 | yp--; | ||
124 | ddfy += 2; | ||
125 | f += ddfy; | ||
126 | } | ||
127 | |||
128 | xp++; | ||
129 | ddfx += 2; | ||
130 | f += ddfx; | ||
131 | |||
132 | /* Fill circle with horizontal lines. */ | ||
133 | rb->lcd_hline(x - xp, x + xp, y - yp); | ||
134 | rb->lcd_hline(x - xp, x + xp, y + yp); | ||
135 | rb->lcd_hline(x - yp, x + yp, y - xp); | ||
136 | rb->lcd_hline(x - yp, x + yp, y + xp); | ||
137 | } | ||
138 | |||
139 | /* Draw last horizontal line (central one). */ | ||
140 | rb->lcd_hline(x - r, x + r, y); | ||
141 | } | ||
142 | |||
143 | /* Initialize GUI. */ | ||
144 | void pd_gui_init(void) | ||
145 | { | ||
146 | /* Reset button flags. */ | ||
147 | play_on = false; | ||
148 | previous_on = false; | ||
149 | next_on = false; | ||
150 | menu_on = false; | ||
151 | action_on = false; | ||
152 | |||
153 | /* Unpause Pure Data. */ | ||
154 | paused = false; | ||
155 | |||
156 | /* Calculate dimension factors. */ | ||
157 | screen_multiplier = ((float) LCD_WIDTH) / 160.0f; | ||
158 | number_corner = 5 * screen_multiplier; | ||
159 | |||
160 | /* Set back- and foreground color. */ | ||
161 | rb->lcd_set_background(BGCOLOR); | ||
162 | rb->lcd_set_foreground(FGCOLOR); | ||
163 | |||
164 | /* Clear background. */ | ||
165 | rb->lcd_clear_display(); | ||
166 | |||
167 | /* Update display. */ | ||
168 | rb->lcd_update(); | ||
169 | } | ||
170 | |||
171 | /* Load PD patch. */ | ||
172 | unsigned int pd_gui_load_patch(struct pd_widget* wg, unsigned int max_widgets) | ||
173 | { | ||
174 | int fd; | ||
175 | char line[100]; | ||
176 | char* saveptr; | ||
177 | unsigned int widgets = 0; | ||
178 | |||
179 | /* Open PD patch. */ | ||
180 | fd = open(filename, O_RDONLY); | ||
181 | |||
182 | /* Check for I/O error. */ | ||
183 | if(!fd) | ||
184 | { | ||
185 | /* Show error message and make plug-in quit. */ | ||
186 | rb->splash(HZ, "Error opening .pd file!"); | ||
187 | quit = true; | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | /* Read lines from PD file. */ | ||
192 | while(rb->read_line(fd, line, sizeof(line)) > 0) | ||
193 | { | ||
194 | /* Check whether we got too many widgets. */ | ||
195 | if(widgets >= max_widgets) | ||
196 | { | ||
197 | rb->splash(HZ, "Too many widgets!"); | ||
198 | quit = true; | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | /* Search for key strings in the line. */ | ||
203 | if((strstr(line, "floatatom") != NULL) && | ||
204 | (strstr(line, "pod_") != NULL)) | ||
205 | { | ||
206 | wg->id = PD_NUMBER; | ||
207 | |||
208 | strtok_r(line, " ", &saveptr); | ||
209 | strtok_r(NULL, " ", &saveptr); | ||
210 | wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
211 | wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
212 | wg->w = 7 * atoi(strtok_r(NULL, " ", &saveptr)) * | ||
213 | screen_multiplier; | ||
214 | wg->h = 16 * screen_multiplier; | ||
215 | strtok_r(NULL, " ", &saveptr); | ||
216 | strtok_r(NULL, " ", &saveptr); | ||
217 | strtok_r(NULL, " ", &saveptr); | ||
218 | strtok_r(NULL, " ", &saveptr); | ||
219 | strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name)); | ||
220 | |||
221 | /* We got one more widget. */ | ||
222 | wg++; | ||
223 | widgets++; | ||
224 | } | ||
225 | else if((strstr(line, "symbolatom") != NULL) && | ||
226 | (strstr(line, "pod_") != NULL)) | ||
227 | { | ||
228 | wg->id = PD_SYMBOL; | ||
229 | |||
230 | strtok_r(line, " ", &saveptr); | ||
231 | strtok_r(NULL, " ", &saveptr); | ||
232 | wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
233 | wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
234 | wg->w = 7 * atoi(strtok_r(NULL, " ", &saveptr)) * | ||
235 | screen_multiplier; | ||
236 | wg->h = 16 * screen_multiplier; | ||
237 | strtok_r(NULL, " ", &saveptr); | ||
238 | strtok_r(NULL, " ", &saveptr); | ||
239 | strtok_r(NULL, " ", &saveptr); | ||
240 | strtok_r(NULL, " ", &saveptr); | ||
241 | strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name)); | ||
242 | |||
243 | /* We got one more widget. */ | ||
244 | wg++; | ||
245 | widgets++; | ||
246 | } | ||
247 | else if((strstr(line, "vsl") != NULL) && | ||
248 | (strstr(line, "pod_") != NULL)) | ||
249 | { | ||
250 | wg->id = PD_VSLIDER; | ||
251 | |||
252 | strtok_r(line, " ", &saveptr); | ||
253 | strtok_r(NULL, " ", &saveptr); | ||
254 | wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
255 | wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
256 | strtok_r(NULL, " ", &saveptr); | ||
257 | wg->w = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
258 | wg->h = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
259 | wg->min = atoi(strtok_r(NULL, " ", &saveptr)); | ||
260 | wg->max = atoi(strtok_r(NULL, " ", &saveptr)); | ||
261 | strtok_r(NULL, " ", &saveptr); | ||
262 | strtok_r(NULL, " ", &saveptr); | ||
263 | strtok_r(NULL, " ", &saveptr); | ||
264 | strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name)); | ||
265 | |||
266 | /* We got one more widget. */ | ||
267 | wg++; | ||
268 | widgets++; | ||
269 | } | ||
270 | else if((strstr(line, "hsl") != NULL) && | ||
271 | (strstr(line, "pod_") != NULL)) | ||
272 | { | ||
273 | wg->id = PD_HSLIDER; | ||
274 | |||
275 | strtok_r(line, " ", &saveptr); | ||
276 | strtok_r(NULL, " ", &saveptr); | ||
277 | wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
278 | wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
279 | strtok_r(NULL, " ", &saveptr); | ||
280 | wg->w = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
281 | wg->h = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
282 | wg->min = atoi(strtok_r(NULL, " ", &saveptr)); | ||
283 | wg->max = atoi(strtok_r(NULL, " ", &saveptr)); | ||
284 | strtok_r(NULL, " ", &saveptr); | ||
285 | strtok_r(NULL, " ", &saveptr); | ||
286 | strtok_r(NULL, " ", &saveptr); | ||
287 | strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name)); | ||
288 | |||
289 | /* We got one more widget. */ | ||
290 | wg++; | ||
291 | widgets++; | ||
292 | } | ||
293 | else if((strstr(line, "vradio") != NULL) && | ||
294 | (strstr(line, "pod_") != NULL)) | ||
295 | { | ||
296 | wg->id = PD_VRADIO; | ||
297 | |||
298 | strtok_r(line, " ", &saveptr); | ||
299 | strtok_r(NULL, " ", &saveptr); | ||
300 | wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
301 | wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
302 | strtok_r(NULL, " ", &saveptr); | ||
303 | wg->w = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
304 | strtok_r(NULL, " ", &saveptr); | ||
305 | strtok_r(NULL, " ", &saveptr); | ||
306 | wg->min = 0; | ||
307 | wg->max = atoi(strtok_r(NULL, " ", &saveptr)); | ||
308 | wg->h = wg->w * wg->max; | ||
309 | strtok_r(NULL, " ", &saveptr); | ||
310 | strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name)); | ||
311 | wg->max--; | ||
312 | |||
313 | /* We got one more widget. */ | ||
314 | wg++; | ||
315 | widgets++; | ||
316 | } | ||
317 | else if((strstr(line, "hradio") != NULL) && | ||
318 | (strstr(line, "pod_") != NULL)) | ||
319 | { | ||
320 | wg->id = PD_HRADIO; | ||
321 | |||
322 | strtok_r(line, " ", &saveptr); | ||
323 | strtok_r(NULL, " ", &saveptr); | ||
324 | wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
325 | wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
326 | strtok_r(NULL, " ", &saveptr); | ||
327 | wg->h = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
328 | strtok_r(NULL, " ", &saveptr); | ||
329 | strtok_r(NULL, " ", &saveptr); | ||
330 | wg->min = 0; | ||
331 | wg->max = atoi(strtok_r(NULL, " ", &saveptr)); | ||
332 | wg->w = wg->h * wg->max; | ||
333 | strtok_r(NULL, " ", &saveptr); | ||
334 | strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name)); | ||
335 | wg->max--; | ||
336 | |||
337 | /* We got one more widget. */ | ||
338 | wg++; | ||
339 | widgets++; | ||
340 | } | ||
341 | else if((strstr(line, "bng") != NULL) && | ||
342 | (strstr(line, "pod_") != NULL)) | ||
343 | { | ||
344 | wg->id = PD_BANG; | ||
345 | |||
346 | strtok_r(line, " ", &saveptr); | ||
347 | strtok_r(NULL, " ", &saveptr); | ||
348 | wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
349 | wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
350 | strtok_r(NULL, " ", &saveptr); | ||
351 | wg->w = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
352 | wg->h = wg->w; | ||
353 | strtok_r(NULL, " ", &saveptr); | ||
354 | strtok_r(NULL, " ", &saveptr); | ||
355 | strtok_r(NULL, " ", &saveptr); | ||
356 | strtok_r(NULL, " ", &saveptr); | ||
357 | strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name)); | ||
358 | wg->min = 0; | ||
359 | wg->max = 1; | ||
360 | |||
361 | /* Clear timeout flag. */ | ||
362 | wg->timeout = 0; | ||
363 | |||
364 | /* We got one more widget. */ | ||
365 | wg++; | ||
366 | widgets++; | ||
367 | } | ||
368 | else if(strstr(line, "text") != NULL) | ||
369 | { | ||
370 | wg->id = PD_TEXT; | ||
371 | |||
372 | strtok_r(line, " ", &saveptr); | ||
373 | strtok_r(NULL, " ", &saveptr); | ||
374 | wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
375 | wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; | ||
376 | strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name)); | ||
377 | char* w = strtok_r(NULL, " ", &saveptr); | ||
378 | while(w != NULL) | ||
379 | { | ||
380 | strcat(wg->name, w); | ||
381 | strcat(wg->name, " "); | ||
382 | w = strtok_r(NULL, " ", &saveptr); | ||
383 | } | ||
384 | /* Cut off unneeded characters (';' and '\n'). */ | ||
385 | int namelen = strlen(wg->name); | ||
386 | if(namelen > 1) | ||
387 | { | ||
388 | /* Cut off '\n'. */ | ||
389 | wg->name[namelen-1] = '\0'; | ||
390 | namelen--; | ||
391 | /* Cut the last semi-colon, if there is one. */ | ||
392 | if(wg->name[namelen-1] == ';') | ||
393 | wg->name[namelen-1] = '\0'; | ||
394 | } | ||
395 | |||
396 | |||
397 | /* We got one more widget. */ | ||
398 | wg++; | ||
399 | widgets++; | ||
400 | } | ||
401 | } | ||
402 | |||
403 | /* Close PD patch. */ | ||
404 | close(fd); | ||
405 | |||
406 | /* Return amount of loaded widgets. */ | ||
407 | return widgets; | ||
408 | } | ||
409 | |||
410 | /* Draw standard user interface. */ | ||
411 | void pd_gui_draw_standard(void) | ||
412 | { | ||
413 | /* Draw main circle. */ | ||
414 | rb->lcd_set_foreground(FGCOLOR); | ||
415 | fillcircle(LCD_WIDTH / 2, | ||
416 | LCD_HEIGHT / 2, | ||
417 | 2 * MIN(LCD_WIDTH, LCD_HEIGHT) / 5); | ||
418 | |||
419 | /* Draw center circle. */ | ||
420 | rb->lcd_set_foreground(action_on ? BTNCOLOR_DARK : BTNCOLOR_LIGHT); | ||
421 | fillcircle(LCD_WIDTH / 2, | ||
422 | LCD_HEIGHT / 2, | ||
423 | MIN(LCD_WIDTH, LCD_HEIGHT) / 8); | ||
424 | |||
425 | /* Draw pressed buttons. */ | ||
426 | if(play_on) | ||
427 | fillcircle(LCD_WIDTH / 2, | ||
428 | 3 * LCD_HEIGHT / 4, | ||
429 | MIN(LCD_WIDTH, LCD_HEIGHT) / 8); | ||
430 | |||
431 | if(previous_on) | ||
432 | fillcircle(LCD_WIDTH / 3, | ||
433 | LCD_HEIGHT / 2, | ||
434 | MIN(LCD_WIDTH, LCD_HEIGHT) / 8); | ||
435 | |||
436 | if(next_on) | ||
437 | fillcircle(2 * LCD_WIDTH / 3 + 1, | ||
438 | LCD_HEIGHT / 2, | ||
439 | MIN(LCD_WIDTH, LCD_HEIGHT) / 8); | ||
440 | |||
441 | if(menu_on) | ||
442 | fillcircle(LCD_WIDTH / 2, | ||
443 | LCD_HEIGHT / 4, | ||
444 | MIN(LCD_WIDTH, LCD_HEIGHT) / 8); | ||
445 | |||
446 | /* Restore foreground color. */ | ||
447 | rb->lcd_set_foreground(FGCOLOR); | ||
448 | } | ||
449 | |||
450 | /* Draw custom user interface. */ | ||
451 | void pd_gui_draw_custom(struct pd_widget* wg, unsigned int widgets) | ||
452 | { | ||
453 | unsigned int i; | ||
454 | int j; | ||
455 | int v; | ||
456 | |||
457 | for(i = 0; i < widgets; wg++, i++) | ||
458 | { | ||
459 | switch(wg->id) | ||
460 | { | ||
461 | case PD_BANG: | ||
462 | /* Clear area to (re-)draw. */ | ||
463 | rb->lcd_set_foreground(BGCOLOR); | ||
464 | rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h); | ||
465 | rb->lcd_set_foreground(FGCOLOR); | ||
466 | /* Draw border (rectangle). */ | ||
467 | rb->lcd_drawrect(wg->x, wg->y, wg->w, wg->h); | ||
468 | /* Draw button (circle), being filled depending on value. */ | ||
469 | if(((int) wg->value) == 0) /* Button not pressed. */ | ||
470 | drawcircle(wg->x + wg->w/2, | ||
471 | wg->y + wg->w/2, | ||
472 | wg->w/2 - 1); | ||
473 | else /* Button pressed. */ | ||
474 | fillcircle(wg->x + wg->w/2, | ||
475 | wg->y + wg->w/2, | ||
476 | wg->w/2 - 1); | ||
477 | break; | ||
478 | |||
479 | case PD_VSLIDER: | ||
480 | /* Clear area to (re-)draw. */ | ||
481 | rb->lcd_set_foreground(BGCOLOR); | ||
482 | rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h); | ||
483 | rb->lcd_set_foreground(FGCOLOR); | ||
484 | /* Draw border. */ | ||
485 | rb->lcd_drawrect(wg->x, wg->y, wg->w, wg->h); | ||
486 | /* Draw slider. */ | ||
487 | v = ((float) wg->h / (wg->max - wg->min)) * | ||
488 | (wg->max - wg->value); | ||
489 | rb->lcd_fillrect(wg->x, wg->y + v, wg->w, 2); | ||
490 | break; | ||
491 | |||
492 | case PD_HSLIDER: | ||
493 | /* Clear area to (re-)draw. */ | ||
494 | rb->lcd_set_foreground(BGCOLOR); | ||
495 | rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h); | ||
496 | rb->lcd_set_foreground(FGCOLOR); | ||
497 | /* Draw border. */ | ||
498 | rb->lcd_drawrect(wg->x, wg->y, wg->w, wg->h); | ||
499 | /* Draw slider. */ | ||
500 | v = ((float) wg->w / (wg->max - wg->min)) * | ||
501 | (wg->max - wg->value); | ||
502 | rb->lcd_fillrect(wg->x + wg->w - v, wg->y, 2, wg->h); | ||
503 | break; | ||
504 | |||
505 | case PD_HRADIO: | ||
506 | /* Clear area to (re-)draw. */ | ||
507 | rb->lcd_set_foreground(BGCOLOR); | ||
508 | rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h); | ||
509 | rb->lcd_set_foreground(FGCOLOR); | ||
510 | for(j = 0; j < wg->w / wg->h; j++) | ||
511 | { | ||
512 | /* Draw border. */ | ||
513 | rb->lcd_drawrect(wg->x + wg->h * j, wg->y, wg->h, wg->h); | ||
514 | /* If marked, draw button. */ | ||
515 | if(((int) wg->value) == j) | ||
516 | rb->lcd_fillrect(wg->x + wg->h * j + 2, wg->y + 2, | ||
517 | wg->h - 4, wg->h - 4); | ||
518 | } | ||
519 | break; | ||
520 | |||
521 | case PD_VRADIO: | ||
522 | /* Clear area to (re-)draw. */ | ||
523 | rb->lcd_set_foreground(BGCOLOR); | ||
524 | rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h); | ||
525 | rb->lcd_set_foreground(FGCOLOR); | ||
526 | for(j = 0; j < wg->h / wg->w; j++) | ||
527 | { | ||
528 | /* Draw border. */ | ||
529 | rb->lcd_drawrect(wg->x, wg->y + wg->w * j, wg->w, wg->w); | ||
530 | /* If marked, draw button. */ | ||
531 | if(((int) wg->value) == j) | ||
532 | rb->lcd_fillrect(wg->x + 2, wg->y + wg->w * j + 2, | ||
533 | wg->w - 4, wg->w - 4); | ||
534 | } | ||
535 | break; | ||
536 | |||
537 | case PD_NUMBER: | ||
538 | rb->lcd_hline(wg->x, | ||
539 | wg->x + wg->w - number_corner, | ||
540 | wg->y); | ||
541 | rb->lcd_drawline(wg->x + wg->w - number_corner, | ||
542 | wg->y, | ||
543 | wg->x + wg->w, | ||
544 | wg->y + number_corner); | ||
545 | rb->lcd_vline(wg->x + wg->w, | ||
546 | wg->y + number_corner, | ||
547 | wg->y + wg->h); | ||
548 | rb->lcd_hline(wg->x, | ||
549 | wg->x + wg->w, | ||
550 | wg->y + wg->h); | ||
551 | rb->lcd_vline(wg->x, | ||
552 | wg->y, | ||
553 | wg->y + wg->h); | ||
554 | char sbuf[12]; | ||
555 | ftoan(wg->value, sbuf, 12); | ||
556 | rb->lcd_putsxy(wg->x + 2, wg->y + 2, sbuf); | ||
557 | break; | ||
558 | |||
559 | case PD_TEXT: | ||
560 | rb->lcd_putsxy(wg->x + 2, wg->y, wg->name); | ||
561 | break; | ||
562 | |||
563 | case PD_SYMBOL: | ||
564 | break; | ||
565 | } | ||
566 | } | ||
567 | } | ||
568 | |||
569 | /* Draw the GUI. */ | ||
570 | void pd_gui_draw(struct pd_widget* wg, unsigned int widgets) | ||
571 | { | ||
572 | /* Draw GUI. */ | ||
573 | if(widgets == 0) | ||
574 | pd_gui_draw_standard(); | ||
575 | else | ||
576 | pd_gui_draw_custom(wg, widgets); | ||
577 | |||
578 | /* Update display. */ | ||
579 | rb->lcd_update(); | ||
580 | } | ||
581 | |||
582 | /* Parse buttons, if needed, send messages to the Pure Data code. */ | ||
583 | bool pd_gui_parse_buttons(unsigned int widgets) | ||
584 | { | ||
585 | static long last_bv = 0; | ||
586 | long bv = rb->button_get(false); | ||
587 | |||
588 | /* Extract differences between current and previous button values. */ | ||
589 | long diff_bv = bv ^ last_bv; | ||
590 | |||
591 | /* If no difference since the last button value, return here. */ | ||
592 | if(diff_bv == 0) | ||
593 | return false; | ||
594 | |||
595 | /* Query whether we have to quit. */ | ||
596 | if(bv == PDPOD_QUIT) | ||
597 | { | ||
598 | /* No need to send the quitting message to Pure Data core, | ||
599 | as setting the quit flag ends threads and jumps | ||
600 | to the cleanup code. */ | ||
601 | quit = true; | ||
602 | return false; | ||
603 | } | ||
604 | |||
605 | /* Check the action (shift, mode) button. */ | ||
606 | if(diff_bv & PDPOD_ACTION) | ||
607 | { | ||
608 | if(bv & PDPOD_ACTION) | ||
609 | { | ||
610 | SEND_TO_CORE("b;\n"); | ||
611 | |||
612 | if(widgets == 0) | ||
613 | action_on = true; | ||
614 | } | ||
615 | else | ||
616 | { | ||
617 | if(widgets == 0) | ||
618 | action_on = false; | ||
619 | } | ||
620 | } | ||
621 | |||
622 | /* Check play button. */ | ||
623 | if(diff_bv & PDPOD_PLAY) | ||
624 | { | ||
625 | if(bv & PDPOD_PLAY) | ||
626 | { | ||
627 | /* Action + play = pause. */ | ||
628 | if(action_on) | ||
629 | { | ||
630 | /* Switch paused state. */ | ||
631 | paused = !paused; | ||
632 | SEND_TO_CORE(paused ? "p 1;\n" : "p 0;\n"); | ||
633 | } | ||
634 | |||
635 | if(!action_on && !paused) | ||
636 | SEND_TO_CORE("d 1;\n"); | ||
637 | |||
638 | if(widgets == 0) | ||
639 | play_on = true; | ||
640 | } | ||
641 | else | ||
642 | { | ||
643 | if(!action_on && !paused) | ||
644 | SEND_TO_CORE("d 0;\n"); | ||
645 | |||
646 | if(widgets == 0) | ||
647 | play_on = false; | ||
648 | } | ||
649 | } | ||
650 | |||
651 | /* Check rewind (previous) button. */ | ||
652 | if(diff_bv & PDPOD_PREVIOUS) | ||
653 | { | ||
654 | if(bv & PDPOD_PREVIOUS) | ||
655 | { | ||
656 | if(!paused) | ||
657 | SEND_TO_CORE("w 1;\n"); | ||
658 | |||
659 | if(widgets == 0) | ||
660 | previous_on = true; | ||
661 | } | ||
662 | else | ||
663 | { | ||
664 | if(!paused) | ||
665 | SEND_TO_CORE("w 0;\n"); | ||
666 | |||
667 | if(widgets == 0) | ||
668 | previous_on = false; | ||
669 | } | ||
670 | } | ||
671 | |||
672 | /* Check forward (next) button. */ | ||
673 | if(diff_bv & PDPOD_NEXT) | ||
674 | { | ||
675 | if(bv & PDPOD_NEXT) | ||
676 | { | ||
677 | if(!paused) | ||
678 | SEND_TO_CORE("f 1;\n"); | ||
679 | |||
680 | if(widgets == 0) | ||
681 | next_on = true; | ||
682 | } | ||
683 | else | ||
684 | { | ||
685 | if(!paused) | ||
686 | SEND_TO_CORE("f 0;\n"); | ||
687 | |||
688 | if(widgets == 0) | ||
689 | next_on = false; | ||
690 | } | ||
691 | } | ||
692 | |||
693 | /* Check menu (select) button. */ | ||
694 | if(diff_bv & PDPOD_MENU) | ||
695 | { | ||
696 | if(bv & PDPOD_MENU) | ||
697 | { | ||
698 | if(!action_on && !paused) | ||
699 | SEND_TO_CORE("m 1;\n"); | ||
700 | |||
701 | if(widgets == 0) | ||
702 | menu_on = true; | ||
703 | } | ||
704 | else | ||
705 | { | ||
706 | if(!action_on && !paused) | ||
707 | SEND_TO_CORE("m 0;\n"); | ||
708 | |||
709 | if(widgets == 0) | ||
710 | menu_on = false; | ||
711 | } | ||
712 | } | ||
713 | |||
714 | /* Check scroll right (or up) button. */ | ||
715 | if(diff_bv & PDPOD_WHEELRIGHT) | ||
716 | { | ||
717 | if(bv & PDPOD_WHEELRIGHT) | ||
718 | { | ||
719 | SEND_TO_CORE(action_on ? "r 10;\n" : "r 1;\n"); | ||
720 | } | ||
721 | } | ||
722 | |||
723 | /* Check scroll left (or down) button. */ | ||
724 | if(diff_bv & PDPOD_WHEELLEFT) | ||
725 | { | ||
726 | if(bv & PDPOD_WHEELLEFT) | ||
727 | { | ||
728 | SEND_TO_CORE(action_on ? "l 10;\n" : "l 1;\n"); | ||
729 | } | ||
730 | } | ||
731 | |||
732 | /* Backup button value. */ | ||
733 | last_bv = bv; | ||
734 | |||
735 | /* GUI has to be updated. */ | ||
736 | return true; | ||
737 | } | ||
738 | |||
739 | /* Emulate timer for widgets which use time-out. */ | ||
740 | bool pd_gui_apply_timeouts(struct pd_widget* wg, unsigned int widgets) | ||
741 | { | ||
742 | unsigned int i; | ||
743 | bool result = false; | ||
744 | |||
745 | for(i = 0; i < widgets; wg++, i++) | ||
746 | { | ||
747 | if(wg->id == PD_BANG) | ||
748 | { | ||
749 | if(wg->timeout > 0) | ||
750 | { | ||
751 | /* Decrement timeout value. */ | ||
752 | wg->timeout--; | ||
753 | |||
754 | /* If zero reached, clear value. */ | ||
755 | if(wg->timeout == 0) | ||
756 | { | ||
757 | wg->value = 0; | ||
758 | result = true; | ||
759 | } | ||
760 | } | ||
761 | } | ||
762 | } | ||
763 | |||
764 | return result; | ||
765 | } | ||
766 | |||
767 | /* Parse and apply message from the Pure Data core. */ | ||
768 | void pd_gui_parse_message(struct datagram* dg, | ||
769 | struct pd_widget* wg, | ||
770 | unsigned int widgets) | ||
771 | { | ||
772 | unsigned int i; | ||
773 | char* saveptr; | ||
774 | char* object = NULL; | ||
775 | char* argument = NULL; | ||
776 | float argvalue = 0; | ||
777 | |||
778 | object = strtok_r(dg->data, " ", &saveptr); | ||
779 | argument = strtok_r(NULL, " ;\n", &saveptr); | ||
780 | |||
781 | if(argument != NULL) | ||
782 | argvalue = atof(argument); | ||
783 | |||
784 | for(i = 0; i < widgets; wg++, i++) | ||
785 | { | ||
786 | if(strncmp(object, wg->name, strlen(wg->name)) == 0) | ||
787 | { | ||
788 | /* If object not a number, set boundaries. */ | ||
789 | if(wg->id != PD_NUMBER) | ||
790 | { | ||
791 | if(argvalue > wg->max) | ||
792 | argvalue = wg->max; | ||
793 | else if(argvalue < wg->min) | ||
794 | argvalue = wg->min; | ||
795 | } | ||
796 | |||
797 | /* Set value. */ | ||
798 | if(wg->id == PD_BANG) | ||
799 | { | ||
800 | wg->value = 1; | ||
801 | wg->timeout = HZ / 10; | ||
802 | } | ||
803 | else | ||
804 | { | ||
805 | wg->value = argvalue; | ||
806 | } | ||
807 | } | ||
808 | } | ||
809 | } | ||