diff options
author | Miika Pekkarinen <miipekk@ihme.org> | 2007-07-21 17:35:19 +0000 |
---|---|---|
committer | Miika Pekkarinen <miipekk@ihme.org> | 2007-07-21 17:35:19 +0000 |
commit | 9d756e2760a0926aa416b22e276c4a5b2685e84e (patch) | |
tree | 21502b59d472d57f6cdb267eb96177784beec706 /apps | |
parent | 6ed7722db0f7e911684f5deb84cc4ae93d15ccac (diff) | |
download | rockbox-9d756e2760a0926aa416b22e276c4a5b2685e84e.tar.gz rockbox-9d756e2760a0926aa416b22e276c4a5b2685e84e.zip |
Queue song statistical data to the tagcache system and update entirely in background. Fixes ratings disappearing or not saving in the DB at all. Fixes also UI delay when stopping playback and new statistics are committed to DB.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13955 a1c6a512-1295-4272-9138-f99709370657
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) |