diff options
author | Daniel Stenberg <daniel@haxx.se> | 2004-01-14 07:59:06 +0000 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2004-01-14 07:59:06 +0000 |
commit | d2b625f818e8e04ace3c7532fe9c38eb0c0b1662 (patch) | |
tree | b835c1d3a3e03581361528dc818c8e4219c40fb8 /apps | |
parent | e99f3b2b13d63361e348a70ea8b19488f617ca3f (diff) | |
download | rockbox-d2b625f818e8e04ace3c7532fe9c38eb0c0b1662.tar.gz rockbox-d2b625f818e8e04ace3c7532fe9c38eb0c0b1662.zip |
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
Diffstat (limited to 'apps')
-rw-r--r-- | apps/wps-display.c | 290 |
1 files changed, 243 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 @@ | |||
54 | 54 | ||
55 | #ifdef HAVE_LCD_BITMAP | 55 | #ifdef HAVE_LCD_BITMAP |
56 | #define MAX_LINES 10 | 56 | #define MAX_LINES 10 |
57 | #define FORMAT_BUFFER_SIZE 800 | ||
57 | #else | 58 | #else |
58 | #define MAX_LINES 2 | 59 | #define MAX_LINES 2 |
60 | #define FORMAT_BUFFER_SIZE 400 | ||
59 | #endif | 61 | #endif |
60 | 62 | #define MAX_SUBLINES 12 | |
61 | #define FORMAT_BUFFER_SIZE 300 | 63 | #define DEFAULT_SUBLINE_TIME_MULTIPLIER 20 /* (10ths of sec) */ |
64 | #define BASE_SUBLINE_TIME 10 /* base time that multiplier is applied to | ||
65 | (1/HZ sec, or 100ths of sec) */ | ||
66 | #define SUBLINE_RESET -1 | ||
62 | 67 | ||
63 | #ifdef HAVE_LCD_CHARCELLS | 68 | #ifdef HAVE_LCD_CHARCELLS |
64 | static unsigned char wps_progress_pat[8]={0,0,0,0,0,0,0,0}; | 69 | 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); | |||
70 | #endif | 75 | #endif |
71 | 76 | ||
72 | static char format_buffer[FORMAT_BUFFER_SIZE]; | 77 | static char format_buffer[FORMAT_BUFFER_SIZE]; |
73 | static char* format_lines[MAX_LINES]; | 78 | static char* format_lines[MAX_LINES][MAX_SUBLINES]; |
74 | static unsigned char line_type[MAX_LINES]; | 79 | static unsigned char line_type[MAX_LINES][MAX_SUBLINES]; |
80 | static unsigned char time_mult[MAX_LINES][MAX_SUBLINES]; | ||
81 | static long subline_expire_time[MAX_LINES]; | ||
82 | static int curr_subline[MAX_LINES]; | ||
83 | |||
75 | static int ff_rewind_count; | 84 | static int ff_rewind_count; |
76 | bool wps_time_countup = true; | 85 | bool wps_time_countup = true; |
77 | static bool wps_loaded = false; | 86 | static bool wps_loaded = false; |
@@ -115,49 +124,76 @@ static void wps_format(char* fmt) | |||
115 | char* buf = format_buffer; | 124 | char* buf = format_buffer; |
116 | char* start_of_line = format_buffer; | 125 | char* start_of_line = format_buffer; |
117 | int line = 0; | 126 | int line = 0; |
127 | int subline; | ||
118 | 128 | ||
119 | strncpy(format_buffer, fmt, sizeof(format_buffer)); | 129 | strncpy(format_buffer, fmt, sizeof(format_buffer)); |
120 | format_buffer[sizeof(format_buffer) - 1] = 0; | 130 | format_buffer[sizeof(format_buffer) - 1] = 0; |
121 | format_lines[line] = buf; | ||
122 | 131 | ||
132 | for (line=0; line<MAX_LINES; line++) | ||
133 | { | ||
134 | for (subline=0; subline<MAX_SUBLINES; subline++) | ||
135 | { | ||
136 | format_lines[line][subline] = 0; | ||
137 | time_mult[line][subline] = 0; | ||
138 | } | ||
139 | subline_expire_time[line] = 0; | ||
140 | curr_subline[line] = SUBLINE_RESET; | ||
141 | } | ||
142 | |||
143 | line = 0; | ||
144 | subline = 0; | ||
145 | format_lines[line][subline] = buf; | ||
146 | |||
123 | while ((*buf) && (line < MAX_LINES)) | 147 | while ((*buf) && (line < MAX_LINES)) |
124 | { | 148 | { |
125 | switch (*buf) | 149 | switch (*buf) |
126 | { | 150 | { |
127 | case '\r': | 151 | /* skip % sequences so "%;" doesn't start a new subline */ |
152 | case '%': | ||
153 | buf++; | ||
154 | break; | ||
155 | |||
156 | case '\r': /* CR */ | ||
128 | *buf = 0; | 157 | *buf = 0; |
129 | break; | 158 | break; |
130 | 159 | ||
131 | case '\n': /* LF */ | 160 | case '\n': /* LF */ |
132 | *buf = 0; | 161 | *buf = 0; |
133 | 162 | ||
134 | if(*start_of_line != '#') /* A comment? */ | 163 | if (*start_of_line != '#') /* A comment? */ |
135 | line++; | 164 | line++; |
136 | 165 | ||
137 | if (line < MAX_LINES) | 166 | if (line < MAX_LINES) |
138 | { | 167 | { |
139 | /* the next line starts on the next byte */ | 168 | /* the next line starts on the next byte */ |
140 | format_lines[line] = buf+1; | 169 | subline = 0; |
141 | start_of_line = format_lines[line]; | 170 | format_lines[line][subline] = buf+1; |
171 | start_of_line = format_lines[line][subline]; | ||
142 | } | 172 | } |
143 | break; | 173 | break; |
144 | } | ||
145 | buf++; | ||
146 | } | ||
147 | |||
148 | /* if supplied input didn't define a format line | ||
149 | for each line on the wps, set the rest to null */ | ||
150 | if (line < MAX_LINES) | ||
151 | { | ||
152 | /* if the final line didn't terminate with a newline, | ||
153 | the line index wasn't incremented */ | ||
154 | if (buf != format_lines[line]) | ||
155 | line++; | ||
156 | 174 | ||
157 | for (; line < MAX_LINES; line++) | 175 | case ';': /* start a new subline */ |
158 | { | 176 | *buf = 0; |
159 | format_lines[line] = NULL; | 177 | subline++; |
178 | if (subline < MAX_SUBLINES) | ||
179 | { | ||
180 | format_lines[line][subline] = buf+1; | ||
181 | } | ||
182 | else /* exceeded max sublines, skip rest of line */ | ||
183 | { | ||
184 | while (*(++buf)) | ||
185 | { | ||
186 | if ((*buf == '\r') || (*buf == '\n')) | ||
187 | { | ||
188 | break; | ||
189 | } | ||
190 | } | ||
191 | buf--; | ||
192 | subline = 0; | ||
193 | } | ||
194 | break; | ||
160 | } | 195 | } |
196 | buf++; | ||
161 | } | 197 | } |
162 | } | 198 | } |
163 | 199 | ||
@@ -169,6 +205,7 @@ void wps_reset(void) | |||
169 | 205 | ||
170 | bool wps_load(char* file, bool display) | 206 | bool wps_load(char* file, bool display) |
171 | { | 207 | { |
208 | int i, s; | ||
172 | char buffer[FORMAT_BUFFER_SIZE]; | 209 | char buffer[FORMAT_BUFFER_SIZE]; |
173 | int fd; | 210 | int fd; |
174 | 211 | ||
@@ -187,17 +224,36 @@ bool wps_load(char* file, bool display) | |||
187 | close(fd); | 224 | close(fd); |
188 | 225 | ||
189 | if ( display ) { | 226 | if ( display ) { |
190 | int i; | 227 | bool any_defined_line; |
191 | lcd_clear_display(); | 228 | lcd_clear_display(); |
192 | #ifdef HAVE_LCD_BITMAP | 229 | #ifdef HAVE_LCD_BITMAP |
193 | lcd_setmargins(0,0); | 230 | lcd_setmargins(0,0); |
194 | #endif | 231 | #endif |
195 | for (i=0; i<MAX_LINES && format_lines[i]; i++) | 232 | for (s=0; s<MAX_SUBLINES; s++) |
196 | lcd_puts(0,i,format_lines[i]); | 233 | { |
197 | lcd_update(); | 234 | any_defined_line = false; |
198 | sleep(HZ); | 235 | for (i=0; i<MAX_LINES; i++) |
236 | { | ||
237 | if (format_lines[i][s]) | ||
238 | { | ||
239 | if (*format_lines[i][s] == 0) | ||
240 | lcd_puts(0,i," "); | ||
241 | else | ||
242 | lcd_puts(0,i,format_lines[i][s]); | ||
243 | any_defined_line = true; | ||
244 | } | ||
245 | else | ||
246 | { | ||
247 | lcd_puts(0,i," "); | ||
248 | } | ||
249 | } | ||
250 | if (any_defined_line) | ||
251 | { | ||
252 | lcd_update(); | ||
253 | sleep(HZ/2); | ||
254 | } | ||
255 | } | ||
199 | } | 256 | } |
200 | |||
201 | wps_loaded = true; | 257 | wps_loaded = true; |
202 | 258 | ||
203 | return numread > 0; | 259 | return numread > 0; |
@@ -276,13 +332,18 @@ static char* get_tag(struct mp3entry* id3, | |||
276 | char* tag, | 332 | char* tag, |
277 | char* buf, | 333 | char* buf, |
278 | int buf_size, | 334 | int buf_size, |
335 | unsigned char* tag_len, | ||
336 | unsigned char* subline_time_mult, | ||
279 | unsigned char* flags) | 337 | unsigned char* flags) |
280 | { | 338 | { |
281 | if ((0 == tag[0]) || (0 == tag[1])) | 339 | if ((0 == tag[0]) || (0 == tag[1])) |
282 | { | 340 | { |
341 | *tag_len = 0; | ||
283 | return NULL; | 342 | return NULL; |
284 | } | 343 | } |
285 | 344 | ||
345 | *tag_len = 2; | ||
346 | |||
286 | switch (tag[0]) | 347 | switch (tag[0]) |
287 | { | 348 | { |
288 | case 'i': /* ID3 Information */ | 349 | case 'i': /* ID3 Information */ |
@@ -510,6 +571,46 @@ static char* get_tag(struct mp3entry* id3, | |||
510 | } | 571 | } |
511 | } | 572 | } |
512 | break; | 573 | break; |
574 | |||
575 | case 't': /* set sub line time multiplier */ | ||
576 | { | ||
577 | int d = 1; | ||
578 | int time_mult = 0; | ||
579 | bool have_point = false; | ||
580 | bool have_tenth = false; | ||
581 | |||
582 | while (((tag[d] >= '0') && | ||
583 | (tag[d] <= '9')) || | ||
584 | (tag[d] == '.')) | ||
585 | { | ||
586 | if (tag[d] != '.') | ||
587 | { | ||
588 | time_mult = time_mult * 10; | ||
589 | time_mult = time_mult + tag[d] - '0'; | ||
590 | if (have_point) | ||
591 | { | ||
592 | have_tenth = true; | ||
593 | d++; | ||
594 | break; | ||
595 | } | ||
596 | } | ||
597 | else | ||
598 | { | ||
599 | have_point = true; | ||
600 | } | ||
601 | d++; | ||
602 | } | ||
603 | |||
604 | if (have_tenth == false) | ||
605 | time_mult *= 10; | ||
606 | |||
607 | *subline_time_mult = time_mult; | ||
608 | *tag_len = d; | ||
609 | |||
610 | buf[0] = 0; | ||
611 | return buf; | ||
612 | } | ||
613 | break; | ||
513 | } | 614 | } |
514 | 615 | ||
515 | return NULL; | 616 | return NULL; |
@@ -594,13 +695,18 @@ static void format_display(char* buf, | |||
594 | int buf_size, | 695 | int buf_size, |
595 | struct mp3entry* id3, | 696 | struct mp3entry* id3, |
596 | char* fmt, | 697 | char* fmt, |
698 | unsigned char* subline_time_mult, | ||
597 | unsigned char* flags) | 699 | unsigned char* flags) |
598 | { | 700 | { |
599 | char temp_buf[128]; | 701 | char temp_buf[128]; |
702 | char* buf_start = buf; | ||
600 | char* buf_end = buf + buf_size - 1; /* Leave room for end null */ | 703 | char* buf_end = buf + buf_size - 1; /* Leave room for end null */ |
601 | char* value = NULL; | 704 | char* value = NULL; |
602 | int level = 0; | 705 | int level = 0; |
603 | 706 | unsigned char tag_length; | |
707 | |||
708 | *subline_time_mult = DEFAULT_SUBLINE_TIME_MULTIPLIER; | ||
709 | |||
604 | while (fmt && *fmt && buf < buf_end) | 710 | while (fmt && *fmt && buf < buf_end) |
605 | { | 711 | { |
606 | switch (*fmt) | 712 | switch (*fmt) |
@@ -639,12 +745,14 @@ static void format_display(char* buf, | |||
639 | case '|': | 745 | case '|': |
640 | case '<': | 746 | case '<': |
641 | case '>': | 747 | case '>': |
748 | case ';': | ||
642 | *buf++ = *fmt++; | 749 | *buf++ = *fmt++; |
643 | break; | 750 | break; |
644 | 751 | ||
645 | case '?': | 752 | case '?': |
646 | fmt++; | 753 | fmt++; |
647 | value = get_tag(id3, fmt, temp_buf, sizeof(temp_buf), flags); | 754 | value = get_tag(id3, fmt, temp_buf, sizeof(temp_buf), |
755 | &tag_length, subline_time_mult, flags); | ||
648 | 756 | ||
649 | while (*fmt && ('<' != *fmt)) | 757 | while (*fmt && ('<' != *fmt)) |
650 | fmt++; | 758 | fmt++; |
@@ -660,8 +768,9 @@ static void format_display(char* buf, | |||
660 | break; | 768 | break; |
661 | 769 | ||
662 | default: | 770 | default: |
663 | value = get_tag(id3, fmt, temp_buf, sizeof(temp_buf), flags); | 771 | value = get_tag(id3, fmt, temp_buf, sizeof(temp_buf), |
664 | fmt += 2; | 772 | &tag_length, subline_time_mult, flags); |
773 | fmt += tag_length; | ||
665 | 774 | ||
666 | if (value) | 775 | if (value) |
667 | { | 776 | { |
@@ -673,18 +782,27 @@ static void format_display(char* buf, | |||
673 | 782 | ||
674 | *buf = 0; | 783 | *buf = 0; |
675 | 784 | ||
785 | /* if resulting line is an empty line, set the subline time to 0 */ | ||
786 | if (*buf_start == 0) | ||
787 | *subline_time_mult = 0; | ||
788 | |||
676 | /* If no flags have been set, the line didn't contain any format codes. | 789 | /* If no flags have been set, the line didn't contain any format codes. |
677 | We still want to refresh it. */ | 790 | We still want to refresh it. */ |
678 | if(*flags == 0) | 791 | if(*flags == 0) |
679 | *flags = WPS_REFRESH_STATIC; | 792 | *flags = WPS_REFRESH_STATIC; |
680 | } | 793 | } |
681 | 794 | ||
682 | bool wps_refresh(struct mp3entry* id3, int ffwd_offset, unsigned char refresh_mode) | 795 | bool wps_refresh(struct mp3entry* id3, int ffwd_offset, |
796 | unsigned char refresh_mode) | ||
683 | { | 797 | { |
684 | char buf[MAX_PATH]; | 798 | char buf[MAX_PATH]; |
685 | unsigned char flags; | 799 | unsigned char flags; |
686 | int i; | 800 | int i; |
687 | bool update_line; | 801 | bool update_line; |
802 | bool only_one_subline; | ||
803 | bool new_subline_refresh; | ||
804 | int search; | ||
805 | int search_start; | ||
688 | #ifdef HAVE_LCD_BITMAP | 806 | #ifdef HAVE_LCD_BITMAP |
689 | int h = font_get(FONT_UI)->height; | 807 | int h = font_get(FONT_UI)->height; |
690 | int offset = global_settings.statusbar ? STATUSBAR_HEIGHT : 0; | 808 | 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 | |||
697 | */ | 815 | */ |
698 | bool enable_pm = false; | 816 | bool enable_pm = false; |
699 | #endif | 817 | #endif |
818 | |||
819 | /* reset to first subline if refresh all flag is set */ | ||
820 | if (refresh_mode == WPS_REFRESH_ALL) | ||
821 | { | ||
822 | for (i=0; i<MAX_LINES; i++) | ||
823 | { | ||
824 | curr_subline[i] = SUBLINE_RESET; | ||
825 | } | ||
826 | } | ||
827 | |||
700 | #ifdef HAVE_LCD_CHARCELLS | 828 | #ifdef HAVE_LCD_CHARCELLS |
701 | for (i=0; i<8; i++) { | 829 | for (i=0; i<8; i++) { |
702 | if (wps_progress_pat[i]==0) | 830 | if (wps_progress_pat[i]==0) |
@@ -714,17 +842,79 @@ bool wps_refresh(struct mp3entry* id3, int ffwd_offset, unsigned char refresh_mo | |||
714 | 842 | ||
715 | for (i = 0; i < MAX_LINES; i++) | 843 | for (i = 0; i < MAX_LINES; i++) |
716 | { | 844 | { |
845 | new_subline_refresh = false; | ||
846 | only_one_subline = false; | ||
847 | |||
848 | /* if time to advance to next sub-line */ | ||
849 | if (TIME_AFTER(current_tick, subline_expire_time[i] - 1) || | ||
850 | (curr_subline[i] == SUBLINE_RESET)) | ||
851 | { | ||
852 | /* search all sublines until the next subline with time > 0 | ||
853 | is found or we get back to the subline we started with */ | ||
854 | if (curr_subline[i] == SUBLINE_RESET) | ||
855 | search_start = 0; | ||
856 | else | ||
857 | search_start = curr_subline[i]; | ||
858 | for (search=0; search<MAX_SUBLINES; search++) | ||
859 | { | ||
860 | curr_subline[i]++; | ||
861 | |||
862 | /* wrap around if beyond last defined subline or MAX_SUBLINES */ | ||
863 | if ((!format_lines[i][curr_subline[i]]) || | ||
864 | (curr_subline[i] == MAX_SUBLINES)) | ||
865 | { | ||
866 | if (curr_subline[i] == 1) | ||
867 | only_one_subline = true; | ||
868 | curr_subline[i] = 0; | ||
869 | } | ||
870 | |||
871 | /* if back where we started after search or | ||
872 | only one subline is defined on the line */ | ||
873 | if (((search > 0) && (curr_subline[i] == search_start)) || | ||
874 | only_one_subline) | ||
875 | { | ||
876 | /* no other subline with a time > 0 exists */ | ||
877 | subline_expire_time[i] = current_tick + 100 * HZ; | ||
878 | break; | ||
879 | } | ||
880 | else | ||
881 | { | ||
882 | /* get initial time multiplier and | ||
883 | line type flags for this subline */ | ||
884 | format_display(buf, sizeof(buf), id3, | ||
885 | format_lines[i][curr_subline[i]], | ||
886 | &time_mult[i][curr_subline[i]], | ||
887 | &line_type[i][curr_subline[i]]); | ||
888 | |||
889 | /* only use this subline if subline time > 0 */ | ||
890 | if (time_mult[i][curr_subline[i]] > 0) | ||
891 | { | ||
892 | new_subline_refresh = true; | ||
893 | subline_expire_time[i] = current_tick + | ||
894 | BASE_SUBLINE_TIME * time_mult[i][curr_subline[i]]; | ||
895 | break; | ||
896 | } | ||
897 | } | ||
898 | } | ||
899 | |||
900 | } | ||
901 | |||
717 | update_line = false; | 902 | update_line = false; |
718 | if ( !format_lines[i] ) | 903 | |
904 | if ( !format_lines[i][curr_subline[i]] ) | ||
719 | break; | 905 | break; |
720 | 906 | ||
721 | if ((line_type[i] & refresh_mode) || | 907 | if ((line_type[i][curr_subline[i]] & refresh_mode) || |
722 | (refresh_mode == WPS_REFRESH_ALL)) | 908 | (refresh_mode == WPS_REFRESH_ALL) || |
909 | new_subline_refresh) | ||
723 | { | 910 | { |
724 | flags = 0; | 911 | flags = 0; |
725 | format_display(buf, sizeof(buf), id3, format_lines[i], &flags); | 912 | format_display(buf, sizeof(buf), id3, |
726 | line_type[i] = flags; | 913 | format_lines[i][curr_subline[i]], |
727 | 914 | &time_mult[i][curr_subline[i]], | |
915 | &flags); | ||
916 | line_type[i][curr_subline[i]] = flags; | ||
917 | |||
728 | #ifdef HAVE_LCD_BITMAP | 918 | #ifdef HAVE_LCD_BITMAP |
729 | /* progress */ | 919 | /* progress */ |
730 | if (flags & refresh_mode & WPS_REFRESH_PLAYER_PROGRESS) { | 920 | 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 | |||
764 | draw_player_progress(id3, ff_rewind_count); | 954 | draw_player_progress(id3, ff_rewind_count); |
765 | } | 955 | } |
766 | #endif | 956 | #endif |
957 | |||
767 | if (flags & WPS_REFRESH_SCROLL) { | 958 | if (flags & WPS_REFRESH_SCROLL) { |
959 | |||
768 | /* scroll line */ | 960 | /* scroll line */ |
769 | if (refresh_mode & WPS_REFRESH_SCROLL) { | 961 | if ((refresh_mode & WPS_REFRESH_SCROLL) || |
962 | new_subline_refresh) { | ||
770 | lcd_puts_scroll(0, i, buf); | 963 | lcd_puts_scroll(0, i, buf); |
771 | update_line = true; | 964 | update_line = true; |
772 | } | 965 | } |
773 | } | 966 | } |
774 | /* dynamic / static line */ | 967 | else if (flags & (WPS_REFRESH_DYNAMIC | WPS_REFRESH_STATIC)) |
775 | else if ((flags & refresh_mode & WPS_REFRESH_DYNAMIC) || | ||
776 | (flags & refresh_mode & WPS_REFRESH_STATIC)) | ||
777 | { | 968 | { |
778 | update_line = true; | 969 | /* dynamic / static line */ |
779 | lcd_puts(0, i, buf); | 970 | if ((refresh_mode & (WPS_REFRESH_DYNAMIC|WPS_REFRESH_STATIC)) || |
971 | new_subline_refresh) | ||
972 | { | ||
973 | update_line = true; | ||
974 | lcd_puts(0, i, buf); | ||
975 | } | ||
780 | } | 976 | } |
781 | } | 977 | } |
782 | #ifdef HAVE_LCD_BITMAP | 978 | #ifdef HAVE_LCD_BITMAP |