Update the discussion of themeing in the manual, and put a note in the wps tags appen...
[kugel-rb.git] / apps / plugins / pdbox / pdbox-gui.c
blob33d15ab6614889a1946a9da4d640830348387966
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2009 Wincent Balin
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 "plugin.h"
23 #include "pdbox.h"
25 #include "lib/xlcd.h"
27 /* Button colors. */
28 #define BTNCOLOR_DARK (LCD_DARKGRAY)
29 #define BTNCOLOR_LIGHT (LCD_LIGHTGRAY)
31 /* Variables in the main code. */
32 extern char* filename;
33 extern bool quit;
35 /* Screen multiplier. */
36 static float screen_multiplier;
38 /* Back- and foreground colors. */
39 static unsigned bgcolor;
40 static unsigned fgcolor;
42 /* Displacement of the slanted corner in the contour of the number widget. */
43 static int number_corner;
45 /* Button flags. */
46 static bool play_on;
47 static bool previous_on;
48 static bool next_on;
49 static bool menu_on;
50 static bool action_on;
52 /* Pause flag. */
53 static bool paused;
56 /* Draw circle using midpoint circle algorithm.
57 Adapted from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm. */
58 void drawcircle(int x, int y, int r)
60 int f = 1 - r;
61 int ddfx = 1;
62 int ddfy = -2 * r;
63 int xp = 0;
64 int yp = r;
66 /* Draw outer points. */
67 rb->lcd_drawpixel(x, y + r);
68 rb->lcd_drawpixel(x, y + r);
69 rb->lcd_drawpixel(x + r, y);
70 rb->lcd_drawpixel(x - r, y);
72 /* Calculate coordinates of points in one octant. */
73 while(xp < yp)
75 /* ddfx == 2 * xp + 1;
76 ddfy == -2 * yp;
77 f == xp*xp + yp*yp - r*r + 2*xp - yp + 1; */
78 if(f >= 0)
80 yp--;
81 ddfy += 2;
82 f += ddfy;
85 xp++;
86 ddfx += 2;
87 f += ddfx;
89 /* Draw pixels in all octants. */
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 - xp, y - yp);
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 rb->lcd_drawpixel(x - yp, y - xp);
101 /* Fill circle. */
102 void fillcircle(int x, int y, int r)
104 int f = 1 - r;
105 int ddfx = 1;
106 int ddfy = -2 * r;
107 int xp = 0;
108 int yp = r;
110 /* Draw outer points. */
111 rb->lcd_drawpixel(x, y + r);
112 rb->lcd_drawpixel(x, y + r);
113 rb->lcd_drawpixel(x + r, y);
114 rb->lcd_drawpixel(x - r, y);
116 /* Calculate coordinates of points in one octant. */
117 while(xp < yp)
119 /* ddfx == 2 * xp + 1;
120 ddfy == -2 * yp;
121 f == xp*xp + yp*yp - r*r + 2*xp - yp + 1; */
122 if(f >= 0)
124 yp--;
125 ddfy += 2;
126 f += ddfy;
129 xp++;
130 ddfx += 2;
131 f += ddfx;
133 /* Fill circle with horizontal lines. */
134 rb->lcd_hline(x - xp, x + xp, y - yp);
135 rb->lcd_hline(x - xp, x + xp, y + yp);
136 rb->lcd_hline(x - yp, x + yp, y - xp);
137 rb->lcd_hline(x - yp, x + yp, y + xp);
140 /* Draw last horizontal line (central one). */
141 rb->lcd_hline(x - r, x + r, y);
144 /* Initialize GUI. */
145 void pd_gui_init(void)
147 /* Reset button flags. */
148 play_on = false;
149 previous_on = false;
150 next_on = false;
151 menu_on = false;
152 action_on = false;
154 /* Unpause Pure Data. */
155 paused = false;
157 /* Calculate dimension factors. */
158 screen_multiplier = ((float) LCD_WIDTH) / 160.0f;
159 number_corner = 5 * screen_multiplier;
161 /* Get back- and foreground colors. */
162 bgcolor = rb->lcd_get_background();
163 fgcolor = rb->lcd_get_foreground();
165 /* Clear background. */
166 rb->lcd_clear_display();
168 /* Draw background of appropriate color. */
169 rb->lcd_set_foreground(bgcolor);
170 rb->lcd_fillrect(0, 0, LCD_WIDTH, LCD_HEIGHT);
171 rb->lcd_set_foreground(fgcolor);
173 /* Update display. */
174 rb->lcd_update();
177 /* Load PD patch. */
178 unsigned int pd_gui_load_patch(struct pd_widget* wg, unsigned int max_widgets)
180 int fd;
181 char line[100];
182 char* saveptr;
183 unsigned int widgets = 0;
185 /* Open PD patch. */
186 fd = open(filename, O_RDONLY);
188 /* Check for I/O error. */
189 if(!fd)
191 /* Show error message and make plug-in quit. */
192 rb->splash(HZ, "Error opening .pd file!");
193 quit = true;
194 return 0;
197 /* Read lines from PD file. */
198 while(rb->read_line(fd, line, sizeof(line)) > 0)
200 /* Check whether we got too many widgets. */
201 if(widgets >= max_widgets)
203 rb->splash(HZ, "Too many widgets!");
204 quit = true;
205 return 0;
208 /* Search for key strings in the line. */
209 if((strstr(line, "floatatom") != NULL) &&
210 (strstr(line, "pod_") != NULL))
212 wg->id = PD_NUMBER;
214 strtok_r(line, " ", &saveptr);
215 strtok_r(NULL, " ", &saveptr);
216 wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
217 wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
218 wg->w = 7 * atoi(strtok_r(NULL, " ", &saveptr)) *
219 screen_multiplier;
220 wg->h = 16 * screen_multiplier;
221 strtok_r(NULL, " ", &saveptr);
222 strtok_r(NULL, " ", &saveptr);
223 strtok_r(NULL, " ", &saveptr);
224 strtok_r(NULL, " ", &saveptr);
225 strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name));
227 /* We got one more widget. */
228 wg++;
229 widgets++;
231 else if((strstr(line, "symbolatom") != NULL) &&
232 (strstr(line, "pod_") != NULL))
234 wg->id = PD_SYMBOL;
236 strtok_r(line, " ", &saveptr);
237 strtok_r(NULL, " ", &saveptr);
238 wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
239 wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
240 wg->w = 7 * atoi(strtok_r(NULL, " ", &saveptr)) *
241 screen_multiplier;
242 wg->h = 16 * screen_multiplier;
243 strtok_r(NULL, " ", &saveptr);
244 strtok_r(NULL, " ", &saveptr);
245 strtok_r(NULL, " ", &saveptr);
246 strtok_r(NULL, " ", &saveptr);
247 strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name));
249 /* We got one more widget. */
250 wg++;
251 widgets++;
253 else if((strstr(line, "vsl") != NULL) &&
254 (strstr(line, "pod_") != NULL))
256 wg->id = PD_VSLIDER;
258 strtok_r(line, " ", &saveptr);
259 strtok_r(NULL, " ", &saveptr);
260 wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
261 wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
262 strtok_r(NULL, " ", &saveptr);
263 wg->w = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
264 wg->h = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
265 wg->min = atoi(strtok_r(NULL, " ", &saveptr));
266 wg->max = atoi(strtok_r(NULL, " ", &saveptr));
267 strtok_r(NULL, " ", &saveptr);
268 strtok_r(NULL, " ", &saveptr);
269 strtok_r(NULL, " ", &saveptr);
270 strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name));
272 /* We got one more widget. */
273 wg++;
274 widgets++;
276 else if((strstr(line, "hsl") != NULL) &&
277 (strstr(line, "pod_") != NULL))
279 wg->id = PD_HSLIDER;
281 strtok_r(line, " ", &saveptr);
282 strtok_r(NULL, " ", &saveptr);
283 wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
284 wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
285 strtok_r(NULL, " ", &saveptr);
286 wg->w = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
287 wg->h = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
288 wg->min = atoi(strtok_r(NULL, " ", &saveptr));
289 wg->max = atoi(strtok_r(NULL, " ", &saveptr));
290 strtok_r(NULL, " ", &saveptr);
291 strtok_r(NULL, " ", &saveptr);
292 strtok_r(NULL, " ", &saveptr);
293 strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name));
295 /* We got one more widget. */
296 wg++;
297 widgets++;
299 else if((strstr(line, "vradio") != NULL) &&
300 (strstr(line, "pod_") != NULL))
302 wg->id = PD_VRADIO;
304 strtok_r(line, " ", &saveptr);
305 strtok_r(NULL, " ", &saveptr);
306 wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
307 wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
308 strtok_r(NULL, " ", &saveptr);
309 wg->w = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
310 strtok_r(NULL, " ", &saveptr);
311 strtok_r(NULL, " ", &saveptr);
312 wg->min = 0;
313 wg->max = atoi(strtok_r(NULL, " ", &saveptr));
314 wg->h = wg->w * wg->max;
315 strtok_r(NULL, " ", &saveptr);
316 strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name));
317 wg->max--;
319 /* We got one more widget. */
320 wg++;
321 widgets++;
323 else if((strstr(line, "hradio") != NULL) &&
324 (strstr(line, "pod_") != NULL))
326 wg->id = PD_HRADIO;
328 strtok_r(line, " ", &saveptr);
329 strtok_r(NULL, " ", &saveptr);
330 wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
331 wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
332 strtok_r(NULL, " ", &saveptr);
333 wg->h = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
334 strtok_r(NULL, " ", &saveptr);
335 strtok_r(NULL, " ", &saveptr);
336 wg->min = 0;
337 wg->max = atoi(strtok_r(NULL, " ", &saveptr));
338 wg->w = wg->h * wg->max;
339 strtok_r(NULL, " ", &saveptr);
340 strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name));
341 wg->max--;
343 /* We got one more widget. */
344 wg++;
345 widgets++;
347 else if((strstr(line, "bng") != NULL) &&
348 (strstr(line, "pod_") != NULL))
350 wg->id = PD_BANG;
352 strtok_r(line, " ", &saveptr);
353 strtok_r(NULL, " ", &saveptr);
354 wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
355 wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
356 strtok_r(NULL, " ", &saveptr);
357 wg->w = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
358 wg->h = wg->w;
359 strtok_r(NULL, " ", &saveptr);
360 strtok_r(NULL, " ", &saveptr);
361 strtok_r(NULL, " ", &saveptr);
362 strtok_r(NULL, " ", &saveptr);
363 strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name));
364 wg->min = 0;
365 wg->max = 1;
367 /* Clear timeout flag. */
368 wg->timeout = 0;
370 /* We got one more widget. */
371 wg++;
372 widgets++;
374 else if(strstr(line, "text") != NULL)
376 wg->id = PD_TEXT;
378 strtok_r(line, " ", &saveptr);
379 strtok_r(NULL, " ", &saveptr);
380 wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
381 wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
382 strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name));
383 char* w = strtok_r(NULL, " ", &saveptr);
384 while(w != NULL)
386 strcat(wg->name, w);
387 strcat(wg->name, " ");
388 w = strtok_r(NULL, " ", &saveptr);
390 /* Cut off unneeded characters (';' and '\n'). */
391 int namelen = strlen(wg->name);
392 if(namelen > 1)
394 /* Cut off '\n'. */
395 wg->name[namelen-1] = '\0';
396 namelen--;
397 /* Cut the last semi-colon, if there is one. */
398 if(wg->name[namelen-1] == ';')
399 wg->name[namelen-1] = '\0';
403 /* We got one more widget. */
404 wg++;
405 widgets++;
409 /* Close PD patch. */
410 close(fd);
412 /* Return amount of loaded widgets. */
413 return widgets;
416 /* Draw standard user interface. */
417 void pd_gui_draw_standard(void)
419 /* Draw main circle. */
420 rb->lcd_set_foreground(fgcolor);
421 fillcircle(LCD_WIDTH / 2,
422 LCD_HEIGHT / 2,
423 2 * MIN(LCD_WIDTH, LCD_HEIGHT) / 5);
425 /* Draw center circle. */
426 rb->lcd_set_foreground(action_on ? BTNCOLOR_DARK : BTNCOLOR_LIGHT);
427 fillcircle(LCD_WIDTH / 2,
428 LCD_HEIGHT / 2,
429 MIN(LCD_WIDTH, LCD_HEIGHT) / 8);
431 /* Draw pressed buttons. */
432 if(play_on)
433 fillcircle(LCD_WIDTH / 2,
434 3 * LCD_HEIGHT / 4,
435 MIN(LCD_WIDTH, LCD_HEIGHT) / 8);
437 if(previous_on)
438 fillcircle(LCD_WIDTH / 3,
439 LCD_HEIGHT / 2,
440 MIN(LCD_WIDTH, LCD_HEIGHT) / 8);
442 if(next_on)
443 fillcircle(2 * LCD_WIDTH / 3 + 1,
444 LCD_HEIGHT / 2,
445 MIN(LCD_WIDTH, LCD_HEIGHT) / 8);
447 if(menu_on)
448 fillcircle(LCD_WIDTH / 2,
449 LCD_HEIGHT / 4,
450 MIN(LCD_WIDTH, LCD_HEIGHT) / 8);
452 /* Restore foreground color. */
453 rb->lcd_set_foreground(fgcolor);
456 /* Draw custom user interface. */
457 void pd_gui_draw_custom(struct pd_widget* wg, unsigned int widgets)
459 unsigned int i;
460 int j;
461 int v;
463 for(i = 0; i < widgets; wg++, i++)
465 switch(wg->id)
467 case PD_BANG:
468 /* Clear area to (re-)draw. */
469 rb->lcd_set_foreground(bgcolor);
470 rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h);
471 rb->lcd_set_foreground(fgcolor);
472 /* Draw border (rectangle). */
473 rb->lcd_drawrect(wg->x, wg->y, wg->w, wg->h);
474 /* Draw button (circle), being filled depending on value. */
475 if(((int) wg->value) == 0) /* Button not pressed. */
476 drawcircle(wg->x + wg->w/2,
477 wg->y + wg->w/2,
478 wg->w/2 - 1);
479 else /* Button pressed. */
480 fillcircle(wg->x + wg->w/2,
481 wg->y + wg->w/2,
482 wg->w/2 - 1);
483 break;
485 case PD_VSLIDER:
486 /* Clear area to (re-)draw. */
487 rb->lcd_set_foreground(bgcolor);
488 rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h);
489 rb->lcd_set_foreground(fgcolor);
490 /* Draw border. */
491 rb->lcd_drawrect(wg->x, wg->y, wg->w, wg->h);
492 /* Draw slider. */
493 v = ((float) wg->h / (wg->max - wg->min)) *
494 (wg->max - wg->value);
495 rb->lcd_fillrect(wg->x, wg->y + v, wg->w, 2);
496 break;
498 case PD_HSLIDER:
499 /* Clear area to (re-)draw. */
500 rb->lcd_set_foreground(bgcolor);
501 rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h);
502 rb->lcd_set_foreground(fgcolor);
503 /* Draw border. */
504 rb->lcd_drawrect(wg->x, wg->y, wg->w, wg->h);
505 /* Draw slider. */
506 v = ((float) wg->w / (wg->max - wg->min)) *
507 (wg->max - wg->value);
508 rb->lcd_fillrect(wg->x + wg->w - v, wg->y, 2, wg->h);
509 break;
511 case PD_HRADIO:
512 /* Clear area to (re-)draw. */
513 rb->lcd_set_foreground(bgcolor);
514 rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h);
515 rb->lcd_set_foreground(fgcolor);
516 for(j = 0; j < wg->w / wg->h; j++)
518 /* Draw border. */
519 rb->lcd_drawrect(wg->x + wg->h * j, wg->y, wg->h, wg->h);
520 /* If marked, draw button. */
521 if(((int) wg->value) == j)
522 rb->lcd_fillrect(wg->x + wg->h * j + 2, wg->y + 2,
523 wg->h - 4, wg->h - 4);
525 break;
527 case PD_VRADIO:
528 /* Clear area to (re-)draw. */
529 rb->lcd_set_foreground(bgcolor);
530 rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h);
531 rb->lcd_set_foreground(fgcolor);
532 for(j = 0; j < wg->h / wg->w; j++)
534 /* Draw border. */
535 rb->lcd_drawrect(wg->x, wg->y + wg->w * j, wg->w, wg->w);
536 /* If marked, draw button. */
537 if(((int) wg->value) == j)
538 rb->lcd_fillrect(wg->x + 2, wg->y + wg->w * j + 2,
539 wg->w - 4, wg->w - 4);
541 break;
543 case PD_NUMBER:
544 rb->lcd_hline(wg->x,
545 wg->x + wg->w - number_corner,
546 wg->y);
547 rb->lcd_drawline(wg->x + wg->w - number_corner,
548 wg->y,
549 wg->x + wg->w,
550 wg->y + number_corner);
551 rb->lcd_vline(wg->x + wg->w,
552 wg->y + number_corner,
553 wg->y + wg->h);
554 rb->lcd_hline(wg->x,
555 wg->x + wg->w,
556 wg->y + wg->h);
557 rb->lcd_vline(wg->x,
558 wg->y,
559 wg->y + wg->h);
560 char sbuf[12];
561 ftoan(wg->value, sbuf, 12);
562 rb->lcd_putsxy(wg->x + 2, wg->y + 2, sbuf);
563 break;
565 case PD_TEXT:
566 rb->lcd_putsxy(wg->x + 2, wg->y, wg->name);
567 break;
569 case PD_SYMBOL:
570 break;
575 /* Draw the GUI. */
576 void pd_gui_draw(struct pd_widget* wg, unsigned int widgets)
578 /* Draw GUI. */
579 if(widgets == 0)
580 pd_gui_draw_standard();
581 else
582 pd_gui_draw_custom(wg, widgets);
584 /* Update display. */
585 rb->lcd_update();
588 /* Parse buttons, if needed, send messages to the Pure Data code. */
589 bool pd_gui_parse_buttons(unsigned int widgets)
591 static long last_bv = 0;
592 long bv = rb->button_get(false);
594 /* Extract differences between current and previous button values. */
595 long diff_bv = bv ^ last_bv;
597 /* If no difference since the last button value, return here. */
598 if(diff_bv == 0)
599 return false;
601 /* Query whether we have to quit. */
602 if(bv == PDPOD_QUIT)
604 /* No need to send the quitting message to Pure Data core,
605 as setting the quit flag ends threads and jumps
606 to the cleanup code. */
607 quit = true;
608 return false;
611 /* Check the action (shift, mode) button. */
612 if(diff_bv & PDPOD_ACTION)
614 if(bv & PDPOD_ACTION)
616 SEND_TO_CORE("b;\n");
618 if(widgets == 0)
619 action_on = true;
621 else
623 if(widgets == 0)
624 action_on = false;
628 /* Check play button. */
629 if(diff_bv & PDPOD_PLAY)
631 if(bv & PDPOD_PLAY)
633 /* Action + play = pause. */
634 if(action_on)
636 /* Switch paused state. */
637 paused = !paused;
638 SEND_TO_CORE(paused ? "p 1;\n" : "p 0;\n");
641 if(!action_on && !paused)
642 SEND_TO_CORE("d 1;\n");
644 if(widgets == 0)
645 play_on = true;
647 else
649 if(!action_on && !paused)
650 SEND_TO_CORE("d 0;\n");
652 if(widgets == 0)
653 play_on = false;
657 /* Check rewind (previous) button. */
658 if(diff_bv & PDPOD_PREVIOUS)
660 if(bv & PDPOD_PREVIOUS)
662 if(!paused)
663 SEND_TO_CORE("w 1;\n");
665 if(widgets == 0)
666 previous_on = true;
668 else
670 if(!paused)
671 SEND_TO_CORE("w 0;\n");
673 if(widgets == 0)
674 previous_on = false;
678 /* Check forward (next) button. */
679 if(diff_bv & PDPOD_NEXT)
681 if(bv & PDPOD_NEXT)
683 if(!paused)
684 SEND_TO_CORE("f 1;\n");
686 if(widgets == 0)
687 next_on = true;
689 else
691 if(!paused)
692 SEND_TO_CORE("f 0;\n");
694 if(widgets == 0)
695 next_on = false;
699 /* Check menu (select) button. */
700 if(diff_bv & PDPOD_MENU)
702 if(bv & PDPOD_MENU)
704 if(!action_on && !paused)
705 SEND_TO_CORE("m 1;\n");
707 if(widgets == 0)
708 menu_on = true;
710 else
712 if(!action_on && !paused)
713 SEND_TO_CORE("m 0;\n");
715 if(widgets == 0)
716 menu_on = false;
720 /* Check scroll right (or up) button. */
721 if(diff_bv & PDPOD_WHEELRIGHT)
723 if(bv & PDPOD_WHEELRIGHT)
725 SEND_TO_CORE(action_on ? "r 10;\n" : "r 1;\n");
729 /* Check scroll left (or down) button. */
730 if(diff_bv & PDPOD_WHEELLEFT)
732 if(bv & PDPOD_WHEELLEFT)
734 SEND_TO_CORE(action_on ? "l 10;\n" : "l 1;\n");
738 /* Backup button value. */
739 last_bv = bv;
741 /* GUI has to be updated. */
742 return true;
745 /* Emulate timer for widgets which use time-out. */
746 bool pd_gui_apply_timeouts(struct pd_widget* wg, unsigned int widgets)
748 unsigned int i;
749 bool result = false;
751 for(i = 0; i < widgets; wg++, i++)
753 if(wg->id == PD_BANG)
755 if(wg->timeout > 0)
757 /* Decrement timeout value. */
758 wg->timeout--;
760 /* If zero reached, clear value. */
761 if(wg->timeout == 0)
763 wg->value = 0;
764 result = true;
770 return result;
773 /* Parse and apply message from the Pure Data core. */
774 void pd_gui_parse_message(struct datagram* dg,
775 struct pd_widget* wg,
776 unsigned int widgets)
778 unsigned int i;
779 char* saveptr;
780 char* object = NULL;
781 char* argument = NULL;
782 float argvalue = 0;
784 object = strtok_r(dg->data, " ", &saveptr);
785 argument = strtok_r(NULL, " ;\n", &saveptr);
787 if(argument != NULL)
788 argvalue = atof(argument);
790 for(i = 0; i < widgets; wg++, i++)
792 if(strncmp(object, wg->name, strlen(wg->name)) == 0)
794 /* If object not a number, set boundaries. */
795 if(wg->id != PD_NUMBER)
797 if(argvalue > wg->max)
798 argvalue = wg->max;
799 else if(argvalue < wg->min)
800 argvalue = wg->min;
803 /* Set value. */
804 if(wg->id == PD_BANG)
806 wg->value = 1;
807 wg->timeout = HZ / 10;
809 else
811 wg->value = argvalue;