diff options
author | Miika Pekkarinen <miipekk@ihme.org> | 2006-04-04 19:28:13 +0000 |
---|---|---|
committer | Miika Pekkarinen <miipekk@ihme.org> | 2006-04-04 19:28:13 +0000 |
commit | 4a63c09c8633cd7305af01d1f270125f7bd12a1e (patch) | |
tree | f9e763dc95bb8add9f9624d42792e1f6a6e176ba /apps | |
parent | 461addf6582e6951374e23233ba3964feb23630b (diff) | |
download | rockbox-4a63c09c8633cd7305af01d1f270125f7bd12a1e.tar.gz rockbox-4a63c09c8633cd7305af01d1f270125f7bd12a1e.zip |
Initial support for the advanced conditional fully configurable tagcache
browser. Browsing not supported by numeric tags yet, and some features
work currently only when tagcache is loaded in ram.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9501 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r-- | apps/main.c | 2 | ||||
-rw-r--r-- | apps/tagcache.h | 1 | ||||
-rw-r--r-- | apps/tagtree.c | 565 | ||||
-rw-r--r-- | apps/tagtree.h | 8 | ||||
-rw-r--r-- | apps/tree.c | 7 |
5 files changed, 382 insertions, 201 deletions
diff --git a/apps/main.c b/apps/main.c index e7a01c899a..596d76223d 100644 --- a/apps/main.c +++ b/apps/main.c | |||
@@ -61,6 +61,7 @@ | |||
61 | #include "database.h" | 61 | #include "database.h" |
62 | #include "dircache.h" | 62 | #include "dircache.h" |
63 | #include "tagcache.h" | 63 | #include "tagcache.h" |
64 | #include "tagtree.h" | ||
64 | #include "lang.h" | 65 | #include "lang.h" |
65 | #include "string.h" | 66 | #include "string.h" |
66 | #include "splash.h" | 67 | #include "splash.h" |
@@ -152,6 +153,7 @@ void init_tagcache(void) | |||
152 | #endif | 153 | #endif |
153 | 154 | ||
154 | tagcache_init(); | 155 | tagcache_init(); |
156 | tagtree_init(); | ||
155 | 157 | ||
156 | #ifdef HAVE_LCD_BITMAP | 158 | #ifdef HAVE_LCD_BITMAP |
157 | /* Clean the text when we are done. */ | 159 | /* Clean the text when we are done. */ |
diff --git a/apps/tagcache.h b/apps/tagcache.h index 052d71b42b..82d475811f 100644 --- a/apps/tagcache.h +++ b/apps/tagcache.h | |||
@@ -50,6 +50,7 @@ struct tagcache_search_clause | |||
50 | int tag; | 50 | int tag; |
51 | int type; | 51 | int type; |
52 | bool numeric; | 52 | bool numeric; |
53 | bool input; | ||
53 | long numeric_data; | 54 | long numeric_data; |
54 | char str[32]; | 55 | char str[32]; |
55 | }; | 56 | }; |
diff --git a/apps/tagtree.c b/apps/tagtree.c index 81998228ee..7cae86a953 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c | |||
@@ -37,9 +37,15 @@ | |||
37 | #include "playlist.h" | 37 | #include "playlist.h" |
38 | #include "keyboard.h" | 38 | #include "keyboard.h" |
39 | #include "gui/list.h" | 39 | #include "gui/list.h" |
40 | #include "buffer.h" | ||
41 | #include "atoi.h" | ||
42 | |||
43 | #define FILE_SEARCH_INSTRUCTIONS ROCKBOX_DIR "/tagnavi.config" | ||
40 | 44 | ||
41 | static int tagtree_play_folder(struct tree_context* c); | 45 | static int tagtree_play_folder(struct tree_context* c); |
42 | static int tagtree_search(struct tree_context* c, char* string); | 46 | |
47 | static const int numeric_tags[] = { tag_year, tag_length, tag_bitrate, tag_tracknumber }; | ||
48 | static const int string_tags[] = { tag_artist, tag_title, tag_album, tag_composer, tag_genre }; | ||
43 | 49 | ||
44 | static char searchstring[32]; | 50 | static char searchstring[32]; |
45 | struct tagentry { | 51 | struct tagentry { |
@@ -48,6 +54,241 @@ struct tagentry { | |||
48 | int extraseek; | 54 | int extraseek; |
49 | }; | 55 | }; |
50 | 56 | ||
57 | #define MAX_TAGS 5 | ||
58 | |||
59 | struct search_instruction { | ||
60 | char name[64]; | ||
61 | int tagorder[MAX_TAGS]; | ||
62 | int tagorder_count; | ||
63 | struct tagcache_search_clause clause[MAX_TAGS][TAGCACHE_MAX_CLAUSES]; | ||
64 | int clause_count[MAX_TAGS]; | ||
65 | int result_seek[MAX_TAGS]; | ||
66 | }; | ||
67 | |||
68 | static struct search_instruction *si, *csi; | ||
69 | static int si_count = 0; | ||
70 | static const char *strp; | ||
71 | |||
72 | static int get_token_str(char *buf, int size) | ||
73 | { | ||
74 | /* Find the start. */ | ||
75 | while (*strp != '"' && *strp != '\0') | ||
76 | strp++; | ||
77 | |||
78 | if (*strp == '\0' || *(++strp) == '\0') | ||
79 | return -1; | ||
80 | |||
81 | /* Read the data. */ | ||
82 | while (*strp != '"' && *strp != '\0' && --size > 0) | ||
83 | *(buf++) = *(strp++); | ||
84 | |||
85 | *buf = '\0'; | ||
86 | if (*strp != '"') | ||
87 | return -2; | ||
88 | |||
89 | strp++; | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | #define MATCH(tag,str1,str2,settag) \ | ||
95 | if (!strcasecmp(str1, str2)) { \ | ||
96 | *tag = settag; \ | ||
97 | return 1; \ | ||
98 | } | ||
99 | |||
100 | static int get_tag(int *tag) | ||
101 | { | ||
102 | char buf[32]; | ||
103 | int i; | ||
104 | |||
105 | /* Find the start. */ | ||
106 | while (*strp == ' ' && *strp != '\0') | ||
107 | strp++; | ||
108 | |||
109 | if (*strp == '\0') | ||
110 | return 0; | ||
111 | |||
112 | for (i = 0; i < (int)sizeof(buf)-1; i++) | ||
113 | { | ||
114 | if (*strp == '\0' || *strp == ' ') | ||
115 | break ; | ||
116 | buf[i] = *strp; | ||
117 | strp++; | ||
118 | } | ||
119 | buf[i] = '\0'; | ||
120 | |||
121 | MATCH(tag, buf, "artist", tag_artist); | ||
122 | MATCH(tag, buf, "song", tag_title); | ||
123 | MATCH(tag, buf, "album", tag_album); | ||
124 | MATCH(tag, buf, "genre", tag_genre); | ||
125 | MATCH(tag, buf, "composer", tag_composer); | ||
126 | MATCH(tag, buf, "year", tag_year); | ||
127 | MATCH(tag, buf, "length", tag_length); | ||
128 | MATCH(tag, buf, "tracknum", tag_tracknumber); | ||
129 | MATCH(tag, buf, "bitrate", tag_bitrate); | ||
130 | |||
131 | logf("NO MATCH: %s\n", buf); | ||
132 | if (buf[0] == '?') | ||
133 | return 0; | ||
134 | |||
135 | return -1; | ||
136 | } | ||
137 | |||
138 | static int get_clause(int *condition) | ||
139 | { | ||
140 | char buf[4]; | ||
141 | int i; | ||
142 | |||
143 | /* Find the start. */ | ||
144 | while (*strp == ' ' && *strp != '\0') | ||
145 | strp++; | ||
146 | |||
147 | if (*strp == '\0') | ||
148 | return 0; | ||
149 | |||
150 | for (i = 0; i < (int)sizeof(buf)-1; i++) | ||
151 | { | ||
152 | if (*strp == '\0' || *strp == ' ') | ||
153 | break ; | ||
154 | buf[i] = *strp; | ||
155 | strp++; | ||
156 | } | ||
157 | buf[i] = '\0'; | ||
158 | |||
159 | MATCH(condition, buf, "=", clause_is); | ||
160 | MATCH(condition, buf, ">", clause_gt); | ||
161 | MATCH(condition, buf, ">=", clause_gteq); | ||
162 | MATCH(condition, buf, "<", clause_lt); | ||
163 | MATCH(condition, buf, "<=", clause_lteq); | ||
164 | MATCH(condition, buf, "~", clause_contains); | ||
165 | MATCH(condition, buf, "^", clause_begins_with); | ||
166 | MATCH(condition, buf, "$", clause_ends_with); | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static bool add_clause(struct search_instruction *inst, | ||
172 | int tag, int type, const char *str) | ||
173 | { | ||
174 | int len = strlen(str); | ||
175 | struct tagcache_search_clause *clause; | ||
176 | |||
177 | if (inst->clause_count[inst->tagorder_count] >= TAGCACHE_MAX_CLAUSES) | ||
178 | { | ||
179 | logf("Too many clauses"); | ||
180 | return false; | ||
181 | } | ||
182 | |||
183 | clause = &inst->clause[inst->tagorder_count] | ||
184 | [inst->clause_count[inst->tagorder_count]]; | ||
185 | if (len >= (int)sizeof(clause->str) - 1) | ||
186 | { | ||
187 | logf("Too long str in condition"); | ||
188 | return false; | ||
189 | } | ||
190 | |||
191 | clause->tag = tag; | ||
192 | clause->type = type; | ||
193 | if (len == 0) | ||
194 | clause->input = true; | ||
195 | else | ||
196 | clause->input = false; | ||
197 | |||
198 | if (tagcache_is_numeric_tag(tag)) | ||
199 | { | ||
200 | clause->numeric = true; | ||
201 | clause->numeric_data = atoi(str); | ||
202 | } | ||
203 | else | ||
204 | { | ||
205 | clause->numeric = false; | ||
206 | strcpy(clause->str, str); | ||
207 | } | ||
208 | |||
209 | inst->clause_count[inst->tagorder_count]++; | ||
210 | |||
211 | return true; | ||
212 | } | ||
213 | |||
214 | static int get_condition(struct search_instruction *inst) | ||
215 | { | ||
216 | int tag; | ||
217 | int condition; | ||
218 | char buf[32]; | ||
219 | |||
220 | switch (*strp) | ||
221 | { | ||
222 | case '?': | ||
223 | case ' ': | ||
224 | case '&': | ||
225 | strp++; | ||
226 | return 1; | ||
227 | case ':': | ||
228 | strp++; | ||
229 | case '\0': | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | if (get_tag(&tag) <= 0) | ||
234 | return -1; | ||
235 | |||
236 | if (get_clause(&condition) <= 0) | ||
237 | return -2; | ||
238 | |||
239 | if (get_token_str(buf, sizeof buf) < 0) | ||
240 | return -3; | ||
241 | |||
242 | logf("got clause: %d/%d [%s]", tag, condition, buf); | ||
243 | add_clause(inst, tag, condition, buf); | ||
244 | |||
245 | return 1; | ||
246 | } | ||
247 | |||
248 | /* example search: | ||
249 | * "Best" artist ? year >= "2000" & title !^ "crap" & genre = "good genre" \ | ||
250 | * : album ? year >= "2000" : songs | ||
251 | * ^ begins with | ||
252 | * * contains | ||
253 | * $ ends with | ||
254 | */ | ||
255 | |||
256 | static bool parse_search(struct search_instruction *inst, const char *str) | ||
257 | { | ||
258 | int ret; | ||
259 | |||
260 | memset(inst, 0, sizeof(struct search_instruction)); | ||
261 | strp = str; | ||
262 | |||
263 | if (get_token_str(inst->name, sizeof inst->name) < 0) | ||
264 | { | ||
265 | logf("No name found."); | ||
266 | return false; | ||
267 | } | ||
268 | |||
269 | while (inst->tagorder_count < MAX_TAGS) | ||
270 | { | ||
271 | ret = get_tag(&inst->tagorder[inst->tagorder_count]); | ||
272 | if (ret < 0) | ||
273 | { | ||
274 | logf("Parse error #1"); | ||
275 | return false; | ||
276 | } | ||
277 | |||
278 | if (ret == 0) | ||
279 | break ; | ||
280 | |||
281 | logf("tag: %d", inst->tagorder[inst->tagorder_count]); | ||
282 | |||
283 | while (get_condition(inst) > 0) ; | ||
284 | |||
285 | inst->tagorder_count++; | ||
286 | } | ||
287 | |||
288 | return true; | ||
289 | } | ||
290 | |||
291 | |||
51 | static struct tagcache_search tcs; | 292 | static struct tagcache_search tcs; |
52 | 293 | ||
53 | static int compare(const void *p1, const void *p2) | 294 | static int compare(const void *p1, const void *p2) |
@@ -58,6 +299,64 @@ static int compare(const void *p1, const void *p2) | |||
58 | return strncasecmp(e1->name, e2->name, MAX_PATH); | 299 | return strncasecmp(e1->name, e2->name, MAX_PATH); |
59 | } | 300 | } |
60 | 301 | ||
302 | void tagtree_init(void) | ||
303 | { | ||
304 | int fd; | ||
305 | char buf[256]; | ||
306 | int pos = 0; | ||
307 | |||
308 | si_count = 0; | ||
309 | |||
310 | fd = open(FILE_SEARCH_INSTRUCTIONS, O_RDONLY); | ||
311 | if (fd < 0) | ||
312 | { | ||
313 | logf("Search instruction file not found."); | ||
314 | return ; | ||
315 | } | ||
316 | |||
317 | si = (struct search_instruction *)(((long)audiobuf & ~0x03) + 0x04); | ||
318 | |||
319 | while ( 1 ) | ||
320 | { | ||
321 | char *p; | ||
322 | char *next = NULL; | ||
323 | int rc; | ||
324 | |||
325 | rc = read(fd, &buf[pos], sizeof(buf)-pos-1); | ||
326 | if (rc >= 0) | ||
327 | buf[pos+rc] = '\0'; | ||
328 | |||
329 | if ( (p = strchr(buf, '\r')) != NULL) | ||
330 | { | ||
331 | *p = '\0'; | ||
332 | next = ++p; | ||
333 | } | ||
334 | else | ||
335 | p = buf; | ||
336 | |||
337 | if ( (p = strchr(p, '\n')) != NULL) | ||
338 | { | ||
339 | *p = '\0'; | ||
340 | next = ++p; | ||
341 | } | ||
342 | |||
343 | if (!parse_search(si + si_count, buf)) | ||
344 | break; | ||
345 | si_count++; | ||
346 | |||
347 | if (next) | ||
348 | { | ||
349 | pos = sizeof(buf) - ((long)next - (long)buf) - 1; | ||
350 | memmove(buf, next, pos); | ||
351 | } | ||
352 | else | ||
353 | break ; | ||
354 | } | ||
355 | close(fd); | ||
356 | |||
357 | audiobuf += sizeof(struct search_instruction) * si_count + 4; | ||
358 | } | ||
359 | |||
61 | int tagtree_load(struct tree_context* c) | 360 | int tagtree_load(struct tree_context* c) |
62 | { | 361 | { |
63 | int i; | 362 | int i; |
@@ -67,8 +366,7 @@ int tagtree_load(struct tree_context* c) | |||
67 | 366 | ||
68 | int table = c->currtable; | 367 | int table = c->currtable; |
69 | int extra = c->currextra; | 368 | int extra = c->currextra; |
70 | int extra2 = c->currextra2; | 369 | |
71 | |||
72 | c->dentry_size = sizeof(struct tagentry); | 370 | c->dentry_size = sizeof(struct tagentry); |
73 | 371 | ||
74 | if (!table) | 372 | if (!table) |
@@ -83,107 +381,34 @@ int tagtree_load(struct tree_context* c) | |||
83 | 381 | ||
84 | switch (table) { | 382 | switch (table) { |
85 | case root: { | 383 | case root: { |
86 | static const int tables[] = {allartists, allalbums, allgenres, allsongs, | 384 | for (i = 0; i < si_count; i++) |
87 | search }; | 385 | { |
88 | unsigned char* labels[] = { str(LANG_ID3DB_ARTISTS), | 386 | dptr->name = (si+i)->name; |
89 | str(LANG_ID3DB_ALBUMS), | 387 | dptr->newtable = navibrowse; |
90 | str(LANG_ID3DB_GENRES), | 388 | dptr->extraseek = i; |
91 | str(LANG_ID3DB_SONGS), | ||
92 | str(LANG_ID3DB_SEARCH)}; | ||
93 | |||
94 | for (i = 0; i < 5; i++) { | ||
95 | dptr->name = &c->name_buffer[namebufused]; | ||
96 | dptr->newtable = tables[i]; | ||
97 | strcpy(dptr->name, (char *)labels[i]); | ||
98 | namebufused += strlen(dptr->name) + 1; | ||
99 | dptr++; | 389 | dptr++; |
100 | } | 390 | } |
101 | c->dirlength = c->filesindir = i; | 391 | c->dirlength = c->filesindir = i; |
102 | return i; | ||
103 | } | ||
104 | |||
105 | case search: { | ||
106 | static const int tables[] = {searchartists, | ||
107 | searchalbums, | ||
108 | searchsongs}; | ||
109 | unsigned char* labels[] = { str(LANG_ID3DB_SEARCH_ARTISTS), | ||
110 | str(LANG_ID3DB_SEARCH_ALBUMS), | ||
111 | str(LANG_ID3DB_SEARCH_SONGS)}; | ||
112 | 392 | ||
113 | for (i = 0; i < 3; i++) { | 393 | return c->dirlength; |
114 | dptr->name = &c->name_buffer[namebufused]; | ||
115 | dptr->newtable = tables[i]; | ||
116 | strcpy(dptr->name, (char *)labels[i]); | ||
117 | namebufused += strlen(dptr->name) + 1; | ||
118 | dptr++; | ||
119 | } | ||
120 | c->dirlength = c->filesindir = i; | ||
121 | return i; | ||
122 | } | 394 | } |
123 | 395 | ||
124 | case searchartists: | 396 | case navibrowse: |
125 | case searchalbums: | 397 | logf("navibrowse..."); |
126 | case searchsongs: | 398 | tagcache_search(&tcs, csi->tagorder[extra]); |
127 | i = tagtree_search(c, searchstring); | 399 | for (i = 0; i < extra; i++) |
128 | c->dirlength = c->filesindir = i; | 400 | { |
129 | if (c->dirfull) { | 401 | tagcache_search_add_filter(&tcs, csi->tagorder[i], csi->result_seek[i]); |
130 | gui_syncsplash(HZ, true, str(LANG_SHOWDIR_BUFFER_FULL)); | 402 | sort = true; |
131 | c->dirfull = false; | 403 | } |
404 | |||
405 | for (i = 0; i < csi->clause_count[extra]; i++) | ||
406 | { | ||
407 | tagcache_search_add_clause(&tcs, &csi->clause[extra][i]); | ||
408 | sort = true; | ||
132 | } | 409 | } |
133 | else | ||
134 | gui_syncsplash(HZ, true, str(LANG_ID3DB_MATCHES), i); | ||
135 | return i; | ||
136 | |||
137 | case allsongs: | ||
138 | logf("songs.."); | ||
139 | tagcache_search(&tcs, tag_title); | ||
140 | break; | ||
141 | |||
142 | case allgenres: | ||
143 | logf("genres.."); | ||
144 | tagcache_search(&tcs, tag_genre); | ||
145 | break; | ||
146 | |||
147 | case allalbums: | ||
148 | logf("albums.."); | ||
149 | tagcache_search(&tcs, tag_album); | ||
150 | break; | ||
151 | |||
152 | case allartists: | ||
153 | logf("artists.."); | ||
154 | tagcache_search(&tcs, tag_artist); | ||
155 | break; | ||
156 | |||
157 | case artist4genres: | ||
158 | logf("artist4genres.."); | ||
159 | tagcache_search(&tcs, tag_artist); | ||
160 | tagcache_search_add_filter(&tcs, tag_genre, extra); | ||
161 | sort = true; | ||
162 | break; | ||
163 | |||
164 | case albums4artist: | ||
165 | logf("albums4artist.."); | ||
166 | tagcache_search(&tcs, tag_album); | ||
167 | tagcache_search_add_filter(&tcs, tag_artist, extra); | ||
168 | sort = true; | ||
169 | break; | ||
170 | |||
171 | case songs4album: | ||
172 | logf("songs4album.."); | ||
173 | tagcache_search(&tcs, tag_title); | ||
174 | tagcache_search_add_filter(&tcs, tag_album, extra); | ||
175 | sort = true; | ||
176 | if (extra2 > 0) | ||
177 | tagcache_search_add_filter(&tcs, tag_artist, extra2); | ||
178 | break; | ||
179 | |||
180 | case songs4artist: | ||
181 | logf("songs4artist.."); | ||
182 | tagcache_search(&tcs, tag_title); | ||
183 | tagcache_search_add_filter(&tcs, tag_artist, extra); | ||
184 | sort = true; | ||
185 | break; | 410 | break; |
186 | 411 | ||
187 | case chunked_next: | 412 | case chunked_next: |
188 | logf("chunked next..."); | 413 | logf("chunked next..."); |
189 | break; | 414 | break; |
@@ -199,10 +424,10 @@ int tagtree_load(struct tree_context* c) | |||
199 | while (tagcache_get_next(&tcs)) | 424 | while (tagcache_get_next(&tcs)) |
200 | { | 425 | { |
201 | dptr->newtable = tcs.result_seek; | 426 | dptr->newtable = tcs.result_seek; |
202 | if (!tcs.ramsearch || table == songs4album) | 427 | if (!tcs.ramsearch || csi->tagorder[extra] == tag_title) |
203 | { | 428 | { |
204 | dptr->name = &c->name_buffer[namebufused]; | 429 | dptr->name = &c->name_buffer[namebufused]; |
205 | if (table == songs4album) | 430 | if (csi->tagorder[extra] == tag_title) |
206 | { | 431 | { |
207 | snprintf(dptr->name, c->name_buffer_size - namebufused, "%02d. %s", | 432 | snprintf(dptr->name, c->name_buffer_size - namebufused, "%02d. %s", |
208 | tagcache_get_numeric(&tcs, tag_tracknumber), | 433 | tagcache_get_numeric(&tcs, tag_tracknumber), |
@@ -264,54 +489,6 @@ int tagtree_load(struct tree_context* c) | |||
264 | return i; | 489 | return i; |
265 | } | 490 | } |
266 | 491 | ||
267 | static int tagtree_search(struct tree_context* c, char* string) | ||
268 | { | ||
269 | struct tagentry *dptr = (struct tagentry *)c->dircache; | ||
270 | int hits = 0; | ||
271 | int namebufused = 0; | ||
272 | |||
273 | switch (c->currtable) { | ||
274 | case searchartists: | ||
275 | tagcache_search(&tcs, tag_artist); | ||
276 | break; | ||
277 | |||
278 | case searchalbums: | ||
279 | tagcache_search(&tcs, tag_album); | ||
280 | break; | ||
281 | |||
282 | case searchsongs: | ||
283 | tagcache_search(&tcs, tag_title); | ||
284 | break; | ||
285 | |||
286 | default: | ||
287 | logf("Invalid table %d\n", c->currtable); | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | while (tagcache_get_next(&tcs)) | ||
292 | { | ||
293 | if (!strcasestr(tcs.result, string)) | ||
294 | continue ; | ||
295 | |||
296 | if (!tcs.ramsearch) | ||
297 | { | ||
298 | dptr->name = &c->name_buffer[namebufused]; | ||
299 | namebufused += tcs.result_len; | ||
300 | strcpy(dptr->name, tcs.result); | ||
301 | } | ||
302 | else | ||
303 | dptr->name = tcs.result; | ||
304 | |||
305 | dptr->newtable = tcs.result_seek; | ||
306 | dptr++; | ||
307 | hits++; | ||
308 | } | ||
309 | |||
310 | tagcache_search_finish(&tcs); | ||
311 | |||
312 | return hits; | ||
313 | } | ||
314 | |||
315 | int tagtree_enter(struct tree_context* c) | 492 | int tagtree_enter(struct tree_context* c) |
316 | { | 493 | { |
317 | int rc = 0; | 494 | int rc = 0; |
@@ -343,53 +520,55 @@ int tagtree_enter(struct tree_context* c) | |||
343 | case root: | 520 | case root: |
344 | c->currtable = newextra; | 521 | c->currtable = newextra; |
345 | c->currextra = newextra; | 522 | c->currextra = newextra; |
523 | if (newextra == navibrowse) | ||
524 | { | ||
525 | int i, j; | ||
526 | |||
527 | csi = si+dptr->extraseek; | ||
528 | c->currextra = 0; | ||
529 | |||
530 | /* Read input as necessary. */ | ||
531 | for (i = 0; i < csi->tagorder_count; i++) | ||
532 | { | ||
533 | for (j = 0; j < csi->clause_count[i]; j++) | ||
534 | { | ||
535 | if (!csi->clause[i][j].input) | ||
536 | continue; | ||
537 | |||
538 | rc = kbd_input(searchstring, sizeof(searchstring)); | ||
539 | if (rc == -1 || !searchstring[0]) | ||
540 | { | ||
541 | c->dirlevel--; | ||
542 | break; | ||
543 | } | ||
544 | |||
545 | if (csi->clause[i][j].numeric) | ||
546 | csi->clause[i][j].numeric_data = atoi(searchstring); | ||
547 | else | ||
548 | strncpy(csi->clause[i][j].str, searchstring, | ||
549 | sizeof(csi->clause[i][j].str)-1); | ||
550 | } | ||
551 | } | ||
552 | |||
553 | } | ||
346 | break; | 554 | break; |
347 | 555 | ||
348 | case allartists: | 556 | case navibrowse: |
349 | case searchartists: | 557 | csi->result_seek[c->currextra] = newextra; |
350 | c->currtable = albums4artist; | 558 | if (c->currextra < csi->tagorder_count-1) |
351 | c->currextra = newextra; | 559 | { |
352 | break; | 560 | c->currextra++; |
353 | 561 | break; | |
354 | case allgenres: | 562 | } |
355 | c->currtable = artist4genres; | ||
356 | c->currextra = newextra; | ||
357 | break; | ||
358 | 563 | ||
359 | case artist4genres: | ||
360 | c->currtable = albums4artist; | ||
361 | c->currextra = newextra; | ||
362 | break; | ||
363 | |||
364 | case allalbums: | ||
365 | c->currtable = songs4album; | ||
366 | c->currextra = newextra; | ||
367 | c->currextra2 = -1; | ||
368 | break; | ||
369 | case albums4artist: | ||
370 | case searchalbums: | ||
371 | c->currtable = songs4album; | ||
372 | c->currextra2 = c->currextra; | ||
373 | c->currextra = newextra; | ||
374 | break; | ||
375 | |||
376 | case allsongs: | ||
377 | case songs4album: | ||
378 | case songs4artist: | ||
379 | case searchsongs: | ||
380 | c->dirlevel--; | 564 | c->dirlevel--; |
381 | if (tagtree_play_folder(c) >= 0) | 565 | if (csi->tagorder[c->currextra] == tag_title) |
382 | rc = 2; | 566 | { |
383 | break; | 567 | if (tagtree_play_folder(c) >= 0) |
384 | 568 | rc = 2; | |
385 | case search: | 569 | } |
386 | rc = kbd_input(searchstring, sizeof(searchstring)); | ||
387 | if (rc == -1 || !searchstring[0]) | ||
388 | c->dirlevel--; | ||
389 | else | ||
390 | c->currtable = newextra; | ||
391 | break; | 570 | break; |
392 | 571 | ||
393 | default: | 572 | default: |
394 | c->dirlevel--; | 573 | c->dirlevel--; |
395 | break; | 574 | break; |
@@ -545,11 +724,11 @@ int tagtree_get_icon(struct tree_context* c) | |||
545 | 724 | ||
546 | switch (c->currtable) | 725 | switch (c->currtable) |
547 | { | 726 | { |
548 | case allsongs: | 727 | case navibrowse: |
549 | case songs4album: | 728 | if (csi->tagorder[c->currextra] == tag_title) |
550 | case songs4artist: | 729 | icon = Icon_Audio; |
551 | case searchsongs: | 730 | else |
552 | icon = Icon_Audio; | 731 | icon = Icon_Folder; |
553 | break; | 732 | break; |
554 | 733 | ||
555 | default: | 734 | default: |
diff --git a/apps/tagtree.h b/apps/tagtree.h index 7eafb7061d..2a275c89f8 100644 --- a/apps/tagtree.h +++ b/apps/tagtree.h | |||
@@ -22,11 +22,11 @@ | |||
22 | #include "tagcache.h" | 22 | #include "tagcache.h" |
23 | #include "tree.h" | 23 | #include "tree.h" |
24 | 24 | ||
25 | enum table { invalid, root, allsongs, allalbums, allartists, allgenres, | 25 | enum table { |
26 | albums4artist, songs4album, songs4artist, artist4genres, | 26 | invalid, root, navibrowse, |
27 | search, searchartists, searchalbums, searchsongs, | 27 | chunked_next }; |
28 | chunked_next }; | ||
29 | 28 | ||
29 | void tagtree_init(void); | ||
30 | int tagtree_enter(struct tree_context* c); | 30 | int tagtree_enter(struct tree_context* c); |
31 | void tagtree_exit(struct tree_context* c); | 31 | void tagtree_exit(struct tree_context* c); |
32 | int tagtree_load(struct tree_context* c); | 32 | int tagtree_load(struct tree_context* c); |
diff --git a/apps/tree.c b/apps/tree.c index 3a0a34b621..f523b1c5f2 100644 --- a/apps/tree.c +++ b/apps/tree.c | |||
@@ -767,10 +767,9 @@ static bool dirbrowse(void) | |||
767 | { | 767 | { |
768 | switch (tc.currtable) | 768 | switch (tc.currtable) |
769 | { | 769 | { |
770 | case allsongs: | 770 | case navibrowse: |
771 | case songs4album: | 771 | if (tc.currextra != tag_title) |
772 | case songs4artist: | 772 | break; |
773 | case searchsongs: | ||
774 | attr=TREE_ATTR_MPA; | 773 | attr=TREE_ATTR_MPA; |
775 | tagtree_get_filename(&tc, buf, sizeof(buf)); | 774 | tagtree_get_filename(&tc, buf, sizeof(buf)); |
776 | break; | 775 | break; |