summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
authorWincent Balin <wincent@rockbox.org>2009-08-04 02:01:55 +0000
committerWincent Balin <wincent@rockbox.org>2009-08-04 02:01:55 +0000
commitbec80ca7ddeff355d0ca46efa331d98c77567fd4 (patch)
tree701d8d4cadf97c4a218c9c2bc3b7e33918db025a /apps/plugins
parent218b31272e5afcb8f98a62974b46f4febbfde39c (diff)
downloadrockbox-bec80ca7ddeff355d0ca46efa331d98c77567fd4.tar.gz
rockbox-bec80ca7ddeff355d0ca46efa331d98c77567fd4.zip
PDBox: Added GUI.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22147 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/pdbox/SOURCES1
-rw-r--r--apps/plugins/pdbox/pdbox-gui.c809
-rw-r--r--apps/plugins/pdbox/pdbox.c62
-rw-r--r--apps/plugins/pdbox/pdbox.h70
4 files changed, 925 insertions, 17 deletions
diff --git a/apps/plugins/pdbox/SOURCES b/apps/plugins/pdbox/SOURCES
index 04cff3c601..22b093fdd9 100644
--- a/apps/plugins/pdbox/SOURCES
+++ b/apps/plugins/pdbox/SOURCES
@@ -1,6 +1,7 @@
1pdbox.c 1pdbox.c
2pdbox-net.c 2pdbox-net.c
3pdbox-func.c 3pdbox-func.c
4pdbox-gui.c
4 5
5TLSF-2.4.4/src/tlsf.c 6TLSF-2.4.4/src/tlsf.c
6/* 7/*
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}
diff --git a/apps/plugins/pdbox/pdbox.c b/apps/plugins/pdbox/pdbox.c
index dd848deba2..5c5677c42e 100644
--- a/apps/plugins/pdbox/pdbox.c
+++ b/apps/plugins/pdbox/pdbox.c
@@ -44,6 +44,7 @@ int sys_soundindevlist[MAXAUDIOINDEV];
44int sys_chinlist[MAXAUDIOINDEV]; 44int sys_chinlist[MAXAUDIOINDEV];
45int sys_soundoutdevlist[MAXAUDIOOUTDEV]; 45int sys_soundoutdevlist[MAXAUDIOOUTDEV];
46int sys_choutlist[MAXAUDIOOUTDEV]; 46int sys_choutlist[MAXAUDIOOUTDEV];
47t_binbuf* inbinbuf;
47 48
48/* References for scheduler variables and functions. */ 49/* References for scheduler variables and functions. */
49extern t_time sys_time; 50extern t_time sys_time;
@@ -59,7 +60,7 @@ rates we expect to see: 32000, 44100, 48000, 88200, 96000. */
59bool quit = false; 60bool quit = false;
60 61
61/* Stack sizes for threads. */ 62/* Stack sizes for threads. */
62#define CORESTACKSIZE (8 * 1024 * 1024) 63#define CORESTACKSIZE (1 * 1024 * 1024)
63#define GUISTACKSIZE (512 * 1024) 64#define GUISTACKSIZE (512 * 1024)
64 65
65/* Thread stacks. */ 66/* Thread stacks. */
@@ -74,30 +75,45 @@ unsigned int gui_thread_id;
74/* GUI thread */ 75/* GUI thread */
75void gui_thread(void) 76void gui_thread(void)
76{ 77{
77/* struct datagram pong; */ 78 struct pd_widget widget[128];
79 unsigned int widgets = 0;
80 struct datagram dg;
81 bool update;
82
83 /* Initialize GUI. */
84 pd_gui_init();
85
86 /* Load PD patch. */
87 widgets = pd_gui_load_patch(widget,
88 sizeof(widget) / sizeof(struct pd_widget));
89
90 /* Draw initial state of UI. */
91 pd_gui_draw(widget, widgets);
78 92
79 /* GUI loop */ 93 /* GUI loop */
80 while(!quit) 94 while(!quit)
81 { 95 {
82#if 0 96 /* Reset update flag. */
83 /* Send ping to the core. */ 97 update = false;
84 SEND_TO_CORE("Ping!"); 98
85 rb->splash(HZ, "Sent ping."); 99 /* Apply timer to widgets. */
100 update |=
101 pd_gui_apply_timeouts(widget, widgets);
86 102
87 /* Wait for answer. */ 103 /* Process buttons. */
88 while(!RECEIVE_FROM_CORE(&pong)) 104 update |=
89 rb->yield(); 105 pd_gui_parse_buttons(widgets);
90 106
91 /* If got a pong -- everything allright. */ 107 /* Receive and parse datagrams. */
92 if(memcmp("Pong!", pong.data, pong.size) == 0) 108 while(RECEIVE_FROM_CORE(&dg))
93 { 109 {
94 rb->splash(HZ, "Got pong!"); 110 update = true;
95 quit = true; 111 pd_gui_parse_message(&dg, widget, widgets);
96 break;
97 } 112 }
98#endif 113
99 if(rb->button_get(false) == BUTTON_OFF) 114 /* If there is something to update in GUI, do so. */
100 quit = true; 115 if(update)
116 pd_gui_draw(widget, widgets);
101 117
102 rb->sleep(1); 118 rb->sleep(1);
103 } 119 }
@@ -120,6 +136,12 @@ void core_thread(void)
120 /* Core scheduler loop */ 136 /* Core scheduler loop */
121 while(!quit) 137 while(!quit)
122 { 138 {
139 /* Receive datagrams. */
140 struct datagram dg;
141
142 while(RECEIVE_TO_CORE(&dg))
143 rockbox_receive_callback(&dg);
144
123 /* Use sys_send_dacs() function as timer. */ 145 /* Use sys_send_dacs() function as timer. */
124 while(sys_send_dacs() != SENDDACS_NO) 146 while(sys_send_dacs() != SENDDACS_NO)
125 sched_tick(sys_time + sys_time_per_dsp_tick); 147 sched_tick(sys_time + sys_time_per_dsp_tick);
@@ -194,6 +216,9 @@ enum plugin_status plugin_start(const void* parameter)
194 return PLUGIN_ERROR; 216 return PLUGIN_ERROR;
195 } 217 }
196 218
219 /* Boost CPU. */
220 cpu_boost(true);
221
197 /* Start threads. */ 222 /* Start threads. */
198 core_thread_id = 223 core_thread_id =
199 rb->create_thread(&core_thread, 224 rb->create_thread(&core_thread,
@@ -237,6 +262,9 @@ enum plugin_status plugin_start(const void* parameter)
237 rb->thread_wait(gui_thread_id); 262 rb->thread_wait(gui_thread_id);
238 rb->thread_wait(core_thread_id); 263 rb->thread_wait(core_thread_id);
239 264
265 /* Unboost CPU. */
266 cpu_boost(false);
267
240 /* Close audio subsystem. */ 268 /* Close audio subsystem. */
241 sys_close_audio(); 269 sys_close_audio();
242 270
diff --git a/apps/plugins/pdbox/pdbox.h b/apps/plugins/pdbox/pdbox.h
index 47aa2ec4d8..5f30013fad 100644
--- a/apps/plugins/pdbox/pdbox.h
+++ b/apps/plugins/pdbox/pdbox.h
@@ -197,4 +197,74 @@ void pd_init(void);
197#define sinh rb_sinh 197#define sinh rb_sinh
198#define tan rb_tan 198#define tan rb_tan
199 199
200#define strtok_r rb->strtok_r
201#define strstr rb->strcasestr
202
203
204/* PdPod GUI declarations. */
205
206enum pd_widget_id
207{
208 PD_BANG,
209 PD_VSLIDER,
210 PD_HSLIDER,
211 PD_VRADIO,
212 PD_HRADIO,
213 PD_NUMBER,
214 PD_SYMBOL,
215 PD_TEXT
216};
217
218struct pd_widget
219{
220 enum pd_widget_id id;
221 char name[128];
222 int x;
223 int y;
224 int w;
225 int h;
226 int min;
227 int max;
228 float value;
229 int timeout;
230};
231
232enum pd_key_id
233{
234 KEY_PLAY,
235 KEY_REWIND,
236 KEY_FORWARD,
237 KEY_MENU,
238 KEY_ACTION,
239 KEY_WHEELLEFT,
240 KEY_WHEELRIGHT,
241 PD_KEYS
242};
243
244/* Map real keys to virtual ones.
245 Feel free to add your preferred keymap here. */
246#if defined(IRIVER_H300_SERIES)
247 /* Added by wincent */
248 #define PDPOD_QUIT (BUTTON_OFF)
249 #define PDPOD_PLAY (BUTTON_ON)
250 #define PDPOD_PREVIOUS (BUTTON_LEFT)
251 #define PDPOD_NEXT (BUTTON_RIGHT)
252 #define PDPOD_MENU (BUTTON_SELECT)
253 #define PDPOD_WHEELLEFT (BUTTON_DOWN)
254 #define PDPOD_WHEELRIGHT (BUTTON_UP)
255 #define PDPOD_ACTION (BUTTON_MODE)
256/* #elif defined(IRIVER_H100_SERIES) */
257#else
258 #warning "No keys defined for this architecture!"
259#endif
260
261/* Prototype of GUI functions. */
262void pd_gui_init(void);
263unsigned int pd_gui_load_patch(struct pd_widget* wg, unsigned int max_widgets);
264void pd_gui_draw(struct pd_widget* wg, unsigned int widgets);
265bool pd_gui_parse_buttons(unsigned int widgets);
266void pd_gui_parse_message(struct datagram* dg,
267 struct pd_widget* wg, unsigned int widgets);
268bool pd_gui_apply_timeouts(struct pd_widget* wg, unsigned int widgets);
269
200#endif 270#endif