tagtree add %reload to allow hot reloading of tagnavi config
adds (static) function tagtree_unload frees all buflib allocations for tagtree adds command %reload that allows a new tagnavi file to be loaded without device restart use it like so.. "Reload..." -> %reload Allocations are now checked for validity (probably a good idea anyway) Change-Id: I2b4b9b7e253f97f3e6575e0ea7a92905e004d47f
This commit is contained in:
parent
d3a3a41b0f
commit
501404d703
1 changed files with 124 additions and 18 deletions
136
apps/tagtree.c
136
apps/tagtree.c
|
@ -105,6 +105,7 @@ enum variables {
|
|||
var_format,
|
||||
menu_next,
|
||||
menu_load,
|
||||
menu_reload,
|
||||
};
|
||||
|
||||
/* Capacity 10 000 entries (for example 10k different artists) */
|
||||
|
@ -114,6 +115,7 @@ static long uniqbuf[UNIQBUF_SIZE / sizeof(long)];
|
|||
#define MAX_TAGS 5
|
||||
#define MAX_MENU_ID_SIZE 32
|
||||
|
||||
#define RELOAD_TAGTREE (-1024)
|
||||
static bool sort_inverse;
|
||||
|
||||
/*
|
||||
|
@ -264,8 +266,12 @@ static struct buflib_callbacks ops = {
|
|||
|
||||
static void* tagtree_alloc(size_t size)
|
||||
{
|
||||
char* buf = core_get_data(tagtree_handle) + tagtree_buf_used;
|
||||
size = ALIGN_UP(size, sizeof(void*));
|
||||
if (size > (tagtree_bufsize - tagtree_buf_used))
|
||||
return NULL;
|
||||
|
||||
char* buf = core_get_data(tagtree_handle) + tagtree_buf_used;
|
||||
|
||||
tagtree_buf_used += size;
|
||||
return buf;
|
||||
}
|
||||
|
@ -273,6 +279,7 @@ static void* tagtree_alloc(size_t size)
|
|||
static void* tagtree_alloc0(size_t size)
|
||||
{
|
||||
void* ret = tagtree_alloc(size);
|
||||
if (ret)
|
||||
memset(ret, 0, size);
|
||||
return ret;
|
||||
}
|
||||
|
@ -281,6 +288,7 @@ static char* tagtree_strdup(const char* buf)
|
|||
{
|
||||
size_t len = strlen(buf) + 1;
|
||||
char* dest = tagtree_alloc(len);
|
||||
if (dest)
|
||||
strcpy(dest, buf);
|
||||
return dest;
|
||||
}
|
||||
|
@ -348,7 +356,8 @@ static int get_tag(int *tag)
|
|||
{"%root_menu", var_rootmenu},
|
||||
{"%format", var_format},
|
||||
{"->", menu_next},
|
||||
{"==>", menu_load}
|
||||
{"==>", menu_load},
|
||||
{"%reload", menu_reload}
|
||||
};
|
||||
char buf[128];
|
||||
unsigned int i;
|
||||
|
@ -467,7 +476,12 @@ static bool read_clause(struct tagcache_search_clause *clause)
|
|||
clause->str = tagtree_strdup(buf);
|
||||
}
|
||||
|
||||
if (TAGCACHE_IS_NUMERIC(clause->tag))
|
||||
if (!clause->str)
|
||||
{
|
||||
logf("tagtree failed to allocate %s", "clause string");
|
||||
return false;
|
||||
}
|
||||
else if (TAGCACHE_IS_NUMERIC(clause->tag))
|
||||
{
|
||||
clause->numeric = true;
|
||||
clause->numeric_data = atoi(clause->str);
|
||||
|
@ -581,10 +595,15 @@ static int add_format(const char *buf)
|
|||
|
||||
if (formats[format_count] == NULL)
|
||||
formats[format_count] = tagtree_alloc0(sizeof(struct display_format));
|
||||
|
||||
if (!formats[format_count])
|
||||
{
|
||||
logf("tagtree failed to allocate %s", "format string");
|
||||
return -2;
|
||||
}
|
||||
if (get_format_str(formats[format_count]) < 0)
|
||||
{
|
||||
logf("get_format_str() parser failed!");
|
||||
if (formats[format_count])
|
||||
memset(formats[format_count], 0, sizeof(struct display_format));
|
||||
return -4;
|
||||
}
|
||||
|
@ -600,7 +619,7 @@ static int add_format(const char *buf)
|
|||
tagtree_lock();
|
||||
while (1)
|
||||
{
|
||||
struct tagcache_search_clause *newclause;
|
||||
struct tagcache_search_clause *new_clause;
|
||||
|
||||
if (clause_count >= TAGCACHE_MAX_CLAUSES)
|
||||
{
|
||||
|
@ -608,10 +627,14 @@ static int add_format(const char *buf)
|
|||
break;
|
||||
}
|
||||
|
||||
newclause = tagtree_alloc(sizeof(struct tagcache_search_clause));
|
||||
|
||||
formats[format_count]->clause[clause_count] = newclause;
|
||||
if (!read_clause(newclause))
|
||||
new_clause = tagtree_alloc(sizeof(struct tagcache_search_clause));
|
||||
if (!new_clause)
|
||||
{
|
||||
logf("tagtree failed to allocate %s", "search clause");
|
||||
return -3;
|
||||
}
|
||||
formats[format_count]->clause[clause_count] = new_clause;
|
||||
if (!read_clause(new_clause))
|
||||
break;
|
||||
|
||||
clause_count++;
|
||||
|
@ -670,10 +693,16 @@ static int get_condition(struct search_instruction *inst)
|
|||
if (clause_count >= TAGCACHE_MAX_CLAUSES)
|
||||
{
|
||||
logf("Too many clauses");
|
||||
return false;
|
||||
return -2;
|
||||
}
|
||||
|
||||
new_clause = tagtree_alloc(sizeof(struct tagcache_search_clause));
|
||||
if (!new_clause)
|
||||
{
|
||||
logf("tagtree failed to allocate %s", "search clause");
|
||||
return -3;
|
||||
}
|
||||
|
||||
inst->clause[inst->tagorder_count][clause_count] = new_clause;
|
||||
|
||||
if (*strp == '|')
|
||||
|
@ -746,6 +775,11 @@ static bool parse_search(struct menu_entry *entry, const char *str)
|
|||
|
||||
/* Allocate a new menu unless link is found. */
|
||||
menus[menu_count] = tagtree_alloc0(sizeof(struct menu_root));
|
||||
if (!menus[menu_count])
|
||||
{
|
||||
logf("tagtree failed to allocate %s", "menu");
|
||||
return false;
|
||||
}
|
||||
strlcpy(menus[menu_count]->id, buf, MAX_MENU_ID_SIZE);
|
||||
entry->link = menu_count;
|
||||
++menu_count;
|
||||
|
@ -1088,6 +1122,11 @@ static int parse_line(int n, char *buf, void *parameters)
|
|||
if (menu == NULL)
|
||||
{
|
||||
menus[menu_count] = tagtree_alloc0(sizeof(struct menu_root));
|
||||
if (!menus[menu_count])
|
||||
{
|
||||
logf("tagtree failed to allocate %s", "menu");
|
||||
return -2;
|
||||
}
|
||||
menu = menus[menu_count];
|
||||
++menu_count;
|
||||
strlcpy(menu->id, data, MAX_MENU_ID_SIZE);
|
||||
|
@ -1135,7 +1174,11 @@ static int parse_line(int n, char *buf, void *parameters)
|
|||
/* Allocate */
|
||||
if (menu->items[menu->itemcount] == NULL)
|
||||
menu->items[menu->itemcount] = tagtree_alloc0(sizeof(struct menu_entry));
|
||||
|
||||
if (!menu->items[menu->itemcount])
|
||||
{
|
||||
logf("tagtree failed to allocate %s", "menu items");
|
||||
return -2;
|
||||
}
|
||||
tagtree_lock();
|
||||
if (parse_search(menu->items[menu->itemcount], buf))
|
||||
menu->itemcount++;
|
||||
|
@ -1148,6 +1191,7 @@ static bool parse_menu(const char *filename)
|
|||
{
|
||||
int fd;
|
||||
char buf[1024];
|
||||
int rc;
|
||||
|
||||
if (menu_count >= TAGMENU_MAX_MENUS)
|
||||
{
|
||||
|
@ -1163,10 +1207,58 @@ static bool parse_menu(const char *filename)
|
|||
}
|
||||
|
||||
/* Now read file for real, parsing into si */
|
||||
fast_readline(fd, buf, sizeof buf, NULL, parse_line);
|
||||
rc = fast_readline(fd, buf, sizeof buf, NULL, parse_line);
|
||||
close(fd);
|
||||
|
||||
return true;
|
||||
return (rc >= 0);
|
||||
}
|
||||
|
||||
static void tagtree_unload(struct tree_context *c)
|
||||
{
|
||||
int i;
|
||||
tagtree_lock();
|
||||
|
||||
remove_event(PLAYBACK_EVENT_TRACK_BUFFER, tagtree_buffer_event);
|
||||
remove_event(PLAYBACK_EVENT_TRACK_FINISH, tagtree_track_finish_event);
|
||||
|
||||
if (c)
|
||||
{
|
||||
tree_lock_cache(c);
|
||||
struct tagentry *dptr = core_get_data(c->cache.entries_handle);
|
||||
menu = menus[c->currextra];
|
||||
if (!menu)
|
||||
{
|
||||
logf("tagtree menu doesn't exist");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < menu->itemcount; i++)
|
||||
{
|
||||
dptr->name = NULL;
|
||||
dptr->newtable = 0;
|
||||
dptr->extraseek = 0;
|
||||
dptr++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < menu_count; i++)
|
||||
menus[i] = NULL;
|
||||
menu_count = 0;
|
||||
|
||||
for (i = 0; i < format_count; i++)
|
||||
formats[i] = NULL;
|
||||
format_count = 0;
|
||||
|
||||
core_free(tagtree_handle);
|
||||
tagtree_handle = 0;
|
||||
tagtree_buf_used = 0;
|
||||
tagtree_bufsize = 0;
|
||||
|
||||
if (c)
|
||||
tree_unlock_cache(c);
|
||||
tagtree_unlock();
|
||||
if (lock_count > 0)
|
||||
tagtree_unlock();/* second unlock to enable re-init */
|
||||
}
|
||||
|
||||
void tagtree_init(void)
|
||||
|
@ -1176,7 +1268,11 @@ void tagtree_init(void)
|
|||
menu = NULL;
|
||||
rootmenu = -1;
|
||||
tagtree_handle = core_alloc_maximum("tagtree", &tagtree_bufsize, &ops);
|
||||
parse_menu(FILE_SEARCH_INSTRUCTIONS);
|
||||
if (!parse_menu(FILE_SEARCH_INSTRUCTIONS))
|
||||
{
|
||||
tagtree_unload(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* safety check since tree.c needs to cast tagentry to entry */
|
||||
if (sizeof(struct tagentry) != sizeof(struct entry))
|
||||
|
@ -1358,6 +1454,9 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init)
|
|||
else
|
||||
tag = csi->tagorder[level];
|
||||
|
||||
if (tag == menu_reload)
|
||||
return RELOAD_TAGTREE;
|
||||
|
||||
if (!tagcache_search(&tcs, tag))
|
||||
return -1;
|
||||
|
||||
|
@ -1691,9 +1790,16 @@ int tagtree_load(struct tree_context* c)
|
|||
|
||||
if (count < 0)
|
||||
{
|
||||
if (count != RELOAD_TAGTREE)
|
||||
splash(HZ, str(LANG_TAGCACHE_BUSY));
|
||||
else /* unload and re-init tagtree */
|
||||
{
|
||||
splash(HZ, str(LANG_WAIT));
|
||||
tagtree_unload(c);
|
||||
tagtree_init();
|
||||
}
|
||||
c->dirlevel = 0;
|
||||
count = load_root(c);
|
||||
splash(HZ, str(LANG_TAGCACHE_BUSY));
|
||||
}
|
||||
|
||||
/* The _total_ numer of entries available. */
|
||||
|
|
Loading…
Reference in a new issue