summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2005-11-17 19:31:29 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2005-11-17 19:31:29 +0000
commit735f4537309d4a66e16dd020fa99149a9d5f8d29 (patch)
tree7326f1f8f45f43c40bc78b86e4809087dffa9aa7
parentbc8a4e4b8cb613b7a0e4f348fe81086f92d9a994 (diff)
downloadrockbox-735f4537309d4a66e16dd020fa99149a9d5f8d29.zip
rockbox-735f4537309d4a66e16dd020fa99149a9d5f8d29.tar.gz
rockbox-735f4537309d4a66e16dd020fa99149a9d5f8d29.tar.bz2
rockbox-735f4537309d4a66e16dd020fa99149a9d5f8d29.tar.xz
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
-rw-r--r--apps/filetree.c1
-rw-r--r--apps/lang/english.lang6
-rw-r--r--apps/playback.c137
-rw-r--r--apps/playlist.c216
-rw-r--r--apps/playlist.h3
-rw-r--r--apps/wps.c4
-rw-r--r--firmware/common/dircache.c41
-rw-r--r--firmware/include/dircache.h3
8 files changed, 336 insertions, 75 deletions
diff --git a/apps/filetree.c b/apps/filetree.c
index a873d85..a9670e1 100644
--- a/apps/filetree.c
+++ b/apps/filetree.c
@@ -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))
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 4e712a2..6afcb57 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -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:
+
diff --git a/apps/playback.c b/apps/playback.c
index 7f28331..b68cb64 100644
--- a/apps/playback.c
+++ b/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);
}
diff --git a/apps/playlist.c b/apps/playlist.c
index a2f46cf..ee09eec 100644
--- a/apps/playlist.c
+++ b/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 = &current_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;
diff --git a/apps/playlist.h b/apps/playlist.h
index efac303..286823e 100644
--- a/apps/playlist.h
+++ b/apps/playlist.h
@@ -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) */
diff --git a/apps/wps.c b/apps/wps.c
index 266c506..573444f 100644
--- a/apps/wps.c
+++ b/apps/wps.c
@@ -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 */
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c
index fa24321..259c34c 100644
--- a/firmware/common/dircache.c
+++ b/firmware/common/dircache.c
@@ -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)
{
diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h
index 48b74e0..11d7335 100644
--- a/firmware/include/dircache.h
+++ b/firmware/include/dircache.h
@@ -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);