diff options
author | Miika Pekkarinen <miipekk@ihme.org> | 2006-07-15 17:36:25 +0000 |
---|---|---|
committer | Miika Pekkarinen <miipekk@ihme.org> | 2006-07-15 17:36:25 +0000 |
commit | 45dfe2a36f03d1ada7036dedb50fb98d7c5421b2 (patch) | |
tree | 866a57b677dce40ef5b772e1514a9ec6a35f60ea /apps/tagtree.c | |
parent | e60cb43a982e03b062bd42dbe260abca299fe14d (diff) | |
download | rockbox-45dfe2a36f03d1ada7036dedb50fb98d7c5421b2.tar.gz rockbox-45dfe2a36f03d1ada7036dedb50fb98d7c5421b2.zip |
Initial runtimedb support for tagcache. Only for developers,
statistical data will be lost in future until changelogs has been
implemented.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10217 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/tagtree.c')
-rw-r--r-- | apps/tagtree.c | 236 |
1 files changed, 206 insertions, 30 deletions
diff --git a/apps/tagtree.c b/apps/tagtree.c index ded2426d41..396248d7ce 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include "gui/list.h" | 39 | #include "gui/list.h" |
40 | #include "buffer.h" | 40 | #include "buffer.h" |
41 | #include "atoi.h" | 41 | #include "atoi.h" |
42 | #include "playback.h" | ||
42 | 43 | ||
43 | #define FILE_SEARCH_INSTRUCTIONS ROCKBOX_DIR "/tagnavi.config" | 44 | #define FILE_SEARCH_INSTRUCTIONS ROCKBOX_DIR "/tagnavi.config" |
44 | 45 | ||
@@ -47,11 +48,28 @@ static int tagtree_play_folder(struct tree_context* c); | |||
47 | static char searchstring[32]; | 48 | static char searchstring[32]; |
48 | #define MAX_TAGS 5 | 49 | #define MAX_TAGS 5 |
49 | 50 | ||
51 | /* | ||
52 | * "%3d. %s" autoscore title | ||
53 | * | ||
54 | * valid = true | ||
55 | * formatstr = "%-3d. %s" | ||
56 | * tags[0] = tag_autoscore | ||
57 | * tags[1] = tag_title | ||
58 | * tag_count = 2 | ||
59 | */ | ||
60 | struct display_format { | ||
61 | bool valid; | ||
62 | char formatstr[64]; | ||
63 | int tags[MAX_TAGS]; | ||
64 | int tag_count; | ||
65 | }; | ||
66 | |||
50 | struct search_instruction { | 67 | struct search_instruction { |
51 | char name[64]; | 68 | char name[64]; |
52 | int tagorder[MAX_TAGS]; | 69 | int tagorder[MAX_TAGS]; |
53 | int tagorder_count; | 70 | int tagorder_count; |
54 | struct tagcache_search_clause clause[MAX_TAGS][TAGCACHE_MAX_CLAUSES]; | 71 | struct tagcache_search_clause clause[MAX_TAGS][TAGCACHE_MAX_CLAUSES]; |
72 | struct display_format format[MAX_TAGS]; | ||
55 | int clause_count[MAX_TAGS]; | 73 | int clause_count[MAX_TAGS]; |
56 | int result_seek[MAX_TAGS]; | 74 | int result_seek[MAX_TAGS]; |
57 | }; | 75 | }; |
@@ -121,6 +139,8 @@ static int get_tag(int *tag) | |||
121 | MATCH(tag, buf, "title", tag_title); | 139 | MATCH(tag, buf, "title", tag_title); |
122 | MATCH(tag, buf, "tracknum", tag_tracknumber); | 140 | MATCH(tag, buf, "tracknum", tag_tracknumber); |
123 | MATCH(tag, buf, "year", tag_year); | 141 | MATCH(tag, buf, "year", tag_year); |
142 | MATCH(tag, buf, "playcount", tag_playcount); | ||
143 | MATCH(tag, buf, "autoscore", tag_virt_autoscore); | ||
124 | 144 | ||
125 | logf("NO MATCH: %s\n", buf); | 145 | logf("NO MATCH: %s\n", buf); |
126 | if (buf[0] == '?') | 146 | if (buf[0] == '?') |
@@ -163,7 +183,7 @@ static int get_clause(int *condition) | |||
163 | return 0; | 183 | return 0; |
164 | } | 184 | } |
165 | 185 | ||
166 | static bool add_clause(struct search_instruction *inst, | 186 | static bool add_clause(struct search_instruction *inst, |
167 | int tag, int type, const char *str) | 187 | int tag, int type, const char *str) |
168 | { | 188 | { |
169 | int len = strlen(str); | 189 | int len = strlen(str); |
@@ -206,14 +226,51 @@ static bool add_clause(struct search_instruction *inst, | |||
206 | return true; | 226 | return true; |
207 | } | 227 | } |
208 | 228 | ||
229 | static int get_format_str(struct display_format *fmt) | ||
230 | { | ||
231 | int ret; | ||
232 | |||
233 | memset(fmt, 0, sizeof(struct display_format)); | ||
234 | |||
235 | if (get_token_str(fmt->formatstr, sizeof fmt->formatstr) < 0) | ||
236 | return -10; | ||
237 | |||
238 | while (fmt->tag_count < MAX_TAGS) | ||
239 | { | ||
240 | ret = get_tag(&fmt->tags[fmt->tag_count]); | ||
241 | if (ret < 0) | ||
242 | return -11; | ||
243 | |||
244 | if (ret == 0) | ||
245 | break; | ||
246 | |||
247 | fmt->tag_count++; | ||
248 | } | ||
249 | |||
250 | fmt->valid = true; | ||
251 | |||
252 | return 1; | ||
253 | } | ||
254 | |||
209 | static int get_condition(struct search_instruction *inst) | 255 | static int get_condition(struct search_instruction *inst) |
210 | { | 256 | { |
257 | struct display_format format; | ||
258 | struct display_format *fmt = NULL; | ||
211 | int tag; | 259 | int tag; |
212 | int condition; | 260 | int condition; |
213 | char buf[32]; | 261 | char buf[32]; |
214 | 262 | ||
215 | switch (*strp) | 263 | switch (*strp) |
216 | { | 264 | { |
265 | case '=': | ||
266 | if (get_format_str(&format) < 0) | ||
267 | { | ||
268 | logf("get_format_str() parser failed!"); | ||
269 | return -4; | ||
270 | } | ||
271 | fmt = &format; | ||
272 | break; | ||
273 | |||
217 | case '?': | 274 | case '?': |
218 | case ' ': | 275 | case ' ': |
219 | case '&': | 276 | case '&': |
@@ -225,6 +282,14 @@ static int get_condition(struct search_instruction *inst) | |||
225 | return 0; | 282 | return 0; |
226 | } | 283 | } |
227 | 284 | ||
285 | if (fmt) | ||
286 | { | ||
287 | memcpy(&inst->format[inst->tagorder_count], fmt, | ||
288 | sizeof(struct display_format)); | ||
289 | } | ||
290 | else | ||
291 | inst->format[inst->tagorder_count].valid = false; | ||
292 | |||
228 | if (get_tag(&tag) <= 0) | 293 | if (get_tag(&tag) <= 0) |
229 | return -1; | 294 | return -1; |
230 | 295 | ||
@@ -294,6 +359,62 @@ static int compare(const void *p1, const void *p2) | |||
294 | return strncasecmp(e1->name, e2->name, MAX_PATH); | 359 | return strncasecmp(e1->name, e2->name, MAX_PATH); |
295 | } | 360 | } |
296 | 361 | ||
362 | static void tagtree_buffer_event(struct mp3entry *id3, bool last_track) | ||
363 | { | ||
364 | (void)id3; | ||
365 | (void)last_track; | ||
366 | |||
367 | logf("be:%d%s", last_track, id3->path); | ||
368 | } | ||
369 | |||
370 | static void tagtree_unbuffer_event(struct mp3entry *id3, bool last_track) | ||
371 | { | ||
372 | (void)last_track; | ||
373 | long playcount; | ||
374 | long playtime; | ||
375 | long lastplayed; | ||
376 | |||
377 | /* Do not gather data unless proper setting has been enabled. */ | ||
378 | if (!global_settings.runtimedb) | ||
379 | return; | ||
380 | |||
381 | /* Don't process unplayed tracks. */ | ||
382 | if (id3->elapsed == 0) | ||
383 | return; | ||
384 | |||
385 | if (!tagcache_find_index(&tcs, id3->path)) | ||
386 | { | ||
387 | logf("tc stat: not found: %s", id3->path); | ||
388 | return; | ||
389 | } | ||
390 | |||
391 | playcount = tagcache_get_numeric(&tcs, tag_playcount); | ||
392 | playtime = tagcache_get_numeric(&tcs, tag_playtime); | ||
393 | lastplayed = tagcache_get_numeric(&tcs, tag_lastplayed); | ||
394 | |||
395 | playcount++; | ||
396 | |||
397 | /* Ignore the last 15s (crossfade etc.) */ | ||
398 | playtime += MIN(id3->length, id3->elapsed + 15 * 1000); | ||
399 | |||
400 | logf("ube:%s", id3->path); | ||
401 | logf("-> %d/%d/%d", last_track, playcount, playtime); | ||
402 | logf("-> %d/%d/%d", id3->elapsed, id3->length, MIN(id3->length, id3->elapsed + 15 * 1000)); | ||
403 | |||
404 | /* lastplayed not yet supported. */ | ||
405 | |||
406 | if (!tagcache_modify_numeric_entry(&tcs, tag_playcount, playcount) | ||
407 | || !tagcache_modify_numeric_entry(&tcs, tag_playtime, playtime) | ||
408 | || !tagcache_modify_numeric_entry(&tcs, tag_lastplayed, tag_lastplayed)) | ||
409 | { | ||
410 | logf("tc stat: modify failed!"); | ||
411 | tagcache_search_finish(&tcs); | ||
412 | return; | ||
413 | } | ||
414 | |||
415 | tagcache_search_finish(&tcs); | ||
416 | } | ||
417 | |||
297 | void tagtree_init(void) | 418 | void tagtree_init(void) |
298 | { | 419 | { |
299 | int fd; | 420 | int fd; |
@@ -350,6 +471,9 @@ void tagtree_init(void) | |||
350 | close(fd); | 471 | close(fd); |
351 | 472 | ||
352 | audiobuf += sizeof(struct search_instruction) * si_count + 4; | 473 | audiobuf += sizeof(struct search_instruction) * si_count + 4; |
474 | |||
475 | audio_set_track_buffer_event(tagtree_buffer_event); | ||
476 | audio_set_track_unbuffer_event(tagtree_unbuffer_event); | ||
353 | } | 477 | } |
354 | 478 | ||
355 | bool show_search_progress(bool init, int count) | 479 | bool show_search_progress(bool init, int count) |
@@ -445,48 +569,100 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, | |||
445 | 569 | ||
446 | while (tagcache_get_next(tcs)) | 570 | while (tagcache_get_next(tcs)) |
447 | { | 571 | { |
572 | struct display_format *fmt = &csi->format[extra]; | ||
573 | |||
448 | if (total_count++ < offset) | 574 | if (total_count++ < offset) |
449 | continue; | 575 | continue; |
450 | 576 | ||
451 | dptr->newtable = navibrowse; | 577 | dptr->newtable = navibrowse; |
452 | dptr->extraseek = tcs->result_seek; | 578 | dptr->extraseek = tcs->result_seek; |
453 | if (!tcs->ramsearch || tag == tag_title) | 579 | if (tag == tag_title) |
580 | dptr->newtable = playtrack; | ||
581 | |||
582 | if (!tcs->ramsearch || fmt->valid) | ||
454 | { | 583 | { |
455 | int tracknum = -1; | 584 | char buf[MAX_PATH]; |
585 | int buf_pos = 0; | ||
456 | 586 | ||
457 | dptr->name = &c->name_buffer[namebufused]; | 587 | if (fmt->valid) |
458 | if (tag == tag_title) | ||
459 | { | ||
460 | dptr->newtable = playtrack; | ||
461 | if (c->currtable != allsubentries && c->dirlevel > 1) | ||
462 | tracknum = tagcache_get_numeric(tcs, tag_tracknumber); | ||
463 | } | ||
464 | |||
465 | if (tracknum > 0) | ||
466 | { | 588 | { |
467 | snprintf(dptr->name, c->name_buffer_size - namebufused, "%02d. %s", | 589 | char fmtbuf[8]; |
468 | tracknum, tcs->result); | 590 | bool read_format = false; |
469 | namebufused += strlen(dptr->name) + 1; | 591 | int fmtbuf_pos = 0; |
470 | if (namebufused >= c->name_buffer_size) | 592 | int parpos = 0; |
593 | |||
594 | memset(buf, 0, sizeof buf); | ||
595 | for (i = 0; fmt->formatstr[i] != '\0'; i++) | ||
471 | { | 596 | { |
472 | logf("chunk mode #1: %d", current_entry_count); | 597 | if (fmt->formatstr[i] == '%') |
473 | c->dirfull = true; | 598 | { |
474 | sort = false; | 599 | read_format = true; |
475 | break ; | 600 | fmtbuf_pos = 0; |
601 | if (parpos >= fmt->tag_count) | ||
602 | { | ||
603 | logf("too many format tags"); | ||
604 | return 0; | ||
605 | } | ||
606 | } | ||
607 | |||
608 | if (read_format) | ||
609 | { | ||
610 | fmtbuf[fmtbuf_pos++] = fmt->formatstr[i]; | ||
611 | if (fmtbuf_pos >= (long)sizeof(fmtbuf)) | ||
612 | { | ||
613 | logf("format parse error"); | ||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | if (fmt->formatstr[i] == 's') | ||
618 | { | ||
619 | fmtbuf[fmtbuf_pos] = '\0'; | ||
620 | read_format = false; | ||
621 | snprintf(&buf[buf_pos], MAX_PATH - buf_pos, fmtbuf, tcs->result); | ||
622 | buf_pos += strlen(&buf[buf_pos]); | ||
623 | parpos++; | ||
624 | } | ||
625 | else if (fmt->formatstr[i] == 'd') | ||
626 | { | ||
627 | fmtbuf[fmtbuf_pos] = '\0'; | ||
628 | read_format = false; | ||
629 | snprintf(&buf[buf_pos], MAX_PATH - buf_pos, fmtbuf, | ||
630 | tagcache_get_numeric(tcs, fmt->tags[parpos])); | ||
631 | buf_pos += strlen(&buf[buf_pos]); | ||
632 | parpos++; | ||
633 | } | ||
634 | continue; | ||
635 | } | ||
636 | |||
637 | buf[buf_pos++] = fmt->formatstr[i]; | ||
638 | |||
639 | if (buf_pos - 1 >= (long)sizeof(buf)) | ||
640 | { | ||
641 | logf("buffer overflow"); | ||
642 | return 0; | ||
643 | } | ||
476 | } | 644 | } |
645 | |||
646 | buf[buf_pos++] = '\0'; | ||
477 | } | 647 | } |
648 | |||
649 | dptr->name = &c->name_buffer[namebufused]; | ||
650 | if (fmt->valid) | ||
651 | namebufused += buf_pos; | ||
478 | else | 652 | else |
479 | { | ||
480 | namebufused += tcs->result_len; | 653 | namebufused += tcs->result_len; |
481 | if (namebufused >= c->name_buffer_size) | 654 | |
482 | { | 655 | if (namebufused >= c->name_buffer_size) |
483 | logf("chunk mode #2: %d", current_entry_count); | 656 | { |
484 | c->dirfull = true; | 657 | logf("chunk mode #2: %d", current_entry_count); |
485 | sort = false; | 658 | c->dirfull = true; |
486 | break ; | 659 | sort = false; |
487 | } | 660 | break ; |
488 | strcpy(dptr->name, tcs->result); | ||
489 | } | 661 | } |
662 | if (fmt->valid) | ||
663 | strcpy(dptr->name, buf); | ||
664 | else | ||
665 | strcpy(dptr->name, tcs->result); | ||
490 | } | 666 | } |
491 | else | 667 | else |
492 | dptr->name = tcs->result; | 668 | dptr->name = tcs->result; |