1
0
Fork 0
forked from len0rd/rockbox

FS#10898 - Add a playlist viewer to the WPS. http://www.rockbox.org/wiki/CustomWPS#Playlist_viewer for an exaplanation how to use it.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24220 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Jonathan Gordon 2010-01-13 06:02:38 +00:00
parent 8b926e98f8
commit dc0ba917fa
6 changed files with 253 additions and 1 deletions

View file

@ -35,6 +35,8 @@
#include "statusbar.h"
#include "scrollbar.h"
#include "screen_access.h"
#include "playlist.h"
#include "playback.h"
#ifdef HAVE_LCD_BITMAP
#include "peakmeter.h"
@ -163,6 +165,94 @@ static void draw_progressbar(struct gui_wps *gwps,
cue_draw_markers(display, state->id3->cuesheet, length,
pb->x, pb->x + pb->width, y+1, pb->height-2);
}
bool audio_peek_track(struct mp3entry* id3, int offset);
static void draw_playlist_viewer_list(struct gui_wps *gwps,
struct playlistviewer *viewer)
{
int lines = viewport_get_nb_lines(viewer->vp);
int line_height = font_get(viewer->vp->font)->height;
int cur_playlist_pos = playlist_get_display_index();
int start_item = MAX(0, cur_playlist_pos + viewer->start_offset);
int i;
struct mp3entry *pid3, id3;
char buf[MAX_PATH*2], tempbuf[MAX_PATH];
gwps->display->set_viewport(viewer->vp);
for(i=start_item; (i-start_item)<lines && i<playlist_amount(); i++)
{
if (i == cur_playlist_pos)
{
pid3 = audio_current_track();
}
else if (i == cur_playlist_pos+1)
{
pid3 = audio_next_track();
}
else if ((i>cur_playlist_pos) && audio_peek_track(&id3, i-cur_playlist_pos))
{
pid3 = &id3;
}
else
pid3 = NULL;
int line = pid3 ? TRACK_HAS_INFO : TRACK_HAS_NO_INFO;
int token = 0, cur_string = 0;
char *filename = playlist_peek(i-cur_playlist_pos);
buf[0] = '\0';
while (token < viewer->lines[line].count)
{
switch (viewer->lines[line].tokens[token])
{
case WPS_TOKEN_STRING:
case WPS_TOKEN_CHARACTER:
strcat(buf, viewer->lines[line].strings[cur_string++]);
break;
case WPS_TOKEN_PLAYLIST_POSITION:
snprintf(tempbuf, sizeof(tempbuf), "%d", i);
strcat(buf, tempbuf);
break;
case WPS_TOKEN_FILE_NAME:
get_dir(tempbuf, sizeof(tempbuf), filename, 0);
strcat(buf, tempbuf);
break;
case WPS_TOKEN_FILE_PATH:
strcat(buf, filename);
break;
case WPS_TOKEN_METADATA_ARTIST:
if (pid3)
strcat(buf, pid3->artist ? pid3->artist : "");
break;
case WPS_TOKEN_METADATA_TRACK_TITLE:
if (pid3)
strcat(buf, pid3->title ? pid3->title : "");
break;
case WPS_TOKEN_TRACK_LENGTH:
if (pid3)
{
format_time(tempbuf, sizeof(tempbuf), pid3->length);
strcat(buf, tempbuf);
}
break;
default:
break;
}
token++;
}
if (viewer->lines[line].scroll)
{
gwps->display->puts_scroll(0, (i-start_item), buf );
}
else
{
gwps->display->putsxy(0, (i-start_item)*line_height, buf );
}
}
}
/* clears the area where the image was shown */
static void clear_image_pos(struct gui_wps *gwps, struct gui_img *img)
@ -595,6 +685,11 @@ static bool get_line(struct gui_wps *gwps,
}
}
break;
#ifdef HAVE_LCD_BITMAP
case WPS_VIEWPORT_CUSTOMLIST:
draw_playlist_viewer_list(gwps, data->tokens[i].value.data);
break;
#endif
default:
{
/* get the value of the tag and copy it to the buffer */

View file

@ -160,6 +160,8 @@ int parse_languagedirection(const char *wps_bufptr,
#ifdef HAVE_LCD_BITMAP
static int parse_viewport_display(const char *wps_bufptr,
struct wps_token *token, struct wps_data *wps_data);
static int parse_playlistview(const char *wps_bufptr,
struct wps_token *token, struct wps_data *wps_data);
static int parse_viewport(const char *wps_bufptr,
struct wps_token *token, struct wps_data *wps_data);
static int parse_statusbar_enable(const char *wps_bufptr,
@ -373,6 +375,9 @@ static const struct wps_tag all_tags[] = {
{ WPS_VIEWPORT_ENABLE, "Vd", WPS_REFRESH_DYNAMIC,
parse_viewport_display },
#ifdef HAVE_LCD_BITMAP
{ WPS_VIEWPORT_CUSTOMLIST, "Vp", WPS_REFRESH_STATIC, parse_playlistview },
#endif
{ WPS_NO_TOKEN, "V", 0, parse_viewport },
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
@ -714,6 +719,119 @@ static int parse_viewport_display(const char *wps_bufptr,
return 1;
}
#ifdef HAVE_LCD_BITMAP
int parse_playlistview_text(struct playlistviewer *viewer,
enum info_line_type line, char* text)
{
int cur_string = 0;
const struct wps_tag *tag;
int taglen = 0;
const char *start = text;
if (*text != '|')
return -1;
text++;
viewer->lines[line].count = 0;
viewer->lines[line].scroll = false;
while (*text != '|')
{
if (*text == '%') /* it is a token of some type */
{
text++;
taglen = 0;
switch(*text)
{
case '%':
case '<':
case '|':
case '>':
case ';':
case '#':
/* escaped characters */
viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_CHARACTER;
viewer->lines[line].strings[cur_string][0] = *text;
viewer->lines[line].strings[cur_string++][0] = '\0';
break;
default:
for (tag = all_tags;
strncmp(text, tag->name, strlen(tag->name)) != 0;
tag++) ;
/* %s isnt stored as a tag so manually check for it */
if (tag->type == WPS_NO_TOKEN)
{
if (!strncmp(tag->name, "s", 1))
{
viewer->lines[line].scroll = true;
taglen = 1;
}
}
else if (tag->type == WPS_TOKEN_UNKNOWN)
{
int i = 0;
/* just copy the string */
viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_STRING;
while (i<(MAX_PLAYLISTLINE_STRLEN-1) && text[i] != '|' && text[i] != '%')
{
viewer->lines[line].strings[cur_string][i] = text[i];
i++;
}
viewer->lines[line].strings[cur_string][i] = '\0';
cur_string++;
taglen = i;
}
else
{
taglen = strlen(tag->name);
viewer->lines[line].tokens[viewer->lines[line].count++] = tag->type;
}
text += taglen;
}
}
else
{
/* regular string */
int i = 0;
/* just copy the string */
viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_STRING;
while (i<(MAX_PLAYLISTLINE_STRLEN-1) && text[i] != '|' && text[i] != '%')
{
viewer->lines[line].strings[cur_string][i] = text[i];
i++;
}
viewer->lines[line].strings[cur_string][i] = '\0';
cur_string++;
text += i;
}
}
return text - start;
}
static int parse_playlistview(const char *wps_bufptr,
struct wps_token *token, struct wps_data *wps_data)
{
(void)wps_data;
/* %Vp|<use icons>|<start offset>|info line text|no info text| */
struct playlistviewer *viewer = skin_buffer_alloc(sizeof(struct playlistviewer));
char *ptr = strchr(wps_bufptr, '|');
int length;
if (!viewer || !ptr)
return WPS_ERROR_INVALID_PARAM;
viewer->vp = &curr_vp->vp;
viewer->show_icons = true;
viewer->start_offset = atoi(ptr+1);
token->value.data = (void*)viewer;
ptr = strchr(ptr+1, '|');
length = parse_playlistview_text(viewer, TRACK_HAS_INFO, ptr);
if (length < 0)
return WPS_ERROR_INVALID_PARAM;
length = parse_playlistview_text(viewer, TRACK_HAS_NO_INFO, ptr+length);
if (length < 0)
return WPS_ERROR_INVALID_PARAM;
return skip_end_of_line(wps_bufptr);
}
#endif
static int parse_viewport(const char *wps_bufptr,
struct wps_token *token,
struct wps_data *wps_data)

View file

@ -81,7 +81,7 @@ static char* get_codectype(const struct mp3entry* id3)
*
* Returns buf if the desired level was found, NULL otherwise.
*/
static char* get_dir(char* buf, int buf_size, const char* path, int level)
char* get_dir(char* buf, int buf_size, const char* path, int level)
{
const char* sep;
const char* last_sep;

View file

@ -54,6 +54,7 @@ enum wps_token_type {
/* Viewport display */
WPS_VIEWPORT_ENABLE,
WPS_VIEWPORT_CUSTOMLIST,
/* Battery */
TOKEN_MARKER_BATTERY,
@ -237,6 +238,7 @@ struct skin_token_list {
struct skin_token_list *next;
};
char* get_dir(char* buf, int buf_size, const char* path, int level);
#endif

View file

@ -225,6 +225,26 @@ struct touchregion {
};
#endif
#define MAX_PLAYLISTLINE_TOKENS 16
#define MAX_PLAYLISTLINE_STRINGS 8
#define MAX_PLAYLISTLINE_STRLEN 8
enum info_line_type {
TRACK_HAS_INFO = 0,
TRACK_HAS_NO_INFO
};
struct playlistviewer {
struct viewport *vp;
bool show_icons;
int start_offset;
struct {
enum wps_token_type tokens[MAX_PLAYLISTLINE_TOKENS];
char strings[MAX_PLAYLISTLINE_STRINGS][MAX_PLAYLISTLINE_STRLEN];
int count;
bool scroll;
} lines[2];
};
#ifdef HAVE_ALBUMART
struct skin_albumart {

View file

@ -629,6 +629,23 @@ struct mp3entry* audio_next_track(void)
return NULL;
}
bool audio_peek_track(struct mp3entry* id3, int offset)
{
int next_idx;
int new_offset = ci.new_track + wps_offset + offset;
if (!audio_have_tracks())
return false;
next_idx = (track_ridx + new_offset) & MAX_TRACK_MASK;
if (tracks[next_idx].id3_hid >= 0)
{
bufread(tracks[next_idx].id3_hid, sizeof(struct mp3entry), id3);
return true;
}
return false;
}
#ifdef HAVE_ALBUMART
int playback_current_aa_hid(int slot)
{