diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index 1bcfb25f5e..b67e889a95 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c @@ -193,7 +193,7 @@ void pcmbuf_watermark_callback(int bytes_left) { /* 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 @@ static void crossfade_start(void) } 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 @@ static void crossfade_start(void) 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* pcmbuf_request_buffer(long length, long *realsize) { 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 @@ void pcmbuf_flush_buffer(long length) 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 5b78ad53ba..7c3d63c5a8 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -296,9 +296,15 @@ bool codec_pcmbuf_insert_split_callback(void *ch1, void *ch2, } 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 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) 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 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) 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 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) 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 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) /* 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 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) 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 70df8113e0..91eacb7c03 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 @@ static int sort_playlist(struct playlist_info* playlist, bool start_current, 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 @@ static int get_next_index(const struct playlist_info* playlist, int steps, (!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 @@ static int get_next_index(const struct playlist_info* playlist, int steps, 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 @@ static int get_next_index(const struct playlist_info* playlist, int steps, } } + /* No luck if the whole playlist was bad. */ + if (playlist->indices[next_index] & PLAYLIST_SKIPPED) + return -1; + return next_index; } @@ -2652,8 +2726,12 @@ int playlist_get_track_info(struct playlist_info* playlist, int index, 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 eee8bf5945..1937c48a12 100644 --- a/apps/playlist.h +++ b/apps/playlist.h @@ -58,6 +58,7 @@ struct playlist_info #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 @@ int playlist_insert_directory(struct playlist_info* playlist, 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 b7a042733e..70c1cf8995 100644 --- a/apps/playlist_viewer.c +++ b/apps/playlist_viewer.c @@ -112,6 +112,7 @@ struct playlist_entry { 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 @@ static int load_entry(int index, int pos, char* p, int size) 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_name(char* dest, const char* src) 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); }