summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/pdbox-gui.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/pdbox-gui.c')
-rw-r--r--apps/plugins/pdbox/pdbox-gui.c809
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. */
35extern char* filename;
36extern bool quit;
37
38/* Screen multiplier. */
39static float screen_multiplier;
40
41/* Displacement of the slanted corner in the contour of the number widget. */
42static int number_corner;
43
44/* Button flags. */
45static bool play_on;
46static bool previous_on;
47static bool next_on;
48static bool menu_on;
49static bool action_on;
50
51/* Pause flag. */
52static bool paused;
53
54
55/* Draw circle using midpoint circle algorithm.
56 Adapted from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm. */
57void 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. */
101void 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. */
144void 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. */
172unsigned 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. */
411void 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. */
451void 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. */
570void 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. */
583bool 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. */
740bool 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. */
768void 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}