Rockbox.org home
release
dev builds
extras
themes manual
wiki
device status forums
mailing lists
IRC bugs
patches
dev guide



Rockbox mail archive

Subject: WPS mode
From: Magnus Holmgren (lear_at_algonet.se)
Date: 2002-08-03


Hi,

Here's another WPS patch, adding a display mode primarily intended for
players.

The first line displays the following information, if available:
"<tracknum> - <title> (<artist>, <album>)". The second line alters every
five seconds between two displays, "<mm:ss><s><p><nnnn>" and
"<-mm:ss><kbps><*>". The fields are as follows: play time, shuffle flag,
playlist flag, playlist index; remaining play time, bitrate, vbr flag.

ID3 information is used if available, otherwise the path is parsed,
assuming the path _ends_ with artist/album/title.mp3.

The patch also makes the time display update 5 times per second rather
than 2, which looks better.

There are a couple of things that could be improved in this patch
though:

* The shuffle, playlist and maybe VBR flags should be symbols, but I
couldn't find any suitable ones.

* The code in draw_screen() uses static buffers to do its work, as I
wasn't sure how much stack was available.

* tracknum isn't displayed at the moment. Seems like it isn't set
properly if a ID3V2 file is playing (haven't tried ID3V1 only).

* The playlist flag remains set even after a playlist isn't used any
more (it needs to be cleard on playlist stop/exit).

* During song change, a random time is sometimes displayed briefly.

* If shuffle is on, the playlist index doesn't refer to the order in the
file, but rather the order in memory.

Despite these things, I use this mode all the time.

-- 
Magnus Holmgren

Index: wps.c
===================================================================
RCS file: /cvsroot/rockbox/apps/wps.c,v
retrieving revision 1.45
diff -b -u -r1.45 wps.c
--- wps.c 1 Aug 2002 13:29:59 -0000 1.45
+++ wps.c 3 Aug 2002 17:46:18 -0000
@@ -40,6 +40,10 @@
 #define PLAY_DISPLAY_DEFAULT 0
 #define PLAY_DISPLAY_FILENAME_SCROLL 1
 #define PLAY_DISPLAY_TRACK_TITLE 2
+#define PLAY_DISPLAY_COMPACT_VERBOSE 3
+
+#define BUTTON_POLL_FREQUENCY 10 /* Number of ticks between each button poll */
+#define BUTTON_POLLS_PER_UPDATE 2 /* Number of polls between display update */
 
 #ifdef HAVE_RECORDER_KEYPAD
 #define RELEASE_MASK (BUTTON_F1 | BUTTON_DOWN)
@@ -47,6 +51,81 @@
 #define RELEASE_MASK (BUTTON_MENU | BUTTON_STOP)
 #endif
 
+/* Tokenize a string from the end. An empty string contains no tokens.
+ *
+ * buffer - pointer to buffer to parse. Always pass it unchanged.
+ * separator - chars that limits a token.
+ * end - tracks current scan position; initialize to NULL before the
+ * first call.
+ * returns the current token, or NULL if there are no more tokens.
+ */
+static char* strrtok_r(char* buffer, char* separator, char** end)
+{
+ if (*end == NULL)
+ {
+ /* First call, init to last char */
+ *end = buffer + strlen(buffer) - 1;
+ }
+
+ /* No more to search? */
+ if (*end < buffer)
+ {
+ return NULL;
+ }
+
+ /* Locate previous separator */
+ while ((*end > buffer) && !strchr(separator, **end))
+ {
+ --*end;
+ }
+
+ /* On a separator? */
+ if (strchr(separator, **end))
+ {
+ **end = 0; /* Terminate preceeding token */
+ }
+
+ --*end; /* Prepare for next round */
+ return *end + 2; /* Return char after sparator */
+}
+
+/* strncat and snprintf rolled into one, with a twist. The string in buffer
+ * will not be made longer than buffer_len.
+ */
+static int strfmt(char* buffer, int buffer_len, char* format, ...)
+{
+ int len;
+ va_list args;
+
+ va_start (args, format);
+ len = strlen(buffer);
+ len = vsnprintf(buffer + len, buffer_len - len, format, args);
+ va_end (args);
+
+ return len;
+}
+
+/* Assume path format of: .../Artist/Album/Title.mp3. */
+static void id3_from_path(char* path, char** artist, char** album, char** title)
+{
+ char* end = NULL;
+
+ *title = strrtok_r(path, "/", &end);
+ *album = strrtok_r(path, "/", &end);
+ *artist = strrtok_r(path, "/", &end);
+
+ if (*title != NULL)
+ {
+ /* Remove any .mp3 suffix */
+ int length = strlen(*title) - 4;
+
+ if ((length > 0) && !strcasecmp(*title + length, ".mp3"))
+ {
+ *(*title + length) = 0;
+ }
+ }
+}
+
 static void draw_screen(struct mp3entry* id3)
 {
     lcd_clear_display();
@@ -132,6 +211,52 @@
 #endif
                 break;
             }
+ case PLAY_DISPLAY_COMPACT_VERBOSE:
+ {
+ static char buffer[MAX_PATH];
+ static char id3buffer[MAX_PATH];
+ char* artist;
+ char* album;
+ char* title;
+ int tracknum;
+
+ if (id3->title)
+ {
+ artist = id3->artist;
+ album = id3->album;
+ title = id3->title;
+ /* Doesn't seem to get set... */
+ tracknum = id3->tracknum;
+ }
+ else
+ {
+ strncpy(id3buffer, id3->path, sizeof(id3buffer));
+ id3buffer[sizeof(id3buffer) - 1] = 0;
+ id3_from_path(id3buffer, &artist, &album, &title);
+ tracknum = 0;
+ }
+
+ buffer[0] = 0;
+
+ if (tracknum)
+ {
+ strfmt(buffer, sizeof(buffer), "%d - ", tracknum);
+ }
+
+ strfmt(buffer, sizeof(buffer), "%s", title ? title : "<N/A>");
+
+ if (artist || album)
+ {
+ strfmt(buffer, sizeof(buffer), " (%s, %s)",
+ artist ? artist : "<N/A>",
+ album ? album : "<N/A>");
+ }
+
+ buffer[sizeof(buffer) - 1] = 0;
+ lcd_puts_scroll(0, 0, buffer);
+
+ break;
+ }
         }
     }
     status_draw();
