From e35f2d06e913be1a268be88aee9707a9cd2985a0 Mon Sep 17 00:00:00 2001 From: jdgordon Date: Mon, 20 Apr 2009 01:41:56 +0000 Subject: [PATCH] beginings of a working touchscreen interface for the WPS. 2 new tags: %T|x|y|width|height|action| <- setup a region (relative to the current viewport) where if pressed the "action" will be done (currently play/stop/prev/next/menu/browse work, suggestions for others to add and better names welcome) %Tl <- used as a conditional to say if the touchscreen was touched in the last , use this to enable/disable button viewports or something... same syntax as other timeout tags cabbiev2 for the mr500 has been modified to demonstrate the new tags. press the pause/play button to pause playback. press the rockbox logo to get back to the menu. pretty icons needed to make this more usable :) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20753 a1c6a512-1295-4272-9138-f99709370657 --- apps/gui/gwps-common.c | 7 +++ apps/gui/gwps.c | 37 +++++++++++++++- apps/gui/gwps.h | 19 ++++++++ apps/gui/wps_parser.c | 86 ++++++++++++++++++++++++++++++++++-- firmware/drivers/button.c | 19 ++++++-- firmware/export/button.h | 2 + uisimulator/sdl/button.c | 6 +++ wps/cabbiev2.320x240x16.mrobe500.wps | 47 ++++++++++++++++++++ 8 files changed, 215 insertions(+), 8 deletions(-) create mode 100644 wps/cabbiev2.320x240x16.mrobe500.wps diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c index 5ab0097b2..1fef9e02c 100644 --- a/apps/gui/gwps-common.c +++ b/apps/gui/gwps-common.c @@ -1292,6 +1292,13 @@ static const char *get_token_value(struct gui_wps *gwps, token->value.i * TIMEOUT_UNIT)) return "v"; return NULL; + case WPS_TOKEN_LASTTOUCH: +#ifdef HAVE_TOUCHSCREEN + if (TIME_BEFORE(current_tick, token->value.i * TIMEOUT_UNIT + + touchscreen_last_touch())) + return "t"; +#endif + return NULL; case WPS_TOKEN_SETTING: { diff --git a/apps/gui/gwps.c b/apps/gui/gwps.c index 0c8a3aa2b..26b531e33 100644 --- a/apps/gui/gwps.c +++ b/apps/gui/gwps.c @@ -293,7 +293,38 @@ void gwps_draw_statusbars(void) { viewportmanager_set_statusbar(wpsbars); } - +#ifdef HAVE_TOUCHSCREEN +static int wps_get_touchaction(struct wps_data *data) +{ + short x,y; + short vx, vy; + int type = action_get_touchscreen_press(&x, &y); + int i; + struct touchregion *r; + if (type != BUTTON_REL) + return ACTION_TOUCHSCREEN; + for (i=0; itouchregion_count; i++) + { + r = &data->touchregion[i]; + /* make sure this region's viewport is visible */ + if (r->wvp->hidden_flags&VP_DRAW_HIDDEN) + continue; + /* reposition the touch inside the viewport */ + vx = x - r->wvp->vp.x; + vy = y - r->wvp->vp.y; + /* check if its inside this viewport */ + if (vx >= 0 && vx < r->wvp->vp.x + r->wvp->vp.width && + vy >= 0 && vy < r->wvp->vp.y + r->wvp->vp.height) + { + /* now see if the point is inside this region */ + if (vx >= r->x && vx < r->x+r->width && + vy >= r->y && vy < r->y+r->height) + return r->action; + } + } + return ACTION_TOUCHSCREEN; +} +#endif /* The WPS can be left in two ways: * a) call a function, which draws over the wps. In this case, the wps * will be still active (i.e. the below function didn't return) @@ -393,6 +424,10 @@ long gui_wps_show(void) playlist or if using the sleep timer. */ if (!(audio_status() & AUDIO_STATUS_PLAY)) exit = true; +#ifdef HAVE_TOUCHSCREEN + if (button == ACTION_TOUCHSCREEN) + button = wps_get_touchaction(gui_wps[SCREEN_MAIN].data); +#endif /* The iPods/X5/M5 use a single button for the A-B mode markers, defined as ACTION_WPSAB_SINGLE in their config files. */ #ifdef ACTION_WPSAB_SINGLE diff --git a/apps/gui/gwps.h b/apps/gui/gwps.h index 1042e1a79..935e015c9 100644 --- a/apps/gui/gwps.h +++ b/apps/gui/gwps.h @@ -88,6 +88,8 @@ struct progressbar { }; #endif + + struct align_pos { char* left; char* center; @@ -297,6 +299,7 @@ enum wps_token_type { /* buttons */ WPS_TOKEN_BUTTON_VOLUME, + WPS_TOKEN_LASTTOUCH, /* Setting option */ WPS_TOKEN_SETTING, @@ -363,6 +366,17 @@ struct wps_viewport { char label; }; +#ifdef HAVE_TOUCHSCREEN +struct touchregion { + struct wps_viewport* wvp;/* The viewport this region is in */ + short int x; /* x-pos */ + short int y; /* y-pos */ + short int width; /* width */ + short int height; /* height */ + int action; /* action this button will return */ +}; +#define MAX_TOUCHREGIONS 12 +#endif /* wps_data this struct holds all necessary data which describes the viewable content of a wps */ @@ -399,6 +413,11 @@ struct wps_data bool full_line_progressbar; #endif +#ifdef HAVE_TOUCHSCREEN + struct touchregion touchregion[MAX_TOUCHREGIONS]; + short touchregion_count; +#endif + #ifdef HAVE_REMOTE_LCD bool remote_wps; #endif diff --git a/apps/gui/wps_parser.c b/apps/gui/wps_parser.c index 390df56cb..290f370fe 100644 --- a/apps/gui/wps_parser.c +++ b/apps/gui/wps_parser.c @@ -121,7 +121,7 @@ struct wps_tag { unsigned char refresh_type; const wps_tag_parse_func parse_func; }; - +static int skip_end_of_line(const char *wps_bufptr); /* prototypes of all special parse functions : */ static int parse_timeout(const char *wps_bufptr, struct wps_token *token, struct wps_data *wps_data); @@ -131,7 +131,7 @@ static int parse_dir_level(const char *wps_bufptr, struct wps_token *token, struct wps_data *wps_data); static int parse_setting(const char *wps_bufptr, struct wps_token *token, struct wps_data *wps_data); - + #ifdef HAVE_LCD_BITMAP static int parse_viewport_display(const char *wps_bufptr, struct wps_token *token, struct wps_data *wps_data); @@ -156,7 +156,18 @@ static int parse_albumart_load(const char *wps_bufptr, static int parse_albumart_conditional(const char *wps_bufptr, struct wps_token *token, struct wps_data *wps_data); #endif /* HAVE_ALBUMART */ - +#ifdef HAVE_TOUCHSCREEN +static int parse_touchregion(const char *wps_bufptr, + struct wps_token *token, struct wps_data *wps_data); +#else +static int fulline_tag_not_supported(const char *wps_bufptr, + struct wps_token *token, struct wps_data *wps_data) +{ + (void)token; (void)wps_data; + return skip_end_of_line(wps_bufptr); +} +#define parse_touchregion fulline_tag_not_supported +#endif #ifdef CONFIG_RTC #define WPS_RTC_REFRESH WPS_REFRESH_DYNAMIC #else @@ -337,7 +348,10 @@ static const struct wps_tag all_tags[] = { #endif { WPS_TOKEN_SETTING, "St", WPS_REFRESH_DYNAMIC, parse_setting }, - + + { WPS_TOKEN_LASTTOUCH, "Tl", WPS_REFRESH_DYNAMIC, parse_timeout }, + { WPS_NO_TOKEN, "T", 0, parse_touchregion }, + { WPS_TOKEN_UNKNOWN, "", 0, NULL } /* the array MUST end with an empty string (first char is \0) */ }; @@ -1142,6 +1156,70 @@ static int parse_albumart_conditional(const char *wps_bufptr, }; #endif /* HAVE_ALBUMART */ +#ifdef HAVE_TOUCHSCREEN + +struct touchaction {char* s; int action;}; +static struct touchaction touchactions[] = { + {"play", ACTION_WPS_PLAY }, {"stop", ACTION_WPS_STOP }, + {"prev", ACTION_WPS_SKIPPREV }, {"next", ACTION_WPS_SKIPNEXT }, + {"menu", ACTION_WPS_MENU }, {"browse", ACTION_WPS_BROWSE } +}; +static int parse_touchregion(const char *wps_bufptr, + struct wps_token *token, struct wps_data *wps_data) +{ + (void)token; + unsigned i; + struct touchregion *region; + const char *ptr = wps_bufptr; + const char *action; + int x,y,w,h; + + /* format: %T|x|y|width|height|action| + * action is one of: + * play - play/pause playback + * stop - stop playback, exit the wps + * prev - prev track + * next - next track + * ffwd + * rwd + * menu - go back to the main menu + * browse - go back to the file/db browser + */ + + if ((wps_data->touchregion_count +1 >= MAX_TOUCHREGIONS) || (*ptr != '|')) + return WPS_ERROR_INVALID_PARAM; + ptr++; + + if (!(ptr = parse_list("dddds", NULL, '|', ptr, &x, &y, &w, &h, &action))) + return WPS_ERROR_INVALID_PARAM; + + /* Check there is a terminating | */ + if (*ptr != '|') + return WPS_ERROR_INVALID_PARAM; + + /* should probably do some bounds checking here with the viewport... but later */ + region = &wps_data->touchregion[wps_data->touchregion_count]; + region->action = ACTION_NONE; + region->x = x; + region->y = y; + region->width = w; + region->height = h; + region->wvp = &wps_data->viewports[wps_data->num_viewports]; + i = 0; + while ((region->action == ACTION_NONE) && + (i < sizeof(touchactions)/sizeof(*touchactions))) + { + if (!strncmp(touchactions[i].s, action, strlen(touchactions[i].s))) + region->action = touchactions[i].action; + i++; + } + if (region->action == ACTION_NONE) + return WPS_ERROR_INVALID_PARAM; + wps_data->touchregion_count++; + return skip_end_of_line(wps_bufptr); +} +#endif + /* Parse a generic token from the given string. Return the length read */ static int parse_token(const char *wps_bufptr, struct wps_data *wps_data) { diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c index 7d4daafdc..6fbe5de22 100644 --- a/firmware/drivers/button.c +++ b/firmware/drivers/button.c @@ -81,6 +81,9 @@ static int button_read(int *data); static int button_read(void); #endif +#ifdef HAVE_TOUCHSCREEN + int last_touchscreen_touch; +#endif #if defined(HAVE_HEADPHONE_DETECTION) static struct timeout hp_detect_timeout; /* Debouncer for headphone plug/unplug */ /* This callback can be used for many different functions if needed - @@ -406,7 +409,9 @@ void button_init(void) remote_filter_first_keypress = false; #endif #endif - +#ifdef HAVE_TOUCHSCREEN + last_touchscreen_touch = 0xffff; +#endif /* Start polling last */ tick_add_task(button_tick); } @@ -522,7 +527,10 @@ static int button_read(void) if (btn && flipped) btn = button_flip(btn); /* swap upside down */ #endif - +#ifdef HAVE_TOUCHSCREEN + if (btn & BUTTON_TOUCHSCREEN) + last_touchscreen_touch = current_tick; +#endif /* Filter the button status. It is only accepted if we get the same status twice in a row. */ #ifndef HAVE_TOUCHSCREEN @@ -536,7 +544,6 @@ static int button_read(void) return retval; } - int button_status(void) { return lastbtn; @@ -547,6 +554,12 @@ void button_clear_queue(void) queue_clear(&button_queue); } +#ifdef HAVE_TOUCHSCREEN +int touchscreen_last_touch(void) +{ + return last_touchscreen_touch; +} +#endif #endif /* SIMULATOR */ #ifdef HAVE_WHEEL_ACCELERATION diff --git a/firmware/export/button.h b/firmware/export/button.h index d5a8001fb..3947f0720 100644 --- a/firmware/export/button.h +++ b/firmware/export/button.h @@ -68,6 +68,8 @@ int button_apply_acceleration(const unsigned int data); #define BUTTON_TOUCHSCREEN 0x08000000 #ifdef HAVE_TOUCHSCREEN +int touchscreen_last_touch(void); + #if (!defined(BUTTON_TOPLEFT) || !defined(BUTTON_TOPMIDDLE) \ || !defined(BUTTON_TOPRIGHT) || !defined(BUTTON_MIDLEFT) \ || !defined(BUTTON_CENTER) || !defined(BUTTON_MIDRIGHT) \ diff --git a/uisimulator/sdl/button.c b/uisimulator/sdl/button.c index e9fa03cbe..9c8f334b4 100644 --- a/uisimulator/sdl/button.c +++ b/uisimulator/sdl/button.c @@ -36,6 +36,7 @@ static intptr_t button_data; /* data value from last message dequeued */ #ifdef HAVE_TOUCHSCREEN #include "touchscreen.h" static int mouse_coords = 0; +static int last_touchscreen_touch = 0xffff; #endif /* how long until repeat kicks in */ #define REPEAT_START 6 @@ -1310,11 +1311,16 @@ void mouse_tick_task(void) } mouse_coords = (x<<16)|y; + last_touchscreen_touch = current_tick; button_event(BUTTON_TOUCHSCREEN, true); if (debug_wps) printf("Mouse at: (%d, %d)\n", x, y); } } +int touchscreen_last_touch(void) +{ + return last_touchscreen_touch; +} #endif void button_init(void) { diff --git a/wps/cabbiev2.320x240x16.mrobe500.wps b/wps/cabbiev2.320x240x16.mrobe500.wps new file mode 100644 index 000000000..222f51bc4 --- /dev/null +++ b/wps/cabbiev2.320x240x16.mrobe500.wps @@ -0,0 +1,47 @@ +# cabbie 2.0 default +# (C) 2007, Johannes Voggenthaler (Zinc Alloy) +#derived from "cabbie" (C) Yohann Misquitta +%wd +%T|286|207|24|24|play| +%T|0|207|84|24|menu| +%X|wpsbackdrop-320x240x16.bmp| +%xl|A|lock-320x240x16.bmp|91|207|2| +%xl|B|battery-320x240x16.bmp|126|207|10| +%xl|C|volume-320x240x16.bmp|177|207|10| +%xl|D|shuffle-320x240x16.bmp|218|211| +%xl|E|repeat-320x240x16.bmp|261|207|4| +%xl|F|playmode-320x240x16.bmp|286|207|5| +%Cl|16|32|s120|s120| +%pb|pb-320x240x16.bmp|10|162|300|15| +%?mh<%xdAa|%xdAb> +%?bp<%?bc<%xdBa|%xdBb>|%?bl<|%xdBc|%xdBd|%xdBe|%xdBf|%xdBg|%xdBh|%xdBi|%xdBj>> +%?pv<%xdCa|%xdCb|%xdCc|%xdCd|%xdCe|%xdCf|%xdCg|%xdCh|%xdCi|%xdCj> +%?ps<%xdD> +%?mm<|%xdEa|%xdEb|%xdEc|%xdEd> +%?mp<%xdFa|%xdFc|%xdFb|%xdFd|%xdFe> +%?C<%Vda%C|%Vdb> +#NowPlaying + +%Vl|a|153|30|-|130|1|-|-| +%s%al%?it<%it|%fn> +%s%al%?ia<%ia|%?d2<%d2|(root)>> +%s%al%?id<%id|%?d1<%d1|(root)>> +#%s%al%iy + +%s%alNext Track: +%s%al%?It<%It|%Fn> +%s%al%Ia + +%Vl|b|0|30|-|130|1|-|-| +%s%ac%?it<%it|%fn> +%s%ac%?ia<%ia|%?d2<%d2|(root)>> +%s%ac%?id<%id|%?d1<%d1|(root)>> +%s%ac%iy + +%acNext Track: +%s%ac%?It<%It|%Fn> +%s%ac%Ia + +%V|0|180|-|20|1|-|-| +%al %pc%ac%pp of %pe%ar%pr + -- 2.11.4.GIT