summaryrefslogtreecommitdiff
path: root/apps/tagtree.c
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2006-07-15 17:36:25 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2006-07-15 17:36:25 +0000
commit45dfe2a36f03d1ada7036dedb50fb98d7c5421b2 (patch)
tree866a57b677dce40ef5b772e1514a9ec6a35f60ea /apps/tagtree.c
parente60cb43a982e03b062bd42dbe260abca299fe14d (diff)
downloadrockbox-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.c236
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);
47static char searchstring[32]; 48static 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 */
60struct display_format {
61 bool valid;
62 char formatstr[64];
63 int tags[MAX_TAGS];
64 int tag_count;
65};
66
50struct search_instruction { 67struct 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
166static bool add_clause(struct search_instruction *inst, 186static 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
229static 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
209static int get_condition(struct search_instruction *inst) 255static 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
362static 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
370static 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
297void tagtree_init(void) 418void 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
355bool show_search_progress(bool init, int count) 479bool 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;