@@ -222,6 +347,38 @@
                 lcd_puts(0, 1, buffer);
                 lcd_update();
            }
+ else if (global_settings.wps_display == PLAY_DISPLAY_COMPACT_VERBOSE)
+ {
+ /* Change display every 5 seconds */
+ #define PDCV_CHANGE_FREQUENCY (5 * BUTTON_POLL_FREQUENCY / BUTTON_POLLS_PER_UPDATE)
+ static int count = 0;
+
+ if (count++ < PDCV_CHANGE_FREQUENCY)
+ {
+ snprintf(buffer, sizeof(buffer), "%02d:%02d%s%s%04d",
+ id3->elapsed / 60000,
+ id3->elapsed % 60000 / 1000,
+ global_settings.playlist_shuffle ? "s" : " ",
+ playlist.amount ? "p" : " ",
+ playlist.index + 1);
+ }
+ else
+ {
+ snprintf(buffer, sizeof(buffer), "-%02d:%02d %3d%s",
+ (id3->length - id3->elapsed) / 60000,
+ (id3->length - id3->elapsed) % 60000 / 1000,
+ id3->bitrate,
+ id3->vbr ? "*" : " ");
+ }
+
+ if (count > (PDCV_CHANGE_FREQUENCY * 2))
+ {
+ count = 0;
+ }
+
+ lcd_puts(0, 1, buffer);
+ lcd_update();
+ }
 #endif
         }
 
@@ -233,7 +390,7 @@
         lcd_drawline(0,LCD_HEIGHT-1,battery_level() * (LCD_WIDTH-1) / 100, LCD_HEIGHT-1);
 #endif
 
- for ( i=0;i<5;i++ ) {
+ for ( i=0;i<BUTTON_POLLS_PER_UPDATE;i++ ) {
             int button = button_get(false);
 
             switch ( button )
@@ -452,7 +609,7 @@
                     break;
 #endif
             }
- sleep(HZ/10);
+ sleep(HZ / BUTTON_POLL_FREQUENCY);
         }
     }
 }
Index: settings_menu.c
===================================================================
RCS file: /cvsroot/rockbox/apps/settings_menu.c,v
retrieving revision 1.8
diff -b -u -r1.8 settings_menu.c
--- settings_menu.c 2 Aug 2002 13:20:03 -0000 1.8
+++ settings_menu.c 3 Aug 2002 17:46:30 -0000
@@ -63,8 +63,8 @@
 
 static void wps_set(void)
 {
- char* names[] = { "Id3 ", "File ", "Parse" };
- set_option("[WPS display]", &global_settings.wps_display, names, 3 );
+ char* names[] = { "Id3 ", "File ", "Parse ", "Verbose" };
+ set_option("[WPS display]", &global_settings.wps_display, names, 4 );
 }
 
 void settings_menu(void)



Page was last modified "Jan 10 2012" The Rockbox Crew
aaa