iRiver: Fixed broken items skipping on playlist: Now skipping and
marking them as bad instead of deleting the entries from playlist.
Faster buffered track skipping and preventing glitches from previous
tracks (still something might occur though, please report them).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7647 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c
index 1bcfb25..b67e889 100644
--- a/apps/pcmbuf.c
+++ b/apps/pcmbuf.c
@@ -193,7 +193,7 @@
{
/* Fill audio buffer by boosting cpu */
pcmbuf_boost(true);
- if (bytes_left <= CHUNK_SIZE * 2)
+ if (bytes_left <= CHUNK_SIZE * 2 && crossfade_mode != CFM_FLUSH)
crossfade_active = false;
}
@@ -347,8 +347,9 @@
}
logf("crossfade_start");
- audiobuffer_fillpos = 0;
pcmbuf_boost(true);
+ while (audiobuffer_fillpos != 0)
+ pcmbuf_flush_fillpos();
crossfade_active = true;
crossfade_pos = audiobuffer_pos;
@@ -360,7 +361,7 @@
break ;
case CFM_FLUSH:
- crossfade_amount = (bytesleft - (CHUNK_SIZE * 2))/2;
+ crossfade_amount = bytesleft /2;
crossfade_rem = crossfade_amount;
break ;
}
@@ -439,13 +440,10 @@
{
void *ptr = NULL;
- if (crossfade_init)
- crossfade_start();
-
- while (audiobuffer_free < length + audiobuffer_fillpos
- + CHUNK_SIZE && !crossfade_active) {
- pcmbuf_boost(false);
- sleep(1);
+ if (!prepare_insert(length))
+ {
+ *realsize = 0;
+ return NULL;
}
if (crossfade_active) {
@@ -473,8 +471,6 @@
int copy_n;
char *buf;
- prepare_insert(length);
-
if (crossfade_active) {
buf = &guardbuf[0];
length = MIN(length, PCMBUF_GUARD);
diff --git a/apps/playback.c b/apps/playback.c
index 5b78ad5..7c3d63c 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -296,9 +296,15 @@
}
while (length > 0) {
+ /* This will prevent old audio from playing when skipping tracks. */
+ if (ci.reload_codec || ci.stop_codec)
+ return true;
+
while ((dest = pcmbuf_request_buffer(dsp_output_size(length),
&output_size)) == NULL) {
- yield();
+ sleep(1);
+ if (ci.reload_codec || ci.stop_codec)
+ return true;
}
/* Get the real input_size for output_size bytes, guarding
@@ -1008,7 +1014,6 @@
off_t size;
int rc, i;
int copy_n;
- int playlist_index;
/* Stop buffer filling if there is no free track entries.
Don't fill up the last track entry (we wan't to store next track
@@ -1025,10 +1030,6 @@
return false;
last_index = playlist_get_display_index();
- playlist_index = playlist_get_display_index() - 1
- + playlist_get_first_index(NULL) + peek_offset;
- if (playlist_index >= playlist_amount())
- playlist_index -= playlist_amount();
peek_again:
/* Get track name from current playlist read position. */
@@ -1038,8 +1039,8 @@
fd = open(trackname, O_RDONLY);
if (fd < 0) {
logf("Open failed");
- /* Delete invalid entry from playlist. */
- playlist_delete(NULL, playlist_index);
+ /* Skip invalid entry from playlist. */
+ playlist_skip_entry(NULL, peek_offset);
continue ;
}
break ;
@@ -1088,8 +1089,8 @@
/* Try skipping to next track. */
if (fill_bytesleft > 0) {
- /* Delete invalid entry from playlist. */
- playlist_delete(NULL, playlist_index);
+ /* Skip invalid entry from playlist. */
+ playlist_skip_entry(NULL, peek_offset);
goto peek_again;
}
return false;
@@ -1104,8 +1105,8 @@
tracks[track_widx].filesize = 0;
tracks[track_widx].filerem = 0;
close(fd);
- /* Delete invalid entry from playlist. */
- playlist_delete(NULL, playlist_index);
+ /* Skip invalid entry from playlist. */
+ playlist_skip_entry(NULL, peek_offset);
goto peek_again;
}
}
diff --git a/apps/playlist.c b/apps/playlist.c
index 70df811..91eacb7 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -99,10 +99,10 @@
/*
Each playlist index has a flag associated with it which identifies what
- type of track it is. These flags are stored in the 3 high order bits of
+ type of track it is. These flags are stored in the 4 high order bits of
the index.
- NOTE: This limits the playlist file size to a max of 512M.
+ NOTE: This limits the playlist file size to a max of 256M.
Bits 31-30:
00 = Playlist track
@@ -112,8 +112,11 @@
Bit 29:
0 = Added track
1 = Queued track
+ Bit 28:
+ 0 = Track entry is valid
+ 1 = Track does not exist on disk and should be skipped
*/
-#define PLAYLIST_SEEK_MASK 0x1FFFFFFF
+#define PLAYLIST_SEEK_MASK 0x07FFFFFF
#define PLAYLIST_INSERT_TYPE_MASK 0xC0000000
#define PLAYLIST_QUEUE_MASK 0x20000000
@@ -122,6 +125,7 @@
#define PLAYLIST_INSERT_TYPE_APPEND 0xC0000000
#define PLAYLIST_QUEUED 0x20000000
+#define PLAYLIST_SKIPPED 0x10000000
#define PLAYLIST_DISPLAY_COUNT 10
@@ -828,6 +832,72 @@
return 0;
}
+/* Marks the index of the track to be skipped that is "steps" away from
+ * current playing track.
+ */
+void playlist_skip_entry(struct playlist_info *playlist, int steps)
+{
+ int index;
+
+ if (playlist == NULL)
+ playlist = ¤t_playlist;
+
+ index = rotate_index(playlist, playlist->index);
+ index += steps;
+ if (index < 0 || index >= playlist->amount)
+ return ;
+
+ index = (index+playlist->first_index) % playlist->amount;
+ playlist->indices[index] |= PLAYLIST_SKIPPED;
+}
+
+/* Calculate how many steps we have to really step when skipping entries
+ * marked as bad.
+ */
+static int calculate_step_count(const struct playlist_info *playlist, int steps)
+{
+ int i, count, direction;
+ int index;
+ int stepped_count = 0;
+
+ if (steps < 0)
+ {
+ direction = -1;
+ count = -steps;
+ }
+ else
+ {
+ direction = 1;
+ count = steps;
+ }
+
+ index = playlist->index;
+ i = 0;
+ while (i < count)
+ {
+ index += direction;
+ /* Boundary check */
+ if (index < 0)
+ index += playlist->amount;
+ if (index >= playlist->amount)
+ index -= playlist->amount;
+
+ /* Check if we found a bad entry. */
+ if (playlist->indices[index] & PLAYLIST_SKIPPED)
+ {
+ steps += direction;
+ /* Are all entries bad? */
+ if (stepped_count++ > playlist->amount)
+ break ;
+ }
+ else
+ i++;
+ }
+
+ return steps;
+}
+
+
/*
* returns the index of the track that is "steps" away from current playing
* track.
@@ -848,6 +918,7 @@
(!global_settings.playlist_shuffle || playlist->amount <= 1))
repeat_mode = REPEAT_ALL;
+ steps = calculate_step_count(playlist, steps);
switch (repeat_mode)
{
case REPEAT_SHUFFLE:
@@ -856,7 +927,6 @@
case REPEAT_OFF:
{
current_index = rotate_index(playlist, current_index);
-
next_index = current_index+steps;
if ((next_index < 0) || (next_index >= playlist->amount))
next_index = -1;
@@ -904,6 +974,10 @@
}
}
+ /* No luck if the whole playlist was bad. */
+ if (playlist->indices[next_index] & PLAYLIST_SKIPPED)
+ return -1;
+
return next_index;
}
@@ -2652,8 +2726,12 @@
info->attr |= PLAYLIST_ATTR_QUEUED;
else
info->attr |= PLAYLIST_ATTR_INSERTED;
+
}
+ if (playlist->indices[index] & PLAYLIST_SKIPPED)
+ info->attr |= PLAYLIST_ATTR_SKIPPED;
+
info->index = index;
info->display_index = rotate_index(playlist, index) + 1;
diff --git a/apps/playlist.h b/apps/playlist.h
index eee8bf5..1937c48 100644
--- a/apps/playlist.h
+++ b/apps/playlist.h
@@ -58,6 +58,7 @@
#define PLAYLIST_ATTR_QUEUED 0x01
#define PLAYLIST_ATTR_INSERTED 0x02
+#define PLAYLIST_ATTR_SKIPPED 0x04
#define DEFAULT_DYNAMIC_PLAYLIST_NAME "/dynamic.m3u"
@@ -99,6 +100,7 @@
bool recurse);
int playlist_insert_playlist(struct playlist_info* playlist, char *filename,
int position, bool queue);
+void playlist_skip_entry(struct playlist_info *playlist, int steps);
int playlist_delete(struct playlist_info* playlist, int index);
int playlist_move(struct playlist_info* playlist, int index, int new_index);
int playlist_randomise(struct playlist_info* playlist, unsigned int seed,
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c
index b7a0427..70c1cf8 100644
--- a/apps/playlist_viewer.c
+++ b/apps/playlist_viewer.c
@@ -112,6 +112,7 @@
int index; /* Playlist index */
int display_index; /* Display index */
bool queued; /* Is track queued? */
+ bool skipped; /* Is track marked as bad? */
};
static struct playlist_viewer_info viewer;
@@ -381,6 +382,7 @@
tracks[pos].index = info.index;
tracks[pos].display_index = info.display_index;
tracks[pos].queued = info.attr & PLAYLIST_ATTR_QUEUED;
+ tracks[pos].skipped = info.attr & PLAYLIST_ATTR_SKIPPED;
result = len;
}
@@ -424,14 +426,18 @@
static void format_line(const struct playlist_entry* track, char* str, int len)
{
char name[MAX_PATH];
+ char *skipped = "";
format_name(name, track->name);
+ if (track->skipped)
+ skipped = "(ERR) ";
+
if (global_settings.playlist_viewer_indices)
/* Display playlist index */
- snprintf(str, len, "%d. %s", track->display_index, name);
+ snprintf(str, len, "%d. %s%s", track->display_index, skipped, name);
else
- snprintf(str, len, "%s", name);
+ snprintf(str, len, "%s%s", skipped, name);
}