diff options
author | Wincent Balin <wincent@rockbox.org> | 2009-08-04 02:01:55 +0000 |
---|---|---|
committer | Wincent Balin <wincent@rockbox.org> | 2009-08-04 02:01:55 +0000 |
commit | bec80ca7ddeff355d0ca46efa331d98c77567fd4 (patch) | |
tree | 701d8d4cadf97c4a218c9c2bc3b7e33918db025a /apps/plugins | |
parent | 218b31272e5afcb8f98a62974b46f4febbfde39c (diff) | |
download | rockbox-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/SOURCES | 1 | ||||
-rw-r--r-- | apps/plugins/pdbox/pdbox-gui.c | 809 | ||||
-rw-r--r-- | apps/plugins/pdbox/pdbox.c | 62 | ||||
-rw-r--r-- | apps/plugins/pdbox/pdbox.h | 70 |
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 @@ pdbox.c pdbox-net.c pdbox-func.c +pdbox-gui.c TLSF-2.4.4/src/tlsf.c /* 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 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 Wincent Balin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "plugin.h" +#include "pdbox.h" + +#include "lib/xlcd.h" + +/* Declare back- and foreground colors. */ +#define BGCOLOR (LCD_BLACK) +#define FGCOLOR (LCD_WHITE) +/* Button colors. */ +#define BTNCOLOR_DARK (LCD_DARKGRAY) +#define BTNCOLOR_LIGHT (LCD_LIGHTGRAY) + +/* Variables in the main code. */ +extern char* filename; +extern bool quit; + +/* Screen multiplier. */ +static float screen_multiplier; + +/* Displacement of the slanted corner in the contour of the number widget. */ +static int number_corner; + +/* Button flags. */ +static bool play_on; +static bool previous_on; +static bool next_on; +static bool menu_on; +static bool action_on; + +/* Pause flag. */ +static bool paused; + + +/* Draw circle using midpoint circle algorithm. + Adapted from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm. */ +void drawcircle(int x, int y, int r) +{ + int f = 1 - r; + int ddfx = 1; + int ddfy = -2 * r; + int xp = 0; + int yp = r; + + /* Draw outer points. */ + rb->lcd_drawpixel(x, y + r); + rb->lcd_drawpixel(x, y + r); + rb->lcd_drawpixel(x + r, y); + rb->lcd_drawpixel(x - r, y); + + /* Calculate coordinates of points in one octant. */ + while(xp < yp) + { + /* ddfx == 2 * xp + 1; + ddfy == -2 * yp; + f == xp*xp + yp*yp - r*r + 2*xp - yp + 1; */ + if(f >= 0) + { + yp--; + ddfy += 2; + f += ddfy; + } + + xp++; + ddfx += 2; + f += ddfx; + + /* Draw pixels in all octants. */ + rb->lcd_drawpixel(x + xp, y + yp); + rb->lcd_drawpixel(x + xp, y - yp); + rb->lcd_drawpixel(x - xp, y + yp); + rb->lcd_drawpixel(x - xp, y - yp); + rb->lcd_drawpixel(x + yp, y + xp); + rb->lcd_drawpixel(x + yp, y - xp); + rb->lcd_drawpixel(x - yp, y + xp); + rb->lcd_drawpixel(x - yp, y - xp); + } +} + +/* Fill circle. */ +void fillcircle(int x, int y, int r) +{ + int f = 1 - r; + int ddfx = 1; + int ddfy = -2 * r; + int xp = 0; + int yp = r; + + /* Draw outer points. */ + rb->lcd_drawpixel(x, y + r); + rb->lcd_drawpixel(x, y + r); + rb->lcd_drawpixel(x + r, y); + rb->lcd_drawpixel(x - r, y); + + /* Calculate coordinates of points in one octant. */ + while(xp < yp) + { + /* ddfx == 2 * xp + 1; + ddfy == -2 * yp; + f == xp*xp + yp*yp - r*r + 2*xp - yp + 1; */ + if(f >= 0) + { + yp--; + ddfy += 2; + f += ddfy; + } + + xp++; + ddfx += 2; + f += ddfx; + + /* Fill circle with horizontal lines. */ + rb->lcd_hline(x - xp, x + xp, y - yp); + rb->lcd_hline(x - xp, x + xp, y + yp); + rb->lcd_hline(x - yp, x + yp, y - xp); + rb->lcd_hline(x - yp, x + yp, y + xp); + } + + /* Draw last horizontal line (central one). */ + rb->lcd_hline(x - r, x + r, y); +} + +/* Initialize GUI. */ +void pd_gui_init(void) +{ + /* Reset button flags. */ + play_on = false; + previous_on = false; + next_on = false; + menu_on = false; + action_on = false; + + /* Unpause Pure Data. */ + paused = false; + + /* Calculate dimension factors. */ + screen_multiplier = ((float) LCD_WIDTH) / 160.0f; + number_corner = 5 * screen_multiplier; + + /* Set back- and foreground color. */ + rb->lcd_set_background(BGCOLOR); + rb->lcd_set_foreground(FGCOLOR); + + /* Clear background. */ + rb->lcd_clear_display(); + + /* Update display. */ + rb->lcd_update(); +} + +/* Load PD patch. */ +unsigned int pd_gui_load_patch(struct pd_widget* wg, unsigned int max_widgets) +{ + int fd; + char line[100]; + char* saveptr; + unsigned int widgets = 0; + + /* Open PD patch. */ + fd = open(filename, O_RDONLY); + + /* Check for I/O error. */ + if(!fd) + { + /* Show error message and make plug-in quit. */ + rb->splash(HZ, "Error opening .pd file!"); + quit = true; + return 0; + } + + /* Read lines from PD file. */ + while(rb->read_line(fd, line, sizeof(line)) > 0) + { + /* Check whether we got too many widgets. */ + if(widgets >= max_widgets) + { + rb->splash(HZ, "Too many widgets!"); + quit = true; + return 0; + } + + /* Search for key strings in the line. */ + if((strstr(line, "floatatom") != NULL) && + (strstr(line, "pod_") != NULL)) + { + wg->id = PD_NUMBER; + + strtok_r(line, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + wg->w = 7 * atoi(strtok_r(NULL, " ", &saveptr)) * + screen_multiplier; + wg->h = 16 * screen_multiplier; + strtok_r(NULL, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name)); + + /* We got one more widget. */ + wg++; + widgets++; + } + else if((strstr(line, "symbolatom") != NULL) && + (strstr(line, "pod_") != NULL)) + { + wg->id = PD_SYMBOL; + + strtok_r(line, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + wg->w = 7 * atoi(strtok_r(NULL, " ", &saveptr)) * + screen_multiplier; + wg->h = 16 * screen_multiplier; + strtok_r(NULL, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name)); + + /* We got one more widget. */ + wg++; + widgets++; + } + else if((strstr(line, "vsl") != NULL) && + (strstr(line, "pod_") != NULL)) + { + wg->id = PD_VSLIDER; + + strtok_r(line, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + strtok_r(NULL, " ", &saveptr); + wg->w = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + wg->h = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + wg->min = atoi(strtok_r(NULL, " ", &saveptr)); + wg->max = atoi(strtok_r(NULL, " ", &saveptr)); + strtok_r(NULL, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name)); + + /* We got one more widget. */ + wg++; + widgets++; + } + else if((strstr(line, "hsl") != NULL) && + (strstr(line, "pod_") != NULL)) + { + wg->id = PD_HSLIDER; + + strtok_r(line, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + strtok_r(NULL, " ", &saveptr); + wg->w = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + wg->h = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + wg->min = atoi(strtok_r(NULL, " ", &saveptr)); + wg->max = atoi(strtok_r(NULL, " ", &saveptr)); + strtok_r(NULL, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name)); + + /* We got one more widget. */ + wg++; + widgets++; + } + else if((strstr(line, "vradio") != NULL) && + (strstr(line, "pod_") != NULL)) + { + wg->id = PD_VRADIO; + + strtok_r(line, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + strtok_r(NULL, " ", &saveptr); + wg->w = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + strtok_r(NULL, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + wg->min = 0; + wg->max = atoi(strtok_r(NULL, " ", &saveptr)); + wg->h = wg->w * wg->max; + strtok_r(NULL, " ", &saveptr); + strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name)); + wg->max--; + + /* We got one more widget. */ + wg++; + widgets++; + } + else if((strstr(line, "hradio") != NULL) && + (strstr(line, "pod_") != NULL)) + { + wg->id = PD_HRADIO; + + strtok_r(line, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + strtok_r(NULL, " ", &saveptr); + wg->h = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + strtok_r(NULL, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + wg->min = 0; + wg->max = atoi(strtok_r(NULL, " ", &saveptr)); + wg->w = wg->h * wg->max; + strtok_r(NULL, " ", &saveptr); + strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name)); + wg->max--; + + /* We got one more widget. */ + wg++; + widgets++; + } + else if((strstr(line, "bng") != NULL) && + (strstr(line, "pod_") != NULL)) + { + wg->id = PD_BANG; + + strtok_r(line, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + strtok_r(NULL, " ", &saveptr); + wg->w = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + wg->h = wg->w; + strtok_r(NULL, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name)); + wg->min = 0; + wg->max = 1; + + /* Clear timeout flag. */ + wg->timeout = 0; + + /* We got one more widget. */ + wg++; + widgets++; + } + else if(strstr(line, "text") != NULL) + { + wg->id = PD_TEXT; + + strtok_r(line, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); + wg->x = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + wg->y = atoi(strtok_r(NULL, " ", &saveptr)) * screen_multiplier; + strncpy(wg->name, strtok_r(NULL, " ", &saveptr), sizeof(wg->name)); + char* w = strtok_r(NULL, " ", &saveptr); + while(w != NULL) + { + strcat(wg->name, w); + strcat(wg->name, " "); + w = strtok_r(NULL, " ", &saveptr); + } + /* Cut off unneeded characters (';' and '\n'). */ + int namelen = strlen(wg->name); + if(namelen > 1) + { + /* Cut off '\n'. */ + wg->name[namelen-1] = '\0'; + namelen--; + /* Cut the last semi-colon, if there is one. */ + if(wg->name[namelen-1] == ';') + wg->name[namelen-1] = '\0'; + } + + + /* We got one more widget. */ + wg++; + widgets++; + } + } + + /* Close PD patch. */ + close(fd); + + /* Return amount of loaded widgets. */ + return widgets; +} + +/* Draw standard user interface. */ +void pd_gui_draw_standard(void) +{ + /* Draw main circle. */ + rb->lcd_set_foreground(FGCOLOR); + fillcircle(LCD_WIDTH / 2, + LCD_HEIGHT / 2, + 2 * MIN(LCD_WIDTH, LCD_HEIGHT) / 5); + + /* Draw center circle. */ + rb->lcd_set_foreground(action_on ? BTNCOLOR_DARK : BTNCOLOR_LIGHT); + fillcircle(LCD_WIDTH / 2, + LCD_HEIGHT / 2, + MIN(LCD_WIDTH, LCD_HEIGHT) / 8); + + /* Draw pressed buttons. */ + if(play_on) + fillcircle(LCD_WIDTH / 2, + 3 * LCD_HEIGHT / 4, + MIN(LCD_WIDTH, LCD_HEIGHT) / 8); + + if(previous_on) + fillcircle(LCD_WIDTH / 3, + LCD_HEIGHT / 2, + MIN(LCD_WIDTH, LCD_HEIGHT) / 8); + + if(next_on) + fillcircle(2 * LCD_WIDTH / 3 + 1, + LCD_HEIGHT / 2, + MIN(LCD_WIDTH, LCD_HEIGHT) / 8); + + if(menu_on) + fillcircle(LCD_WIDTH / 2, + LCD_HEIGHT / 4, + MIN(LCD_WIDTH, LCD_HEIGHT) / 8); + + /* Restore foreground color. */ + rb->lcd_set_foreground(FGCOLOR); +} + +/* Draw custom user interface. */ +void pd_gui_draw_custom(struct pd_widget* wg, unsigned int widgets) +{ + unsigned int i; + int j; + int v; + + for(i = 0; i < widgets; wg++, i++) + { + switch(wg->id) + { + case PD_BANG: + /* Clear area to (re-)draw. */ + rb->lcd_set_foreground(BGCOLOR); + rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h); + rb->lcd_set_foreground(FGCOLOR); + /* Draw border (rectangle). */ + rb->lcd_drawrect(wg->x, wg->y, wg->w, wg->h); + /* Draw button (circle), being filled depending on value. */ + if(((int) wg->value) == 0) /* Button not pressed. */ + drawcircle(wg->x + wg->w/2, + wg->y + wg->w/2, + wg->w/2 - 1); + else /* Button pressed. */ + fillcircle(wg->x + wg->w/2, + wg->y + wg->w/2, + wg->w/2 - 1); + break; + + case PD_VSLIDER: + /* Clear area to (re-)draw. */ + rb->lcd_set_foreground(BGCOLOR); + rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h); + rb->lcd_set_foreground(FGCOLOR); + /* Draw border. */ + rb->lcd_drawrect(wg->x, wg->y, wg->w, wg->h); + /* Draw slider. */ + v = ((float) wg->h / (wg->max - wg->min)) * + (wg->max - wg->value); + rb->lcd_fillrect(wg->x, wg->y + v, wg->w, 2); + break; + + case PD_HSLIDER: + /* Clear area to (re-)draw. */ + rb->lcd_set_foreground(BGCOLOR); + rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h); + rb->lcd_set_foreground(FGCOLOR); + /* Draw border. */ + rb->lcd_drawrect(wg->x, wg->y, wg->w, wg->h); + /* Draw slider. */ + v = ((float) wg->w / (wg->max - wg->min)) * + (wg->max - wg->value); + rb->lcd_fillrect(wg->x + wg->w - v, wg->y, 2, wg->h); + break; + + case PD_HRADIO: + /* Clear area to (re-)draw. */ + rb->lcd_set_foreground(BGCOLOR); + rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h); + rb->lcd_set_foreground(FGCOLOR); + for(j = 0; j < wg->w / wg->h; j++) + { + /* Draw border. */ + rb->lcd_drawrect(wg->x + wg->h * j, wg->y, wg->h, wg->h); + /* If marked, draw button. */ + if(((int) wg->value) == j) + rb->lcd_fillrect(wg->x + wg->h * j + 2, wg->y + 2, + wg->h - 4, wg->h - 4); + } + break; + + case PD_VRADIO: + /* Clear area to (re-)draw. */ + rb->lcd_set_foreground(BGCOLOR); + rb->lcd_fillrect(wg->x, wg->y, wg->w, wg->h); + rb->lcd_set_foreground(FGCOLOR); + for(j = 0; j < wg->h / wg->w; j++) + { + /* Draw border. */ + rb->lcd_drawrect(wg->x, wg->y + wg->w * j, wg->w, wg->w); + /* If marked, draw button. */ + if(((int) wg->value) == j) + rb->lcd_fillrect(wg->x + 2, wg->y + wg->w * j + 2, + wg->w - 4, wg->w - 4); + } + break; + + case PD_NUMBER: + rb->lcd_hline(wg->x, + wg->x + wg->w - number_corner, + wg->y); + rb->lcd_drawline(wg->x + wg->w - number_corner, + wg->y, + wg->x + wg->w, + wg->y + number_corner); + rb->lcd_vline(wg->x + wg->w, + wg->y + number_corner, + wg->y + wg->h); + rb->lcd_hline(wg->x, + wg->x + wg->w, + wg->y + wg->h); + rb->lcd_vline(wg->x, + wg->y, + wg->y + wg->h); + char sbuf[12]; + ftoan(wg->value, sbuf, 12); + rb->lcd_putsxy(wg->x + 2, wg->y + 2, sbuf); + break; + + case PD_TEXT: + rb->lcd_putsxy(wg->x + 2, wg->y, wg->name); + break; + + case PD_SYMBOL: + break; + } + } +} + +/* Draw the GUI. */ +void pd_gui_draw(struct pd_widget* wg, unsigned int widgets) +{ + /* Draw GUI. */ + if(widgets == 0) + pd_gui_draw_standard(); + else + pd_gui_draw_custom(wg, widgets); + + /* Update display. */ + rb->lcd_update(); +} + +/* Parse buttons, if needed, send messages to the Pure Data code. */ +bool pd_gui_parse_buttons(unsigned int widgets) +{ + static long last_bv = 0; + long bv = rb->button_get(false); + + /* Extract differences between current and previous button values. */ + long diff_bv = bv ^ last_bv; + + /* If no difference since the last button value, return here. */ + if(diff_bv == 0) + return false; + + /* Query whether we have to quit. */ + if(bv == PDPOD_QUIT) + { + /* No need to send the quitting message to Pure Data core, + as setting the quit flag ends threads and jumps + to the cleanup code. */ + quit = true; + return false; + } + + /* Check the action (shift, mode) button. */ + if(diff_bv & PDPOD_ACTION) + { + if(bv & PDPOD_ACTION) + { + SEND_TO_CORE("b;\n"); + + if(widgets == 0) + action_on = true; + } + else + { + if(widgets == 0) + action_on = false; + } + } + + /* Check play button. */ + if(diff_bv & PDPOD_PLAY) + { + if(bv & PDPOD_PLAY) + { + /* Action + play = pause. */ + if(action_on) + { + /* Switch paused state. */ + paused = !paused; + SEND_TO_CORE(paused ? "p 1;\n" : "p 0;\n"); + } + + if(!action_on && !paused) + SEND_TO_CORE("d 1;\n"); + + if(widgets == 0) + play_on = true; + } + else + { + if(!action_on && !paused) + SEND_TO_CORE("d 0;\n"); + + if(widgets == 0) + play_on = false; + } + } + + /* Check rewind (previous) button. */ + if(diff_bv & PDPOD_PREVIOUS) + { + if(bv & PDPOD_PREVIOUS) + { + if(!paused) + SEND_TO_CORE("w 1;\n"); + + if(widgets == 0) + previous_on = true; + } + else + { + if(!paused) + SEND_TO_CORE("w 0;\n"); + + if(widgets == 0) + previous_on = false; + } + } + + /* Check forward (next) button. */ + if(diff_bv & PDPOD_NEXT) + { + if(bv & PDPOD_NEXT) + { + if(!paused) + SEND_TO_CORE("f 1;\n"); + + if(widgets == 0) + next_on = true; + } + else + { + if(!paused) + SEND_TO_CORE("f 0;\n"); + + if(widgets == 0) + next_on = false; + } + } + + /* Check menu (select) button. */ + if(diff_bv & PDPOD_MENU) + { + if(bv & PDPOD_MENU) + { + if(!action_on && !paused) + SEND_TO_CORE("m 1;\n"); + + if(widgets == 0) + menu_on = true; + } + else + { + if(!action_on && !paused) + SEND_TO_CORE("m 0;\n"); + + if(widgets == 0) + menu_on = false; + } + } + + /* Check scroll right (or up) button. */ + if(diff_bv & PDPOD_WHEELRIGHT) + { + if(bv & PDPOD_WHEELRIGHT) + { + SEND_TO_CORE(action_on ? "r 10;\n" : "r 1;\n"); + } + } + + /* Check scroll left (or down) button. */ + if(diff_bv & PDPOD_WHEELLEFT) + { + if(bv & PDPOD_WHEELLEFT) + { + SEND_TO_CORE(action_on ? "l 10;\n" : "l 1;\n"); + } + } + + /* Backup button value. */ + last_bv = bv; + + /* GUI has to be updated. */ + return true; +} + +/* Emulate timer for widgets which use time-out. */ +bool pd_gui_apply_timeouts(struct pd_widget* wg, unsigned int widgets) +{ + unsigned int i; + bool result = false; + + for(i = 0; i < widgets; wg++, i++) + { + if(wg->id == PD_BANG) + { + if(wg->timeout > 0) + { + /* Decrement timeout value. */ + wg->timeout--; + + /* If zero reached, clear value. */ + if(wg->timeout == 0) + { + wg->value = 0; + result = true; + } + } + } + } + + return result; +} + +/* Parse and apply message from the Pure Data core. */ +void pd_gui_parse_message(struct datagram* dg, + struct pd_widget* wg, + unsigned int widgets) +{ + unsigned int i; + char* saveptr; + char* object = NULL; + char* argument = NULL; + float argvalue = 0; + + object = strtok_r(dg->data, " ", &saveptr); + argument = strtok_r(NULL, " ;\n", &saveptr); + + if(argument != NULL) + argvalue = atof(argument); + + for(i = 0; i < widgets; wg++, i++) + { + if(strncmp(object, wg->name, strlen(wg->name)) == 0) + { + /* If object not a number, set boundaries. */ + if(wg->id != PD_NUMBER) + { + if(argvalue > wg->max) + argvalue = wg->max; + else if(argvalue < wg->min) + argvalue = wg->min; + } + + /* Set value. */ + if(wg->id == PD_BANG) + { + wg->value = 1; + wg->timeout = HZ / 10; + } + else + { + wg->value = argvalue; + } + } + } +} 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]; int sys_chinlist[MAXAUDIOINDEV]; int sys_soundoutdevlist[MAXAUDIOOUTDEV]; int sys_choutlist[MAXAUDIOOUTDEV]; +t_binbuf* inbinbuf; /* References for scheduler variables and functions. */ extern t_time sys_time; @@ -59,7 +60,7 @@ rates we expect to see: 32000, 44100, 48000, 88200, 96000. */ bool quit = false; /* Stack sizes for threads. */ -#define CORESTACKSIZE (8 * 1024 * 1024) +#define CORESTACKSIZE (1 * 1024 * 1024) #define GUISTACKSIZE (512 * 1024) /* Thread stacks. */ @@ -74,30 +75,45 @@ unsigned int gui_thread_id; /* GUI thread */ void gui_thread(void) { -/* struct datagram pong; */ + struct pd_widget widget[128]; + unsigned int widgets = 0; + struct datagram dg; + bool update; + + /* Initialize GUI. */ + pd_gui_init(); + + /* Load PD patch. */ + widgets = pd_gui_load_patch(widget, + sizeof(widget) / sizeof(struct pd_widget)); + + /* Draw initial state of UI. */ + pd_gui_draw(widget, widgets); /* GUI loop */ while(!quit) { -#if 0 - /* Send ping to the core. */ - SEND_TO_CORE("Ping!"); - rb->splash(HZ, "Sent ping."); + /* Reset update flag. */ + update = false; + + /* Apply timer to widgets. */ + update |= + pd_gui_apply_timeouts(widget, widgets); - /* Wait for answer. */ - while(!RECEIVE_FROM_CORE(&pong)) - rb->yield(); + /* Process buttons. */ + update |= + pd_gui_parse_buttons(widgets); - /* If got a pong -- everything allright. */ - if(memcmp("Pong!", pong.data, pong.size) == 0) + /* Receive and parse datagrams. */ + while(RECEIVE_FROM_CORE(&dg)) { - rb->splash(HZ, "Got pong!"); - quit = true; - break; + update = true; + pd_gui_parse_message(&dg, widget, widgets); } -#endif - if(rb->button_get(false) == BUTTON_OFF) - quit = true; + + /* If there is something to update in GUI, do so. */ + if(update) + pd_gui_draw(widget, widgets); rb->sleep(1); } @@ -120,6 +136,12 @@ void core_thread(void) /* Core scheduler loop */ while(!quit) { + /* Receive datagrams. */ + struct datagram dg; + + while(RECEIVE_TO_CORE(&dg)) + rockbox_receive_callback(&dg); + /* Use sys_send_dacs() function as timer. */ while(sys_send_dacs() != SENDDACS_NO) sched_tick(sys_time + sys_time_per_dsp_tick); @@ -194,6 +216,9 @@ enum plugin_status plugin_start(const void* parameter) return PLUGIN_ERROR; } + /* Boost CPU. */ + cpu_boost(true); + /* Start threads. */ core_thread_id = rb->create_thread(&core_thread, @@ -237,6 +262,9 @@ enum plugin_status plugin_start(const void* parameter) rb->thread_wait(gui_thread_id); rb->thread_wait(core_thread_id); + /* Unboost CPU. */ + cpu_boost(false); + /* Close audio subsystem. */ sys_close_audio(); 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); #define sinh rb_sinh #define tan rb_tan +#define strtok_r rb->strtok_r +#define strstr rb->strcasestr + + +/* PdPod GUI declarations. */ + +enum pd_widget_id +{ + PD_BANG, + PD_VSLIDER, + PD_HSLIDER, + PD_VRADIO, + PD_HRADIO, + PD_NUMBER, + PD_SYMBOL, + PD_TEXT +}; + +struct pd_widget +{ + enum pd_widget_id id; + char name[128]; + int x; + int y; + int w; + int h; + int min; + int max; + float value; + int timeout; +}; + +enum pd_key_id +{ + KEY_PLAY, + KEY_REWIND, + KEY_FORWARD, + KEY_MENU, + KEY_ACTION, + KEY_WHEELLEFT, + KEY_WHEELRIGHT, + PD_KEYS +}; + +/* Map real keys to virtual ones. + Feel free to add your preferred keymap here. */ +#if defined(IRIVER_H300_SERIES) + /* Added by wincent */ + #define PDPOD_QUIT (BUTTON_OFF) + #define PDPOD_PLAY (BUTTON_ON) + #define PDPOD_PREVIOUS (BUTTON_LEFT) + #define PDPOD_NEXT (BUTTON_RIGHT) + #define PDPOD_MENU (BUTTON_SELECT) + #define PDPOD_WHEELLEFT (BUTTON_DOWN) + #define PDPOD_WHEELRIGHT (BUTTON_UP) + #define PDPOD_ACTION (BUTTON_MODE) +/* #elif defined(IRIVER_H100_SERIES) */ +#else + #warning "No keys defined for this architecture!" +#endif + +/* Prototype of GUI functions. */ +void pd_gui_init(void); +unsigned int pd_gui_load_patch(struct pd_widget* wg, unsigned int max_widgets); +void pd_gui_draw(struct pd_widget* wg, unsigned int widgets); +bool pd_gui_parse_buttons(unsigned int widgets); +void pd_gui_parse_message(struct datagram* dg, + struct pd_widget* wg, unsigned int widgets); +bool pd_gui_apply_timeouts(struct pd_widget* wg, unsigned int widgets); + #endif |