summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2002-09-01 19:50:45 +0000
committerBjörn Stenberg <bjorn@haxx.se>2002-09-01 19:50:45 +0000
commit26964fd95760ed0a5c9db94f9ba60a843a094c36 (patch)
tree6eb171ae19b087e29686815a130d06693ebc8a1b
parent862f479becd57735cc8c1fb8c9af46ace37adcbe (diff)
downloadrockbox-26964fd95760ed0a5c9db94f9ba60a843a094c36.tar.gz
rockbox-26964fd95760ed0a5c9db94f9ba60a843a094c36.zip
Merged Magnus Holmgren's wps.config code.
Moved wps.config from root to /.rockbox dir. Removed WPS display setting. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2111 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/settings.c13
-rw-r--r--apps/settings.h6
-rw-r--r--apps/settings_menu.c14
-rw-r--r--apps/status.c14
-rw-r--r--apps/wps-display.c852
-rw-r--r--apps/wps.c2
6 files changed, 463 insertions, 438 deletions
diff --git a/apps/settings.c b/apps/settings.c
index 2926b6a175..6ca733cf37 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -42,7 +42,7 @@
42#endif 42#endif
43 43
44struct user_settings global_settings; 44struct user_settings global_settings;
45char rockboxdir[] = "/.rockbox/"; /* config/font/data file directory */ 45char rockboxdir[] = ROCKBOX_DIR; /* config/font/data file directory */
46 46
47#define CONFIG_BLOCK_VERSION 1 47#define CONFIG_BLOCK_VERSION 1
48#define CONFIG_BLOCK_SIZE 512 48#define CONFIG_BLOCK_SIZE 512
@@ -67,7 +67,7 @@ offset abs
670x0c 0x20 <poweroff timer byte> 670x0c 0x20 <poweroff timer byte>
680x0d 0x21 <resume settings byte> 680x0d 0x21 <resume settings byte>
690x0e 0x22 <shuffle,mp3filter,sort_case,discharge,statusbar,show_hidden> 690x0e 0x22 <shuffle,mp3filter,sort_case,discharge,statusbar,show_hidden>
700x0f 0x23 <scroll speed & WPS display byte> 700x0f 0x23 <scroll speed>
710x10 0x24 <ff/rewind accleration rate> 710x10 0x24 <ff/rewind accleration rate>
720x11 0x25 <AVC byte> 720x11 0x25 <AVC byte>
730x12 0x26 <(int) Resume playlist index, or -1 if no playlist resume> 730x12 0x26 <(int) Resume playlist index, or -1 if no playlist resume>
@@ -267,9 +267,7 @@ int settings_save( void )
267 ((global_settings.show_hidden_files & 1) << 5) | 267 ((global_settings.show_hidden_files & 1) << 5) |
268 ((global_settings.scrollbar & 1) << 6)); 268 ((global_settings.scrollbar & 1) << 6));
269 269
270 config_block[0xf] = (unsigned char) 270 config_block[0xf] = (unsigned char)(global_settings.scroll_speed << 3);
271 ((global_settings.scroll_speed << 3) |
272 (global_settings.wps_display & 7));
273 271
274 config_block[0x10] = (unsigned char)global_settings.ff_rewind_accel; 272 config_block[0x10] = (unsigned char)global_settings.ff_rewind_accel;
275 config_block[0x11] = (unsigned char)global_settings.avc; 273 config_block[0x11] = (unsigned char)global_settings.avc;
@@ -360,10 +358,6 @@ void settings_load(void)
360 if (c != 31) 358 if (c != 31)
361 global_settings.scroll_speed = c; 359 global_settings.scroll_speed = c;
362 360
363 c = config_block[0xf] & 7;
364 if (c != 7)
365 global_settings.wps_display = c;
366
367 if (config_block[0x10] != 0xFF) 361 if (config_block[0x10] != 0xFF)
368 global_settings.ff_rewind_accel = config_block[0x10]; 362 global_settings.ff_rewind_accel = config_block[0x10];
369 363
@@ -414,7 +408,6 @@ void settings_reset(void) {
414 global_settings.contrast = DEFAULT_CONTRAST_SETTING; 408 global_settings.contrast = DEFAULT_CONTRAST_SETTING;
415 global_settings.poweroff = DEFAULT_POWEROFF_SETTING; 409 global_settings.poweroff = DEFAULT_POWEROFF_SETTING;
416 global_settings.backlight = DEFAULT_BACKLIGHT_SETTING; 410 global_settings.backlight = DEFAULT_BACKLIGHT_SETTING;
417 global_settings.wps_display = DEFAULT_WPS_DISPLAY;
418 global_settings.mp3filter = true; 411 global_settings.mp3filter = true;
419 global_settings.sort_case = false; 412 global_settings.sort_case = false;
420 global_settings.statusbar = true; 413 global_settings.statusbar = true;
diff --git a/apps/settings.h b/apps/settings.h
index b17643b982..3971d41b7b 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -23,6 +23,8 @@
23#include <stdbool.h> 23#include <stdbool.h>
24#include "file.h" 24#include "file.h"
25 25
26#define ROCKBOX_DIR "/.rockbox"
27
26/* data structures */ 28/* data structures */
27 29
28#define RESUME_OFF 0 30#define RESUME_OFF 0
@@ -66,9 +68,6 @@ struct user_settings
66 int ff_rewind_accel; /* FF/Rewind acceleration (in seconds per doubling) */ 68 int ff_rewind_accel; /* FF/Rewind acceleration (in seconds per doubling) */
67 int disk_spindown; /* time until disk spindown, in seconds (0=off) */ 69 int disk_spindown; /* time until disk spindown, in seconds (0=off) */
68 70
69 /* while playing screen settings */
70 int wps_display; /* 0=id3, 1=file, 2=parse */
71
72 /* show status bar */ 71 /* show status bar */
73 bool statusbar; /* 0=hide, 1=show */ 72 bool statusbar; /* 0=hide, 1=show */
74 73
@@ -119,7 +118,6 @@ extern char rockboxdir[];
119#define MIN_CONTRAST_SETTING 5 118#define MIN_CONTRAST_SETTING 5
120#define DEFAULT_POWEROFF_SETTING 0 119#define DEFAULT_POWEROFF_SETTING 0
121#define DEFAULT_BACKLIGHT_SETTING 5 120#define DEFAULT_BACKLIGHT_SETTING 5
122#define DEFAULT_WPS_DISPLAY 0
123#define DEFAULT_FF_REWIND_ACCEL_SETTING 3 121#define DEFAULT_FF_REWIND_ACCEL_SETTING 3
124 122
125#endif /* __SETTINGS_H__ */ 123#endif /* __SETTINGS_H__ */
diff --git a/apps/settings_menu.c b/apps/settings_menu.c
index 22468b642e..eeb6af8e71 100644
--- a/apps/settings_menu.c
+++ b/apps/settings_menu.c
@@ -94,19 +94,6 @@ static Menu scroll_speed(void)
94 return MENU_OK; 94 return MENU_OK;
95} 95}
96 96
97static Menu wps_set(void)
98{
99#ifdef HAVE_LCD_BITMAP
100 char* names[] = { "ID3 Tags ", "Filename ", "Dir Parse ", "Custom WPS " };
101 set_option("[WPS display]", &global_settings.wps_display, names, 4 );
102#else
103 char* names[] = { "1 Line ID3 ", "1 Line ID3+", "2 Line ID3 ", "Filename ",
104 "Dir Parse ", "Custom WPS " };
105 set_option("[WPS display]", &global_settings.wps_display, names, 6 );
106#endif
107 return MENU_OK;
108}
109
110#ifdef HAVE_CHARGE_CTRL 97#ifdef HAVE_CHARGE_CTRL
111static Menu deep_discharge(void) 98static Menu deep_discharge(void)
112{ 99{
@@ -188,7 +175,6 @@ Menu settings_menu(void)
188 { "Backlight Timer", backlight_timer }, 175 { "Backlight Timer", backlight_timer },
189 { "Contrast", contrast }, 176 { "Contrast", contrast },
190 { "Scroll speed", scroll_speed }, 177 { "Scroll speed", scroll_speed },
191 { "While Playing", wps_set },
192#ifdef HAVE_CHARGE_CTRL 178#ifdef HAVE_CHARGE_CTRL
193 { "Deep discharge", deep_discharge }, 179 { "Deep discharge", deep_discharge },
194#endif 180#endif
diff --git a/apps/status.c b/apps/status.c
index 47d01e30dd..fe4762e3ea 100644
--- a/apps/status.c
+++ b/apps/status.c
@@ -36,7 +36,6 @@
36static enum playmode current_mode = STATUS_STOP; 36static enum playmode current_mode = STATUS_STOP;
37 37
38#ifdef HAVE_LCD_BITMAP 38#ifdef HAVE_LCD_BITMAP
39bool statusbar_enabled = true;
40long switch_tick; 39long switch_tick;
41bool plug_state; 40bool plug_state;
42bool battery_state; 41bool battery_state;
@@ -54,17 +53,6 @@ void status_set_playmode(enum playmode mode)
54 status_draw(); 53 status_draw();
55} 54}
56 55
57#ifdef HAVE_LCD_BITMAP
58bool statusbar(bool state)
59{
60 bool laststate = statusbar_enabled;
61
62 statusbar_enabled = state;
63
64 return(laststate);
65}
66#endif
67
68void status_draw(void) 56void status_draw(void)
69{ 57{
70 int battlevel = battery_level(); 58 int battlevel = battery_level();
@@ -133,7 +121,7 @@ void status_draw(void)
133 } 121 }
134#endif 122#endif
135#ifdef HAVE_LCD_BITMAP 123#ifdef HAVE_LCD_BITMAP
136 if(global_settings.statusbar && statusbar_enabled) { 124 if (global_settings.statusbar) {
137 statusbar_wipe(); 125 statusbar_wipe();
138#ifdef HAVE_CHARGE_CTRL 126#ifdef HAVE_CHARGE_CTRL
139 if(charger_inserted()) { 127 if(charger_inserted()) {
diff --git a/apps/wps-display.c b/apps/wps-display.c
index a09efb08eb..0f27570e23 100644
--- a/apps/wps-display.c
+++ b/apps/wps-display.c
@@ -16,6 +16,12 @@
16 * KIND, either express or implied. 16 * KIND, either express or implied.
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19
20/* ID3 formatting based on code from the MAD Winamp plugin (in_mad.dll),
21 * Copyright (C) 2000-2001 Robert Leslie.
22 * See http://www.mars.org/home/rob/proj/mpeg/ for more information.
23 */
24
19#include <stdio.h> 25#include <stdio.h>
20#include <string.h> 26#include <string.h>
21#include <stdlib.h> 27#include <stdlib.h>
@@ -26,8 +32,10 @@
26#include "settings.h" 32#include "settings.h"
27#include "playlist.h" 33#include "playlist.h"
28#include "kernel.h" 34#include "kernel.h"
35#include "system.h"
29#include "status.h" 36#include "status.h"
30#include "wps-display.h" 37#include "wps-display.h"
38#include "debug.h"
31 39
32#ifdef HAVE_LCD_BITMAP 40#ifdef HAVE_LCD_BITMAP
33#include "icons.h" 41#include "icons.h"
@@ -38,321 +46,454 @@
38#include "ajf.h" 46#include "ajf.h"
39#endif 47#endif
40 48
41#define WPS_CONFIG "/wps.config" 49#define WPS_CONFIG ROCKBOX_DIR "/wps.config"
42 50
43#ifdef HAVE_LCD_BITMAP 51#define MAX_LINES 10
44 #define PLAY_DISPLAY_2LINEID3 0 52#define FORMAT_BUFFER_SIZE 300
45 #define PLAY_DISPLAY_FILENAME_SCROLL 1
46 #define PLAY_DISPLAY_TRACK_TITLE 2
47 #define PLAY_DISPLAY_CUSTOM_WPS 3
48#else
49 #define PLAY_DISPLAY_1LINEID3 0
50 #define PLAY_DISPLAY_1LINEID3_PLUS 1
51 #define PLAY_DISPLAY_2LINEID3 2
52 #define PLAY_DISPLAY_FILENAME_SCROLL 3
53 #define PLAY_DISPLAY_TRACK_TITLE 4
54 #define PLAY_DISPLAY_CUSTOM_WPS 5
55#endif
56 53
57#define LINE_LEN 64 54struct format_flags
55{
56 bool dynamic;
57 bool scroll;
58#ifdef HAVE_LCD_CHARCELLS
59 bool player_progress;
60#endif
61};
58 62
63static char format_buffer[FORMAT_BUFFER_SIZE];
64static char* format_lines[MAX_LINES];
65static bool dynamic_lines[MAX_LINES];
59static int ff_rewind_count; 66static int ff_rewind_count;
60static char custom_wps[5][LINE_LEN];
61static char display[5][LINE_LEN];
62static int scroll_line;
63static int scroll_line_custom;
64bool wps_time_countup = true; 67bool wps_time_countup = true;
65 68
66static bool load_custom_wps(void) 69/* Set format string to use for WPS, splitting it into lines */
70static void wps_format(char* fmt)
67{ 71{
68 int fd; 72 char* buf = format_buffer;
69 int l = 0; 73 int line = 0;
70 int numread = 1; 74
71 char cchr[0]; 75 strncpy(format_buffer, fmt, sizeof(format_buffer));
76 format_buffer[sizeof(format_buffer) - 1] = 0;
77 format_lines[line] = buf;
78
79 while (*buf)
80 {
81 switch (*buf++)
82 {
83 case '\r':
84 *(buf - 1) = 0;
85 break;
72 86
73 for (l=0;l<=5;l++) 87 case '\n': /* LF */
74 custom_wps[l][0] = 0; 88 *(buf - 1) = 0;
89 line++;
90
91 if (line < MAX_LINES)
92 {
93 format_lines[line] = buf;
94 }
95
96 break;
97 }
98 }
99
100 for (; line < MAX_LINES; line++)
101 {
102 format_lines[line] = NULL;
103 }
104}
75 105
76 l = 0; 106static bool load_custom_wps(void)
107{
108 char buffer[FORMAT_BUFFER_SIZE];
109 int fd;
77 110
78 fd = open(WPS_CONFIG, O_RDONLY); 111 fd = open(WPS_CONFIG, O_RDONLY);
79 if (-1 == fd) 112
113 if (-1 != fd)
80 { 114 {
115 int numread = read(fd, buffer, sizeof(buffer) - 1);
116
117 if (numread > 0)
118 {
119 buffer[numread] = 0;
120 wps_format(buffer);
121 }
122
81 close(fd); 123 close(fd);
82 return false; 124 return numread > 0;
83 } 125 }
126
127 return false;
128}
84 129
85 while(l<=5) 130/* Format time into buf.
86 { 131 *
87 numread = read(fd, cchr, 1); 132 * buf - buffer to format to.
88 if (numread==0) 133 * buf_size - size of buffer.
89 break; 134 * time - time to format, in milliseconds.
135 */
136static void format_time(char* buf, int buf_size, int time)
137{
138 snprintf(buf, buf_size, "%d:%02d", time / 60000, time % 60000 / 1000);
139}
90 140
91 switch (cchr[0]) 141/* Extract a part from a path.
92 { 142 *
93 case '\n': /* LF */ 143 * buf - buffer extract part to.
94 l++; 144 * buf_size - size of buffer.
95 break; 145 * path - path to extract from.
146 * level - what to extract. 0 is file name, 1 is parent of file, 2 is
147 * parent of parent, etc.
148 *
149 * Returns buf if the desired level was found, NULL otherwise.
150 */
151static char* get_dir(char* buf, int buf_size, char* path, int level)
152{
153 char* sep;
154 char* last_sep;
155 int len;
96 156
97 case '\r': /* CR ... Ignore it */ 157 sep = path + strlen(path);
98 break; 158 last_sep = sep;
99 159
100 default: 160 while (sep > path)
101 snprintf(custom_wps[l], LINE_LEN, 161 {
102 "%s%c", custom_wps[l], cchr[0]); 162 if ('/' == *(--sep))
163 {
164 if (!level)
165 {
103 break; 166 break;
167 }
168
169 level--;
170 last_sep = sep - 1;
104 } 171 }
105 } 172 }
106 close(fd);
107 173
108 scroll_line_custom = 0; 174 if (level || (last_sep <= sep))
109 for (l=0;l<=5;l++)
110 { 175 {
111 if (custom_wps[l][0] == '%' && custom_wps[l][1] == 's') 176 return NULL;
112 scroll_line_custom = l;
113 } 177 }
114 return true; 178
179 len = MIN(last_sep - sep, buf_size - 1);
180 strncpy(buf, sep + 1, len);
181 buf[len] = 0;
182 return buf;
115} 183}
116 184
117static bool display_custom_wps( struct mp3entry* id3, 185/* Get the tag specified by the two characters at fmt.
118 int x_val, 186 *
119 int y_val, 187 * id3 - ID3 data to get tag values from.
120 bool do_scroll, 188 * tag - string (of two characters) specifying the tag to get.
121 char *wps_string) 189 * buf - buffer to certain tags, such as track number, play time or
190 * directory name.
191 * buf_size - size of buffer.
192 * flags - flags in this struct will be set depending on the tag:
193 * dynamic - if the tag data changes over time (like play time);
194 * player_progress - set if the tag is %pb.
195 *
196 * Returns the tag. NULL indicates the tag wasn't available.
197 */
198static char* get_tag(struct mp3entry* id3, char* tag, char* buf, int buf_size,
199 struct format_flags* flags)
122{ 200{
123 char bigbuf[LINE_LEN*2]; 201 if ((0 == tag[0]) || (0 == tag[1]))
124 char buf[LINE_LEN];
125 int i;
126 int con_flag = 0; /* (0)Not inside of if/else
127 (1)Inside of If
128 (2)Inside of Else */
129 char con_if[LINE_LEN];
130 char con_else[LINE_LEN];
131 char cchr1;
132 char cchr2;
133 char cchr3;
134 unsigned int seek;
135
136 char* szLast;
137
138 szLast = strrchr(id3->path, '/');
139 if (szLast)
140 /* point to the first letter in the file name */
141 szLast++;
142
143 bigbuf[0] = 0;
144
145 seek = -1;
146 while(1)
147 { 202 {
148 seek++; 203 return NULL;
149 cchr1 = wps_string[seek]; 204 }
150 buf[0] = 0; 205
151 if (cchr1 == '%') 206 switch (tag[0])
207 {
208 case 'i': /* ID3 Information */
209 switch (tag[1])
152 { 210 {
153 seek++; 211 case 't': /* ID3 Title */
154 cchr2 = wps_string[seek]; 212 return id3->title;
155 switch(cchr2) 213
214 case 'a': /* ID3 Artist */
215 return id3->artist;
216
217 case 'n': /* ID3 Track Number */
218 if (id3->tracknum)
156 { 219 {
157 case 'i': /* ID3 Information */ 220 snprintf(buf, buf_size, "%d", id3->tracknum);
158 seek++; 221 return buf;
159 cchr3 = wps_string[seek];
160 switch(cchr3)
161 {
162 case 't': /* ID3 Title */
163 strncpy(buf,
164 id3->title ? id3->title : "<no title>",
165 LINE_LEN);
166 break;
167 case 'a': /* ID3 Artist */
168 strncpy(buf,
169 id3->artist ? id3->artist : "<no artist>",
170 LINE_LEN);
171 break;
172 case 'n': /* ID3 Track Number */
173 snprintf(buf, LINE_LEN, "%d",
174 id3->tracknum);
175 break;
176 case 'd': /* ID3 Album/Disc */
177 strncpy(buf, id3->album ? id3->album : "<no album>", LINE_LEN);
178 break;
179 }
180 break;
181 case 'f': /* File Information */
182 seek++;
183 cchr3 = wps_string[seek];
184 switch(cchr3)
185 {
186 case 'c': /* Conditional Filename \ ID3 Artist-Title */
187 if (id3->artist && id3->title)
188 snprintf(buf, LINE_LEN, "%s - %s",
189 id3->artist?id3->artist:"<no artist>",
190 id3->title?id3->title:"<no title>");
191 else
192 strncpy(buf,
193 szLast ? szLast : id3->path,
194 LINE_LEN );
195 break;
196
197 case 'd': /* Conditional Filename \ ID3 Title-Artist */
198 if (id3->artist && id3->title)
199 snprintf(buf, LINE_LEN, "%s - %s",
200 id3->title?id3->title:"<no title>",
201 id3->artist?id3->artist:"<no artist>");
202 else
203 strncpy(buf, szLast ? szLast : id3->path,
204 LINE_LEN);
205 break;
206
207 case 'b': /* File Bitrate */
208 snprintf(buf, LINE_LEN, "%d", id3->bitrate);
209 break;
210
211 case 'f': /* File Frequency */
212 snprintf(buf, LINE_LEN, "%d", id3->frequency);
213 break;
214
215 case 'p': /* File Path */
216 strncpy(buf, id3->path, LINE_LEN );
217 break;
218
219 case 'n': /* File Name */
220 strncpy(buf, szLast ? szLast : id3->path,
221 LINE_LEN );
222 break;
223
224 case 's': /* File Size (In Kilobytes) */
225 snprintf(buf, LINE_LEN, "%d",
226 id3->filesize / 1024);
227 break;
228 }
229 break;
230
231 case 'p': /* Playlist/Song Information */
232 seek++;
233 cchr3 = wps_string[seek];
234
235 switch(cchr3)
236 {
237#if defined(HAVE_LCD_CHARCELLS) && !defined(SIMULATOR)
238 case 'b': /* Progress Bar (PLAYER ONLY)*/
239 draw_player_progress(id3, ff_rewind_count);
240 snprintf(buf, LINE_LEN, "\x01");
241 break;
242#endif
243 case 'p': /* Playlist Position */
244 snprintf(buf, LINE_LEN, "%d", id3->index + 1);
245 break;
246
247 case 'e': /* Playlist Total Entries */
248 snprintf(buf, LINE_LEN, "%d", playlist.amount);
249 break;
250
251 case 'c': /* Current Time in Song */
252 i = id3->elapsed + ff_rewind_count;
253 snprintf(buf, LINE_LEN, "%d:%02d",
254 i / 60000,
255 i % 60000 / 1000);
256 wps_time_countup = true;
257 break;
258
259 case 'r': /* Remaining Time in Song */
260 i = id3->length - id3->elapsed + ff_rewind_count;
261 snprintf(buf, LINE_LEN, "%d:%02d",
262 i / 60000,
263 i % 60000 / 1000 );
264 wps_time_countup = false;
265 break;
266
267 case 't': /* Total Time */
268 snprintf(buf, LINE_LEN, "%d:%02d",
269 id3->length / 60000,
270 id3->length % 60000 / 1000);
271 break;
272 }
273 break;
274
275 case '%': /* Displays % */
276 buf[0] = '%';
277 buf[1] = 0;
278 break;
279
280 case '?': /* Conditional Display of ID3/File */
281 switch(con_flag)
282 {
283 case 0:
284 con_if[0] = 0;
285 con_else[0] = 0;
286 con_flag = 1;
287 break;
288 default:
289 if (id3->artist && id3->title)
290 strncpy(buf, con_if, LINE_LEN);
291 else
292 strncpy(buf, con_else, LINE_LEN);
293 con_flag = 0;
294 break;
295 }
296 break;
297
298 case ':': /* Seperator for Conditional ID3/File Display */
299 con_flag = 2;
300 break;
301 } 222 }
223 else
224 {
225 return NULL;
226 }
227
228 case 'd': /* ID3 Album/Disc */
229 return id3->album;
230 }
231 break;
232
233 case 'f': /* File Information */
234 switch(tag[1])
235 {
236 case 'v': /* VBR file? */
237 return id3->vbr ? "(avg)" : NULL;
238
239 case 'b': /* File Bitrate */
240 snprintf(buf, buf_size, "%d", id3->bitrate);
241 return buf;
302 242
303 switch(con_flag) 243 case 'f': /* File Frequency */
244 snprintf(buf, buf_size, "%d", id3->frequency);
245 return buf;
246
247 case 'p': /* File Path */
248 return id3->path;
249
250 case 'm': /* File Name - With Extension */
251 return get_dir(buf, buf_size, id3->path, 0);
252
253 case 'n': /* File Name */
254 if (get_dir(buf, buf_size, id3->path, 0))
304 { 255 {
305 case 0: 256 /* Remove extension */
306 snprintf(bigbuf, sizeof bigbuf, "%s%s", bigbuf, buf); 257 char* sep = strrchr(buf, '.');
307 break;
308 258
309 case 1: 259 if (NULL != sep)
310 snprintf(con_if, sizeof con_if, "%s%s", con_if, buf); 260 {
311 break; 261 *sep = 0;
262 }
312 263
313 case 2: 264 return buf;
314 snprintf(con_else, sizeof con_else, "%s%s", con_else, buf);
315 break;
316 } 265 }
317 } 266 else
318 else
319 {
320 switch(con_flag)
321 { 267 {
322 case 0: 268 return NULL;
323 snprintf(bigbuf, sizeof bigbuf, "%s%c", bigbuf, cchr1);
324 break;
325
326 case 1:
327 snprintf(con_if, sizeof con_if, "%s%c", con_if, cchr1);
328 break;
329
330 case 2:
331 snprintf(con_else, sizeof con_else, "%s%c",
332 con_else, cchr1);
333 break;
334 } 269 }
270
271 case 's': /* File Size (in kilobytes) */
272 snprintf(buf, buf_size, "%d", id3->filesize / 1024);
273 return buf;
335 } 274 }
275 break;
336 276
337 if (seek >= strlen(wps_string)) 277 case 'p': /* Playlist/Song Information */
278 switch(tag[1])
338 { 279 {
339 if (do_scroll) 280#if defined(HAVE_LCD_CHARCELLS) && !defined(SIMULATOR)
340 { 281 case 'b': /* Player progress bar */
341 lcd_stop_scroll(); 282 flags->player_progress = true;
342 lcd_puts_scroll(x_val, y_val, bigbuf); 283 flags->dynamic = true;
343 } 284 return "\x01";
344 else 285#endif
345 lcd_puts(x_val, y_val, bigbuf); 286
287 case 'p': /* Playlist Position */
288 snprintf(buf, buf_size, "%d", id3->index + 1);
289 return buf;
290
291 case 'e': /* Playlist Total Entries */
292 snprintf(buf, buf_size, "%d", playlist.amount);
293 return buf;
346 294
347 return true; 295 case 'c': /* Current Time in Song */
296 flags->dynamic = true;
297 format_time(buf, buf_size, id3->elapsed + ff_rewind_count);
298 return buf;
299
300 case 'r': /* Remaining Time in Song */
301 flags->dynamic = true;
302 format_time(buf, buf_size, id3->length - id3->elapsed + ff_rewind_count);
303 return buf;
304
305 case 't': /* Total Time */
306 format_time(buf, buf_size, id3->length);
307 return buf;
308 }
309 break;
310
311 case 'd': /* Directory path information */
312 switch(tag[1])
313 {
314 case '1': /* Parent folder */
315 return get_dir(buf, buf_size, id3->path, 1);
316
317 case '2': /* Parent of parent */
318 return get_dir(buf, buf_size, id3->path, 2);
319
320 case '3': /* Parent of parent of parent */
321 return get_dir(buf, buf_size, id3->path, 3);
348 } 322 }
323 break;
349 } 324 }
350 return true; 325
326 return NULL;
327}
328
329/* Skip to the end of the current %? conditional.
330 *
331 * fmt - string to skip it. Should point to somewhere after the leading
332 * "<" char (and before or at the last ">").
333 * to_else - if true, skip to the else part (after the "|", if any), else skip
334 * to the end (the ">").
335 *
336 * Returns the new position in fmt.
337 */
338static char* skip_conditional(char* fmt, bool to_else)
339{
340 int level = 1;
341
342 while (*fmt)
343 {
344 switch (*fmt++)
345 {
346 case '%':
347 break;
348
349 case '|':
350 if (to_else && (1 == level))
351 return fmt;
352
353 continue;
354
355 case '>':
356 if (0 == --level)
357 {
358 if (to_else)
359 fmt--;
360
361 return fmt;
362 }
363 continue;
364
365 default:
366 continue;
367 }
368
369 switch (*fmt++)
370 {
371 case 0:
372 case '%':
373 case '|':
374 case '<':
375 case '>':
376 break;
377
378 case '?':
379 while (*fmt && ('<' != *fmt))
380 fmt++;
381
382 if ('<' == *fmt)
383 fmt++;
384
385 level++;
386 break;
387
388 default:
389 break;
390 }
391 }
392
393 return fmt;
394}
395
396/* Generate the display based on id3 information and format string.
397 *
398 * buf - char buffer to write the display to.
399 * buf_size - the size of buffer.
400 * id3 - the ID3 data to format with.
401 * fmt - format description.
402 * flags - flags in this struct will be set depending on the tag:
403 * dynamic - if the tag data changes over time (like play time);
404 * player_progress - set if the tag is %pb.
405 * scroll - if line scrolling is requested.
406 */
407static void format_display(char* buf,
408 int buf_size,
409 struct mp3entry* id3,
410 char* fmt,
411 struct format_flags* flags)
412{
413 char temp_buf[128];
414 char* buf_end = buf + buf_size - 1; /* Leave room for end null */
415 char* value = NULL;
416 int level = 0;
417
418 while (fmt && *fmt && buf < buf_end)
419 {
420 switch (*fmt)
421 {
422 case '%':
423 ++fmt;
424 break;
425
426 case '|':
427 case '>':
428 if (level > 0)
429 {
430 fmt = skip_conditional(fmt, false);
431 level--;
432 continue;
433 }
434 /* Else fall through */
435
436 default:
437 *buf++ = *fmt++;
438 continue;
439 }
440
441 switch (*fmt)
442 {
443 case 0:
444 *buf++ = '%';
445 break;
446
447 case 's':
448 flags->scroll = true;
449 ++fmt;
450 break;
451
452 case '%':
453 case '|':
454 case '<':
455 case '>':
456 *buf++ = *fmt++;
457 break;
458
459 case '?':
460 fmt++;
461 value = get_tag(id3, fmt, temp_buf, sizeof(temp_buf), flags);
462
463 while (*fmt && ('<' != *fmt))
464 fmt++;
465
466 if ('<' == *fmt)
467 fmt++;
468
469 /* No value, so skip to else part */
470 if (NULL == value)
471 fmt = skip_conditional(fmt, true);
472
473 level++;
474 break;
475
476 default:
477 value = get_tag(id3, fmt, temp_buf, sizeof(temp_buf), flags);
478 fmt += 2;
479
480 if (value)
481 {
482 while (*value && (buf < buf_end))
483 *buf++ = *value++;
484 }
485 }
486 }
487
488 *buf = 0;
351} 489}
352 490
353bool wps_refresh(struct mp3entry* id3, int ffwd_offset, bool refresh_scroll) 491bool wps_refresh(struct mp3entry* id3, int ffwd_offset, bool refresh_all)
354{ 492{
355 int l; 493 char buf[MAX_PATH];
494 struct format_flags flags;
495 bool scroll_active = false;
496 int i;
356#ifdef HAVE_LCD_BITMAP 497#ifdef HAVE_LCD_BITMAP
357 int bmp_time_line; 498 int bmp_time_line;
358#endif 499#endif
@@ -367,25 +508,38 @@ bool wps_refresh(struct mp3entry* id3, int ffwd_offset, bool refresh_scroll)
367 ff_rewind_count = ffwd_offset; 508 ff_rewind_count = ffwd_offset;
368 509
369#ifdef HAVE_LCD_CHARCELL 510#ifdef HAVE_LCD_CHARCELL
370 for (l = 0; l <= 1; l++) 511 for (i = 0; i < 2; i++)
371#else 512#else
372 for (l = 0; l <= 5; l++) 513 for (i = 0; i < MAX_LINES; i++)
373#endif 514#endif
374 { 515 {
375 if (global_settings.wps_display == PLAY_DISPLAY_CUSTOM_WPS) 516 if ( !format_lines[i] )
376 { 517 break;
377 scroll_line = scroll_line_custom; 518
378 if (scroll_line != l) 519 if (dynamic_lines[i] || refresh_all)
379 display_custom_wps(id3, 0, l, false, custom_wps[l]);
380 if (scroll_line == l && refresh_scroll)
381 display_custom_wps(id3, 0, l, true, custom_wps[l]);
382 }
383 else
384 { 520 {
385 if (scroll_line != l) 521 flags.dynamic = false;
386 display_custom_wps(id3, 0, l, false, display[l]); 522 flags.scroll = false;
387 if (scroll_line == l && refresh_scroll) 523#ifdef HAVE_LCD_CHARCELLS
388 display_custom_wps(id3, 0, l, true, display[l]); 524 flags.player_progress = false;
525#endif
526 format_display(buf, sizeof(buf), id3, format_lines[i], &flags);
527 dynamic_lines[i] = flags.dynamic;
528
529#ifdef HAVE_LCD_CHARCELLS
530 if (flags.player_progress)
531 draw_player_progress(id3, ff_rewind_count);
532#endif
533
534 if (!scroll_active && flags.scroll && !flags.dynamic)
535 {
536 scroll_active = true;
537 lcd_puts_scroll(0, i, buf);
538 }
539 else
540 {
541 lcd_puts(0, i, buf);
542 }
389 } 543 }
390 } 544 }
391#ifdef HAVE_LCD_BITMAP 545#ifdef HAVE_LCD_BITMAP
@@ -393,10 +547,12 @@ bool wps_refresh(struct mp3entry* id3, int ffwd_offset, bool refresh_scroll)
393 bmp_time_line = 5; 547 bmp_time_line = 5;
394 else 548 else
395 bmp_time_line = 6; 549 bmp_time_line = 6;
396 snprintf(display[bmp_time_line], sizeof display[bmp_time_line],
397 "%s","Time: %pc/%pt");
398 550
399 slidebar(0, LCD_HEIGHT-6, LCD_WIDTH, 6, id3->elapsed*100/id3->length, Grow_Right); 551 format_display(buf, sizeof(buf), id3, "Time: %pc/%pt", &flags);
552 lcd_puts(0, bmp_time_line, buf);
553
554 slidebar(0, LCD_HEIGHT-6, LCD_WIDTH, 6,
555 id3->elapsed * 100 / id3->length, Grow_Right);
400 lcd_update(); 556 lcd_update();
401#endif 557#endif
402 return true; 558 return true;
@@ -414,6 +570,7 @@ void wps_display(struct mp3entry* id3)
414#endif 570#endif
415 571
416 lcd_clear_display(); 572 lcd_clear_display();
573
417 if (!id3 && !mpeg_is_playing()) 574 if (!id3 && !mpeg_is_playing())
418 { 575 {
419#ifdef HAVE_LCD_CHARCELLS 576#ifdef HAVE_LCD_CHARCELLS
@@ -426,123 +583,28 @@ void wps_display(struct mp3entry* id3)
426 } 583 }
427 else 584 else
428 { 585 {
429 static int last_wps = -1; 586 static bool wps_loaded = false;
430 if ((last_wps != global_settings.wps_display 587
431 && global_settings.wps_display == PLAY_DISPLAY_CUSTOM_WPS)) 588 if (!wps_loaded) {
432 {
433 load_custom_wps(); 589 load_custom_wps();
434 last_wps = global_settings.wps_display; 590 wps_loaded = true;
435 }
436 591
437 switch ( global_settings.wps_display ) { 592 if ( !format_buffer[0] ) {
438 case PLAY_DISPLAY_TRACK_TITLE:
439 {
440 char ch = '/';
441 char* end;
442 char* szTok;
443 char* szDelimit;
444 char* szPeriod;
445 char szArtist[26];
446 char szBuff[257];
447 int tmpcnt = 0;
448
449 szBuff[sizeof(szBuff)-1] = 0;
450 strncpy(szBuff, id3->path, sizeof szBuff);
451
452 szTok = strtok_r(szBuff, "/", &end);
453 szTok = strtok_r(NULL, "/", &end);
454
455 /* Assume path format of: Genre/Artist/Album/Mp3_file */
456 strncpy(szArtist, szTok, sizeof szArtist);
457 szArtist[sizeof(szArtist)-1] = 0;
458 szDelimit = strrchr(id3->path, ch);
459 lcd_puts(0, 0, szArtist ? szArtist : "<nothing>");
460
461 /* removes the .mp3 from the end of the display buffer */
462 szPeriod = strrchr(szDelimit, '.');
463 if (szPeriod != NULL)
464 *szPeriod = 0;
465
466 strncpy(display[0], ++szDelimit, sizeof display[0]);
467#ifdef HAVE_LCD_CHARCELLS
468 snprintf(display[1], sizeof display[1], "%s", "%pc/%pt");
469#endif
470 for (tmpcnt=2;tmpcnt<=5;tmpcnt++)
471 display[tmpcnt][0] = 0;
472 scroll_line = 0;
473 break;
474 }
475 case PLAY_DISPLAY_FILENAME_SCROLL:
476 {
477 snprintf(display[0], sizeof display[0], "%s", "%pp/%pe: %fn");
478#ifdef HAVE_LCD_CHARCELLS
479 snprintf(display[1], sizeof display[1], "%s", "%pc/%pt");
480#endif
481 scroll_line = 0;
482 break;
483 }
484 case PLAY_DISPLAY_2LINEID3:
485 {
486#ifdef HAVE_LCD_BITMAP 593#ifdef HAVE_LCD_BITMAP
487 int l = 0; 594 wps_format("%s%fp\n"
488 595 "%it\n"
489 strncpy( display[l++], "%fn", LINE_LEN ); 596 "%id\n"
490 strncpy( display[l++], "%it", LINE_LEN ); 597 "%ia\n"
491 strncpy( display[l++], "%id", LINE_LEN ); 598 "%fb kbit %fv\n"
492 strncpy( display[l++], "%ia", LINE_LEN ); 599 "%ff Hz\n");
493
494 if (!global_settings.statusbar && font_height <= 8)
495 {
496 if (id3->vbr)
497 strncpy(display[l++], "%fb kbit (avg)", LINE_LEN);
498 else
499 strncpy(display[l++], "%fb kbit", LINE_LEN);
500
501 strncpy(display[l++], "%ff Hz", LINE_LEN);
502 }
503 else
504 {
505 if (id3->vbr)
506 strncpy(display[l++], "%fb kbit(a) %ffHz", LINE_LEN);
507 else
508 strncpy(display[l++], "%fb kbit %ffHz", LINE_LEN);
509 }
510 scroll_line = 0;
511#else 600#else
512 strncpy(display[0], "%ia", LINE_LEN); 601 wps_format("%s%pp/%pe: %?ia<%ia - >%?it<%it|%fm>\n"
513 strncpy(display[1], "%it", LINE_LEN); 602 "%pc/%pt\n");
514 scroll_line = 1;
515#endif
516 break;
517 }
518#ifdef HAVE_LCD_CHARCELLS
519 case PLAY_DISPLAY_1LINEID3:
520 {
521 strncpy(display[0], "%pp/%pe: %fc", LINE_LEN);
522 strncpy(display[1], "%pc/%pt", LINE_LEN);
523 scroll_line = 0;
524 break;
525 }
526 case PLAY_DISPLAY_1LINEID3_PLUS:
527 {
528 strncpy(display[0], "%pp/%pe: %fc", LINE_LEN);
529 strncpy(display[1], "%pr%pb%fbkps", LINE_LEN);
530 scroll_line = 0;
531 break;
532 }
533#endif 603#endif
534 case PLAY_DISPLAY_CUSTOM_WPS:
535 {
536 if (custom_wps[0] == 0)
537 {
538 strncpy(display[0], "Couldn't Load Custom WPS", LINE_LEN);
539 strncpy(display[1], "%pc/%pt", LINE_LEN);
540 }
541 break;
542 } 604 }
543 } 605 }
544 } 606 }
545 wps_refresh(id3,0,false); 607 wps_refresh(id3, 0, true);
546 status_draw(); 608 status_draw();
547 lcd_update(); 609 lcd_update();
548} 610}
diff --git a/apps/wps.c b/apps/wps.c
index e7231f1438..8576dbf973 100644
--- a/apps/wps.c
+++ b/apps/wps.c
@@ -783,7 +783,6 @@ int wps_show(void)
783 /* toggle status bar */ 783 /* toggle status bar */
784#ifdef HAVE_RECORDER_KEYPAD 784#ifdef HAVE_RECORDER_KEYPAD
785 case BUTTON_F3: 785 case BUTTON_F3:
786#ifdef HAVE_LCD_BITMAP
787 global_settings.statusbar = !global_settings.statusbar; 786 global_settings.statusbar = !global_settings.statusbar;
788 settings_save(); 787 settings_save();
789 if(global_settings.statusbar) 788 if(global_settings.statusbar)
@@ -791,7 +790,6 @@ int wps_show(void)
791 else 790 else
792 lcd_setmargins(0, 0); 791 lcd_setmargins(0, 0);
793 restore = true; 792 restore = true;
794#endif
795 break; 793 break;
796#endif 794#endif
797 795