summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/onplay.h1
-rw-r--r--apps/tagnavi.config93
-rw-r--r--apps/tagtree.c94
-rw-r--r--apps/tree.c4
4 files changed, 93 insertions, 99 deletions
diff --git a/apps/onplay.h b/apps/onplay.h
index 03861e9cf6..26b1247f7b 100644
--- a/apps/onplay.h
+++ b/apps/onplay.h
@@ -28,6 +28,7 @@
28enum { 28enum {
29 ONPLAY_NO_CUSTOMACTION, 29 ONPLAY_NO_CUSTOMACTION,
30 ONPLAY_CUSTOMACTION_SHUFFLE_SONGS, 30 ONPLAY_CUSTOMACTION_SHUFFLE_SONGS,
31 ONPLAY_CUSTOMACTION_FIRSTLETTER,
31}; 32};
32 33
33int onplay(char* file, int attr, int from_context, bool hotkey, int customaction); 34int onplay(char* file, int attr, int from_context, bool hotkey, int customaction);
diff --git a/apps/tagnavi.config b/apps/tagnavi.config
index b599f9577c..6335610253 100644
--- a/apps/tagnavi.config
+++ b/apps/tagnavi.config
@@ -30,96 +30,13 @@
30# 30#
31 31
32# Define the A to Z Artist sub menu 32# Define the A to Z Artist sub menu
33%menu_start "custom_artist" "Artist A to Z" 33%byfirstletter "custom_artist" "Artist A to Z" "canonicalartist"
34"Numeric" -> canonicalartist ? canonicalartist < "A" -> album -> title = "fmt_title"
35"A" -> canonicalartist ? canonicalartist ^ "A" -> album -> title = "fmt_title"
36"B" -> canonicalartist ? canonicalartist ^ "B" -> album -> title = "fmt_title"
37"C" -> canonicalartist ? canonicalartist ^ "C" -> album -> title = "fmt_title"
38"D" -> canonicalartist ? canonicalartist ^ "D" -> album -> title = "fmt_title"
39"E" -> canonicalartist ? canonicalartist ^ "E" -> album -> title = "fmt_title"
40"F" -> canonicalartist ? canonicalartist ^ "F" -> album -> title = "fmt_title"
41"G" -> canonicalartist ? canonicalartist ^ "G" -> album -> title = "fmt_title"
42"H" -> canonicalartist ? canonicalartist ^ "H" -> album -> title = "fmt_title"
43"I" -> canonicalartist ? canonicalartist ^ "I" -> album -> title = "fmt_title"
44"J" -> canonicalartist ? canonicalartist ^ "J" -> album -> title = "fmt_title"
45"K" -> canonicalartist ? canonicalartist ^ "K" -> album -> title = "fmt_title"
46"L" -> canonicalartist ? canonicalartist ^ "L" -> album -> title = "fmt_title"
47"M" -> canonicalartist ? canonicalartist ^ "M" -> album -> title = "fmt_title"
48"N" -> canonicalartist ? canonicalartist ^ "N" -> album -> title = "fmt_title"
49"O" -> canonicalartist ? canonicalartist ^ "O" -> album -> title = "fmt_title"
50"P" -> canonicalartist ? canonicalartist ^ "P" -> album -> title = "fmt_title"
51"Q" -> canonicalartist ? canonicalartist ^ "Q" -> album -> title = "fmt_title"
52"R" -> canonicalartist ? canonicalartist ^ "R" -> album -> title = "fmt_title"
53"S" -> canonicalartist ? canonicalartist ^ "S" -> album -> title = "fmt_title"
54"T" -> canonicalartist ? canonicalartist ^ "T" -> album -> title = "fmt_title"
55"U" -> canonicalartist ? canonicalartist ^ "U" -> album -> title = "fmt_title"
56"V" -> canonicalartist ? canonicalartist ^ "V" -> album -> title = "fmt_title"
57"W" -> canonicalartist ? canonicalartist ^ "W" -> album -> title = "fmt_title"
58"X" -> canonicalartist ? canonicalartist ^ "X" -> album -> title = "fmt_title"
59"Y" -> canonicalartist ? canonicalartist ^ "Y" -> album -> title = "fmt_title"
60"Z" -> canonicalartist ? canonicalartist ^ "Z" -> album -> title = "fmt_title"
61
62# ^ An empy line ends the menu
63
64# Define the A to Z album sub menu 34# Define the A to Z album sub menu
65%menu_start "custom_album" "Album A to Z" 35%byfirstletter "custom_album" "Album A to Z" "album"
66"Numeric" -> album ? album < "A" -> title = "fmt_title"
67"A" -> album ? album ^ "A" -> title = "fmt_title"
68"B" -> album ? album ^ "B" -> title = "fmt_title"
69"C" -> album ? album ^ "C" -> title = "fmt_title"
70"D" -> album ? album ^ "D" -> title = "fmt_title"
71"E" -> album ? album ^ "E" -> title = "fmt_title"
72"F" -> album ? album ^ "F" -> title = "fmt_title"
73"G" -> album ? album ^ "G" -> title = "fmt_title"
74"H" -> album ? album ^ "H" -> title = "fmt_title"
75"I" -> album ? album ^ "I" -> title = "fmt_title"
76"J" -> album ? album ^ "J" -> title = "fmt_title"
77"K" -> album ? album ^ "K" -> title = "fmt_title"
78"L" -> album ? album ^ "L" -> title = "fmt_title"
79"M" -> album ? album ^ "M" -> title = "fmt_title"
80"N" -> album ? album ^ "N" -> title = "fmt_title"
81"O" -> album ? album ^ "O" -> title = "fmt_title"
82"P" -> album ? album ^ "P" -> title = "fmt_title"
83"Q" -> album ? album ^ "Q" -> title = "fmt_title"
84"R" -> album ? album ^ "R" -> title = "fmt_title"
85"S" -> album ? album ^ "S" -> title = "fmt_title"
86"T" -> album ? album ^ "T" -> title = "fmt_title"
87"U" -> album ? album ^ "U" -> title = "fmt_title"
88"V" -> album ? album ^ "V" -> title = "fmt_title"
89"W" -> album ? album ^ "W" -> title = "fmt_title"
90"X" -> album ? album ^ "X" -> title = "fmt_title"
91"Y" -> album ? album ^ "Y" -> title = "fmt_title"
92"Z" -> album ? album ^ "Z" -> title = "fmt_title"
93
94# Define the A to Z track sub menu 36# Define the A to Z track sub menu
95%menu_start "custom_track" "Track A to Z" 37%byfirstletter "custom_track" "Track A to Z" "title"
96"Numeric" -> title ? title < "A" -> title = "fmt_title" 38
97"A" -> title ? title ^ "A" -> title = "fmt_title" 39# ^ An empy line ends the menu
98"B" -> title ? title ^ "B" -> title = "fmt_title"
99"C" -> title ? title ^ "C" -> title = "fmt_title"
100"D" -> title ? title ^ "D" -> title = "fmt_title"
101"E" -> title ? title ^ "E" -> title = "fmt_title"
102"F" -> title ? title ^ "F" -> title = "fmt_title"
103"G" -> title ? title ^ "G" -> title = "fmt_title"
104"H" -> title ? title ^ "H" -> title = "fmt_title"
105"I" -> title ? title ^ "I" -> title = "fmt_title"
106"J" -> title ? title ^ "J" -> title = "fmt_title"
107"K" -> title ? title ^ "K" -> title = "fmt_title"
108"L" -> title ? title ^ "L" -> title = "fmt_title"
109"M" -> title ? title ^ "M" -> title = "fmt_title"
110"N" -> title ? title ^ "N" -> title = "fmt_title"
111"O" -> title ? title ^ "O" -> title = "fmt_title"
112"P" -> title ? title ^ "P" -> title = "fmt_title"
113"Q" -> title ? title ^ "Q" -> title = "fmt_title"
114"R" -> title ? title ^ "R" -> title = "fmt_title"
115"S" -> title ? title ^ "S" -> title = "fmt_title"
116"T" -> title ? title ^ "T" -> title = "fmt_title"
117"U" -> title ? title ^ "U" -> title = "fmt_title"
118"V" -> title ? title ^ "V" -> title = "fmt_title"
119"W" -> title ? title ^ "W" -> title = "fmt_title"
120"X" -> title ? title ^ "X" -> title = "fmt_title"
121"Y" -> title ? title ^ "Y" -> title = "fmt_title"
122"Z" -> title ? title ^ "Z" -> title = "fmt_title"
123 40
124# Define the A to Z sub menu 41# Define the A to Z sub menu
125%menu_start "a2z" "A to Z..." 42%menu_start "a2z" "A to Z..."
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 {
173static struct display_format *formats[TAGMENU_MAX_FMTS]; 174static struct display_format *formats[TAGMENU_MAX_FMTS];
174static int format_count; 175static int format_count;
175 176
177#define MENUENTRY_MAX_NAME 64
176struct menu_entry { 178struct 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
1059static bool parse_menu(const char *filename); 1062static bool parse_menu(const char *filename);
1060 1063
1064static 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
1077static 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
1088static 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
1061static int parse_line(int n, char *buf, void *parameters) 1121static 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
1450static int retrieve_entries(struct tree_context *c, int offset, bool init) 1517static 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++;
diff --git a/apps/tree.c b/apps/tree.c
index ac82b6c2df..c422100de8 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -205,6 +205,7 @@ static int tree_voice_cb(int selected_item, void * data)
205 struct tree_context * local_tc=(struct tree_context *)data; 205 struct tree_context * local_tc=(struct tree_context *)data;
206 char *name; 206 char *name;
207 int attr=0; 207 int attr=0;
208 int customaction = ONPLAY_NO_CUSTOMACTION;
208#ifdef HAVE_TAGCACHE 209#ifdef HAVE_TAGCACHE
209 bool id3db = *(local_tc->dirfilter) == SHOW_ID3DB; 210 bool id3db = *(local_tc->dirfilter) == SHOW_ID3DB;
210 char buf[AVERAGE_FILENAME_LENGTH*2]; 211 char buf[AVERAGE_FILENAME_LENGTH*2];
@@ -213,6 +214,7 @@ static int tree_voice_cb(int selected_item, void * data)
213 { 214 {
214 attr = tagtree_get_attr(local_tc); 215 attr = tagtree_get_attr(local_tc);
215 name = tagtree_get_entry_name(local_tc, selected_item, buf, sizeof(buf)); 216 name = tagtree_get_entry_name(local_tc, selected_item, buf, sizeof(buf));
217 customaction = tagtree_get_custom_action(local_tc);
216 } 218 }
217 else 219 else
218#endif 220#endif
@@ -245,7 +247,7 @@ static int tree_voice_cb(int selected_item, void * data)
245 did_clip = false; 247 did_clip = false;
246 } 248 }
247 } 249 }
248 bool spell_name = false; 250 bool spell_name = (customaction == ONPLAY_CUSTOMACTION_FIRSTLETTER);
249 if(!did_clip) 251 if(!did_clip)
250 { 252 {
251 /* say the number or spell if required or as a fallback */ 253 /* say the number or spell if required or as a fallback */