diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/onplay.c | 7 | ||||
-rw-r--r-- | apps/tagcache.c | 183 | ||||
-rw-r--r-- | apps/tagcache.h | 6 | ||||
-rw-r--r-- | apps/tagtree.c | 49 |
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) | |||
953 | static bool set_rating_inline(void) | 953 | static 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 | |||
145 | struct tagcache_command_entry { | ||
146 | long command; | ||
147 | long idx_id; | ||
148 | long tag; | ||
149 | long data; | ||
139 | }; | 150 | }; |
140 | 151 | ||
152 | static struct tagcache_command_entry command_queue[TAGCACHE_COMMAND_QUEUE_LENGTH]; | ||
153 | static volatile int command_queue_widx = 0; | ||
154 | static volatile int command_queue_ridx = 0; | ||
155 | static 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. */ | ||
158 | static 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 | ||
2740 | long 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 | |||
2757 | long tagcache_get_serial(void) | ||
2758 | { | ||
2759 | return current_tcmh.serial; | ||
2760 | } | ||
2761 | |||
2762 | long tagcache_get_commitid(void) | ||
2763 | { | ||
2764 | return current_tcmh.commitid; | ||
2765 | } | ||
2766 | |||
2767 | static bool modify_numeric_entry(int masterfd, int idx_id, int tag, long data) | 2758 | static 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 | ||
2786 | bool tagcache_modify_numeric_entry(struct tagcache_search *tcs, | 2778 | bool 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 | |||
2795 | static 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 | |||
2806 | void 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 | |||
2859 | static 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 | |||
2892 | long 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 | |||
2908 | void tagcache_update_numeric(int idx_id, int tag, long data) | ||
2909 | { | ||
2910 | queue_command(CMD_UPDATE_NUMERIC, idx_id, tag, data); | ||
2911 | } | ||
2912 | |||
2913 | long tagcache_get_serial(void) | ||
2914 | { | ||
2915 | return current_tcmh.serial; | ||
2916 | } | ||
2917 | |||
2918 | long tagcache_get_commitid(void) | ||
2919 | { | ||
2920 | return current_tcmh.commitid; | ||
2921 | } | ||
2799 | 2922 | ||
2800 | static bool write_tag(int fd, const char *tagstr, const char *datastr) | 2923 | static 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 | ||
3943 | void tagcache_shutdown(void) | 4068 | void 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); | |||
170 | long tagcache_get_serial(void); | 175 | long tagcache_get_serial(void); |
171 | bool tagcache_import_changelog(void); | 176 | bool tagcache_import_changelog(void); |
172 | bool tagcache_create_changelog(struct tagcache_search *tcs); | 177 | bool tagcache_create_changelog(struct tagcache_search *tcs); |
178 | void tagcache_update_numeric(int idx_id, int tag, long data); | ||
173 | bool tagcache_modify_numeric_entry(struct tagcache_search *tcs, | 179 | bool 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 | ||
700 | bool tagtree_export(void) | 687 | bool tagtree_export(void) |