Add AI to the pong plugin, to allow single-player operation.
[kugel-rb.git] / apps / plugins / pdbox / pdbox-gui.c
blob696b083b0d6621770b96711ac16fc566e0310d8e
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 /* Reset value. */
228 wg->value = 0;
230 /* We got one more widget. */
231 wg++;
232 widgets++;
234 else if((strstr(line, "symbolatom") != NULL) &&
235 (strstr(line, "pod_") != NULL))
237 wg->id = PD_SYMBOL;
239 strtok_r(line, " ", &saveptr);
240 strtok_r(NULL, " ", &saveptr);
241 wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
242 wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
243 wg->w = 7 * atoi(strtok_r(NULL, " ", &saveptr)) *
244 screen_multiplier;
245 wg->h = 16 * screen_multiplier;
246 strtok_r(NULL, " ", &saveptr);
247 strtok_r(NULL, " ", &saveptr);
248 strtok_r(NULL, " ", &saveptr);
249 strtok_r(NULL, " ", &saveptr);
250 strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name));
252 /* Reset value. */
253 wg->value = 0;
255 /* We got one more widget. */
256 wg++;
257 widgets++;
259 else if((strstr(line, "vsl") != NULL) &&
260 (strstr(line, "pod_") != NULL))
262 wg->id = PD_VSLIDER;
264 strtok_r(line, " ", &saveptr);
265 strtok_r(NULL, " ", &saveptr);
266 wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
267 wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
268 strtok_r(NULL, " ", &saveptr);
269 wg->w = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
270 wg->h = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
271 wg->min = atoi(strtok_r(NULL, " ", &saveptr));
272 wg->max = atoi(strtok_r(NULL, " ", &saveptr));
273 strtok_r(NULL, " ", &saveptr);
274 strtok_r(NULL, " ", &saveptr);
275 strtok_r(NULL, " ", &saveptr);
276 strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name));
278 /* Reset value. */
279 wg->value = 0;
281 /* We got one more widget. */
282 wg++;
283 widgets++;
285 else if((strstr(line, "hsl") != NULL) &&
286 (strstr(line, "pod_") != NULL))
288 wg->id = PD_HSLIDER;
290 strtok_r(line, " ", &saveptr);
291 strtok_r(NULL, " ", &saveptr);
292 wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
293 wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
294 strtok_r(NULL, " ", &saveptr);
295 wg->w = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
296 wg->h = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
297 wg->min = atoi(strtok_r(NULL, " ", &saveptr));
298 wg->max = atoi(strtok_r(NULL, " ", &saveptr));
299 strtok_r(NULL, " ", &saveptr);
300 strtok_r(NULL, " ", &saveptr);
301 strtok_r(NULL, " ", &saveptr);
302 strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name));
304 /* Reset value. */
305 wg->value = 0;
307 /* We got one more widget. */
308 wg++;
309 widgets++;
311 else if((strstr(line, "vradio") != NULL) &&
312 (strstr(line, "pod_") != NULL))
314 wg->id = PD_VRADIO;
316 strtok_r(line, " ", &saveptr);
317 strtok_r(NULL, " ", &saveptr);
318 wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
319 wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
320 strtok_r(NULL, " ", &saveptr);
321 wg->w = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
322 strtok_r(NULL, " ", &saveptr);
323 strtok_r(NULL, " ", &saveptr);
324 wg->min = 0;
325 wg->max = atoi(strtok_r(NULL, " ", &saveptr));
326 wg->h = wg->w * wg->max;
327 strtok_r(NULL, " ", &saveptr);
328 strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name));
329 wg->max--;
331 /* Reset value. */
332 wg->value = 0;
334 /* We got one more widget. */
335 wg++;
336 widgets++;
338 else if((strstr(line, "hradio") != NULL) &&
339 (strstr(line, "pod_") != NULL))
341 wg->id = PD_HRADIO;
343 strtok_r(line, " ", &saveptr);
344 strtok_r(NULL, " ", &saveptr);
345 wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
346 wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
347 strtok_r(NULL, " ", &saveptr);
348 wg->h = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
349 strtok_r(NULL, " ", &saveptr);
350 strtok_r(NULL, " ", &saveptr);
351 wg->min = 0;
352 wg->max = atoi(strtok_r(NULL, " ", &saveptr));
353 wg->w = wg->h * wg->max;
354 strtok_r(NULL, " ", &saveptr);
355 strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name));
356 wg->max--;
358 /* Reset value. */
359 wg->value = 0;
361 /* We got one more widget. */
362 wg++;
363 widgets++;
365 else if((strstr(line, "bng") != NULL) &&
366 (strstr(line, "pod_") != NULL))
368 wg->id = PD_BANG;
370 strtok_r(line, " ", &saveptr);
371 strtok_r(NULL, " ", &saveptr);
372 wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
373 wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
374 strtok_r(NULL, " ", &saveptr);
375 wg->w = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
376 wg->h = wg->w;
377 strtok_r(NULL, " ", &saveptr);
378 strtok_r(NULL, " ", &saveptr);
379 strtok_r(NULL, " ", &saveptr);
380 strtok_r(NULL, " ", &saveptr);
381 strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name));
382 wg->min = 0;
383 wg->max = 1;
385 /* Reset value. */
386 wg->value = 0;
388 /* Clear timeout flag. */
389 wg->timeout = 0;
391 /* We got one more widget. */
392 wg++;
393 widgets++;
395 else if(strstr(line, "text") != NULL)
397 wg->id = PD_TEXT;
399 strtok_r(line, " ", &saveptr);
400 strtok_r(NULL, " ", &saveptr);
401 wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
402 wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier;
403 strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name));
404 char* w = strtok_r(NULL, " ", &saveptr);
405 while(w != NULL)
407 strcat(wg->name, w);
408 strcat(wg->name, " ");
409 w = strtok_r(NULL, " ", &saveptr);
411 /* Cut off unneeded characters (';' and '\n'). */
412 int namelen = strlen(wg->name);
413 if(namelen > 1)
415 /* Cut off '\n'. */
416 wg->name[namelen-1] = '\0';
417 namelen--;
418 /* Cut the last semi-colon, if there is one. */
419 if(wg->name[namelen-1] == ';')
420 wg->name[namelen-1] = '\0';
424 /* We got one more widget. */
425 wg++;
426 widgets++;
430 /* Close PD patch. */
431 close(fd);
433 /* Return amount of loaded widgets. */
434 return widgets;
437 /* Draw standard user interface. */
438 void pd_gui_draw_standard(void)
440 /* Draw main circle. */
441 rb->lcd_set_foreground(fgcolor);
442 fillcircle(LCD_WIDTH / 2,
443 LCD_HEIGHT / 2,
444 2 * MIN(LCD_WIDTH, LCD_HEIGHT) / 5);
446 /* Draw center circle. */
447 rb->lcd_set_foreground(action_on ? BTNCOLOR_DARK : BTNCOLOR_LIGHT);
448 fillcircle(LCD_WIDTH / 2,
449 LCD_HEIGHT / 2,
450 MIN(LCD_WIDTH, LCD_HEIGHT) / 8);
452 /* Draw pressed buttons. */
453 if(play_on)
454 fillcircle(LCD_WIDTH / 2,
455 3 * LCD_HEIGHT / 4,
456 MIN(LCD_WIDTH, LCD_HEIGHT) / 8);
458 if(previous_on)
459 fillcircle(LCD_WIDTH / 3,
460 LCD_HEIGHT / 2,
461 MIN(LCD_WIDTH, LCD_HEIGHT) / 8);
463 if(next_on)
464 fillcircle(2 * LCD_WIDTH / 3 + 1,
465 LCD_HEIGHT / 2,
466 MIN(LCD_WIDTH, LCD_HEIGHT) / 8);
468 if(menu_on)
469 fillcircle(LCD_WIDTH / 2,
470 LCD_HEIGHT / 4,
471 MIN(LCD_WIDTH, LCD_HEIGHT) / 8);
473 /* Restore foreground color. */
474 rb->lcd_set_foreground(fgcolor);
477 /* Draw custom user interface. */
478 void pd_gui_draw_custom(struct pd_widget* wg, unsigned int widgets)
480 unsigned int i;
481 int j;
482 int v;
484 for(i = 0; i < widgets; wg++, i++)
486 switch(wg->id)
488 case PD_BANG:
489 /* Clear area to (re-)draw. */
490 rb->lcd_set_foreground(bgcolor);
491 rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h);
492 rb->lcd_set_foreground(fgcolor);
493 /* Draw border (rectangle). */
494 rb->lcd_drawrect(wg->x, wg->y, wg->w, wg->h);
495 /* Draw button (circle), being filled depending on value. */
496 if(((int) wg->value) == 0) /* Button not pressed. */
497 drawcircle(wg->x + wg->w/2,
498 wg->y + wg->w/2,
499 wg->w/2 - 1);
500 else /* Button pressed. */
501 fillcircle(wg->x + wg->w/2,
502 wg->y + wg->w/2,
503 wg->w/2 - 1);
504 break;
506 case PD_VSLIDER:
507 /* Clear area to (re-)draw. */
508 rb->lcd_set_foreground(bgcolor);
509 rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h);
510 rb->lcd_set_foreground(fgcolor);
511 /* Draw border. */
512 rb->lcd_drawrect(wg->x, wg->y, wg->w, wg->h);
513 /* Draw slider. */
514 v = ((float) wg->h / (wg->max - wg->min)) *
515 (wg->max - wg->value);
516 rb->lcd_fillrect(wg->x, wg->y + v, wg->w, 2);
517 break;
519 case PD_HSLIDER:
520 /* Clear area to (re-)draw. */
521 rb->lcd_set_foreground(bgcolor);
522 rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h);
523 rb->lcd_set_foreground(fgcolor);
524 /* Draw border. */
525 rb->lcd_drawrect(wg->x, wg->y, wg->w, wg->h);
526 /* Draw slider. */
527 v = ((float) wg->w / (wg->max - wg->min)) *
528 (wg->max - wg->value);
529 rb->lcd_fillrect(wg->x + wg->w - v, wg->y, 2, wg->h);
530 break;
532 case PD_HRADIO:
533 /* Clear area to (re-)draw. */
534 rb->lcd_set_foreground(bgcolor);
535 rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h);
536 rb->lcd_set_foreground(fgcolor);
537 for(j = 0; j < wg->w / wg->h; j++)
539 /* Draw border. */
540 rb->lcd_drawrect(wg->x + wg->h * j, wg->y, wg->h, wg->h);
541 /* If marked, draw button. */
542 if(((int) wg->value) == j)
543 rb->lcd_fillrect(wg->x + wg->h * j + 2, wg->y + 2,
544 wg->h - 4, wg->h - 4);
546 break;
548 case PD_VRADIO:
549 /* Clear area to (re-)draw. */
550 rb->lcd_set_foreground(bgcolor);
551 rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h);
552 rb->lcd_set_foreground(fgcolor);
553 for(j = 0; j < wg->h / wg->w; j++)
555 /* Draw border. */
556 rb->lcd_drawrect(wg->x, wg->y + wg->w * j, wg->w, wg->w);
557 /* If marked, draw button. */
558 if(((int) wg->value) == j)
559 rb->lcd_fillrect(wg->x + 2, wg->y + wg->w * j + 2,
560 wg->w - 4, wg->w - 4);
562 break;
564 case PD_NUMBER:
565 rb->lcd_hline(wg->x,
566 wg->x + wg->w - number_corner,
567 wg->y);
568 rb->lcd_drawline(wg->x + wg->w - number_corner,
569 wg->y,
570 wg->x + wg->w,
571 wg->y + number_corner);
572 rb->lcd_vline(wg->x + wg->w,
573 wg->y + number_corner,
574 wg->y + wg->h);
575 rb->lcd_hline(wg->x,
576 wg->x + wg->w,
577 wg->y + wg->h);
578 rb->lcd_vline(wg->x,
579 wg->y,
580 wg->y + wg->h);
581 char sbuf[8];
582 ftoan(wg->value, sbuf, 8);
583 rb->lcd_putsxy(wg->x + 2, wg->y + 2, sbuf);
584 break;
586 case PD_TEXT:
587 rb->lcd_putsxy(wg->x + 2, wg->y, wg->name);
588 break;
590 case PD_SYMBOL:
591 break;
596 /* Draw the GUI. */
597 void pd_gui_draw(struct pd_widget* wg, unsigned int widgets)
599 /* Draw GUI. */
600 if(widgets == 0)
601 pd_gui_draw_standard();
602 else
603 pd_gui_draw_custom(wg, widgets);
605 /* Update display. */
606 rb->lcd_update();
609 /* Parse buttons, if needed, send messages to the Pure Data code. */
610 bool pd_gui_parse_buttons(unsigned int widgets)
612 static long last_bv = 0;
613 long bv = rb->button_get(false);
615 /* Extract differences between current and previous button values. */
616 long diff_bv = bv ^ last_bv;
618 /* If no difference since the last button value, return here. */
619 if(diff_bv == 0)
620 return false;
622 /* Query whether we have to quit. */
623 if(bv == PDPOD_QUIT)
625 /* No need to send the quitting message to Pure Data core,
626 as setting the quit flag ends threads and jumps
627 to the cleanup code. */
628 quit = true;
629 return false;
632 /* Check the action (shift, mode) button. */
633 if(diff_bv & PDPOD_ACTION)
635 if(bv & PDPOD_ACTION)
637 SEND_TO_CORE("b;\n");
639 if(widgets == 0)
640 action_on = true;
642 else
644 if(widgets == 0)
645 action_on = false;
649 /* Check play button. */
650 if(diff_bv & PDPOD_PLAY)
652 if(bv & PDPOD_PLAY)
654 /* Action + play = pause. */
655 if(action_on)
657 /* Switch paused state. */
658 paused = !paused;
659 SEND_TO_CORE(paused ? "p 1;\n" : "p 0;\n");
662 if(!action_on && !paused)
663 SEND_TO_CORE("d 1;\n");
665 if(widgets == 0)
666 play_on = true;
668 else
670 if(!action_on && !paused)
671 SEND_TO_CORE("d 0;\n");
673 if(widgets == 0)
674 play_on = false;
678 /* Check rewind (previous) button. */
679 if(diff_bv & PDPOD_PREVIOUS)
681 if(bv & PDPOD_PREVIOUS)
683 if(!paused)
684 SEND_TO_CORE("w 1;\n");
686 if(widgets == 0)
687 previous_on = true;
689 else
691 if(!paused)
692 SEND_TO_CORE("w 0;\n");
694 if(widgets == 0)
695 previous_on = false;
699 /* Check forward (next) button. */
700 if(diff_bv & PDPOD_NEXT)
702 if(bv & PDPOD_NEXT)
704 if(!paused)
705 SEND_TO_CORE("f 1;\n");
707 if(widgets == 0)
708 next_on = true;
710 else
712 if(!paused)
713 SEND_TO_CORE("f 0;\n");
715 if(widgets == 0)
716 next_on = false;
720 /* Check menu (select) button. */
721 if(diff_bv & PDPOD_MENU)
723 if(bv & PDPOD_MENU)
725 if(!action_on && !paused)
726 SEND_TO_CORE("m 1;\n");
728 if(widgets == 0)
729 menu_on = true;
731 else
733 if(!action_on && !paused)
734 SEND_TO_CORE("m 0;\n");
736 if(widgets == 0)
737 menu_on = false;
741 /* Check scroll right (or up) button. */
742 if(diff_bv & PDPOD_WHEELRIGHT)
744 if(bv & PDPOD_WHEELRIGHT)
746 SEND_TO_CORE(action_on ? "r 10;\n" : "r 1;\n");
750 /* Check scroll left (or down) button. */
751 if(diff_bv & PDPOD_WHEELLEFT)
753 if(bv & PDPOD_WHEELLEFT)
755 SEND_TO_CORE(action_on ? "l 10;\n" : "l 1;\n");
759 /* Backup button value. */
760 last_bv = bv;
762 /* GUI has to be updated. */
763 return true;
766 /* Emulate timer for widgets which use time-out. */
767 bool pd_gui_apply_timeouts(struct pd_widget* wg, unsigned int widgets)
769 unsigned int i;
770 bool result = false;
772 for(i = 0; i < widgets; wg++, i++)
774 if(wg->id == PD_BANG)
776 if(wg->timeout > 0)
778 /* Decrement timeout value. */
779 wg->timeout--;
781 /* If zero reached, clear value. */
782 if(wg->timeout == 0)
784 wg->value = 0;
785 result = true;
791 return result;
794 /* Parse and apply message from the Pure Data core. */
795 void pd_gui_parse_message(struct datagram* dg,
796 struct pd_widget* wg,
797 unsigned int widgets)
799 unsigned int i;
800 char* saveptr;
801 char* object = NULL;
802 char* argument = NULL;
803 float argvalue = 0;
805 object = strtok_r(dg->data, " ", &saveptr);
806 argument = strtok_r(NULL, " ;\n", &saveptr);
808 if(argument != NULL)
809 argvalue = atof(argument);
811 for(i = 0; i < widgets; wg++, i++)
813 if(strncmp(object, wg->name, strlen(wg->name)) == 0)
815 /* If object not a number, set boundaries. */
816 if(wg->id != PD_NUMBER)
818 if(argvalue > wg->max)
819 argvalue = wg->max;
820 else if(argvalue < wg->min)
821 argvalue = wg->min;
824 /* Set value. */
825 if(wg->id == PD_BANG)
827 wg->value = 1;
828 wg->timeout = HZ / 10;
830 else
832 wg->value = argvalue;