diff options
author | William Wilgus <wilgus.william@gmail.com> | 2024-09-23 03:23:36 -0400 |
---|---|---|
committer | William Wilgus <wilgus.william@gmail.com> | 2024-11-02 17:27:22 -0400 |
commit | 06986d27f06528c8eb9f672a8f4913d3e3e7a307 (patch) | |
tree | eba4e37fbc0685621702b7ab04ad69f6616253b0 /apps/tagtree.c | |
parent | 67ad6589fbcd65281364dba51aabefdc55990b2d (diff) | |
download | rockbox-06986d27f06528c8eb9f672a8f4913d3e3e7a307.tar.gz rockbox-06986d27f06528c8eb9f672a8f4913d3e3e7a307.zip |
Generate A-Z menus in the tagtree
this adds a new command %byfirstletter
%byfirstletter "custom_track" "Track A to Z" "title"
^ command ^menu name ^menu title ^subitem
need a better name for subitem btw..
this patch also allows us to tell when we are in the BFL menu
by checking customaction == ONPLAY_CUSTOMACTION_FIRSTLETTER
we then enable spelling of the letters in the menu
it spells Numeric too but that shouldn't matter with the upcoming voice patch
Change-Id: I59815f697a4ef84a8cb540783b620d15f6670e00
Diffstat (limited to 'apps/tagtree.c')
-rw-r--r-- | apps/tagtree.c | 94 |
1 files changed, 84 insertions, 10 deletions
diff --git a/apps/tagtree.c b/apps/tagtree.c index 83bfb4e36d..4983231663 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c | |||
@@ -112,6 +112,7 @@ enum variables { | |||
112 | var_include, | 112 | var_include, |
113 | var_rootmenu, | 113 | var_rootmenu, |
114 | var_format, | 114 | var_format, |
115 | menu_byfirstletter, | ||
115 | menu_next, | 116 | menu_next, |
116 | menu_load, | 117 | menu_load, |
117 | menu_reload, | 118 | menu_reload, |
@@ -173,11 +174,12 @@ struct display_format { | |||
173 | static struct display_format *formats[TAGMENU_MAX_FMTS]; | 174 | static struct display_format *formats[TAGMENU_MAX_FMTS]; |
174 | static int format_count; | 175 | static int format_count; |
175 | 176 | ||
177 | #define MENUENTRY_MAX_NAME 64 | ||
176 | struct menu_entry { | 178 | struct menu_entry { |
177 | char name[64]; | 179 | char name[MENUENTRY_MAX_NAME]; |
178 | int type; | 180 | int type; |
179 | struct search_instruction { | 181 | struct search_instruction { |
180 | char name[64]; | 182 | char name[MENUENTRY_MAX_NAME]; |
181 | int tagorder[MAX_TAGS]; | 183 | int tagorder[MAX_TAGS]; |
182 | int tagorder_count; | 184 | int tagorder_count; |
183 | struct tagcache_search_clause *clause[MAX_TAGS][TAGCACHE_MAX_CLAUSES]; | 185 | struct tagcache_search_clause *clause[MAX_TAGS][TAGCACHE_MAX_CLAUSES]; |
@@ -381,6 +383,7 @@ static int get_tag(int *tag) | |||
381 | TAG_MATCH("comment", tag_comment), | 383 | TAG_MATCH("comment", tag_comment), |
382 | TAG_MATCH("discnum", tag_discnumber), | 384 | TAG_MATCH("discnum", tag_discnumber), |
383 | TAG_MATCH("%format", var_format), | 385 | TAG_MATCH("%format", var_format), |
386 | TAG_MATCH("%byfirstletter", menu_byfirstletter), | ||
384 | TAG_MATCH("%reload", menu_reload), | 387 | TAG_MATCH("%reload", menu_reload), |
385 | 388 | ||
386 | TAG_MATCH("filename", tag_filename), | 389 | TAG_MATCH("filename", tag_filename), |
@@ -1058,6 +1061,63 @@ int tagtree_import(void) | |||
1058 | 1061 | ||
1059 | static bool parse_menu(const char *filename); | 1062 | static bool parse_menu(const char *filename); |
1060 | 1063 | ||
1064 | static bool alloc_menu_item(void) | ||
1065 | { | ||
1066 | /* Allocate */ | ||
1067 | if (menu->items[menu->itemcount] == NULL) | ||
1068 | menu->items[menu->itemcount] = tagtree_alloc0(sizeof(struct menu_entry)); | ||
1069 | if (!menu->items[menu->itemcount]) | ||
1070 | { | ||
1071 | logf("tagtree failed to allocate %s", "menu items"); | ||
1072 | return false; | ||
1073 | } | ||
1074 | return true; | ||
1075 | } | ||
1076 | |||
1077 | static void firstletter_parse_buf(char *buf) | ||
1078 | { | ||
1079 | core_pin(tagtree_handle); | ||
1080 | if (parse_search(menu->items[menu->itemcount], buf)) | ||
1081 | { | ||
1082 | menu->items[menu->itemcount]->type = menu_byfirstletter; | ||
1083 | menu->itemcount++; | ||
1084 | } | ||
1085 | core_unpin(tagtree_handle);; | ||
1086 | } | ||
1087 | |||
1088 | static void build_firstletter_menu(char *buf, size_t bufsz) | ||
1089 | { | ||
1090 | const char *subitem = buf; | ||
1091 | size_t l = strlen(buf) + 1; | ||
1092 | buf+=l; | ||
1093 | bufsz-=l; | ||
1094 | |||
1095 | const char *showalbum = ""; | ||
1096 | const char * const fmt ="\"%s\" -> %s ? %s %c \"%c\" -> %s title = \"fmt_title\""; | ||
1097 | if (!alloc_menu_item()) | ||
1098 | return; | ||
1099 | |||
1100 | if (strcasestr(subitem, "artist") != NULL) | ||
1101 | showalbum = "album ->"; /* album subitem for canonicalartist */ | ||
1102 | |||
1103 | /* Numeric ex: "Numeric" -> album ? album < "A" -> title = "fmt_title" */ | ||
1104 | snprintf(buf, bufsz, fmt, | ||
1105 | str(LANG_DISPLAY_NUMERIC), subitem, subitem,'<', 'A', showalbum); | ||
1106 | |||
1107 | firstletter_parse_buf(buf); | ||
1108 | |||
1109 | for (int i = 0; i < 26; i++) | ||
1110 | { | ||
1111 | if (!alloc_menu_item()) | ||
1112 | return; | ||
1113 | |||
1114 | snprintf(buf, bufsz, fmt, "#", subitem, subitem,'^', 'A' + i, showalbum); | ||
1115 | buf[1] = 'A' + i; /* overwrite the placeholder # with the current letter */ | ||
1116 | /* ex: "A" -> title ? title ^ "A" -> title = "fmt_title" */ | ||
1117 | firstletter_parse_buf(buf); | ||
1118 | } | ||
1119 | } | ||
1120 | |||
1061 | static int parse_line(int n, char *buf, void *parameters) | 1121 | static int parse_line(int n, char *buf, void *parameters) |
1062 | { | 1122 | { |
1063 | char data[256]; | 1123 | char data[256]; |
@@ -1127,7 +1187,7 @@ static int parse_line(int n, char *buf, void *parameters) | |||
1127 | logf("Load menu fail: %s", data); | 1187 | logf("Load menu fail: %s", data); |
1128 | } | 1188 | } |
1129 | break; | 1189 | break; |
1130 | 1190 | case menu_byfirstletter: /* Fallthrough */ | |
1131 | case var_menu_start: | 1191 | case var_menu_start: |
1132 | if (menu_count >= TAGMENU_MAX_MENUS) | 1192 | if (menu_count >= TAGMENU_MAX_MENUS) |
1133 | { | 1193 | { |
@@ -1169,6 +1229,19 @@ static int parse_line(int n, char *buf, void *parameters) | |||
1169 | return 0; | 1229 | return 0; |
1170 | } | 1230 | } |
1171 | logf("menu: %s", menu->title); | 1231 | logf("menu: %s", menu->title); |
1232 | |||
1233 | if (variable == menu_byfirstletter) | ||
1234 | { | ||
1235 | if (get_token_str(data, sizeof(data)) < 0) | ||
1236 | { | ||
1237 | logf("%%firstletter_menu has no subitem"); /*artist,album*/ | ||
1238 | return 0; | ||
1239 | } | ||
1240 | logf("A-Z Menu subitem: %s", data); | ||
1241 | read_menu = false; | ||
1242 | build_firstletter_menu(data, sizeof(data)); | ||
1243 | break; | ||
1244 | } | ||
1172 | read_menu = true; | 1245 | read_menu = true; |
1173 | break; | 1246 | break; |
1174 | 1247 | ||
@@ -1202,14 +1275,8 @@ static int parse_line(int n, char *buf, void *parameters) | |||
1202 | return 0; | 1275 | return 0; |
1203 | } | 1276 | } |
1204 | 1277 | ||
1205 | /* Allocate */ | 1278 | if (!alloc_menu_item()) |
1206 | if (menu->items[menu->itemcount] == NULL) | ||
1207 | menu->items[menu->itemcount] = tagtree_alloc0(sizeof(struct menu_entry)); | ||
1208 | if (!menu->items[menu->itemcount]) | ||
1209 | { | ||
1210 | logf("tagtree failed to allocate %s", "menu items"); | ||
1211 | return -2; | 1279 | return -2; |
1212 | } | ||
1213 | core_pin(tagtree_handle); | 1280 | core_pin(tagtree_handle); |
1214 | if (parse_search(menu->items[menu->itemcount], buf)) | 1281 | if (parse_search(menu->items[menu->itemcount], buf)) |
1215 | menu->itemcount++; | 1282 | menu->itemcount++; |
@@ -1449,6 +1516,7 @@ static void tcs_get_basename(struct tagcache_search *tcs, bool is_basename) | |||
1449 | 1516 | ||
1450 | static int retrieve_entries(struct tree_context *c, int offset, bool init) | 1517 | static int retrieve_entries(struct tree_context *c, int offset, bool init) |
1451 | { | 1518 | { |
1519 | logf( "%s", __func__); | ||
1452 | char tcs_buf[TAGCACHE_BUFSZ]; | 1520 | char tcs_buf[TAGCACHE_BUFSZ]; |
1453 | const long tcs_bufsz = sizeof(tcs_buf); | 1521 | const long tcs_bufsz = sizeof(tcs_buf); |
1454 | struct tagcache_search tcs; | 1522 | struct tagcache_search tcs; |
@@ -1818,6 +1886,12 @@ static int load_root(struct tree_context *c) | |||
1818 | dptr->extraseek = i; | 1886 | dptr->extraseek = i; |
1819 | dptr->customaction = ONPLAY_CUSTOMACTION_SHUFFLE_SONGS; | 1887 | dptr->customaction = ONPLAY_CUSTOMACTION_SHUFFLE_SONGS; |
1820 | break; | 1888 | break; |
1889 | |||
1890 | case menu_byfirstletter: | ||
1891 | dptr->newtable = TABLE_NAVIBROWSE; | ||
1892 | dptr->extraseek = i; | ||
1893 | dptr->customaction = ONPLAY_CUSTOMACTION_FIRSTLETTER; | ||
1894 | break; | ||
1821 | } | 1895 | } |
1822 | 1896 | ||
1823 | dptr++; | 1897 | dptr++; |