summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/onplay.c7
-rw-r--r--apps/tagcache.c183
-rw-r--r--apps/tagcache.h6
-rw-r--r--apps/tagtree.c49
4 files changed, 185 insertions, 60 deletions
diff --git a/apps/onplay.c b/apps/onplay.c
index cba03733fd..d7c2504650 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -953,11 +953,14 @@ char *rating_name(int selected_item, void * data, char *buffer)
953static bool set_rating_inline(void) 953static bool set_rating_inline(void)
954{ 954{
955 struct mp3entry* id3 = audio_current_track(); 955 struct mp3entry* id3 = audio_current_track();
956 if(id3) { 956 if (id3 && id3->tagcache_idx)
957 if(id3->rating<10) 957 {
958 if (id3->rating<10)
958 id3->rating++; 959 id3->rating++;
959 else 960 else
960 id3->rating=0; 961 id3->rating=0;
962
963 tagcache_update_numeric(id3->tagcache_idx, tag_rating, id3->rating);
961 } 964 }
962 return false; 965 return false;
963} 966}
diff --git a/apps/tagcache.c b/apps/tagcache.c
index f832f1e543..6d738bc5fb 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -136,8 +136,26 @@ enum tagcache_queue {
136 Q_IMPORT_CHANGELOG, 136 Q_IMPORT_CHANGELOG,
137 Q_UPDATE, 137 Q_UPDATE,
138 Q_REBUILD, 138 Q_REBUILD,
139
140 /* Internal tagcache command queue. */
141 CMD_UPDATE_MASTER_HEADER,
142 CMD_UPDATE_NUMERIC,
143};
144
145struct tagcache_command_entry {
146 long command;
147 long idx_id;
148 long tag;
149 long data;
139}; 150};
140 151
152static struct tagcache_command_entry command_queue[TAGCACHE_COMMAND_QUEUE_LENGTH];
153static volatile int command_queue_widx = 0;
154static volatile int command_queue_ridx = 0;
155static struct mutex command_queue_mutex;
156/* Timestamp of the last added event, so we can wait a bit before committing the
157 * whole queue at once. */
158static long command_queue_timestamp = 0;
141 159
142/* Tag database structures. */ 160/* Tag database structures. */
143 161
@@ -2737,33 +2755,6 @@ static void free_tempbuf(void)
2737 tempbuf_size = 0; 2755 tempbuf_size = 0;
2738} 2756}
2739 2757
2740long tagcache_increase_serial(void)
2741{
2742 long old;
2743
2744 if (!tc_stat.ready)
2745 return -2;
2746
2747 while (read_lock)
2748 sleep(1);
2749
2750 old = current_tcmh.serial++;
2751 if (!update_master_header())
2752 return -1;
2753
2754 return old;
2755}
2756
2757long tagcache_get_serial(void)
2758{
2759 return current_tcmh.serial;
2760}
2761
2762long tagcache_get_commitid(void)
2763{
2764 return current_tcmh.commitid;
2765}
2766
2767static bool modify_numeric_entry(int masterfd, int idx_id, int tag, long data) 2758static bool modify_numeric_entry(int masterfd, int idx_id, int tag, long data)
2768{ 2759{
2769 struct index_entry idx; 2760 struct index_entry idx;
@@ -2783,6 +2774,7 @@ static bool modify_numeric_entry(int masterfd, int idx_id, int tag, long data)
2783 return write_index(masterfd, idx_id, &idx); 2774 return write_index(masterfd, idx_id, &idx);
2784} 2775}
2785 2776
2777#if 0
2786bool tagcache_modify_numeric_entry(struct tagcache_search *tcs, 2778bool tagcache_modify_numeric_entry(struct tagcache_search *tcs,
2787 int tag, long data) 2779 int tag, long data)
2788{ 2780{
@@ -2796,6 +2788,137 @@ bool tagcache_modify_numeric_entry(struct tagcache_search *tcs,
2796 2788
2797 return modify_numeric_entry(tcs->masterfd, tcs->idx_id, tag, data); 2789 return modify_numeric_entry(tcs->masterfd, tcs->idx_id, tag, data);
2798} 2790}
2791#endif
2792
2793#define COMMAND_QUEUE_IS_EMPTY (command_queue_ridx == command_queue_widx)
2794
2795static bool command_queue_is_full(void)
2796{
2797 int next;
2798
2799 next = command_queue_widx + 1;
2800 if (next >= TAGCACHE_COMMAND_QUEUE_LENGTH)
2801 next = 0;
2802
2803 return (next == command_queue_ridx);
2804}
2805
2806void run_command_queue(bool force)
2807{
2808 struct master_header myhdr;
2809 int masterfd;
2810
2811 if (COMMAND_QUEUE_IS_EMPTY)
2812 return;
2813
2814 if (!force && !command_queue_is_full()
2815 && current_tick - TAGCACHE_COMMAND_QUEUE_COMMIT_DELAY
2816 < command_queue_timestamp)
2817 {
2818 return;
2819 }
2820
2821 mutex_lock(&command_queue_mutex);
2822
2823 if ( (masterfd = open_master_fd(&myhdr, true)) < 0)
2824 return;
2825
2826 while (command_queue_ridx != command_queue_widx)
2827 {
2828 struct tagcache_command_entry *ce = &command_queue[command_queue_ridx];
2829
2830 switch (ce->command)
2831 {
2832 case CMD_UPDATE_MASTER_HEADER:
2833 {
2834 close(masterfd);
2835 update_master_header();
2836
2837 /* Re-open the masterfd. */
2838 if ( (masterfd = open_master_fd(&myhdr, true)) < 0)
2839 return;
2840
2841 break;
2842 }
2843 case CMD_UPDATE_NUMERIC:
2844 {
2845 modify_numeric_entry(masterfd, ce->idx_id, ce->tag, ce->data);
2846 break;
2847 }
2848 }
2849
2850 if (++command_queue_ridx >= TAGCACHE_COMMAND_QUEUE_LENGTH)
2851 command_queue_ridx = 0;
2852 }
2853
2854 close(masterfd);
2855
2856 mutex_unlock(&command_queue_mutex);
2857}
2858
2859static void queue_command(int cmd, long idx_id, int tag, long data)
2860{
2861 while (1)
2862 {
2863 int next;
2864
2865 mutex_lock(&command_queue_mutex);
2866 next = command_queue_widx + 1;
2867 if (next >= TAGCACHE_COMMAND_QUEUE_LENGTH)
2868 next = 0;
2869
2870 /* Make sure queue is not full. */
2871 if (next != command_queue_ridx)
2872 {
2873 struct tagcache_command_entry *ce = &command_queue[command_queue_widx];
2874
2875 ce->command = cmd;
2876 ce->idx_id = idx_id;
2877 ce->tag = tag;
2878 ce->data = data;
2879
2880 command_queue_widx = next;
2881 command_queue_timestamp = current_tick;
2882 mutex_unlock(&command_queue_mutex);
2883 break;
2884 }
2885
2886 /* Queue is full, try again later... */
2887 mutex_unlock(&command_queue_mutex);
2888 sleep(1);
2889 }
2890}
2891
2892long tagcache_increase_serial(void)
2893{
2894 long old;
2895
2896 if (!tc_stat.ready)
2897 return -2;
2898
2899 while (read_lock)
2900 sleep(1);
2901
2902 old = current_tcmh.serial++;
2903 queue_command(CMD_UPDATE_MASTER_HEADER, 0, 0, 0);
2904
2905 return old;
2906}
2907
2908void tagcache_update_numeric(int idx_id, int tag, long data)
2909{
2910 queue_command(CMD_UPDATE_NUMERIC, idx_id, tag, data);
2911}
2912
2913long tagcache_get_serial(void)
2914{
2915 return current_tcmh.serial;
2916}
2917
2918long tagcache_get_commitid(void)
2919{
2920 return current_tcmh.commitid;
2921}
2799 2922
2800static bool write_tag(int fd, const char *tagstr, const char *datastr) 2923static bool write_tag(int fd, const char *tagstr, const char *datastr)
2801{ 2924{
@@ -3860,6 +3983,8 @@ static void tagcache_thread(void)
3860 3983
3861 while (1) 3984 while (1)
3862 { 3985 {
3986 run_command_queue(false);
3987
3863 queue_wait_w_tmo(&tagcache_queue, &ev, HZ); 3988 queue_wait_w_tmo(&tagcache_queue, &ev, HZ);
3864 3989
3865 switch (ev.id) 3990 switch (ev.id)
@@ -3942,6 +4067,9 @@ bool tagcache_prepare_shutdown(void)
3942 4067
3943void tagcache_shutdown(void) 4068void tagcache_shutdown(void)
3944{ 4069{
4070 /* Flush the command queue. */
4071 run_command_queue(true);
4072
3945#ifdef HAVE_EEPROM_SETTINGS 4073#ifdef HAVE_EEPROM_SETTINGS
3946 if (tc_stat.ramcache) 4074 if (tc_stat.ramcache)
3947 tagcache_dumpsave(); 4075 tagcache_dumpsave();
@@ -4023,6 +4151,7 @@ void tagcache_init(void)
4023 write_lock = read_lock = 0; 4151 write_lock = read_lock = 0;
4024 4152
4025#ifndef __PCTOOL__ 4153#ifndef __PCTOOL__
4154 mutex_init(&command_queue_mutex);
4026 queue_init(&tagcache_queue, true); 4155 queue_init(&tagcache_queue, true);
4027 create_thread(tagcache_thread, tagcache_stack, 4156 create_thread(tagcache_thread, tagcache_stack,
4028 sizeof(tagcache_stack), tagcache_thread_name 4157 sizeof(tagcache_stack), tagcache_thread_name
diff --git a/apps/tagcache.h b/apps/tagcache.h
index 70677c602b..3d80c6975f 100644
--- a/apps/tagcache.h
+++ b/apps/tagcache.h
@@ -63,6 +63,11 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
63/* Always strict align entries for best performance and binary compatability. */ 63/* Always strict align entries for best performance and binary compatability. */
64#define TAGCACHE_STRICT_ALIGN 1 64#define TAGCACHE_STRICT_ALIGN 1
65 65
66/* Max events in the internal tagcache command queue. */
67#define TAGCACHE_COMMAND_QUEUE_LENGTH 32
68/* Idle time before committing events in the command queue. */
69#define TAGCACHE_COMMAND_QUEUE_COMMIT_DELAY HZ*2
70
66#define TAGCACHE_MAX_FILTERS 4 71#define TAGCACHE_MAX_FILTERS 4
67#define TAGCACHE_MAX_CLAUSES 32 72#define TAGCACHE_MAX_CLAUSES 32
68 73
@@ -170,6 +175,7 @@ long tagcache_increase_serial(void);
170long tagcache_get_serial(void); 175long tagcache_get_serial(void);
171bool tagcache_import_changelog(void); 176bool tagcache_import_changelog(void);
172bool tagcache_create_changelog(struct tagcache_search *tcs); 177bool tagcache_create_changelog(struct tagcache_search *tcs);
178void tagcache_update_numeric(int idx_id, int tag, long data);
173bool tagcache_modify_numeric_entry(struct tagcache_search *tcs, 179bool tagcache_modify_numeric_entry(struct tagcache_search *tcs,
174 int tag, long data); 180 int tag, long data);
175 181
diff --git a/apps/tagtree.c b/apps/tagtree.c
index 03673fc653..271f30ffa8 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -624,9 +624,14 @@ static void tagtree_buffer_event(struct mp3entry *id3, bool last_track)
624 } 624 }
625 625
626 id3->playcount = tagcache_get_numeric(&tcs, tag_playcount); 626 id3->playcount = tagcache_get_numeric(&tcs, tag_playcount);
627 if(!id3->rating) id3->rating = tagcache_get_numeric(&tcs, tag_rating); 627 if (!id3->rating)
628 id3->rating = tagcache_get_numeric(&tcs, tag_rating);
628 id3->lastplayed = tagcache_get_numeric(&tcs, tag_lastplayed); 629 id3->lastplayed = tagcache_get_numeric(&tcs, tag_lastplayed);
629 id3->score = tagcache_get_numeric(&tcs, tag_virt_autoscore) / 10; 630 id3->score = tagcache_get_numeric(&tcs, tag_virt_autoscore) / 10;
631 id3->playtime = tagcache_get_numeric(&tcs, tag_playtime);
632
633 /* Store our tagcache index pointer. */
634 id3->tagcache_idx = tcs.idx_id;
630 635
631 tagcache_search_finish(&tcs); 636 tagcache_search_finish(&tcs);
632} 637}
@@ -635,7 +640,6 @@ static void tagtree_unbuffer_event(struct mp3entry *id3, bool last_track)
635{ 640{
636 (void)last_track; 641 (void)last_track;
637 long playcount; 642 long playcount;
638 long rating;
639 long playtime; 643 long playtime;
640 long lastplayed; 644 long lastplayed;
641 645
@@ -646,55 +650,38 @@ static void tagtree_unbuffer_event(struct mp3entry *id3, bool last_track)
646 return; 650 return;
647 } 651 }
648 652
649 /* Don't process unplayed tracks. */ 653 if (!id3->tagcache_idx)
650 if (id3->elapsed == 0)
651 { 654 {
652 logf("not logging unplayed track"); 655 logf("No tagcache index pointer found");
653 return; 656 return;
654 } 657 }
655 658
656 if (!tagcache_find_index(&tcs, id3->path)) 659 /* Don't process unplayed tracks. */
660 if (id3->elapsed == 0)
657 { 661 {
658 logf("tc stat: not found: %s", id3->path); 662 logf("not logging unplayed track");
659 return; 663 return;
660 } 664 }
661 665
662 playcount = tagcache_get_numeric(&tcs, tag_playcount); 666 playcount = id3->playcount + 1;
663 playtime = tagcache_get_numeric(&tcs, tag_playtime);
664 lastplayed = tagcache_get_numeric(&tcs, tag_lastplayed);
665
666 playcount++;
667
668 rating = (long) id3->rating;
669
670 lastplayed = tagcache_increase_serial(); 667 lastplayed = tagcache_increase_serial();
671 if (lastplayed < 0) 668 if (lastplayed < 0)
672 { 669 {
673 logf("incorrect tc serial:%ld", lastplayed); 670 logf("incorrect tc serial:%ld", lastplayed);
674 tagcache_search_finish(&tcs);
675 return; 671 return;
676 } 672 }
677 673
678 /* Ignore the last 15s (crossfade etc.) */ 674 /* Ignore the last 15s (crossfade etc.) */
679 playtime += MIN(id3->length, id3->elapsed + 15 * 1000); 675 playtime = id3->playtime + MIN(id3->length, id3->elapsed + 15 * 1000);
680 676
681 logf("ube:%s", id3->path); 677 logf("ube:%s", id3->path);
682 logf("-> %d/%ld/%ld/%ld", last_track, playcount, rating, playtime); 678 logf("-> %d/%ld/%ld", last_track, playcount, playtime);
683 logf("-> %ld/%ld/%ld", id3->elapsed, id3->length, MIN(id3->length, id3->elapsed + 15 * 1000)); 679 logf("-> %ld/%ld/%ld", id3->elapsed, id3->length, MIN(id3->length, id3->elapsed + 15 * 1000));
684 680
685 /* lastplayed not yet supported. */ 681 /* Queue the updates to the tagcache system. */
686 682 tagcache_update_numeric(id3->tagcache_idx, tag_playcount, playcount);
687 if (!tagcache_modify_numeric_entry(&tcs, tag_playcount, playcount) 683 tagcache_update_numeric(id3->tagcache_idx, tag_playtime, playtime);
688 || !tagcache_modify_numeric_entry(&tcs, tag_rating, rating) 684 tagcache_update_numeric(id3->tagcache_idx, tag_lastplayed, lastplayed);
689 || !tagcache_modify_numeric_entry(&tcs, tag_playtime, playtime)
690 || !tagcache_modify_numeric_entry(&tcs, tag_lastplayed, lastplayed))
691 {
692 logf("tc stat: modify failed!");
693 tagcache_search_finish(&tcs);
694 return;
695 }
696
697 tagcache_search_finish(&tcs);
698} 685}
699 686
700bool tagtree_export(void) 687bool tagtree_export(void)