summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2004-01-14 07:59:06 +0000
committerDaniel Stenberg <daniel@haxx.se>2004-01-14 07:59:06 +0000
commitd2b625f818e8e04ace3c7532fe9c38eb0c0b1662 (patch)
treeb835c1d3a3e03581361528dc818c8e4219c40fb8
parente99f3b2b13d63361e348a70ea8b19488f617ca3f (diff)
Craig Sather's patch #749974:
Adds the ability to define 2 or more alternating lines on each line of the WPS and the ability to control how long each alternating line is displayed before switching to the next one. Backward compatible with the current WPS specification language (existing WPS files will display the same as they do now). His HTML version of the docs is found at: http://home.pacbell.net/csath/rockbox/details.html git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4229 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/wps-display.c290
-rw-r--r--docs/CUSTOM_WPS_FORMAT53
2 files changed, 296 insertions, 47 deletions
diff --git a/apps/wps-display.c b/apps/wps-display.c
index 68d3eb531d..6553e9b542 100644
--- a/apps/wps-display.c
+++ b/apps/wps-display.c
@@ -54,11 +54,16 @@
#ifdef HAVE_LCD_BITMAP
#define MAX_LINES 10
+#define FORMAT_BUFFER_SIZE 800
#else
#define MAX_LINES 2
+#define FORMAT_BUFFER_SIZE 400
#endif
-
-#define FORMAT_BUFFER_SIZE 300
+#define MAX_SUBLINES 12
+#define DEFAULT_SUBLINE_TIME_MULTIPLIER 20 /* (10ths of sec) */
+#define BASE_SUBLINE_TIME 10 /* base time that multiplier is applied to
+ (1/HZ sec, or 100ths of sec) */
+#define SUBLINE_RESET -1
#ifdef HAVE_LCD_CHARCELLS
static unsigned char wps_progress_pat[8]={0,0,0,0,0,0,0,0};
@@ -70,8 +75,12 @@ static char map_fullbar_char(char ascii_val);
#endif
static char format_buffer[FORMAT_BUFFER_SIZE];
-static char* format_lines[MAX_LINES];
-static unsigned char line_type[MAX_LINES];
+static char* format_lines[MAX_LINES][MAX_SUBLINES];
+static unsigned char line_type[MAX_LINES][MAX_SUBLINES];
+static unsigned char time_mult[MAX_LINES][MAX_SUBLINES];
+static long subline_expire_time[MAX_LINES];
+static int curr_subline[MAX_LINES];
+
static int ff_rewind_count;
bool wps_time_countup = true;
static bool wps_loaded = false;
@@ -115,49 +124,76 @@ static void wps_format(char* fmt)
char* buf = format_buffer;
char* start_of_line = format_buffer;
int line = 0;
+ int subline;
strncpy(format_buffer, fmt, sizeof(format_buffer));
format_buffer[sizeof(format_buffer) - 1] = 0;
- format_lines[line] = buf;
+ for (line=0; line<MAX_LINES; line++)
+ {
+ for (subline=0; subline<MAX_SUBLINES; subline++)
+ {
+ format_lines[line][subline] = 0;
+ time_mult[line][subline] = 0;
+ }
+ subline_expire_time[line] = 0;
+ curr_subline[line] = SUBLINE_RESET;
+ }
+
+ line = 0;
+ subline = 0;
+ format_lines[line][subline] = buf;
+
while ((*buf) && (line < MAX_LINES))
{
switch (*buf)
{
- case '\r':
+ /* skip % sequences so "%;" doesn't start a new subline */
+ case '%':
+ buf++;
+ break;
+
+ case '\r': /* CR */
*buf = 0;
break;
case '\n': /* LF */
*buf = 0;
- if(*start_of_line != '#') /* A comment? */
+ if (*start_of_line != '#') /* A comment? */
line++;
if (line < MAX_LINES)
{
/* the next line starts on the next byte */
- format_lines[line] = buf+1;
- start_of_line = format_lines[line];
+ subline = 0;
+ format_lines[line][subline] = buf+1;
+ start_of_line = format_lines[line][subline];
}
break;
- }
- buf++;
- }
-
- /* if supplied input didn't define a format line
- for each line on the wps, set the rest to null */
- if (line < MAX_LINES)
- {
- /* if the final line didn't terminate with a newline,
- the line index wasn't incremented */
- if (buf != format_lines[line])
- line++;
- for (; line < MAX_LINES; line++)
- {
- format_lines[line] = NULL;
+ case ';': /* start a new subline */
+ *buf = 0;
+ subline++;
+ if (subline < MAX_SUBLINES)
+ {
+ format_lines[line][subline] = buf+1;
+ }
+ else /* exceeded max sublines, skip rest of line */
+ {
+ while (*(++buf))
+ {
+ if ((*buf == '\r') || (*buf == '\n'))
+ {
+ break;
+ }
+ }
+ buf--;
+ subline = 0;
+ }
+ break;
}
+ buf++;
}
}
@@ -169,6 +205,7 @@ void wps_reset(void)
bool wps_load(char* file, bool display)
{
+ int i, s;
char buffer[FORMAT_BUFFER_SIZE];
int fd;
@@ -187,17 +224,36 @@ bool wps_load(char* file, bool display)
close(fd);
if ( display ) {
- int i;
+ bool any_defined_line;
lcd_clear_display();
#ifdef HAVE_LCD_BITMAP
lcd_setmargins(0,0);
#endif
- for (i=0; i<MAX_LINES && format_lines[i]; i++)
- lcd_puts(0,i,format_lines[i]);
- lcd_update();
- sleep(HZ);
+ for (s=0; s<MAX_SUBLINES; s++)
+ {
+ any_defined_line = false;
+ for (i=0; i<MAX_LINES; i++)
+ {
+ if (format_lines[i][s])
+ {
+ if (*format_lines[i][s] == 0)
+ lcd_puts(0,i," ");
+ else
+ lcd_puts(0,i,format_lines[i][s]);
+ any_defined_line = true;
+ }
+ else
+ {
+ lcd_puts(0,i," ");
+ }
+ }
+ if (any_defined_line)
+ {
+ lcd_update();
+ sleep(HZ/2);
+ }
+ }
}
-
wps_loaded = true;
return numread > 0;
@@ -276,13 +332,18 @@ static char* get_tag(struct mp3entry* id3,
char* tag,
char* buf,
int buf_size,
+ unsigned char* tag_len,
+ unsigned char* subline_time_mult,
unsigned char* flags)
{
if ((0 == tag[0]) || (0 == tag[1]))
{
+ *tag_len = 0;
return NULL;
}
+ *tag_len = 2;
+
switch (tag[0])
{
case 'i': /* ID3 Information */
@@ -510,6 +571,46 @@ static char* get_tag(struct mp3entry* id3,
}
}
break;
+
+ case 't': /* set sub line time multiplier */
+ {
+ int d = 1;
+ int time_mult = 0;
+ bool have_point = false;
+ bool have_tenth = false;
+
+ while (((tag[d] >= '0') &&
+ (tag[d] <= '9')) ||
+ (tag[d] == '.'))
+ {
+ if (tag[d] != '.')
+ {
+ time_mult = time_mult * 10;
+ time_mult = time_mult + tag[d] - '0';
+ if (have_point)
+ {
+ have_tenth = true;
+ d++;
+ break;
+ }
+ }
+ else
+ {
+ have_point = true;
+ }
+ d++;
+ }
+
+ if (have_tenth == false)
+ time_mult *= 10;
+
+ *subline_time_mult = time_mult;
+ *tag_len = d;
+
+ buf[0] = 0;
+ return buf;
+ }
+ break;
}
return NULL;
@@ -594,13 +695,18 @@ static void format_display(char* buf,
int buf_size,
struct mp3entry* id3,
char* fmt,
+ unsigned char* subline_time_mult,
unsigned char* flags)
{
char temp_buf[128];
+ char* buf_start = buf;
char* buf_end = buf + buf_size - 1; /* Leave room for end null */
char* value = NULL;
int level = 0;
-
+ unsigned char tag_length;
+
+ *subline_time_mult = DEFAULT_SUBLINE_TIME_MULTIPLIER;
+
while (fmt && *fmt && buf < buf_end)
{
switch (*fmt)
@@ -639,12 +745,14 @@ static void format_display(char* buf,
case '|':
case '<':
case '>':
+ case ';':
*buf++ = *fmt++;
break;
case '?':
fmt++;
- value = get_tag(id3, fmt, temp_buf, sizeof(temp_buf), flags);
+ value = get_tag(id3, fmt, temp_buf, sizeof(temp_buf),
+ &tag_length, subline_time_mult, flags);
while (*fmt && ('<' != *fmt))
fmt++;
@@ -660,8 +768,9 @@ static void format_display(char* buf,
break;
default:
- value = get_tag(id3, fmt, temp_buf, sizeof(temp_buf), flags);
- fmt += 2;
+ value = get_tag(id3, fmt, temp_buf, sizeof(temp_buf),
+ &tag_length, subline_time_mult, flags);
+ fmt += tag_length;
if (value)
{
@@ -673,18 +782,27 @@ static void format_display(char* buf,
*buf = 0;
+ /* if resulting line is an empty line, set the subline time to 0 */
+ if (*buf_start == 0)
+ *subline_time_mult = 0;
+
/* If no flags have been set, the line didn't contain any format codes.
We still want to refresh it. */
if(*flags == 0)
*flags = WPS_REFRESH_STATIC;
}
-bool wps_refresh(struct mp3entry* id3, int ffwd_offset, unsigned char refresh_mode)
+bool wps_refresh(struct mp3entry* id3, int ffwd_offset,
+ unsigned char refresh_mode)
{
char buf[MAX_PATH];
unsigned char flags;
int i;
bool update_line;
+ bool only_one_subline;
+ bool new_subline_refresh;
+ int search;
+ int search_start;
#ifdef HAVE_LCD_BITMAP
int h = font_get(FONT_UI)->height;
int offset = global_settings.statusbar ? STATUSBAR_HEIGHT : 0;
@@ -697,6 +815,16 @@ bool wps_refresh(struct mp3entry* id3, int ffwd_offset, unsigned char refresh_mo
*/
bool enable_pm = false;
#endif
+
+ /* reset to first subline if refresh all flag is set */
+ if (refresh_mode == WPS_REFRESH_ALL)
+ {
+ for (i=0; i<MAX_LINES; i++)
+ {
+ curr_subline[i] = SUBLINE_RESET;
+ }
+ }
+
#ifdef HAVE_LCD_CHARCELLS
for (i=0; i<8; i++) {
if (wps_progress_pat[i]==0)
@@ -714,17 +842,79 @@ bool wps_refresh(struct mp3entry* id3, int ffwd_offset, unsigned char refresh_mo
for (i = 0; i < MAX_LINES; i++)
{
+ new_subline_refresh = false;
+ only_one_subline = false;
+
+ /* if time to advance to next sub-line */
+ if (TIME_AFTER(current_tick, subline_expire_time[i] - 1) ||
+ (curr_subline[i] == SUBLINE_RESET))
+ {
+ /* search all sublines until the next subline with time > 0
+ is found or we get back to the subline we started with */
+ if (curr_subline[i] == SUBLINE_RESET)
+ search_start = 0;
+ else
+ search_start = curr_subline[i];
+ for (search=0; search<MAX_SUBLINES; search++)
+ {
+ curr_subline[i]++;
+
+ /* wrap around if beyond last defined subline or MAX_SUBLINES */
+ if ((!format_lines[i][curr_subline[i]]) ||
+ (curr_subline[i] == MAX_SUBLINES))
+ {
+ if (curr_subline[i] == 1)
+ only_one_subline = true;
+ curr_subline[i] = 0;
+ }
+
+ /* if back where we started after search or
+ only one subline is defined on the line */
+ if (((search > 0) && (curr_subline[i] == search_start)) ||
+ only_one_subline)
+ {
+ /* no other subline with a time > 0 exists */
+ subline_expire_time[i] = current_tick + 100 * HZ;
+ break;
+ }
+ else
+ {
+ /* get initial time multiplier and
+ line type flags for this subline */
+ format_display(buf, sizeof(buf), id3,
+ format_lines[i][curr_subline[i]],
+ &time_mult[i][curr_subline[i]],
+ &line_type[i][curr_subline[i]]);
+
+ /* only use this subline if subline time > 0 */
+ if (time_mult[i][curr_subline[i]] > 0)
+ {
+ new_subline_refresh = true;
+ subline_expire_time[i] = current_tick +
+ BASE_SUBLINE_TIME * time_mult[i][curr_subline[i]];
+ break;
+ }
+ }
+ }
+
+ }
+
update_line = false;
- if ( !format_lines[i] )
+
+ if ( !format_lines[i][curr_subline[i]] )
break;
- if ((line_type[i] & refresh_mode) ||
- (refresh_mode == WPS_REFRESH_ALL))
+ if ((line_type[i][curr_subline[i]] & refresh_mode) ||
+ (refresh_mode == WPS_REFRESH_ALL) ||
+ new_subline_refresh)
{
flags = 0;
- format_display(buf, sizeof(buf), id3, format_lines[i], &flags);
- line_type[i] = flags;
-
+ format_display(buf, sizeof(buf), id3,
+ format_lines[i][curr_subline[i]],
+ &time_mult[i][curr_subline[i]],
+ &flags);
+ line_type[i][curr_subline[i]] = flags;
+
#ifdef HAVE_LCD_BITMAP
/* progress */
if (flags & refresh_mode & WPS_REFRESH_PLAYER_PROGRESS) {
@@ -764,19 +954,25 @@ bool wps_refresh(struct mp3entry* id3, int ffwd_offset, unsigned char refresh_mo
draw_player_progress(id3, ff_rewind_count);
}
#endif
+
if (flags & WPS_REFRESH_SCROLL) {
+
/* scroll line */
- if (refresh_mode & WPS_REFRESH_SCROLL) {
+ if ((refresh_mode & WPS_REFRESH_SCROLL) ||
+ new_subline_refresh) {
lcd_puts_scroll(0, i, buf);
update_line = true;
}
}
- /* dynamic / static line */
- else if ((flags & refresh_mode & WPS_REFRESH_DYNAMIC) ||
- (flags & refresh_mode & WPS_REFRESH_STATIC))
+ else if (flags & (WPS_REFRESH_DYNAMIC | WPS_REFRESH_STATIC))
{
- update_line = true;
- lcd_puts(0, i, buf);
+ /* dynamic / static line */
+ if ((refresh_mode & (WPS_REFRESH_DYNAMIC|WPS_REFRESH_STATIC)) ||
+ new_subline_refresh)
+ {
+ update_line = true;
+ lcd_puts(0, i, buf);
+ }
}
}
#ifdef HAVE_LCD_BITMAP
diff --git a/docs/CUSTOM_WPS_FORMAT b/docs/CUSTOM_WPS_FORMAT
index 9a11c398cd..11d53859a8 100644
--- a/docs/CUSTOM_WPS_FORMAT
+++ b/docs/CUSTOM_WPS_FORMAT
@@ -76,11 +76,64 @@ Conditional Tags (If/Else block):
so the text in the if and else part can contain all %
commands, including conditionals.
+Alternating Sublines
+--------------------
+It is possible to group items on each line into 2 or more groups or "sublines".
+Each subline will be displayed in succession on the line for a specified time,
+alternating continuously through each defined subline.
+
+Items on a line are broken into sublines with the semicolon ';' character. The
+display time for each subline defaults to 2 seconds unless modified by using
+the '%t' tag to specify an alternate time (in seconds and optional tenths of a
+second) for the subline to be displayed.
+
+Subline related special characters and tags:
+ ; : Split items on a line into separate sublines
+ %t : Set the subline display time. The '%t' is followed by either integer
+ seconds (%t5), or seconds and tenths of a second (%t3.5).
+
+
+Each alternating subline can still be optionally scrolled while it is being
+displayed, and scrollable formats can be displayed on the same line with
+non-scrollable formats (such as track elapsed time) as long as they are
+separated into different sublines.
+
+ Example subline definition:
+
+ %s%t4%ia;%s%it;%t3%pc %pr : Display id3 artist for 4 seconds,
+ Display id3 title for 2 seconds,
+ Display current and remaining track time
+ for 3 seconds,
+ repeat...
+
+Conditionals can be used with sublines to display a different set and/or number
+of sublines on the line depending on the evaluation of the conditional.
+
+ Example subline with conditionals:
+
+ %?it<%t8%s%it|%s%fn>;%?ia<%t3%s%ia|%t0>
+
+ The format above will do two different things depending if ID3
+ tags are present. If the ID3 artist and title are present :
+
+ Display id3 title for 8 seconds,
+ Display id3 artist for 3 seconds,
+ repeat...
+
+ If the ID3 artist and title are not present :
+ Display the filename continuously.
+
+Note that by using a subline display time of 0 in one branch of a conditional,
+a subline can be skipped (not displayed) when that condition is met.
+
+-----------
+
Other Tags:
%% : Display a '%'
%< : Display a '<'
%| : Display a '|'
%> : Display a '>'
+ %; : Display a ';'
%s : Indicate that the line should scroll. Can occur anywhere in
a line (given that the text is displayed; see conditionals
above). You can specify up to 10 scrolling lines.