From fb03079b50da50aaf655d8d44479119c96b70d90 Mon Sep 17 00:00:00 2001 From: roolku Date: Mon, 26 Mar 2007 15:08:59 +0000 Subject: [PATCH] Rating support for database and WPS (based on FS# 6301). A value between 0 and 10 can be assigned to the currently playing track using the WPS context menu. This value is displayed in the WPS using the %rr tag (replacing autoscore) and can be used as "rating" in tagnavi.config (examples provided). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12922 a1c6a512-1295-4272-9138-f99709370657 --- apps/onplay.c | 43 ++++++++++++++++++++++++++++++++--- apps/tagcache.c | 11 +++++---- apps/tagcache.h | 8 +++---- apps/tagnavi.config | 7 ++++-- apps/tagtree.c | 10 ++++++-- firmware/export/id3.h | 1 + manual/rockbox_interface/tagcache.tex | 8 ++++--- manual/rockbox_interface/wps.tex | 5 ++++ 8 files changed, 74 insertions(+), 19 deletions(-) diff --git a/apps/onplay.c b/apps/onplay.c index be9f2d070..60fc418d4 100644 --- a/apps/onplay.c +++ b/apps/onplay.c @@ -869,6 +869,34 @@ static int onplay_callback(int key, int menu) return key; } + +char rating_menu_string[32]; + +static void create_rating_menu(void) +{ + struct mp3entry* id3 = audio_current_track(); + if(id3) + snprintf(rating_menu_string, sizeof rating_menu_string, + "%s: %d", str(LANG_MENU_SET_RATING), id3->rating); + else + snprintf(rating_menu_string, sizeof rating_menu_string, + "%s: -", str(LANG_MENU_SET_RATING)); +} + +static bool set_rating_inline(void) +{ + struct mp3entry* id3 = audio_current_track(); + if(id3) { + if(id3->rating<10) + id3->rating++; + else + id3->rating=0; + } + create_rating_menu(); + return false; +} + + int onplay(char* file, int attr, int from) { #if CONFIG_CODEC == SWCODEC @@ -908,6 +936,13 @@ int onplay(char* file, int attr, int from) if (context == CONTEXT_WPS) { + if(file && global_settings.runtimedb) + { + create_rating_menu(); + items[i].desc = rating_menu_string; + items[i].function = set_rating_inline; + i++; + } items[i].desc = ID2P(LANG_BOOKMARK_MENU); items[i].function = bookmark_menu; i++; @@ -1037,9 +1072,11 @@ int onplay(char* file, int attr, int from) if (i) { m = menu_init( items, i, onplay_callback, NULL, NULL, NULL ); - result = menu_show(m); - if (result >= 0) - items[result].function(); + do { + result = menu_show(m); + if (result >= 0) + items[result].function(); + } while (items[result].function == set_rating_inline); menu_exit(m); if (exit_to_main) diff --git a/apps/tagcache.c b/apps/tagcache.c index 6f49d372e..7a1fec75a 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c @@ -115,13 +115,13 @@ static const int unique_tags[] = { tag_artist, tag_album, tag_genre, /* Numeric tags (we can use these tags with conditional clauses). */ static const int numeric_tags[] = { tag_year, tag_tracknumber, tag_length, - tag_bitrate, tag_playcount, tag_playtime, tag_lastplayed, tag_commitid, + tag_bitrate, tag_playcount, tag_rating, tag_playtime, tag_lastplayed, tag_commitid, tag_virt_entryage, tag_virt_autoscore }; /* String presentation of the tags defined in tagcache.h. Must be in correct order! */ static const char *tags_str[] = { "artist", "album", "genre", "title", "filename", "composer", "comment", "albumartist", "year", "tracknumber", - "bitrate", "length", "playcount", "playtime", "lastplayed", "commitid" }; + "bitrate", "length", "playcount", "rating", "playtime", "lastplayed", "commitid" }; /* Status information of the tagcache. */ static struct tagcache_stat tc_stat; @@ -167,7 +167,7 @@ struct master_header { /* For the endianess correction */ static const char *tagfile_entry_ec = "ss"; -static const char *index_entry_ec = "lllllllllllllllll"; /* (1 + TAG_COUNT) * l */ +static const char *index_entry_ec = "llllllllllllllllll"; /* (1 + TAG_COUNT) * l */ static const char *tagcache_header_ec = "lll"; static const char *master_header_ec = "llllll"; @@ -1499,8 +1499,9 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename) id3->albumartist = get_tag_string(entry, tag_albumartist); id3->playcount = get_tag_numeric(entry, tag_playcount); + id3->rating = get_tag_numeric(entry, tag_rating); id3->lastplayed = get_tag_numeric(entry, tag_lastplayed); - id3->rating = get_tag_numeric(entry, tag_virt_autoscore) / 10; + id3->score = get_tag_numeric(entry, tag_virt_autoscore) / 10; id3->year = get_tag_numeric(entry, tag_year); id3->tracknum = get_tag_numeric(entry, tag_tracknumber); @@ -2850,7 +2851,7 @@ static int parse_changelog_line(int line_n, const char *buf, void *parameters) char tag_data[TAG_MAXLEN+32]; int idx_id; long masterfd = (long)parameters; - const int import_tags[] = { tag_playcount, tag_playtime, tag_lastplayed, + const int import_tags[] = { tag_playcount, tag_rating, tag_playtime, tag_lastplayed, tag_commitid }; int i; (void)line_n; diff --git a/apps/tagcache.h b/apps/tagcache.h index 0cfdedf31..7b7aa021c 100644 --- a/apps/tagcache.h +++ b/apps/tagcache.h @@ -24,12 +24,12 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title, tag_filename, tag_composer, tag_comment, tag_albumartist, tag_year, - tag_tracknumber, tag_bitrate, tag_length, tag_playcount, tag_playtime, - tag_lastplayed, tag_commitid, + tag_tracknumber, tag_bitrate, tag_length, tag_playcount, tag_rating, + tag_playtime, tag_lastplayed, tag_commitid, /* Virtual tags */ tag_virt_entryage, tag_virt_autoscore }; -#define TAG_COUNT 16 +#define TAG_COUNT 17 /* Maximum length of a single tag. */ #define TAG_MAXLEN (MAX_PATH*2) @@ -41,7 +41,7 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title, #define IDX_BUF_DEPTH 64 /* Tag Cache Header version 'TCHxx'. Increment when changing internal structures. */ -#define TAGCACHE_MAGIC 0x54434808 +#define TAGCACHE_MAGIC 0x54434809 /* How much to allocate extra space for ramcache. */ #define TAGCACHE_RESERVE 32768 diff --git a/apps/tagnavi.config b/apps/tagnavi.config index 24428e223..5e9dd73b3 100644 --- a/apps/tagnavi.config +++ b/apps/tagnavi.config @@ -10,9 +10,10 @@ %format "fmt_title" "%s" title %format "fmt_mostplayed" "(%3d) %s - %s" playcount artist title %sort = "inverse" %limit = "100" %format "fmt_lastplayed" "%06d%s - %s" lastplayed artist title %sort = "inverse" %limit = "99" %strip = "6" -%format "fmt_best_tracks" "%02d. %s (%3d)" tracknum title autoscore +%format "fmt_best_tracks" "%02d. %s (%2d)" tracknum title rating %sort = "inverse" %format "fmt_played" "(%3d/%d) %s" autoscore playcount title %format "fmt_score" "(%3d) %s" autoscore title +%format "fmt_rating" "(%2d) %s" rating title %sort = "inverse" # Include our custom menu %include "/.rockbox/tagnavi_custom.config" @@ -28,6 +29,7 @@ "Title" -> title ? title ~ "" "Filename" -> filename ? filename ~ "" "Score" -> title = "fmt_score" ? autoscore > "" +"Rating" -> title = "fmt_rating" ? rating > "" # ^ An empy line ends the menu @@ -42,12 +44,13 @@ "Genre" -> genre -> artist -> album -> title = "fmt_title" "Composer" -> composer -> album -> title = "fmt_title" "Track" -> title +"Rating" -> rating -> title = "fmt_rating" "Year" -> year ? year > "1000" & year < "2008" -> artist -> album -> title = "fmt_title" "Search..." ==> "search" "Most played tracks" -> title = "fmt_mostplayed" ? playcount > "0" "Last played tracks" -> title = "fmt_lastplayed" ? playcount > "0" "Never played tracks" -> artist ? playcount == "0" -> album -> title = "fmt_title" -"Best tracks" -> artist ? playcount > "1" & autoscore > "85" -> album -> title = "fmt_best_tracks" +"Best tracks" -> artist ? playcount > "1" & rating > "8" -> album -> title = "fmt_best_tracks" "List played tracks" -> title = "fmt_played" ? playcount > "0" "Last added tracks" -> artist ? entryage == "0" -> album -> title = "fmt_title" "Custom view..." ==> "custom" diff --git a/apps/tagtree.c b/apps/tagtree.c index 33c36b7b8..66a644e59 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c @@ -205,6 +205,7 @@ static int get_tag(int *tag) MATCH(tag, buf, "tracknum", tag_tracknumber); MATCH(tag, buf, "year", tag_year); MATCH(tag, buf, "playcount", tag_playcount); + MATCH(tag, buf, "rating", tag_rating); MATCH(tag, buf, "lastplayed", tag_lastplayed); MATCH(tag, buf, "commitid", tag_commitid); MATCH(tag, buf, "entryage", tag_virt_entryage); @@ -603,8 +604,9 @@ static void tagtree_buffer_event(struct mp3entry *id3, bool last_track) } id3->playcount = tagcache_get_numeric(&tcs, tag_playcount); + if(!id3->rating) id3->rating = tagcache_get_numeric(&tcs, tag_rating); id3->lastplayed = tagcache_get_numeric(&tcs, tag_lastplayed); - id3->rating = tagcache_get_numeric(&tcs, tag_virt_autoscore) / 10; + id3->score = tagcache_get_numeric(&tcs, tag_virt_autoscore) / 10; tagcache_search_finish(&tcs); } @@ -613,6 +615,7 @@ static void tagtree_unbuffer_event(struct mp3entry *id3, bool last_track) { (void)last_track; long playcount; + long rating; long playtime; long lastplayed; @@ -642,6 +645,8 @@ static void tagtree_unbuffer_event(struct mp3entry *id3, bool last_track) playcount++; + rating = (long) id3->rating; + lastplayed = tagcache_increase_serial(); if (lastplayed < 0) { @@ -654,12 +659,13 @@ static void tagtree_unbuffer_event(struct mp3entry *id3, bool last_track) playtime += MIN(id3->length, id3->elapsed + 15 * 1000); logf("ube:%s", id3->path); - logf("-> %d/%ld/%ld", last_track, playcount, playtime); + logf("-> %d/%ld/%d/%ld", last_track, playcount, rating, playtime); logf("-> %ld/%ld/%ld", id3->elapsed, id3->length, MIN(id3->length, id3->elapsed + 15 * 1000)); /* lastplayed not yet supported. */ if (!tagcache_modify_numeric_entry(&tcs, tag_playcount, playcount) + || !tagcache_modify_numeric_entry(&tcs, tag_rating, rating) || !tagcache_modify_numeric_entry(&tcs, tag_playtime, playtime) || !tagcache_modify_numeric_entry(&tcs, tag_lastplayed, lastplayed)) { diff --git a/firmware/export/id3.h b/firmware/export/id3.h index d3d5dd35c..5cc600fac 100644 --- a/firmware/export/id3.h +++ b/firmware/export/id3.h @@ -199,6 +199,7 @@ struct mp3entry { /* runtime database fields */ short rating; + short score; long playcount; long lastplayed; diff --git a/manual/rockbox_interface/tagcache.tex b/manual/rockbox_interface/tagcache.tex index c6869c934..8f7a942eb 100644 --- a/manual/rockbox_interface/tagcache.tex +++ b/manual/rockbox_interface/tagcache.tex @@ -65,9 +65,11 @@ you can use the database. Unlike \setting{Initialize Now}, the \setting{Update Now} function does not remove runtime database information. -\item[Gather Runtime Data (Experimental).] - When enabled, this option allows the most played, unplayed and most recently - played tracks to be logged and scored. +\item[Gather Runtime Data.] + When enabled, rockbox will record how often and how long a track is being played, + when it was last played and its rating. This information can be displayed in + the WPS and is used in the database browser to, for example, show the most played, + unplayed and most recently played tracks. \item[Export modifications.] This allows for the runtime data to be exported to the file \\ diff --git a/manual/rockbox_interface/wps.tex b/manual/rockbox_interface/wps.tex index 401128ea6..606672b7b 100644 --- a/manual/rockbox_interface/wps.tex +++ b/manual/rockbox_interface/wps.tex @@ -164,6 +164,11 @@ to bring up the \setting{Playlist Viewer Menu}. \item [Add to playlist] \item [Add to new playlist] \end{description} +\subsubsection{Rating} +The menu entry is only shown if \setting{Gather Runtime Information} is enabled. It allows the +asignment of a personal rating value (0..10) to a track which can be displayed in the WPS (%rr) +and is used in the Database browser. Press \ButtonRight to increment the value (it wraps at 10). + \subsubsection{Bookmarks} This allows you to create a bookmark in the currently-playing track. -- 2.11.4.GIT