Added dircache support to playlist. Now playlist filename pointers are
automatically accuired from dircache. WPS UI response with dircache enabled should be instant. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7931 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
bc8a4e4b8c
commit
735f453730
8 changed files with 336 additions and 75 deletions
|
@ -340,6 +340,7 @@ int ft_enter(struct tree_context* c)
|
|||
int start_index=0;
|
||||
|
||||
lcd_stop_scroll();
|
||||
gui_syncsplash(0, true, str(LANG_WAIT));
|
||||
switch ( file->attr & TREE_ATTR_MASK ) {
|
||||
case TREE_ATTR_M3U:
|
||||
if (bookmark_autoload(buf))
|
||||
|
|
|
@ -3431,3 +3431,9 @@ eng: "Clear current presets?"
|
|||
voice: "Clear current presets?"
|
||||
new:
|
||||
|
||||
id: LANG_WAIT
|
||||
desc: general please wait splash
|
||||
eng: "=== Please Wait ==="
|
||||
voice: "Please wait"
|
||||
new:
|
||||
|
||||
|
|
137
apps/playback.c
137
apps/playback.c
|
@ -165,9 +165,6 @@ static volatile int buf_widx;
|
|||
/* Step count to the next unbuffered track. */
|
||||
static int last_peek_offset;
|
||||
|
||||
/* Index of the last buffered track. */
|
||||
static int last_index;
|
||||
|
||||
/* Track information (count in file buffer, read/write indexes for
|
||||
track ring structure. */
|
||||
int track_count;
|
||||
|
@ -589,7 +586,7 @@ static bool rebuffer_and_seek(int newpos)
|
|||
|
||||
while (cur_ti->available == 0 && cur_ti->filerem > 0) {
|
||||
yield();
|
||||
if (ci.stop_codec || ci.reload_codec)
|
||||
if (ci.stop_codec || ci.reload_codec || !queue_empty(&audio_queue))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1048,8 +1045,6 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
|
|||
if (tracks[track_widx].filesize != 0)
|
||||
return false;
|
||||
|
||||
last_index = playlist_get_display_index();
|
||||
|
||||
peek_again:
|
||||
/* Get track name from current playlist read position. */
|
||||
logf("Buffering track:%d/%d", track_widx, track_ridx);
|
||||
|
@ -1456,7 +1451,6 @@ void audio_update_trackinfo(void)
|
|||
} else {
|
||||
pcmbuf_add_event(codec_track_changed);
|
||||
}
|
||||
last_index = playlist_get_display_index();
|
||||
}
|
||||
|
||||
static void audio_stop_playback(void)
|
||||
|
@ -1519,8 +1513,8 @@ bool codec_request_next_track_callback(void)
|
|||
{
|
||||
if (current_codec == CODEC_IDX_VOICE) {
|
||||
voice_remaining = 0;
|
||||
/* Terminate the codec if they are messages waiting on the queue or
|
||||
core has been requested the codec to be terminated. */
|
||||
/* Terminate the codec if there are messages waiting on the queue or
|
||||
the core has been requested the codec to be terminated. */
|
||||
return !ci_voice.stop_codec && queue_empty(&voice_codec_queue);
|
||||
}
|
||||
|
||||
|
@ -1531,12 +1525,7 @@ bool codec_request_next_track_callback(void)
|
|||
|
||||
/* Advance to next track. */
|
||||
if (ci.reload_codec && new_track > 0) {
|
||||
if (!playlist_check(new_track)) {
|
||||
ci.reload_codec = false;
|
||||
return false;
|
||||
}
|
||||
last_peek_offset--;
|
||||
playlist_next(new_track);
|
||||
if (++track_ridx == MAX_TRACK)
|
||||
track_ridx = 0;
|
||||
|
||||
|
@ -1549,7 +1538,6 @@ bool codec_request_next_track_callback(void)
|
|||
if (tracks[track_ridx].filesize == 0) {
|
||||
logf("Loading from disk...");
|
||||
new_track = 0;
|
||||
last_index = -1;
|
||||
queue_post(&audio_queue, AUDIO_PLAY, 0);
|
||||
return false;
|
||||
}
|
||||
|
@ -1557,12 +1545,7 @@ bool codec_request_next_track_callback(void)
|
|||
|
||||
/* Advance to previous track. */
|
||||
else if (ci.reload_codec && new_track < 0) {
|
||||
if (!playlist_check(new_track)) {
|
||||
ci.reload_codec = false;
|
||||
return false;
|
||||
}
|
||||
last_peek_offset++;
|
||||
playlist_next(new_track);
|
||||
if (--track_ridx < 0)
|
||||
track_ridx = MAX_TRACK-1;
|
||||
if (tracks[track_ridx].filesize == 0 ||
|
||||
|
@ -1570,7 +1553,6 @@ bool codec_request_next_track_callback(void)
|
|||
/*+ (off_t)tracks[track_ridx].codecsize*/ > filebuflen) {
|
||||
logf("Loading from disk...");
|
||||
new_track = 0;
|
||||
last_index = -1;
|
||||
queue_post(&audio_queue, AUDIO_PLAY, 0);
|
||||
return false;
|
||||
}
|
||||
|
@ -1597,7 +1579,6 @@ bool codec_request_next_track_callback(void)
|
|||
logf("No more tracks [2]");
|
||||
ci.stop_codec = true;
|
||||
new_track = 0;
|
||||
last_index = -1;
|
||||
queue_post(&audio_queue, AUDIO_PLAY, 0);
|
||||
return false;
|
||||
}
|
||||
|
@ -1652,7 +1633,6 @@ static void initiate_track_change(int peek_index)
|
|||
|
||||
/* Detect if disk is spinning.. */
|
||||
if (filling) {
|
||||
playlist_next(peek_index);
|
||||
queue_post(&audio_queue, AUDIO_PLAY, 0);
|
||||
} else {
|
||||
new_track = peek_index;
|
||||
|
@ -1677,35 +1657,49 @@ static void initiate_dir_change(int direction)
|
|||
void audio_thread(void)
|
||||
{
|
||||
struct event ev;
|
||||
int last_tick = 0;
|
||||
bool play_pending = false;
|
||||
|
||||
while (1) {
|
||||
yield_codecs();
|
||||
|
||||
audio_check_buffer();
|
||||
if (!play_pending)
|
||||
{
|
||||
yield_codecs();
|
||||
audio_check_buffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
// ata_spin();
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
queue_wait_w_tmo(&audio_queue, &ev, 0);
|
||||
if (ev.id == SYS_TIMEOUT && play_pending)
|
||||
{
|
||||
ev.id = AUDIO_PLAY;
|
||||
ev.data = 0;
|
||||
}
|
||||
|
||||
switch (ev.id) {
|
||||
case AUDIO_PLAY:
|
||||
/* Refuse to start playback if we are already playing
|
||||
the requested track. This is needed because when skipping
|
||||
tracks fast, AUDIO_PLAY commands will get queued with the
|
||||
the same track and playback will stutter. */
|
||||
if (last_index == playlist_get_display_index() && playing
|
||||
&& pcm_is_playing()) {
|
||||
logf("already playing req. track");
|
||||
/* Don't start playing immediately if user is skipping tracks
|
||||
* fast to prevent UI lag. */
|
||||
track_count = 0;
|
||||
last_peek_offset = 0;
|
||||
if (current_tick - last_tick < HZ/2)
|
||||
{
|
||||
play_pending = true;
|
||||
break ;
|
||||
}
|
||||
|
||||
play_pending = false;
|
||||
|
||||
/* Do not start crossfading if audio is paused. */
|
||||
if (paused) {
|
||||
audio_stop_playback();
|
||||
paused = false;
|
||||
}
|
||||
if (paused)
|
||||
pcmbuf_play_stop();
|
||||
|
||||
#ifdef CONFIG_TUNER
|
||||
/* check if radio is playing */
|
||||
if(radio_get_status() != FMRADIO_OFF){
|
||||
radio_stop();
|
||||
if (radio_get_status() != FMRADIO_OFF) {
|
||||
radio_stop();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1751,15 +1745,13 @@ void audio_thread(void)
|
|||
|
||||
case AUDIO_NEXT:
|
||||
logf("audio_next");
|
||||
if (global_settings.beep)
|
||||
pcmbuf_beep(5000, 100, 2500*global_settings.beep);
|
||||
last_tick = current_tick;
|
||||
initiate_track_change(1);
|
||||
break ;
|
||||
|
||||
case AUDIO_PREV:
|
||||
logf("audio_prev");
|
||||
if (global_settings.beep)
|
||||
pcmbuf_beep(5000, 100, 2500*global_settings.beep);
|
||||
last_tick = current_tick;
|
||||
initiate_track_change(-1);
|
||||
break;
|
||||
|
||||
|
@ -1793,7 +1785,7 @@ void audio_thread(void)
|
|||
// audio_change_track();
|
||||
break ;
|
||||
|
||||
#ifndef SIMULATOR
|
||||
#ifndef SIMULATOR
|
||||
case SYS_USB_CONNECTED:
|
||||
logf("USB: Audio core");
|
||||
audio_stop_playback();
|
||||
|
@ -1973,12 +1965,28 @@ void voice_init(void)
|
|||
|
||||
struct mp3entry* audio_current_track(void)
|
||||
{
|
||||
// logf("audio_current_track");
|
||||
const char *filename;
|
||||
const char *p;
|
||||
static struct mp3entry temp_id3;
|
||||
|
||||
if (track_count > 0 && cur_ti->taginfo_ready)
|
||||
return (struct mp3entry *)&cur_ti->id3;
|
||||
else
|
||||
return NULL;
|
||||
else {
|
||||
filename = playlist_peek(0);
|
||||
if (!filename)
|
||||
filename = "No file!";
|
||||
p = strrchr(filename, '/');
|
||||
if (!p)
|
||||
p = filename;
|
||||
else
|
||||
p++;
|
||||
|
||||
memset(&temp_id3, 0, sizeof(struct mp3entry));
|
||||
strncpy(temp_id3.path, p, sizeof(temp_id3.path)-1);
|
||||
temp_id3.title = &temp_id3.path[0];
|
||||
|
||||
return &temp_id3;
|
||||
}
|
||||
}
|
||||
|
||||
struct mp3entry* audio_next_track(void)
|
||||
|
@ -1994,16 +2002,12 @@ struct mp3entry* audio_next_track(void)
|
|||
if (!tracks[next_idx].taginfo_ready)
|
||||
return NULL;
|
||||
|
||||
//logf("audio_next_track");
|
||||
|
||||
return &tracks[next_idx].id3;
|
||||
}
|
||||
|
||||
bool audio_has_changed_track(void)
|
||||
{
|
||||
if (track_changed && track_count > 0 && playing) {
|
||||
if (!cur_ti->taginfo_ready)
|
||||
return false;
|
||||
if (track_changed) {
|
||||
track_changed = false;
|
||||
return true;
|
||||
}
|
||||
|
@ -2014,7 +2018,6 @@ bool audio_has_changed_track(void)
|
|||
void audio_play(int offset)
|
||||
{
|
||||
logf("audio_play");
|
||||
last_index = -1;
|
||||
queue_post(&audio_queue, AUDIO_PLAY, (void *)offset);
|
||||
}
|
||||
|
||||
|
@ -2043,11 +2046,37 @@ void audio_resume(void)
|
|||
|
||||
void audio_next(void)
|
||||
{
|
||||
/* Prevent UI lag and update the WPS immediately. */
|
||||
if (global_settings.beep)
|
||||
pcmbuf_beep(5000, 100, 2500*global_settings.beep);
|
||||
|
||||
if (!playlist_check(1))
|
||||
return ;
|
||||
playlist_next(1);
|
||||
track_changed = true;
|
||||
|
||||
/* Force WPS to update even if audio thread is blocked spinning. */
|
||||
if (mutex_bufferfill.locked)
|
||||
cur_ti->taginfo_ready = false;
|
||||
|
||||
queue_post(&audio_queue, AUDIO_NEXT, 0);
|
||||
}
|
||||
|
||||
void audio_prev(void)
|
||||
{
|
||||
/* Prevent UI lag and update the WPS immediately. */
|
||||
if (global_settings.beep)
|
||||
pcmbuf_beep(5000, 100, 2500*global_settings.beep);
|
||||
|
||||
if (!playlist_check(-1))
|
||||
return ;
|
||||
playlist_next(-1);
|
||||
track_changed = true;
|
||||
|
||||
/* Force WPS to update even if audio thread is blocked spinning. */
|
||||
if (mutex_bufferfill.locked)
|
||||
cur_ti->taginfo_ready = false;
|
||||
|
||||
queue_post(&audio_queue, AUDIO_PREV, 0);
|
||||
}
|
||||
|
||||
|
|
216
apps/playlist.c
216
apps/playlist.c
|
@ -86,6 +86,9 @@
|
|||
#include "button.h"
|
||||
#include "filetree.h"
|
||||
#include "abrepeat.h"
|
||||
#include "dircache.h"
|
||||
#include "thread.h"
|
||||
#include "usb.h"
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
#include "icons.h"
|
||||
#include "widgets.h"
|
||||
|
@ -162,7 +165,7 @@ static int get_next_index(const struct playlist_info* playlist, int steps,
|
|||
static void find_and_set_playlist_index(struct playlist_info* playlist,
|
||||
unsigned int seek);
|
||||
static int compare(const void* p1, const void* p2);
|
||||
static int get_filename(struct playlist_info* playlist, int seek,
|
||||
static int get_filename(struct playlist_info* playlist, int index, int seek,
|
||||
bool control_file, char *buf, int buf_length);
|
||||
static int get_next_directory(char *dir);
|
||||
static int get_next_dir(char *dir, bool is_forward, bool recursion);
|
||||
|
@ -175,6 +178,14 @@ static void display_buffer_full(void);
|
|||
static int flush_pending_control(struct playlist_info* playlist);
|
||||
static int rotate_index(const struct playlist_info* playlist, int index);
|
||||
|
||||
#ifdef HAVE_DIRCACHE
|
||||
#define PLAYLIST_LOAD_POINTERS 1
|
||||
|
||||
static struct event_queue playlist_queue;
|
||||
static long playlist_stack[(DEFAULT_STACK_SIZE + 0x400)/sizeof(long)];
|
||||
static const char playlist_thread_name[] = "playlist cachectrl";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* remove any files and indices associated with the playlist
|
||||
*/
|
||||
|
@ -394,11 +405,15 @@ static int add_indices_to_playlist(struct playlist_info* playlist,
|
|||
{
|
||||
/* Store a new entry */
|
||||
playlist->indices[ playlist->amount ] = i+count;
|
||||
playlist->amount++;
|
||||
#ifdef HAVE_DIRCACHE
|
||||
if (playlist->filenames)
|
||||
playlist->filenames[ playlist->amount ] = NULL;
|
||||
#endif
|
||||
if ( playlist->amount >= playlist->max_playlist_size ) {
|
||||
display_buffer_full();
|
||||
return -1;
|
||||
}
|
||||
playlist->amount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -406,6 +421,10 @@ static int add_indices_to_playlist(struct playlist_info* playlist,
|
|||
i+= count;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DIRCACHE
|
||||
queue_post(&playlist_queue, PLAYLIST_LOAD_POINTERS, 0);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -499,8 +518,14 @@ static int add_track_to_playlist(struct playlist_info* playlist,
|
|||
|
||||
/* shift indices so that track can be added */
|
||||
for (i=playlist->amount; i>insert_position; i--)
|
||||
{
|
||||
playlist->indices[i] = playlist->indices[i-1];
|
||||
|
||||
#ifdef HAVE_DIRCACHE
|
||||
if (playlist->filenames)
|
||||
playlist->filenames[i] = playlist->filenames[i-1];
|
||||
#endif
|
||||
}
|
||||
|
||||
/* update stored indices if needed */
|
||||
if (playlist->amount > 0 && insert_position <= playlist->index)
|
||||
playlist->index++;
|
||||
|
@ -554,6 +579,12 @@ static int add_track_to_playlist(struct playlist_info* playlist,
|
|||
|
||||
playlist->indices[insert_position] = flags | seek_pos;
|
||||
|
||||
#ifdef HAVE_DIRCACHE
|
||||
if (playlist->filenames)
|
||||
playlist->filenames[insert_position] = NULL;
|
||||
queue_post(&playlist_queue, PLAYLIST_LOAD_POINTERS, 0);
|
||||
#endif
|
||||
|
||||
playlist->amount++;
|
||||
playlist->num_inserted_tracks++;
|
||||
|
||||
|
@ -693,7 +724,13 @@ static int remove_track_from_playlist(struct playlist_info* playlist,
|
|||
|
||||
/* shift indices now that track has been removed */
|
||||
for (i=position; i<playlist->amount; i++)
|
||||
{
|
||||
playlist->indices[i] = playlist->indices[i+1];
|
||||
#ifdef HAVE_DIRCACHE
|
||||
if (playlist->filenames)
|
||||
playlist->filenames[i] = playlist->filenames[i+1];
|
||||
#endif
|
||||
}
|
||||
|
||||
playlist->amount--;
|
||||
|
||||
|
@ -780,6 +817,14 @@ static int randomise_playlist(struct playlist_info* playlist,
|
|||
store = playlist->indices[candidate];
|
||||
playlist->indices[candidate] = playlist->indices[count];
|
||||
playlist->indices[count] = store;
|
||||
#ifdef HAVE_DIRCACHE
|
||||
if (playlist->filenames)
|
||||
{
|
||||
store = (int)playlist->filenames[candidate];
|
||||
playlist->filenames[candidate] = playlist->filenames[count];
|
||||
playlist->filenames[count] = (struct dircache_entry *)store;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (start_current)
|
||||
|
@ -817,6 +862,13 @@ static int sort_playlist(struct playlist_info* playlist, bool start_current,
|
|||
qsort(playlist->indices, playlist->amount,
|
||||
sizeof(playlist->indices[0]), compare);
|
||||
|
||||
#ifdef HAVE_DIRCACHE
|
||||
/** We need to re-check the song names from disk because qsort can't
|
||||
* sort two arrays at once :/
|
||||
* FIXME: Please implement a better way to do this. */
|
||||
queue_post(&playlist_queue, PLAYLIST_LOAD_POINTERS, 0);
|
||||
#endif
|
||||
|
||||
if (start_current)
|
||||
find_and_set_playlist_index(playlist, current);
|
||||
|
||||
|
@ -1040,10 +1092,88 @@ static int compare(const void* p1, const void* p2)
|
|||
return *e1 - *e2;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DIRCACHE
|
||||
/**
|
||||
* Thread to update filename pointers to dircache on background
|
||||
* without affecting playlist load up performance.
|
||||
*/
|
||||
static void playlist_thread(void)
|
||||
{
|
||||
struct event ev;
|
||||
bool dirty_pointers = false;
|
||||
static char tmp[MAX_PATH+1];
|
||||
|
||||
struct playlist_info *playlist;
|
||||
int index;
|
||||
int seek;
|
||||
bool control_file;
|
||||
|
||||
while (1)
|
||||
{
|
||||
queue_wait_w_tmo(&playlist_queue, &ev, HZ*5);
|
||||
|
||||
switch (ev.id)
|
||||
{
|
||||
case PLAYLIST_LOAD_POINTERS:
|
||||
dirty_pointers = true;
|
||||
break ;
|
||||
|
||||
/* Start the background scanning after 5s. */
|
||||
case SYS_TIMEOUT:
|
||||
if (!dirty_pointers)
|
||||
break ;
|
||||
|
||||
playlist = ¤t_playlist;
|
||||
if (!dircache_is_enabled() || !playlist->filenames
|
||||
|| playlist->amount <= 0)
|
||||
break ;
|
||||
|
||||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||
cpu_boost(true);
|
||||
#endif
|
||||
for (index = 0; index < playlist->amount
|
||||
&& queue_empty(&playlist_queue); index++)
|
||||
{
|
||||
/* Process only pointers that are not already loaded. */
|
||||
if (playlist->filenames[index])
|
||||
continue ;
|
||||
|
||||
control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK;
|
||||
seek = playlist->indices[index] & PLAYLIST_SEEK_MASK;
|
||||
|
||||
/* Load the filename from playlist file. */
|
||||
if (get_filename(playlist, index, seek, control_file, tmp,
|
||||
sizeof(tmp)) < 0)
|
||||
break ;
|
||||
|
||||
/* Set the dircache entry pointer. */
|
||||
playlist->filenames[index] = dircache_get_entry_ptr(tmp);
|
||||
|
||||
/* And be on background so user doesn't notice any delays. */
|
||||
yield();
|
||||
}
|
||||
|
||||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||
cpu_boost(false);
|
||||
#endif
|
||||
dirty_pointers = false;
|
||||
break ;
|
||||
|
||||
#ifndef SIMULATOR
|
||||
case SYS_USB_CONNECTED:
|
||||
usb_acknowledge(SYS_USB_CONNECTED_ACK);
|
||||
usb_wait_for_disconnect(&playlist_queue);
|
||||
break ;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* gets pathname for track at seek index
|
||||
*/
|
||||
static int get_filename(struct playlist_info* playlist, int seek,
|
||||
static int get_filename(struct playlist_info* playlist, int index, int seek,
|
||||
bool control_file, char *buf, int buf_length)
|
||||
{
|
||||
int fd;
|
||||
|
@ -1054,13 +1184,26 @@ static int get_filename(struct playlist_info* playlist, int seek,
|
|||
if (buf_length > MAX_PATH+1)
|
||||
buf_length = MAX_PATH+1;
|
||||
|
||||
if (playlist->in_ram && !control_file)
|
||||
#ifdef HAVE_DIRCACHE
|
||||
if (dircache_is_enabled() && playlist->filenames)
|
||||
{
|
||||
if (playlist->filenames[index] != NULL)
|
||||
{
|
||||
dircache_copy_path(playlist->filenames[index], tmp_buf, sizeof(tmp_buf)-1);
|
||||
max = strlen(tmp_buf) + 1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)index;
|
||||
#endif
|
||||
|
||||
if (playlist->in_ram && !control_file && max < 0)
|
||||
{
|
||||
strncpy(tmp_buf, &playlist->buffer[seek], sizeof(tmp_buf));
|
||||
tmp_buf[MAX_PATH] = '\0';
|
||||
max = strlen(tmp_buf) + 1;
|
||||
}
|
||||
else
|
||||
else if (max < 0)
|
||||
{
|
||||
if (control_file)
|
||||
fd = playlist->control_fd;
|
||||
|
@ -1482,6 +1625,16 @@ void playlist_init(void)
|
|||
playlist->buffer = buffer_alloc(playlist->buffer_size);
|
||||
mutex_init(&playlist->control_mutex);
|
||||
empty_playlist(playlist, true);
|
||||
|
||||
#ifdef HAVE_DIRCACHE
|
||||
playlist->filenames = buffer_alloc(
|
||||
playlist->max_playlist_size * sizeof(int));
|
||||
memset(playlist->filenames, 0,
|
||||
playlist->max_playlist_size * sizeof(int));
|
||||
create_thread(playlist_thread, playlist_stack, sizeof(playlist_stack),
|
||||
playlist_thread_name);
|
||||
queue_init(&playlist_queue);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1906,8 +2059,9 @@ int playlist_add(const char *filename)
|
|||
return -1;
|
||||
}
|
||||
|
||||
playlist->indices[playlist->amount++] = playlist->buffer_end_pos;
|
||||
|
||||
playlist->indices[playlist->amount] = playlist->buffer_end_pos;
|
||||
playlist->amount++;
|
||||
|
||||
strcpy(&playlist->buffer[playlist->buffer_end_pos], filename);
|
||||
playlist->buffer_end_pos += len;
|
||||
playlist->buffer[playlist->buffer_end_pos++] = '\0';
|
||||
|
@ -1991,7 +2145,7 @@ char* playlist_peek(int steps)
|
|||
control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK;
|
||||
seek = playlist->indices[index] & PLAYLIST_SEEK_MASK;
|
||||
|
||||
if (get_filename(playlist, seek, control_file, now_playing,
|
||||
if (get_filename(playlist, index, seek, control_file, now_playing,
|
||||
MAX_PATH+1) < 0)
|
||||
return NULL;
|
||||
|
||||
|
@ -2003,11 +2157,21 @@ char* playlist_peek(int steps)
|
|||
(workaround for buggy playlist creation tools) */
|
||||
while (temp_ptr)
|
||||
{
|
||||
fd = open(temp_ptr, O_RDONLY);
|
||||
if (fd >= 0)
|
||||
#ifdef HAVE_DIRCACHE
|
||||
if (dircache_is_enabled())
|
||||
{
|
||||
close(fd);
|
||||
break;
|
||||
if (dircache_get_entry_ptr(temp_ptr))
|
||||
break;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
fd = open(temp_ptr, O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
close(fd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
temp_ptr = strchr(temp_ptr+1, '/');
|
||||
|
@ -2278,16 +2442,26 @@ int playlist_create_ex(struct playlist_info* playlist,
|
|||
{
|
||||
int num_indices = index_buffer_size / sizeof(int);
|
||||
|
||||
#ifdef HAVE_DIRCACHE
|
||||
num_indices /= 2;
|
||||
#endif
|
||||
if (num_indices > global_settings.max_files_in_playlist)
|
||||
num_indices = global_settings.max_files_in_playlist;
|
||||
|
||||
playlist->max_playlist_size = num_indices;
|
||||
playlist->indices = index_buffer;
|
||||
#ifdef HAVE_DIRCACHE
|
||||
playlist->filenames = (const struct dircache_entry **)
|
||||
&playlist->indices[num_indices];
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
playlist->max_playlist_size = current_playlist.max_playlist_size;
|
||||
playlist->indices = current_playlist.indices;
|
||||
#ifdef HAVE_DIRCACHE
|
||||
playlist->filenames = current_playlist.filenames;
|
||||
#endif
|
||||
}
|
||||
|
||||
playlist->buffer_size = 0;
|
||||
|
@ -2336,9 +2510,15 @@ int playlist_set_current(struct playlist_info* playlist)
|
|||
current_playlist.dirlen = playlist->dirlen;
|
||||
|
||||
if (playlist->indices && playlist->indices != current_playlist.indices)
|
||||
{
|
||||
memcpy(current_playlist.indices, playlist->indices,
|
||||
playlist->max_playlist_size*sizeof(int));
|
||||
|
||||
playlist->max_playlist_size*sizeof(int));
|
||||
#ifdef HAVE_DIRCACHE
|
||||
memcpy(current_playlist.filenames, playlist->filenames,
|
||||
playlist->max_playlist_size*sizeof(int));
|
||||
#endif
|
||||
}
|
||||
|
||||
current_playlist.first_index = playlist->first_index;
|
||||
current_playlist.amount = playlist->amount;
|
||||
current_playlist.last_insert_pos = playlist->last_insert_pos;
|
||||
|
@ -2620,7 +2800,7 @@ int playlist_move(struct playlist_info* playlist, int index, int new_index)
|
|||
queue = playlist->indices[index] & PLAYLIST_QUEUE_MASK;
|
||||
seek = playlist->indices[index] & PLAYLIST_SEEK_MASK;
|
||||
|
||||
if (get_filename(playlist, seek, control_file, filename,
|
||||
if (get_filename(playlist, index, seek, control_file, filename,
|
||||
sizeof(filename)) < 0)
|
||||
return -1;
|
||||
|
||||
|
@ -2812,7 +2992,7 @@ int playlist_get_track_info(struct playlist_info* playlist, int index,
|
|||
control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK;
|
||||
seek = playlist->indices[index] & PLAYLIST_SEEK_MASK;
|
||||
|
||||
if (get_filename(playlist, seek, control_file, info->filename,
|
||||
if (get_filename(playlist, index, seek, control_file, info->filename,
|
||||
sizeof(info->filename)) < 0)
|
||||
return -1;
|
||||
|
||||
|
@ -2883,7 +3063,7 @@ int playlist_save(struct playlist_info* playlist, char *filename)
|
|||
/* Don't save queued files */
|
||||
if (!queue)
|
||||
{
|
||||
if (get_filename(playlist, seek, control_file, tmp_buf,
|
||||
if (get_filename(playlist, index, seek, control_file, tmp_buf,
|
||||
MAX_PATH+1) < 0)
|
||||
{
|
||||
result = -1;
|
||||
|
|
|
@ -36,7 +36,8 @@ struct playlist_info
|
|||
int control_fd; /* descriptor of the open control file */
|
||||
bool control_created; /* has control file been created? */
|
||||
int dirlen; /* Length of the path to the playlist file */
|
||||
unsigned long *indices; /* array of indices */
|
||||
unsigned long *indices; /* array of indices */
|
||||
const struct dircache_entry **filenames; /* Entries from dircache */
|
||||
int max_playlist_size; /* Max number of files in playlist. Mirror of
|
||||
global_settings.max_files_in_playlist */
|
||||
bool in_ram; /* playlist stored in ram (dirplay) */
|
||||
|
|
|
@ -597,6 +597,7 @@ long wps_show(void)
|
|||
#endif
|
||||
#endif
|
||||
left_lastclick = current_tick;
|
||||
update_track = true;
|
||||
|
||||
#ifdef AB_REPEAT_ENABLE
|
||||
/* if we're in A/B repeat mode and the current position
|
||||
|
@ -604,7 +605,6 @@ long wps_show(void)
|
|||
if ( ab_repeat_mode_enabled() && ab_after_A_marker(id3->elapsed) )
|
||||
{
|
||||
ab_jump_to_A_marker();
|
||||
update_track = true;
|
||||
break;
|
||||
}
|
||||
/* ...otherwise, do it normally */
|
||||
|
@ -655,6 +655,7 @@ long wps_show(void)
|
|||
#endif
|
||||
#endif
|
||||
right_lastclick = current_tick;
|
||||
update_track = true;
|
||||
|
||||
#ifdef AB_REPEAT_ENABLE
|
||||
/* if we're in A/B repeat mode and the current position is
|
||||
|
@ -662,7 +663,6 @@ long wps_show(void)
|
|||
if ( ab_repeat_mode_enabled() && ab_before_A_marker(id3->elapsed) )
|
||||
{
|
||||
ab_jump_to_A_marker();
|
||||
update_track = true;
|
||||
break;
|
||||
}
|
||||
/* ...otherwise, do it normally */
|
||||
|
|
|
@ -77,6 +77,7 @@ static struct dircache_entry* allocate_entry(void)
|
|||
dircache_size += sizeof(struct dircache_entry);
|
||||
next_entry->name_len = 0;
|
||||
next_entry->d_name = NULL;
|
||||
next_entry->up = NULL;
|
||||
next_entry->down = NULL;
|
||||
next_entry->next = NULL;
|
||||
|
||||
|
@ -88,6 +89,7 @@ static struct dircache_entry* dircache_gen_next(struct dircache_entry *ce)
|
|||
struct dircache_entry *next_entry;
|
||||
|
||||
next_entry = allocate_entry();
|
||||
next_entry->up = ce->up;
|
||||
ce->next = next_entry;
|
||||
|
||||
return next_entry;
|
||||
|
@ -98,6 +100,7 @@ static struct dircache_entry* dircache_gen_down(struct dircache_entry *ce)
|
|||
struct dircache_entry *next_entry;
|
||||
|
||||
next_entry = allocate_entry();
|
||||
next_entry->up = ce;
|
||||
ce->down = next_entry;
|
||||
|
||||
return next_entry;
|
||||
|
@ -176,6 +179,7 @@ static int dircache_travel(struct fat_dir *dir, struct dircache_entry *ce)
|
|||
int depth = 0;
|
||||
int result;
|
||||
|
||||
memset(ce, 0, sizeof(struct dircache_entry));
|
||||
dir_recursion[0].dir = dir;
|
||||
dir_recursion[0].ce = ce;
|
||||
|
||||
|
@ -517,6 +521,43 @@ void dircache_disable(void)
|
|||
logf("Cache released");
|
||||
}
|
||||
|
||||
const struct dircache_entry *dircache_get_entry_ptr(const char *filename)
|
||||
{
|
||||
if (!dircache_initialized || filename == NULL)
|
||||
return NULL;
|
||||
|
||||
return dircache_get_entry(filename, false, false);
|
||||
}
|
||||
|
||||
void dircache_copy_path(const struct dircache_entry *entry, char *buf, int size)
|
||||
{
|
||||
const struct dircache_entry *down[MAX_SCAN_DEPTH];
|
||||
int depth = 0;
|
||||
|
||||
if (size <= 0)
|
||||
return ;
|
||||
|
||||
buf[0] = '\0';
|
||||
|
||||
if (entry == NULL)
|
||||
return ;
|
||||
|
||||
do {
|
||||
down[depth] = entry;
|
||||
entry = entry->up;
|
||||
depth++;
|
||||
} while (entry != NULL && depth < MAX_SCAN_DEPTH);
|
||||
|
||||
while (--depth >= 0)
|
||||
{
|
||||
snprintf(buf, size, "/%s", down[depth]->d_name);
|
||||
buf += down[depth]->name_len; /* '/' + d_name */
|
||||
size -= down[depth]->name_len;
|
||||
if (size <= 0)
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Directory cache live updating functions --- */
|
||||
static struct dircache_entry* dircache_new_entry(const char *path, int attribute)
|
||||
{
|
||||
|
|
|
@ -47,6 +47,7 @@ struct dircache_maindata {
|
|||
/* Exported structures. */
|
||||
struct dircache_entry {
|
||||
struct dircache_entry *next;
|
||||
struct dircache_entry *up;
|
||||
struct dircache_entry *down;
|
||||
int attribute;
|
||||
long size;
|
||||
|
@ -71,6 +72,8 @@ int dircache_build(int last_size);
|
|||
bool dircache_is_enabled(void);
|
||||
int dircache_get_cache_size(void);
|
||||
void dircache_disable(void);
|
||||
const struct dircache_entry *dircache_get_entry_ptr(const char *filename);
|
||||
void dircache_copy_path(const struct dircache_entry *entry, char *buf, int size);
|
||||
|
||||
void dircache_bind(int fd, const char *path);
|
||||
void dircache_update_filesize(int fd, long newsize);
|
||||
|
|
Loading…
Reference in a new issue