summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/playlist.c160
-rw-r--r--apps/playlist.h4
-rw-r--r--apps/tagcache.c150
-rw-r--r--firmware/export/config.h2
4 files changed, 171 insertions, 145 deletions
diff --git a/apps/playlist.c b/apps/playlist.c
index 015e41ae0e..176cfc3af7 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -106,8 +106,9 @@
#include "plugin.h" /* To borrow a temp buffer to rewrite a .m3u8 file */
#include "panic.h"
#include "logdiskf.h"
-
-#undef HAVE_DIRCACHE
+#ifdef HAVE_DIRCACHE
+#include "dircache.h"
+#endif
#define PLAYLIST_CONTROL_FILE_VERSION 2
@@ -205,6 +206,25 @@ static const char playlist_thread_name[] = "playlist cachectrl";
static struct mutex current_playlist_mutex SHAREDBSS_ATTR;
static struct mutex created_playlist_mutex SHAREDBSS_ATTR;
+#ifdef HAVE_DIRCACHE
+static void copy_filerefs(struct dircache_fileref *dcfto,
+ const struct dircache_fileref *dcffrom,
+ int count)
+{
+ if (!dcfto)
+ return;
+
+ if (dcffrom)
+ memmove(dcfto, dcffrom, count * sizeof (*dcfto));
+ else
+ {
+ /* just initialize the destination */
+ for (int i = 0; i < count; i++, dcfto++)
+ dircache_fileref_init(dcfto);
+ }
+}
+#endif /* HAVE_DIRCACHE */
+
/* Check if the filename suggests M3U or M3U8 format. */
static bool is_m3u8(const char* filename)
{
@@ -401,6 +421,8 @@ static int recreate_control(struct playlist_info* playlist)
int i;
int result = 0;
+ temp_file[0] = 0;
+
if(playlist->control_fd >= 0)
{
char* dir = playlist->filename;
@@ -408,6 +430,7 @@ static int recreate_control(struct playlist_info* playlist)
char c = playlist->filename[playlist->dirlen-1];
close(playlist->control_fd);
+ playlist->control_fd = 0;
snprintf(temp_file, sizeof(temp_file), "%s_temp",
playlist->control_filename);
@@ -571,10 +594,9 @@ static int add_indices_to_playlist(struct playlist_info* playlist,
/* Store a new entry */
playlist->indices[ playlist->amount ] = i+count;
-#ifdef HAVE_DIRCACHE
- if (playlist->filenames)
- playlist->filenames[ playlist->amount ] = -1;
-#endif
+ #ifdef HAVE_DIRCACHE
+ copy_filerefs(&playlist->dcfrefs[playlist->amount], NULL, 1);
+ #endif
playlist->amount++;
}
}
@@ -779,8 +801,8 @@ static int add_track_to_playlist(struct playlist_info* playlist,
{
playlist->indices[i] = playlist->indices[i-1];
#ifdef HAVE_DIRCACHE
- if (playlist->filenames)
- playlist->filenames[i] = playlist->filenames[i-1];
+ if (playlist->dcfrefs)
+ playlist->dcfrefs[i] = playlist->dcfrefs[i-1];
#endif
}
@@ -814,8 +836,7 @@ 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] = -1;
+ copy_filerefs(&playlist->dcfrefs[insert_position], NULL, 1);
#endif
playlist->amount++;
@@ -886,8 +907,8 @@ static int remove_track_from_playlist(struct playlist_info* playlist,
{
playlist->indices[i] = playlist->indices[i+1];
#ifdef HAVE_DIRCACHE
- if (playlist->filenames)
- playlist->filenames[i] = playlist->filenames[i+1];
+ if (playlist->dcfrefs)
+ playlist->dcfrefs[i] = playlist->dcfrefs[i+1];
#endif
}
@@ -934,7 +955,6 @@ static int randomise_playlist(struct playlist_info* playlist,
{
int count;
int candidate;
- long store;
unsigned int current = playlist->indices[playlist->index];
/* seed 0 is used to identify sorted playlist for resume purposes */
@@ -951,15 +971,15 @@ static int randomise_playlist(struct playlist_info* playlist,
candidate = rand() % (count + 1);
/* now swap the values at the 'count' and 'candidate' positions */
- store = playlist->indices[candidate];
+ int indextmp = playlist->indices[candidate];
playlist->indices[candidate] = playlist->indices[count];
- playlist->indices[count] = store;
+ playlist->indices[count] = indextmp;
#ifdef HAVE_DIRCACHE
- if (playlist->filenames)
+ if (playlist->dcfrefs)
{
- store = playlist->filenames[candidate];
- playlist->filenames[candidate] = playlist->filenames[count];
- playlist->filenames[count] = store;
+ struct dircache_fileref dcftmp = playlist->dcfrefs[candidate];
+ playlist->dcfrefs[candidate] = playlist->dcfrefs[count];
+ playlist->dcfrefs[count] = dcftmp;
}
#endif
}
@@ -1001,7 +1021,7 @@ static int sort_playlist(struct playlist_info* playlist, bool start_current,
/** 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. */
- memset((void*)playlist->filenames, 0xff, playlist->max_playlist_size * sizeof(int));
+ copy_filerefs(playlist->dcfrefs, NULL, playlist->max_playlist_size);
queue_post(&playlist_queue, PLAYLIST_LOAD_POINTERS, 0);
#endif
@@ -1245,11 +1265,6 @@ static void playlist_flush_callback(void)
}
}
-static bool is_dircache_pointers_intact(void)
-{
- return dircache_get_appflag(DIRCACHE_APPFLAG_PLAYLIST) ? true : false;
-}
-
static void playlist_thread(void)
{
struct queue_event ev;
@@ -1290,24 +1305,26 @@ static void playlist_thread(void)
register_storage_idle_func(playlist_flush_callback);
}
- if (!dircache_is_enabled() || !playlist->filenames
- || playlist->amount <= 0)
- {
+ if (!playlist->dcfrefs || playlist->amount <= 0)
break ;
- }
/* Check if previously loaded pointers are intact. */
- if (is_dircache_pointers_intact() && !dirty_pointers)
+ if (!dirty_pointers)
break ;
-#ifdef HAVE_ADJUSTABLE_CPU_FREQ
- cpu_boost(true);
-#endif
+ struct dircache_info info;
+ dircache_get_info(&info);
+
+ if (info.status != DIRCACHE_READY)
+ break ;
+
+ trigger_cpu_boost();
+
for (index = 0; index < playlist->amount
&& queue_empty(&playlist_queue); index++)
{
- /* Process only pointers that are not already loaded. */
- if (is_dircache_pointers_intact() && playlist->filenames[index] >= 0)
+ /* Process only pointers that are superficially stale. */
+ if (dircache_search(DCS_FILEREF, &playlist->dcfrefs[index], NULL) == 0)
continue ;
control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK;
@@ -1320,19 +1337,16 @@ static void playlist_thread(void)
break ;
}
- /* Set the dircache entry pointer. */
- playlist->filenames[index] = dircache_get_entry_id(tmp);
+ /* Obtain the dircache file entry cookie. */
+ dircache_search(DCS_CACHED_PATH | DCS_UPDATE_FILEREF,
+ &playlist->dcfrefs[index], tmp);
/* And be on background so user doesn't notice any delays. */
yield();
}
-
- if (dircache_is_enabled())
- dircache_set_appflag(DIRCACHE_APPFLAG_PLAYLIST);
-
-#ifdef HAVE_ADJUSTABLE_CPU_FREQ
- cpu_boost(false);
-#endif
+
+ cancel_cpu_boost();
+
if (index == playlist->amount)
dirty_pointers = false;
@@ -1364,17 +1378,12 @@ static int get_filename(struct playlist_info* playlist, int index, int seek,
buf_length = MAX_PATH+1;
#ifdef HAVE_DIRCACHE
- if (is_dircache_pointers_intact() && playlist->filenames)
+ if (playlist->dcfrefs)
{
- if (playlist->filenames[index] >= 0)
- {
- max = dircache_copy_path(playlist->filenames[index],
- tmp_buf, sizeof(tmp_buf)-1);
- }
+ max = dircache_get_fileref_path(&playlist->dcfrefs[index],
+ tmp_buf, sizeof(tmp_buf));
}
-#else
- (void)index;
-#endif
+#endif /* HAVE_DIRCACHE */
if (playlist->in_ram && !control_file && max < 0)
{
@@ -1406,12 +1415,16 @@ static int get_filename(struct playlist_info* playlist, int index, int seek,
{
max = read(fd, tmp_buf, MIN((size_t) buf_length, sizeof(tmp_buf)));
- if ((max > 0) && !utf8)
+ if (max > 0)
{
+ /* playlist file may end without a new line - terminate buffer */
+ tmp_buf[MIN(max, (int)sizeof(tmp_buf) - 1)] = '\0';
+
/* Use dir_buf as a temporary buffer. Note that dir_buf must
* be as large as tmp_buf.
*/
- max = convert_m3u(tmp_buf, max, sizeof(tmp_buf), dir_buf);
+ if (!utf8)
+ max = convert_m3u(tmp_buf, max, sizeof(tmp_buf), dir_buf);
}
}
}
@@ -1432,6 +1445,8 @@ static int get_filename(struct playlist_info* playlist, int index, int seek,
strlcpy(dir_buf, playlist->filename, playlist->dirlen);
return format_track_path(buf, tmp_buf, buf_length, dir_buf);
+
+ (void)index;
}
static int get_next_directory(char *dir){
@@ -1974,11 +1989,12 @@ static int move_callback(int handle, void* current, void* new)
struct playlist_info* playlist = &current_playlist;
if (current == playlist->indices)
playlist->indices = new;
- else if (current == playlist->filenames)
- playlist->filenames = new;
else if (current == playlist->buffer)
playlist->buffer = new;
-
+#ifdef HAVE_DIRCACHE
+ else if (current == playlist->dcfrefs)
+ playlist->dcfrefs = new;
+#endif /* HAVE_DIRCACHE */
return BUFLIB_CB_OK;
}
@@ -2019,15 +2035,15 @@ void playlist_init(void)
#ifdef HAVE_DIRCACHE
handle = core_alloc_ex("playlist dc",
- playlist->max_playlist_size * sizeof(int), &ops);
- playlist->filenames = core_get_data(handle);
- memset((void*)playlist->filenames, 0xff,
- playlist->max_playlist_size * sizeof(int));
+ playlist->max_playlist_size * sizeof(*playlist->dcfrefs), &ops);
+ playlist->dcfrefs = core_get_data(handle);
+ copy_filerefs(playlist->dcfrefs, NULL, playlist->max_playlist_size);
create_thread(playlist_thread, playlist_stack, sizeof(playlist_stack),
0, playlist_thread_name IF_PRIO(, PRIORITY_BACKGROUND)
IF_COP(, CPU));
+
queue_init(&playlist_queue, true);
-#endif
+#endif /* HAVE_DIRCACHE */
}
/*
@@ -2513,8 +2529,9 @@ int playlist_add(const char *filename)
playlist->indices[playlist->amount] = playlist->buffer_end_pos;
#ifdef HAVE_DIRCACHE
- playlist->filenames[playlist->amount] = -1;
+ copy_filerefs(&playlist->dcfrefs[playlist->amount], NULL, 1);
#endif
+
playlist->amount++;
strcpy((char*)&playlist->buffer[playlist->buffer_end_pos], filename);
@@ -2863,18 +2880,19 @@ int playlist_create_ex(struct playlist_info* playlist,
if (index_buffer)
{
- int num_indices = index_buffer_size / sizeof(int);
-
+ size_t unit_size = sizeof (*playlist->indices);
#ifdef HAVE_DIRCACHE
- num_indices /= 2;
+ unit_size += sizeof (*playlist->dcfrefs);
#endif
+ int num_indices = index_buffer_size / unit_size;
+
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 = (int*)&playlist->indices[num_indices];
+ playlist->dcfrefs = (void *)&playlist->indices[num_indices];
#endif
}
else
@@ -2882,7 +2900,7 @@ int playlist_create_ex(struct playlist_info* playlist,
playlist->max_playlist_size = current_playlist.max_playlist_size;
playlist->indices = current_playlist.indices;
#ifdef HAVE_DIRCACHE
- playlist->filenames = current_playlist.filenames;
+ playlist->dcfrefs = current_playlist.dcfrefs;
#endif
}
@@ -2942,8 +2960,8 @@ int playlist_set_current(struct playlist_info* playlist)
memcpy((void*)current_playlist.indices, (void*)playlist->indices,
playlist->max_playlist_size*sizeof(int));
#ifdef HAVE_DIRCACHE
- memcpy((void*)current_playlist.filenames, (void*)playlist->filenames,
- playlist->max_playlist_size*sizeof(int));
+ copy_filerefs(current_playlist.dcfrefs, playlist->dcfrefs,
+ playlist->max_playlist_size);
#endif
}
diff --git a/apps/playlist.h b/apps/playlist.h
index a331838fde..6048001ff7 100644
--- a/apps/playlist.h
+++ b/apps/playlist.h
@@ -82,7 +82,9 @@ struct playlist_info
bool control_created; /* has control file been created? */
int dirlen; /* Length of the path to the playlist file */
volatile unsigned long *indices; /* array of indices */
- volatile int *filenames; /* Array of dircache indices */
+#ifdef HAVE_DIRCACHE
+ struct dircache_fileref *dcfrefs; /* Dircache entry shortcuts */
+#endif
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/tagcache.c b/apps/tagcache.c
index 2b6041227b..df252ca0bc 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -90,6 +90,10 @@
#undef HAVE_DIRCACHE
+#ifdef HAVE_DIRCACHE
+#include "dircache.h"
+#endif
+
#ifdef __PCTOOL__
#define yield() do { } while(0)
#define sim_sleep(timeout) do { } while(0)
@@ -112,6 +116,9 @@ static long tempbufidx; /* Current location in buffer. */
static size_t tempbuf_size; /* Buffer size (TEMPBUF_SIZE). */
static long tempbuf_left; /* Buffer space left. */
static long tempbuf_pos;
+#ifndef __PCTOOL__
+static int tempbuf_handle;
+#endif
#define SORTED_TAGS_COUNT 8
#define TAGCACHE_IS_UNIQUE(tag) (BIT_N(tag) & TAGCACHE_UNIQUE_TAGS)
@@ -289,17 +296,6 @@ static ssize_t ecwrite_index_entry(int fd, struct index_entry *buf)
return ecwrite(fd, buf, 1, index_entry_ec, tc_stat.econ);
}
-#ifdef HAVE_DIRCACHE
-/**
- * Returns true if specified flag is still present, i.e., dircache
- * has not been reloaded.
- */
-static bool is_dircache_intact(void)
-{
- return dircache_get_appflag(DIRCACHE_APPFLAG_TAGCACHE);
-}
-#endif
-
static int open_tag_fd(struct tagcache_header *hdr, int tag, bool write)
{
int fd;
@@ -434,7 +430,7 @@ static long find_entry_ram(const char *filename, int dc)
return -1;
}
-#endif
+#endif /* defined (HAVE_TC_RAMCACHE) && defined (HAVE_DIRCACHE) */
static long find_entry_disk(const char *filename_raw, bool localfd)
{
@@ -590,7 +586,7 @@ static bool get_index(int masterfd, int idxid,
if (ramcache_hdr->indices[idxid].flag & FLAG_DELETED)
return false;
-# ifdef HAVE_DIRCACHE
+#ifdef HAVE_DIRCACHE
if (!(ramcache_hdr->indices[idxid].flag & FLAG_DIRCACHE)
|| is_dircache_intact())
#endif
@@ -599,8 +595,6 @@ static bool get_index(int masterfd, int idxid,
return true;
}
}
-#else
- (void)use_ram;
#endif
if (masterfd < 0)
@@ -632,6 +626,8 @@ static bool get_index(int masterfd, int idxid,
return false;
return true;
+
+ (void)use_ram;
}
#ifndef __PCTOOL__
@@ -724,7 +720,7 @@ static bool retrieve(struct tagcache_search *tcs, struct index_entry *idx,
{
struct tagfile_entry *ep;
-# ifdef HAVE_DIRCACHE
+#ifdef HAVE_DIRCACHE
if (tag == tag_filename && (idx->flag & FLAG_DIRCACHE))
{
/* for tag_filename, seek is a dircache index */
@@ -745,7 +741,7 @@ static bool retrieve(struct tagcache_search *tcs, struct index_entry *idx,
}
}
else
-# endif
+#endif /* HAVE_DIRCACHE */
if (tag != tag_filename)
{
ep = (struct tagfile_entry *)&ramcache_hdr->tags[tag][seek];
@@ -1511,8 +1507,7 @@ static bool get_next(struct tagcache_search *tcs)
#ifdef HAVE_TC_RAMCACHE
if (tcs->ramsearch)
{
-
-#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
+#ifdef HAVE_DIRCACHE
if (tcs->type == tag_filename && (flag & FLAG_DIRCACHE))
{
if (is_dircache_intact())
@@ -1537,7 +1532,7 @@ static bool get_next(struct tagcache_search *tcs)
}
}
else
-#endif
+#endif /* HAVE_DIRCACHE */
if (tcs->type != tag_filename)
{
struct tagfile_entry *ep;
@@ -1766,6 +1761,13 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename)
return true;
}
+#elif defined (HAVE_TC_RAMCACHE)
+/* temporary dummy function until integration is sorted out --jethead71 */
+bool tagcache_fill_tags(struct mp3entry *id3, const char *filename)
+{
+ return false;
+ (void)id3; (void)filename;
+}
#endif
static inline void write_item(const char *item)
@@ -2982,27 +2984,25 @@ static bool commit(void)
#ifdef HAVE_TC_RAMCACHE
tc_stat.ramcache = false;
#endif
-
+
+ /* Beyond here, jump to commit_error to undo locks and restore dircache */
+ rc = false;
read_lock++;
/* Try to steal every buffer we can :) */
if (tempbuf_size == 0)
local_allocation = true;
-#if 0 /* FIXME: How much big? dircache buffer can no longer be taken but
- may be freed to make room and the cache resumed. --jethead71 */
#ifdef HAVE_DIRCACHE
if (tempbuf_size == 0)
{
- /* Shut down dircache to free its allocation. */
+ /* Suspend dircache to free its allocation. */
dircache_free_buffer();
- if (tempbuf_size > 0)
- {
- dircache_buffer_stolen = true;
- }
+ dircache_buffer_stolen = true;
+
+ allocate_tempbuf();
}
-#endif
-#endif
+#endif /* HAVE_DIRCACHE */
#ifdef HAVE_TC_RAMCACHE
if (tempbuf_size == 0 && tc_stat.ramcache_allocated > 0)
@@ -3021,8 +3021,7 @@ static bool commit(void)
logf("delaying commit until next boot");
tc_stat.commit_delayed = true;
close(tmpfd);
- read_lock--;
- return false;
+ goto commit_error;
}
logf("commit %ld entries...", tch.entry_count);
@@ -3053,8 +3052,7 @@ static bool commit(void)
tc_stat.commit_delayed = true;
tc_stat.commit_step = 0;
- read_lock--;
- return false;
+ goto commit_error;
}
}
@@ -3063,8 +3061,7 @@ static bool commit(void)
logf("Failure to commit numeric indices");
close(tmpfd);
tc_stat.commit_step = 0;
- read_lock--;
- return false;
+ goto commit_error;
}
close(tmpfd);
@@ -3073,10 +3070,7 @@ static bool commit(void)
/* Update the master index headers. */
if ( (masterfd = open_master_fd(&tcmh, true)) < 0)
- {
- read_lock--;
- return false;
- }
+ goto commit_error;
remove(TAGCACHE_FILE_TEMP);
@@ -3101,39 +3095,53 @@ static bool commit(void)
tempbuf_size = 0;
}
-#ifdef HAVE_DIRCACHE
- /* Rebuild the dircache, if we stole the buffer. */
- if (dircache_buffer_stolen)
- dircache_resume();
-#endif
-
#ifdef HAVE_TC_RAMCACHE
if (ramcache_buffer_stolen)
+ {
+ ramcache_buffer_stolen = false;
move_lock--;
+ }
+
/* Reload tagcache. */
if (tc_stat.ramcache_allocated > 0)
tagcache_start_scan();
#endif
+ rc = true;
+
+commit_error:
+#ifdef HAVE_TC_RAMCACHE
+ if (ramcache_buffer_stolen)
+ move_lock--;
+#endif
+
read_lock--;
-
- return true;
-}
-#ifndef __PCTOOL__
-static int tempbuf_handle;
+#ifdef HAVE_DIRCACHE
+ /* Resume the dircache, if we stole the buffer. */
+ if (dircache_buffer_stolen)
+ dircache_resume();
#endif
+
+ return rc;
+}
static void allocate_tempbuf(void)
{
/* Yeah, malloc would be really nice now :) */
+ size_t size;
+ tempbuf_size = 0;
+
#ifdef __PCTOOL__
- tempbuf_size = 32*1024*1024;
- tempbuf = malloc(tempbuf_size);
+ size = 32*1024*1024;
+ tempbuf = malloc(size);
#else
- tempbuf_handle = core_alloc_maximum("tc tempbuf", &tempbuf_size, NULL);
+ tempbuf_handle = core_alloc_maximum("tc tempbuf", &size, NULL);
tempbuf = core_get_data(tempbuf_handle);
#endif
+
+ if (tempbuf)
+ tempbuf_size = size;
}
static void free_tempbuf(void)
@@ -4133,9 +4141,14 @@ static bool load_tagcache(void)
goto failure;
}
-# ifdef HAVE_DIRCACHE
- if (dircache_is_enabled())
+ if (global_settings.tagcache_autoupdate)
{
+ /* Check if entry has been removed. */
+ #ifdef HAVE_DIRCACHE
+ /* This will be very slow unless dircache is enabled
+ or target is flash based. */
+##################
+ if (dircache_search( /* will get this! -- jethead71 */
dc = dircache_get_entry_id(buf);
if (dc < 0)
{
@@ -4148,24 +4161,17 @@ static bool load_tagcache(void)
idx->flag |= FLAG_DIRCACHE;
idx->tag_seek[tag_filename] = dc;
- }
- else
-# endif
- {
- /* This will be very slow unless dircache is enabled
- or target is flash based, but do it anyway for
- consistency. */
- /* Check if entry has been removed. */
- if (global_settings.tagcache_autoupdate)
+ #else /* ndef HAVE_DIRCACHE */
+ /* This will be very slow unless target is flash based;
+ do it anyway for consistency. */
+ if (!file_exists(buf))
{
- if (!file_exists(buf))
- {
- logf("Entry no longer valid.");
- logf("-> %s", buf);
- delete_entry(fe->idx_id);
- continue;
- }
+ logf("Entry no longer valid.");
+ logf("-> %s", buf);
+ delete_entry(fe->idx_id);
+ continue;
}
+ #endif /* HAVE_DIRCACHE */
}
continue ;
diff --git a/firmware/export/config.h b/firmware/export/config.h
index b769b63c32..73464526a6 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -853,7 +853,7 @@ Lyre prototype 1 */
#define HAVE_DIRCACHE
#endif
#ifdef HAVE_TAGCACHE
-//#define HAVE_TC_RAMCACHE
+#define HAVE_TC_RAMCACHE
#endif
#endif