forked from len0rd/rockbox
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;
|
int start_index=0;
|
||||||
|
|
||||||
lcd_stop_scroll();
|
lcd_stop_scroll();
|
||||||
|
gui_syncsplash(0, true, str(LANG_WAIT));
|
||||||
switch ( file->attr & TREE_ATTR_MASK ) {
|
switch ( file->attr & TREE_ATTR_MASK ) {
|
||||||
case TREE_ATTR_M3U:
|
case TREE_ATTR_M3U:
|
||||||
if (bookmark_autoload(buf))
|
if (bookmark_autoload(buf))
|
||||||
|
|
|
@ -3431,3 +3431,9 @@ eng: "Clear current presets?"
|
||||||
voice: "Clear current presets?"
|
voice: "Clear current presets?"
|
||||||
new:
|
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. */
|
/* Step count to the next unbuffered track. */
|
||||||
static int last_peek_offset;
|
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 information (count in file buffer, read/write indexes for
|
||||||
track ring structure. */
|
track ring structure. */
|
||||||
int track_count;
|
int track_count;
|
||||||
|
@ -589,7 +586,7 @@ static bool rebuffer_and_seek(int newpos)
|
||||||
|
|
||||||
while (cur_ti->available == 0 && cur_ti->filerem > 0) {
|
while (cur_ti->available == 0 && cur_ti->filerem > 0) {
|
||||||
yield();
|
yield();
|
||||||
if (ci.stop_codec || ci.reload_codec)
|
if (ci.stop_codec || ci.reload_codec || !queue_empty(&audio_queue))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1048,8 +1045,6 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
|
||||||
if (tracks[track_widx].filesize != 0)
|
if (tracks[track_widx].filesize != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
last_index = playlist_get_display_index();
|
|
||||||
|
|
||||||
peek_again:
|
peek_again:
|
||||||
/* Get track name from current playlist read position. */
|
/* Get track name from current playlist read position. */
|
||||||
logf("Buffering track:%d/%d", track_widx, track_ridx);
|
logf("Buffering track:%d/%d", track_widx, track_ridx);
|
||||||
|
@ -1456,7 +1451,6 @@ void audio_update_trackinfo(void)
|
||||||
} else {
|
} else {
|
||||||
pcmbuf_add_event(codec_track_changed);
|
pcmbuf_add_event(codec_track_changed);
|
||||||
}
|
}
|
||||||
last_index = playlist_get_display_index();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void audio_stop_playback(void)
|
static void audio_stop_playback(void)
|
||||||
|
@ -1519,8 +1513,8 @@ bool codec_request_next_track_callback(void)
|
||||||
{
|
{
|
||||||
if (current_codec == CODEC_IDX_VOICE) {
|
if (current_codec == CODEC_IDX_VOICE) {
|
||||||
voice_remaining = 0;
|
voice_remaining = 0;
|
||||||
/* Terminate the codec if they are messages waiting on the queue or
|
/* Terminate the codec if there are messages waiting on the queue or
|
||||||
core has been requested the codec to be terminated. */
|
the core has been requested the codec to be terminated. */
|
||||||
return !ci_voice.stop_codec && queue_empty(&voice_codec_queue);
|
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. */
|
/* Advance to next track. */
|
||||||
if (ci.reload_codec && new_track > 0) {
|
if (ci.reload_codec && new_track > 0) {
|
||||||
if (!playlist_check(new_track)) {
|
|
||||||
ci.reload_codec = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
last_peek_offset--;
|
last_peek_offset--;
|
||||||
playlist_next(new_track);
|
|
||||||
if (++track_ridx == MAX_TRACK)
|
if (++track_ridx == MAX_TRACK)
|
||||||
track_ridx = 0;
|
track_ridx = 0;
|
||||||
|
|
||||||
|
@ -1549,7 +1538,6 @@ bool codec_request_next_track_callback(void)
|
||||||
if (tracks[track_ridx].filesize == 0) {
|
if (tracks[track_ridx].filesize == 0) {
|
||||||
logf("Loading from disk...");
|
logf("Loading from disk...");
|
||||||
new_track = 0;
|
new_track = 0;
|
||||||
last_index = -1;
|
|
||||||
queue_post(&audio_queue, AUDIO_PLAY, 0);
|
queue_post(&audio_queue, AUDIO_PLAY, 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1557,12 +1545,7 @@ bool codec_request_next_track_callback(void)
|
||||||
|
|
||||||
/* Advance to previous track. */
|
/* Advance to previous track. */
|
||||||
else if (ci.reload_codec && new_track < 0) {
|
else if (ci.reload_codec && new_track < 0) {
|
||||||
if (!playlist_check(new_track)) {
|
|
||||||
ci.reload_codec = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
last_peek_offset++;
|
last_peek_offset++;
|
||||||
playlist_next(new_track);
|
|
||||||
if (--track_ridx < 0)
|
if (--track_ridx < 0)
|
||||||
track_ridx = MAX_TRACK-1;
|
track_ridx = MAX_TRACK-1;
|
||||||
if (tracks[track_ridx].filesize == 0 ||
|
if (tracks[track_ridx].filesize == 0 ||
|
||||||
|
@ -1570,7 +1553,6 @@ bool codec_request_next_track_callback(void)
|
||||||
/*+ (off_t)tracks[track_ridx].codecsize*/ > filebuflen) {
|
/*+ (off_t)tracks[track_ridx].codecsize*/ > filebuflen) {
|
||||||
logf("Loading from disk...");
|
logf("Loading from disk...");
|
||||||
new_track = 0;
|
new_track = 0;
|
||||||
last_index = -1;
|
|
||||||
queue_post(&audio_queue, AUDIO_PLAY, 0);
|
queue_post(&audio_queue, AUDIO_PLAY, 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1597,7 +1579,6 @@ bool codec_request_next_track_callback(void)
|
||||||
logf("No more tracks [2]");
|
logf("No more tracks [2]");
|
||||||
ci.stop_codec = true;
|
ci.stop_codec = true;
|
||||||
new_track = 0;
|
new_track = 0;
|
||||||
last_index = -1;
|
|
||||||
queue_post(&audio_queue, AUDIO_PLAY, 0);
|
queue_post(&audio_queue, AUDIO_PLAY, 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1652,7 +1633,6 @@ static void initiate_track_change(int peek_index)
|
||||||
|
|
||||||
/* Detect if disk is spinning.. */
|
/* Detect if disk is spinning.. */
|
||||||
if (filling) {
|
if (filling) {
|
||||||
playlist_next(peek_index);
|
|
||||||
queue_post(&audio_queue, AUDIO_PLAY, 0);
|
queue_post(&audio_queue, AUDIO_PLAY, 0);
|
||||||
} else {
|
} else {
|
||||||
new_track = peek_index;
|
new_track = peek_index;
|
||||||
|
@ -1677,35 +1657,49 @@ static void initiate_dir_change(int direction)
|
||||||
void audio_thread(void)
|
void audio_thread(void)
|
||||||
{
|
{
|
||||||
struct event ev;
|
struct event ev;
|
||||||
|
int last_tick = 0;
|
||||||
|
bool play_pending = false;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
yield_codecs();
|
if (!play_pending)
|
||||||
|
{
|
||||||
audio_check_buffer();
|
yield_codecs();
|
||||||
|
audio_check_buffer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ata_spin();
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
queue_wait_w_tmo(&audio_queue, &ev, 0);
|
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) {
|
switch (ev.id) {
|
||||||
case AUDIO_PLAY:
|
case AUDIO_PLAY:
|
||||||
/* Refuse to start playback if we are already playing
|
/* Don't start playing immediately if user is skipping tracks
|
||||||
the requested track. This is needed because when skipping
|
* fast to prevent UI lag. */
|
||||||
tracks fast, AUDIO_PLAY commands will get queued with the
|
track_count = 0;
|
||||||
the same track and playback will stutter. */
|
last_peek_offset = 0;
|
||||||
if (last_index == playlist_get_display_index() && playing
|
if (current_tick - last_tick < HZ/2)
|
||||||
&& pcm_is_playing()) {
|
{
|
||||||
logf("already playing req. track");
|
play_pending = true;
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
|
play_pending = false;
|
||||||
|
|
||||||
/* Do not start crossfading if audio is paused. */
|
/* Do not start crossfading if audio is paused. */
|
||||||
if (paused) {
|
if (paused)
|
||||||
audio_stop_playback();
|
pcmbuf_play_stop();
|
||||||
paused = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_TUNER
|
#ifdef CONFIG_TUNER
|
||||||
/* check if radio is playing */
|
/* check if radio is playing */
|
||||||
if(radio_get_status() != FMRADIO_OFF){
|
if (radio_get_status() != FMRADIO_OFF) {
|
||||||
radio_stop();
|
radio_stop();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1751,15 +1745,13 @@ void audio_thread(void)
|
||||||
|
|
||||||
case AUDIO_NEXT:
|
case AUDIO_NEXT:
|
||||||
logf("audio_next");
|
logf("audio_next");
|
||||||
if (global_settings.beep)
|
last_tick = current_tick;
|
||||||
pcmbuf_beep(5000, 100, 2500*global_settings.beep);
|
|
||||||
initiate_track_change(1);
|
initiate_track_change(1);
|
||||||
break ;
|
break ;
|
||||||
|
|
||||||
case AUDIO_PREV:
|
case AUDIO_PREV:
|
||||||
logf("audio_prev");
|
logf("audio_prev");
|
||||||
if (global_settings.beep)
|
last_tick = current_tick;
|
||||||
pcmbuf_beep(5000, 100, 2500*global_settings.beep);
|
|
||||||
initiate_track_change(-1);
|
initiate_track_change(-1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1793,7 +1785,7 @@ void audio_thread(void)
|
||||||
// audio_change_track();
|
// audio_change_track();
|
||||||
break ;
|
break ;
|
||||||
|
|
||||||
#ifndef SIMULATOR
|
#ifndef SIMULATOR
|
||||||
case SYS_USB_CONNECTED:
|
case SYS_USB_CONNECTED:
|
||||||
logf("USB: Audio core");
|
logf("USB: Audio core");
|
||||||
audio_stop_playback();
|
audio_stop_playback();
|
||||||
|
@ -1973,12 +1965,28 @@ void voice_init(void)
|
||||||
|
|
||||||
struct mp3entry* audio_current_track(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)
|
if (track_count > 0 && cur_ti->taginfo_ready)
|
||||||
return (struct mp3entry *)&cur_ti->id3;
|
return (struct mp3entry *)&cur_ti->id3;
|
||||||
else
|
else {
|
||||||
return NULL;
|
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)
|
struct mp3entry* audio_next_track(void)
|
||||||
|
@ -1994,16 +2002,12 @@ struct mp3entry* audio_next_track(void)
|
||||||
if (!tracks[next_idx].taginfo_ready)
|
if (!tracks[next_idx].taginfo_ready)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
//logf("audio_next_track");
|
|
||||||
|
|
||||||
return &tracks[next_idx].id3;
|
return &tracks[next_idx].id3;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool audio_has_changed_track(void)
|
bool audio_has_changed_track(void)
|
||||||
{
|
{
|
||||||
if (track_changed && track_count > 0 && playing) {
|
if (track_changed) {
|
||||||
if (!cur_ti->taginfo_ready)
|
|
||||||
return false;
|
|
||||||
track_changed = false;
|
track_changed = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2014,7 +2018,6 @@ bool audio_has_changed_track(void)
|
||||||
void audio_play(int offset)
|
void audio_play(int offset)
|
||||||
{
|
{
|
||||||
logf("audio_play");
|
logf("audio_play");
|
||||||
last_index = -1;
|
|
||||||
queue_post(&audio_queue, AUDIO_PLAY, (void *)offset);
|
queue_post(&audio_queue, AUDIO_PLAY, (void *)offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2043,11 +2046,37 @@ void audio_resume(void)
|
||||||
|
|
||||||
void audio_next(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);
|
queue_post(&audio_queue, AUDIO_NEXT, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_prev(void)
|
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);
|
queue_post(&audio_queue, AUDIO_PREV, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
216
apps/playlist.c
216
apps/playlist.c
|
@ -86,6 +86,9 @@
|
||||||
#include "button.h"
|
#include "button.h"
|
||||||
#include "filetree.h"
|
#include "filetree.h"
|
||||||
#include "abrepeat.h"
|
#include "abrepeat.h"
|
||||||
|
#include "dircache.h"
|
||||||
|
#include "thread.h"
|
||||||
|
#include "usb.h"
|
||||||
#ifdef HAVE_LCD_BITMAP
|
#ifdef HAVE_LCD_BITMAP
|
||||||
#include "icons.h"
|
#include "icons.h"
|
||||||
#include "widgets.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,
|
static void find_and_set_playlist_index(struct playlist_info* playlist,
|
||||||
unsigned int seek);
|
unsigned int seek);
|
||||||
static int compare(const void* p1, const void* p2);
|
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);
|
bool control_file, char *buf, int buf_length);
|
||||||
static int get_next_directory(char *dir);
|
static int get_next_directory(char *dir);
|
||||||
static int get_next_dir(char *dir, bool is_forward, bool recursion);
|
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 flush_pending_control(struct playlist_info* playlist);
|
||||||
static int rotate_index(const struct playlist_info* playlist, int index);
|
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
|
* 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 */
|
/* Store a new entry */
|
||||||
playlist->indices[ playlist->amount ] = i+count;
|
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 ) {
|
if ( playlist->amount >= playlist->max_playlist_size ) {
|
||||||
display_buffer_full();
|
display_buffer_full();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
playlist->amount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -406,6 +421,10 @@ static int add_indices_to_playlist(struct playlist_info* playlist,
|
||||||
i+= count;
|
i+= count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_DIRCACHE
|
||||||
|
queue_post(&playlist_queue, PLAYLIST_LOAD_POINTERS, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,8 +518,14 @@ static int add_track_to_playlist(struct playlist_info* playlist,
|
||||||
|
|
||||||
/* shift indices so that track can be added */
|
/* shift indices so that track can be added */
|
||||||
for (i=playlist->amount; i>insert_position; i--)
|
for (i=playlist->amount; i>insert_position; i--)
|
||||||
|
{
|
||||||
playlist->indices[i] = playlist->indices[i-1];
|
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 */
|
/* update stored indices if needed */
|
||||||
if (playlist->amount > 0 && insert_position <= playlist->index)
|
if (playlist->amount > 0 && insert_position <= playlist->index)
|
||||||
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;
|
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->amount++;
|
||||||
playlist->num_inserted_tracks++;
|
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 */
|
/* shift indices now that track has been removed */
|
||||||
for (i=position; i<playlist->amount; i++)
|
for (i=position; i<playlist->amount; i++)
|
||||||
|
{
|
||||||
playlist->indices[i] = playlist->indices[i+1];
|
playlist->indices[i] = playlist->indices[i+1];
|
||||||
|
#ifdef HAVE_DIRCACHE
|
||||||
|
if (playlist->filenames)
|
||||||
|
playlist->filenames[i] = playlist->filenames[i+1];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
playlist->amount--;
|
playlist->amount--;
|
||||||
|
|
||||||
|
@ -780,6 +817,14 @@ static int randomise_playlist(struct playlist_info* playlist,
|
||||||
store = playlist->indices[candidate];
|
store = playlist->indices[candidate];
|
||||||
playlist->indices[candidate] = playlist->indices[count];
|
playlist->indices[candidate] = playlist->indices[count];
|
||||||
playlist->indices[count] = store;
|
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)
|
if (start_current)
|
||||||
|
@ -817,6 +862,13 @@ static int sort_playlist(struct playlist_info* playlist, bool start_current,
|
||||||
qsort(playlist->indices, playlist->amount,
|
qsort(playlist->indices, playlist->amount,
|
||||||
sizeof(playlist->indices[0]), compare);
|
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)
|
if (start_current)
|
||||||
find_and_set_playlist_index(playlist, current);
|
find_and_set_playlist_index(playlist, current);
|
||||||
|
|
||||||
|
@ -1040,10 +1092,88 @@ static int compare(const void* p1, const void* p2)
|
||||||
return *e1 - *e2;
|
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
|
* 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)
|
bool control_file, char *buf, int buf_length)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -1054,13 +1184,26 @@ static int get_filename(struct playlist_info* playlist, int seek,
|
||||||
if (buf_length > MAX_PATH+1)
|
if (buf_length > MAX_PATH+1)
|
||||||
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));
|
strncpy(tmp_buf, &playlist->buffer[seek], sizeof(tmp_buf));
|
||||||
tmp_buf[MAX_PATH] = '\0';
|
tmp_buf[MAX_PATH] = '\0';
|
||||||
max = strlen(tmp_buf) + 1;
|
max = strlen(tmp_buf) + 1;
|
||||||
}
|
}
|
||||||
else
|
else if (max < 0)
|
||||||
{
|
{
|
||||||
if (control_file)
|
if (control_file)
|
||||||
fd = playlist->control_fd;
|
fd = playlist->control_fd;
|
||||||
|
@ -1482,6 +1625,16 @@ void playlist_init(void)
|
||||||
playlist->buffer = buffer_alloc(playlist->buffer_size);
|
playlist->buffer = buffer_alloc(playlist->buffer_size);
|
||||||
mutex_init(&playlist->control_mutex);
|
mutex_init(&playlist->control_mutex);
|
||||||
empty_playlist(playlist, true);
|
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;
|
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);
|
strcpy(&playlist->buffer[playlist->buffer_end_pos], filename);
|
||||||
playlist->buffer_end_pos += len;
|
playlist->buffer_end_pos += len;
|
||||||
playlist->buffer[playlist->buffer_end_pos++] = '\0';
|
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;
|
control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK;
|
||||||
seek = playlist->indices[index] & PLAYLIST_SEEK_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)
|
MAX_PATH+1) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -2003,11 +2157,21 @@ char* playlist_peek(int steps)
|
||||||
(workaround for buggy playlist creation tools) */
|
(workaround for buggy playlist creation tools) */
|
||||||
while (temp_ptr)
|
while (temp_ptr)
|
||||||
{
|
{
|
||||||
fd = open(temp_ptr, O_RDONLY);
|
#ifdef HAVE_DIRCACHE
|
||||||
if (fd >= 0)
|
if (dircache_is_enabled())
|
||||||
{
|
{
|
||||||
close(fd);
|
if (dircache_get_entry_ptr(temp_ptr))
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
fd = open(temp_ptr, O_RDONLY);
|
||||||
|
if (fd >= 0)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
temp_ptr = strchr(temp_ptr+1, '/');
|
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);
|
int num_indices = index_buffer_size / sizeof(int);
|
||||||
|
|
||||||
|
#ifdef HAVE_DIRCACHE
|
||||||
|
num_indices /= 2;
|
||||||
|
#endif
|
||||||
if (num_indices > global_settings.max_files_in_playlist)
|
if (num_indices > global_settings.max_files_in_playlist)
|
||||||
num_indices = global_settings.max_files_in_playlist;
|
num_indices = global_settings.max_files_in_playlist;
|
||||||
|
|
||||||
playlist->max_playlist_size = num_indices;
|
playlist->max_playlist_size = num_indices;
|
||||||
playlist->indices = index_buffer;
|
playlist->indices = index_buffer;
|
||||||
|
#ifdef HAVE_DIRCACHE
|
||||||
|
playlist->filenames = (const struct dircache_entry **)
|
||||||
|
&playlist->indices[num_indices];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
playlist->max_playlist_size = current_playlist.max_playlist_size;
|
playlist->max_playlist_size = current_playlist.max_playlist_size;
|
||||||
playlist->indices = current_playlist.indices;
|
playlist->indices = current_playlist.indices;
|
||||||
|
#ifdef HAVE_DIRCACHE
|
||||||
|
playlist->filenames = current_playlist.filenames;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
playlist->buffer_size = 0;
|
playlist->buffer_size = 0;
|
||||||
|
@ -2336,9 +2510,15 @@ int playlist_set_current(struct playlist_info* playlist)
|
||||||
current_playlist.dirlen = playlist->dirlen;
|
current_playlist.dirlen = playlist->dirlen;
|
||||||
|
|
||||||
if (playlist->indices && playlist->indices != current_playlist.indices)
|
if (playlist->indices && playlist->indices != current_playlist.indices)
|
||||||
|
{
|
||||||
memcpy(current_playlist.indices, 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.first_index = playlist->first_index;
|
||||||
current_playlist.amount = playlist->amount;
|
current_playlist.amount = playlist->amount;
|
||||||
current_playlist.last_insert_pos = playlist->last_insert_pos;
|
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;
|
queue = playlist->indices[index] & PLAYLIST_QUEUE_MASK;
|
||||||
seek = playlist->indices[index] & PLAYLIST_SEEK_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)
|
sizeof(filename)) < 0)
|
||||||
return -1;
|
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;
|
control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK;
|
||||||
seek = playlist->indices[index] & PLAYLIST_SEEK_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)
|
sizeof(info->filename)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -2883,7 +3063,7 @@ int playlist_save(struct playlist_info* playlist, char *filename)
|
||||||
/* Don't save queued files */
|
/* Don't save queued files */
|
||||||
if (!queue)
|
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)
|
MAX_PATH+1) < 0)
|
||||||
{
|
{
|
||||||
result = -1;
|
result = -1;
|
||||||
|
|
|
@ -36,7 +36,8 @@ struct playlist_info
|
||||||
int control_fd; /* descriptor of the open control file */
|
int control_fd; /* descriptor of the open control file */
|
||||||
bool control_created; /* has control file been created? */
|
bool control_created; /* has control file been created? */
|
||||||
int dirlen; /* Length of the path to the playlist file */
|
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
|
int max_playlist_size; /* Max number of files in playlist. Mirror of
|
||||||
global_settings.max_files_in_playlist */
|
global_settings.max_files_in_playlist */
|
||||||
bool in_ram; /* playlist stored in ram (dirplay) */
|
bool in_ram; /* playlist stored in ram (dirplay) */
|
||||||
|
|
|
@ -597,6 +597,7 @@ long wps_show(void)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
left_lastclick = current_tick;
|
left_lastclick = current_tick;
|
||||||
|
update_track = true;
|
||||||
|
|
||||||
#ifdef AB_REPEAT_ENABLE
|
#ifdef AB_REPEAT_ENABLE
|
||||||
/* if we're in A/B repeat mode and the current position
|
/* 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) )
|
if ( ab_repeat_mode_enabled() && ab_after_A_marker(id3->elapsed) )
|
||||||
{
|
{
|
||||||
ab_jump_to_A_marker();
|
ab_jump_to_A_marker();
|
||||||
update_track = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* ...otherwise, do it normally */
|
/* ...otherwise, do it normally */
|
||||||
|
@ -655,6 +655,7 @@ long wps_show(void)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
right_lastclick = current_tick;
|
right_lastclick = current_tick;
|
||||||
|
update_track = true;
|
||||||
|
|
||||||
#ifdef AB_REPEAT_ENABLE
|
#ifdef AB_REPEAT_ENABLE
|
||||||
/* if we're in A/B repeat mode and the current position is
|
/* 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) )
|
if ( ab_repeat_mode_enabled() && ab_before_A_marker(id3->elapsed) )
|
||||||
{
|
{
|
||||||
ab_jump_to_A_marker();
|
ab_jump_to_A_marker();
|
||||||
update_track = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* ...otherwise, do it normally */
|
/* ...otherwise, do it normally */
|
||||||
|
|
|
@ -77,6 +77,7 @@ static struct dircache_entry* allocate_entry(void)
|
||||||
dircache_size += sizeof(struct dircache_entry);
|
dircache_size += sizeof(struct dircache_entry);
|
||||||
next_entry->name_len = 0;
|
next_entry->name_len = 0;
|
||||||
next_entry->d_name = NULL;
|
next_entry->d_name = NULL;
|
||||||
|
next_entry->up = NULL;
|
||||||
next_entry->down = NULL;
|
next_entry->down = NULL;
|
||||||
next_entry->next = 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;
|
struct dircache_entry *next_entry;
|
||||||
|
|
||||||
next_entry = allocate_entry();
|
next_entry = allocate_entry();
|
||||||
|
next_entry->up = ce->up;
|
||||||
ce->next = next_entry;
|
ce->next = next_entry;
|
||||||
|
|
||||||
return 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;
|
struct dircache_entry *next_entry;
|
||||||
|
|
||||||
next_entry = allocate_entry();
|
next_entry = allocate_entry();
|
||||||
|
next_entry->up = ce;
|
||||||
ce->down = next_entry;
|
ce->down = next_entry;
|
||||||
|
|
||||||
return 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 depth = 0;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
|
memset(ce, 0, sizeof(struct dircache_entry));
|
||||||
dir_recursion[0].dir = dir;
|
dir_recursion[0].dir = dir;
|
||||||
dir_recursion[0].ce = ce;
|
dir_recursion[0].ce = ce;
|
||||||
|
|
||||||
|
@ -517,6 +521,43 @@ void dircache_disable(void)
|
||||||
logf("Cache released");
|
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 --- */
|
/* --- Directory cache live updating functions --- */
|
||||||
static struct dircache_entry* dircache_new_entry(const char *path, int attribute)
|
static struct dircache_entry* dircache_new_entry(const char *path, int attribute)
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,6 +47,7 @@ struct dircache_maindata {
|
||||||
/* Exported structures. */
|
/* Exported structures. */
|
||||||
struct dircache_entry {
|
struct dircache_entry {
|
||||||
struct dircache_entry *next;
|
struct dircache_entry *next;
|
||||||
|
struct dircache_entry *up;
|
||||||
struct dircache_entry *down;
|
struct dircache_entry *down;
|
||||||
int attribute;
|
int attribute;
|
||||||
long size;
|
long size;
|
||||||
|
@ -71,6 +72,8 @@ int dircache_build(int last_size);
|
||||||
bool dircache_is_enabled(void);
|
bool dircache_is_enabled(void);
|
||||||
int dircache_get_cache_size(void);
|
int dircache_get_cache_size(void);
|
||||||
void dircache_disable(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_bind(int fd, const char *path);
|
||||||
void dircache_update_filesize(int fd, long newsize);
|
void dircache_update_filesize(int fd, long newsize);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue