summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2006-09-19 11:54:33 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2006-09-19 11:54:33 +0000
commitba34c379676f629d94b80d0c4076e6b08ade171e (patch)
tree5aa0ad237f799c01f8b80a25dddb2a974399b767 /apps
parent1d5b248f7b8ed9a82f63587f9090556a45885405 (diff)
downloadrockbox-ba34c379676f629d94b80d0c4076e6b08ade171e.tar.gz
rockbox-ba34c379676f629d94b80d0c4076e6b08ade171e.zip
Improved tag browser configuration file syntax with submenus and
includes (custom user menu, without overwriting by default menu). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11000 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/tagnavi.config61
-rw-r--r--apps/tagtree.c263
-rw-r--r--apps/tree.c2
3 files changed, 271 insertions, 55 deletions
diff --git a/apps/tagnavi.config b/apps/tagnavi.config
index 55418718bf..9821c30faf 100644
--- a/apps/tagnavi.config
+++ b/apps/tagnavi.config
@@ -1,15 +1,46 @@
-"Artist" artist : album : title = "%02d. %s" tracknum title
-"Album" album : title = "%02d. %s" tracknum title
-"Genre" genre : artist : album : title = "%02d. %s" tracknum title
-"Composer" composer : album : title = "%02d. %s" tracknum title
-"Track" title
-"Year" year ? year > "1000" & year < "2008" : artist : album : title = "%02d. %s" tracknum title
-"Search by artist" artist ? artist ~ "" : album : title = "%02d. %s" tracknum title
-"Search by album" album ? album ~ "" : title = "%02d. %s" tracknum title
-"Search by title" title ? title ~ ""
-"Search by filename" filename ? filename ~ ""
-"Search by score" title = "(%3d) %s" autoscore title ? autoscore > ""
-"Most played tracks" title = "(%3d) %s" playcount title %sort = "inverse" %limit = "100" ? playcount > "0"
-"Never played tracks" artist ? playcount == "0" : album : title = "%02d. %s" tracknum title
-"Best tracks" artist ? playcount > "1" & autoscore > "85" : album : title = "%02d. %s (%3d)" tracknum title autoscore
-"List played tracks" title = "(%3d/%d) %s" autoscore playcount title ? playcount > "0"
+#! rockbox/tagbrowser/2.0
+# ^ Version header must be the first line of every file
+
+# Tag Browser configuration file, do not edit as changes will be lost!
+# Instead, you can modify "/.rockbox/tagnavi_custom.config" which will never
+# get overwritten automatically.
+
+# Include our custom menu
+%include "/.rockbox/tagnavi_custom.config"
+
+#
+# === Begin of "Search by..." sub menu
+#
+
+# Define the search sub menu
+%menu_start "search" "Search by..."
+"Artist" -> artist ? artist ~ "" -> album -> title = "%02d. %s" tracknum title
+"Artist -> (score > 85)" artist ? artist ~ "" & autoscore >= "85" -> album -> title = "%02d. %s" tracknum title
+"Album" -> album ? album ~ "" -> title = "%02d. %s" tracknum title
+"Title" -> title ? title ~ ""
+"Filename" -> filename ? filename ~ ""
+"Score" -> title = "(%3d) %s" autoscore title ? autoscore > ""
+
+# ^ An empy line ends the menu
+
+#
+# === Begin of main menu
+#
+
+# Define the title of the main menu
+%menu_start "main" "Browse by..."
+"Artist" -> artist -> album -> title = "%02d. %s" tracknum title
+"Album" -> album -> title = "%02d. %s" tracknum title
+"Genre" -> genre -> artist -> album -> title = "%02d. %s" tracknum title
+"Composer" -> composer -> album -> title = "%02d. %s" tracknum title
+"Track" -> title
+"Year" -> year ? year > "1000" & year < "2008" -> artist -> album -> title = "%02d. %s" tracknum title
+"Search..." ==> "search"
+"Most played tracks" -> title = "(%3d) %s" playcount title %sort = "inverse" %limit = "100" ? playcount > "0"
+"Never played tracks" -> artist ? playcount == "0" -> album -> title = "%02d. %s" tracknum title
+"Best tracks" -> artist ? playcount > "1" & autoscore > "85" -> album -> title = "%02d. %s (%3d)" tracknum title autoscore
+"List played tracks" -> title = "(%3d/%d) %s" autoscore playcount title ? playcount > "0"
+"Custom view..." ==> "custom"
+
+# And finally set main menu as our root menu
+%root_menu "main"
diff --git a/apps/tagtree.c b/apps/tagtree.c
index c674cf4ebd..7a710c6fc3 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -51,7 +51,12 @@ static char searchstring[32];
enum variables {
var_sorttype = 100,
- var_limit
+ var_limit,
+ var_menu_start,
+ var_include,
+ var_rootmenu,
+ menu_next,
+ menu_load,
};
/* Capacity 10 000 entries (for example 10k different artists) */
@@ -95,9 +100,30 @@ struct search_instruction {
int result_seek[MAX_TAGS];
};
-static struct search_instruction *si, *csi;
-static int si_count = 0;
+struct menu_entry {
+ char name[64];
+ int type;
+ struct search_instruction *si;
+ int link;
+};
+
+#define TAGNAVI_VERSION "#! rockbox/tagbrowser/2.0"
+#define TAGMENU_MAX_ITEMS 32
+#define TAGMENU_MAX_MENUS 8
+struct root_menu {
+ char title[64];
+ char id[32];
+ int itemcount;
+ struct root_menu *parent;
+ struct menu_entry *items[TAGMENU_MAX_ITEMS];
+};
+
+static struct root_menu menus[TAGMENU_MAX_MENUS];
+static struct root_menu *menu;
+static struct search_instruction *csi;
static const char *strp;
+static int menu_count;
+static int root_menu;
static int current_offset;
static int current_entry_count;
@@ -138,10 +164,10 @@ static int get_tag(int *tag)
int i;
/* Find the start. */
- while (*strp == ' ' && *strp != '\0')
+ while ((*strp == ' ' || *strp == '>') && *strp != '\0')
strp++;
- if (*strp == '\0' || *strp == '?' || *strp == ':')
+ if (*strp == '\0' || *strp == '?')
return 0;
for (i = 0; i < (int)sizeof(buf)-1; i++)
@@ -167,6 +193,11 @@ static int get_tag(int *tag)
MATCH(tag, buf, "autoscore", tag_virt_autoscore);
MATCH(tag, buf, "%sort", var_sorttype);
MATCH(tag, buf, "%limit", var_limit);
+ MATCH(tag, buf, "%menu_start", var_menu_start);
+ MATCH(tag, buf, "%include", var_include);
+ MATCH(tag, buf, "%root_menu", var_rootmenu);
+ MATCH(tag, buf, "->", menu_next);
+ MATCH(tag, buf, "==>", menu_load);
logf("NO MATCH: %s\n", buf);
if (buf[0] == '?')
@@ -337,8 +368,7 @@ static int get_condition(struct search_instruction *inst)
case '&':
strp++;
return 1;
- case ':':
- strp++;
+ case '-':
case '\0':
return 0;
}
@@ -366,25 +396,56 @@ static int get_condition(struct search_instruction *inst)
* $ ends with
*/
-static bool parse_search(struct search_instruction *inst, const char *str)
+static bool parse_search(struct menu_entry *entry, const char *str)
{
int ret;
+ int type;
+ struct search_instruction *inst = entry->si;
+ char buf[MAX_PATH];
+ int i;
- memset(inst, 0, sizeof(struct search_instruction));
strp = str;
- if (get_token_str(inst->name, sizeof inst->name) < 0)
+ /* Parse entry name */
+ if (get_token_str(entry->name, sizeof entry->name) < 0)
{
logf("No name found.");
return false;
}
+ /* Parse entry type */
+ if (get_tag(&entry->type) <= 0)
+ return false;
+
+ if (entry->type == menu_load)
+ {
+ if (get_token_str(buf, sizeof buf) < 0)
+ return false;
+
+ /* Find the matching root menu or "create" it */
+ for (i = 0; i < menu_count; i++)
+ {
+ if (!strcasecmp(menus[i].id, buf))
+ {
+ entry->link = i;
+ menus[i].parent = menu;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ if (entry->type != menu_next)
+ return false;
+
while (inst->tagorder_count < MAX_TAGS)
{
ret = get_tag(&inst->tagorder[inst->tagorder_count]);
if (ret < 0)
{
logf("Parse error #1");
+ logf("%s", strp);
return false;
}
@@ -396,6 +457,9 @@ static bool parse_search(struct search_instruction *inst, const char *str)
while (get_condition(inst) > 0) ;
inst->tagorder_count++;
+
+ if (get_tag(&type) <= 0 || type != menu_next)
+ break;
}
return true;
@@ -520,46 +584,142 @@ bool tagtree_import(void)
return false;
}
-void tagtree_init(void)
+static bool parse_menu(const char *filename)
{
int fd;
char buf[256];
+ char data[256];
+ int variable;
int rc;
- int line_count;
+ bool first = true;
+ bool read_menu = false;
+ int i;
+
+ if (menu_count >= TAGMENU_MAX_MENUS)
+ return false;
- fd = open(FILE_SEARCH_INSTRUCTIONS, O_RDONLY);
+ fd = open(filename, O_RDONLY);
if (fd < 0)
{
logf("Search instruction file not found.");
- return ;
+ return false;
}
- /* Pre-pass search instructions file to count how many entries */
- line_count = 0;
- while ( 1 )
- {
- rc = read_line(fd, buf, sizeof(buf)-1);
- if (rc <= 0)
- break;
- line_count++;
- }
-
- /* Allocate memory for searches */
- si = (struct search_instruction *) buffer_alloc(sizeof(struct search_instruction) * line_count + 4);
-
/* Now read file for real, parsing into si */
- lseek(fd, 0L, SEEK_SET);
while ( 1 )
{
rc = read_line(fd, buf, sizeof(buf)-1);
if (rc <= 0)
- break;
- if (!parse_search(si + si_count, buf))
break;
- si_count++;
+
+ if (first)
+ {
+ if (strcasecmp(TAGNAVI_VERSION, buf))
+ {
+ logf("Version mismatch");
+ break;
+ }
+ first = false;
+ }
+
+ if (buf[0] == '#')
+ continue;
+
+ if (buf[0] == '\0')
+ {
+ if (read_menu)
+ {
+ /* End the menu */
+ menu_count++;
+ menu = &menus[menu_count];
+ read_menu = false;
+ }
+ continue;
+ }
+
+ if (!read_menu)
+ {
+ strp = buf;
+ if (get_tag(&variable) <= 0)
+ continue;
+
+ switch (variable)
+ {
+ case var_include:
+ if (get_token_str(data, sizeof(data)) < 0)
+ {
+ logf("%include empty");
+ return false;
+ }
+
+ if (!parse_menu(data))
+ {
+ logf("Load menu fail: %s", data);
+ }
+ break;
+
+ case var_menu_start:
+ if (get_token_str(menu->id, sizeof(menu->id)) < 0)
+ {
+ logf("%menu_start id empty");
+ return false;
+ }
+ if (get_token_str(menu->title, sizeof(menu->title)) < 0)
+ {
+ logf("%menu_start title empty");
+ return false;
+ }
+ menu->itemcount = 0;
+ read_menu = true;
+ break;
+
+ case var_rootmenu:
+ if (get_token_str(data, sizeof(data)) < 0)
+ {
+ logf("%root_menu empty");
+ return false;
+ }
+
+ for (i = 0; i < menu_count; i++)
+ {
+ if (!strcasecmp(menus[i].id, data))
+ {
+ root_menu = i;
+ }
+ }
+ break;
+ }
+
+ continue;
+ }
+
+ /* Allocate */
+ if (menu->items[menu->itemcount] == NULL)
+ {
+ menu->items[menu->itemcount] = buffer_alloc(sizeof(struct menu_entry));
+ memset(menu->items[menu->itemcount], 0, sizeof(struct menu_entry));
+ menu->items[menu->itemcount]->si = buffer_alloc(sizeof(struct search_instruction));
+ memset(menu->items[menu->itemcount]->si, 0, sizeof(struct search_instruction));
+ }
+
+ if (!parse_search(menu->items[menu->itemcount], buf))
+ continue;
+
+ menu->itemcount++;
}
close(fd);
+ return true;
+}
+
+void tagtree_init(void)
+{
+ memset(menus, 0, sizeof menus);
+ menu_count = 0;
+ menu = &menus[0];
+ root_menu = 0;
+ parse_menu(FILE_SEARCH_INSTRUCTIONS);
+
uniqbuf = buffer_alloc(UNIQBUF_SIZE);
audio_set_track_buffer_event(tagtree_buffer_event);
audio_set_track_unbuffer_event(tagtree_unbuffer_event);
@@ -858,11 +1018,27 @@ static int load_root(struct tree_context *c)
tc = c;
c->currtable = root;
- for (i = 0; i < si_count; i++)
+ if (c->dirlevel == 0)
+ c->currextra = root_menu;
+
+ menu = &menus[c->currextra];
+
+ for (i = 0; i < menu->itemcount; i++)
{
- dptr->name = (si+i)->name;
- dptr->newtable = navibrowse;
- dptr->extraseek = i;
+ dptr->name = menu->items[i]->name;
+ switch (menu->items[i]->type)
+ {
+ case menu_next:
+ dptr->newtable = navibrowse;
+ dptr->extraseek = i;
+ break;
+
+ case menu_load:
+ dptr->newtable = root;
+ dptr->extraseek = menu->items[i]->link;
+ break;
+ }
+
dptr++;
}
@@ -884,13 +1060,13 @@ int tagtree_load(struct tree_context* c)
c->dirfull = false;
table = root;
c->currtable = table;
+ c->currextra = root_menu;
}
switch (table)
{
case root:
count = load_root(c);
- c->dirlevel = 0;
break;
case allsubentries:
@@ -945,11 +1121,17 @@ int tagtree_enter(struct tree_context* c)
case root:
c->currextra = newextra;
- if (newextra == navibrowse)
+ if (newextra == root)
+ {
+ menu = &menus[seek];
+ c->currextra = seek;
+ }
+
+ else if (newextra == navibrowse)
{
int i, j;
- csi = si+seek;
+ csi = menu->items[seek]->si;
c->currextra = 0;
/* Read input as necessary. */
@@ -963,7 +1145,7 @@ int tagtree_enter(struct tree_context* c)
rc = kbd_input(searchstring, sizeof(searchstring));
if (rc == -1 || !searchstring[0])
{
- c->dirlevel--;
+ tagtree_exit(c);
return 0;
}
@@ -1024,7 +1206,8 @@ int tagtree_enter(struct tree_context* c)
void tagtree_exit(struct tree_context* c)
{
c->dirfull = false;
- c->dirlevel--;
+ if (c->dirlevel > 0)
+ c->dirlevel--;
c->selected_item=c->selected_item_history[c->dirlevel];
gui_synclist_select_item(&tree_lists, c->selected_item);
c->currtable = c->table_history[c->dirlevel];
diff --git a/apps/tree.c b/apps/tree.c
index 1f68a8560b..584aaa8006 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -532,10 +532,12 @@ static bool check_changed_id3mode(bool currmode)
currmode = global_settings.dirfilter == SHOW_ID3DB;
if (currmode) {
curr_context=CONTEXT_ID3DB;
+ tc.dirlevel = 0;
tagtree_load(&tc);
}
else
{
+ tc.dirlevel = 0;
curr_context=CONTEXT_TREE;
ft_load(&tc, NULL);
reload_dir = true;