diff options
-rw-r--r-- | apps/lang/english.lang | 14 | ||||
-rw-r--r-- | apps/settings_menu.c | 2 | ||||
-rw-r--r-- | apps/tagcache.c | 121 | ||||
-rw-r--r-- | apps/tagcache.h | 8 | ||||
-rw-r--r-- | apps/tagnavi.config | 1 | ||||
-rw-r--r-- | apps/tagtree.c | 16 | ||||
-rw-r--r-- | apps/tagtree.h | 1 |
7 files changed, 156 insertions, 7 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 95d41ba264..0bf10055e6 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang | |||
@@ -8557,3 +8557,17 @@ | |||
8557 | *: "Auto update" | 8557 | *: "Auto update" |
8558 | </voice> | 8558 | </voice> |
8559 | </phrase> | 8559 | </phrase> |
8560 | <phrase> | ||
8561 | id: LANG_TAGCACHE_EXPORT | ||
8562 | desc: in tag cache settings | ||
8563 | user: | ||
8564 | <source> | ||
8565 | *: "Export modifications" | ||
8566 | </source> | ||
8567 | <dest> | ||
8568 | *: "Export modifications" | ||
8569 | </dest> | ||
8570 | <voice> | ||
8571 | *: "Export modifications" | ||
8572 | </voice> | ||
8573 | </phrase> | ||
diff --git a/apps/settings_menu.c b/apps/settings_menu.c index f00612a180..c85075d0b2 100644 --- a/apps/settings_menu.c +++ b/apps/settings_menu.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include "dir.h" | 50 | #include "dir.h" |
51 | #include "dircache.h" | 51 | #include "dircache.h" |
52 | #include "tagcache.h" | 52 | #include "tagcache.h" |
53 | #include "tagtree.h" | ||
53 | #include "rbunicode.h" | 54 | #include "rbunicode.h" |
54 | #include "splash.h" | 55 | #include "splash.h" |
55 | #include "yesno.h" | 56 | #include "yesno.h" |
@@ -1568,6 +1569,7 @@ static bool tagcache_settings_menu(void) | |||
1568 | { ID2P(LANG_TAGCACHE_FORCE_UPDATE), tagcache_rebuild }, | 1569 | { ID2P(LANG_TAGCACHE_FORCE_UPDATE), tagcache_rebuild }, |
1569 | { ID2P(LANG_TAGCACHE_UPDATE), tagcache_update }, | 1570 | { ID2P(LANG_TAGCACHE_UPDATE), tagcache_update }, |
1570 | { ID2P(LANG_RUNTIMEDB_ACTIVE), tagcache_runtimedb }, | 1571 | { ID2P(LANG_RUNTIMEDB_ACTIVE), tagcache_runtimedb }, |
1572 | { ID2P(LANG_TAGCACHE_EXPORT), tagtree_export }, | ||
1571 | }; | 1573 | }; |
1572 | 1574 | ||
1573 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, | 1575 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, |
diff --git a/apps/tagcache.c b/apps/tagcache.c index a5675850bf..47d9c4ed80 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c | |||
@@ -478,6 +478,7 @@ static bool build_lookup_list(struct tagcache_search *tcs) | |||
478 | { | 478 | { |
479 | struct index_entry *idx = &hdr->indices[i]; | 479 | struct index_entry *idx = &hdr->indices[i]; |
480 | int seek; | 480 | int seek; |
481 | char buf[256]; | ||
481 | char *str = NULL; | 482 | char *str = NULL; |
482 | struct tagfile_entry *entry; | 483 | struct tagfile_entry *entry; |
483 | 484 | ||
@@ -485,8 +486,16 @@ static bool build_lookup_list(struct tagcache_search *tcs) | |||
485 | 486 | ||
486 | if (!tagcache_is_numeric_tag(tcs->clause[j]->tag)) | 487 | if (!tagcache_is_numeric_tag(tcs->clause[j]->tag)) |
487 | { | 488 | { |
488 | entry = (struct tagfile_entry *)&hdr->tags[tcs->clause[j]->tag][seek]; | 489 | if (tcs->clause[j]->tag == tag_filename) |
489 | str = entry->tag_data; | 490 | { |
491 | tagcache_retrieve(tcs, i, buf, sizeof buf); | ||
492 | str = buf; | ||
493 | } | ||
494 | else | ||
495 | { | ||
496 | entry = (struct tagfile_entry *)&hdr->tags[tcs->clause[j]->tag][seek]; | ||
497 | str = entry->tag_data; | ||
498 | } | ||
490 | } | 499 | } |
491 | 500 | ||
492 | 501 | ||
@@ -2104,6 +2113,114 @@ static int open_master_fd(struct tagcache_header *hdr) | |||
2104 | return fd; | 2113 | return fd; |
2105 | } | 2114 | } |
2106 | 2115 | ||
2116 | static bool write_tag(int fd, const char *tagstr, const char *datastr) | ||
2117 | { | ||
2118 | char buf[256]; | ||
2119 | int i; | ||
2120 | |||
2121 | snprintf(buf, sizeof buf, "%s=\"", tagstr); | ||
2122 | for (i = strlen(buf); i < (long)sizeof(buf)-2; i++) | ||
2123 | { | ||
2124 | if (*datastr == '\0') | ||
2125 | break; | ||
2126 | |||
2127 | if (*datastr == '"') | ||
2128 | { | ||
2129 | buf[i] = '\\'; | ||
2130 | *datastr++; | ||
2131 | continue; | ||
2132 | } | ||
2133 | |||
2134 | buf[i] = *(datastr++); | ||
2135 | } | ||
2136 | |||
2137 | strcpy(&buf[i], "\" "); | ||
2138 | |||
2139 | write(fd, buf, i + 2); | ||
2140 | |||
2141 | return true; | ||
2142 | } | ||
2143 | |||
2144 | bool tagcache_create_changelog(struct tagcache_search *tcs) | ||
2145 | { | ||
2146 | static const char *tags_str[] = { "artist", "album", "genre", "title", | ||
2147 | "filename", "playcount", "playtime", "lastplayed" }; | ||
2148 | static const int tags[] = { tag_artist, tag_album, tag_genre, tag_title, | ||
2149 | tag_filename, tag_playcount, tag_playtime, tag_lastplayed }; | ||
2150 | struct tagcache_header myhdr; | ||
2151 | struct index_entry idx; | ||
2152 | char buf[256]; | ||
2153 | char temp[32]; | ||
2154 | int clfd; | ||
2155 | int i, j; | ||
2156 | |||
2157 | if (!tagcache_search(tcs, tag_filename)) | ||
2158 | return false; | ||
2159 | |||
2160 | /* Initialize the changelog */ | ||
2161 | clfd = open(TAGCACHE_FILE_CHANGELOG, O_WRONLY | O_CREAT | O_TRUNC); | ||
2162 | if (clfd < 0) | ||
2163 | { | ||
2164 | logf("failure to open changelog"); | ||
2165 | return false; | ||
2166 | } | ||
2167 | |||
2168 | if (tcs->masterfd < 0) | ||
2169 | { | ||
2170 | if ( (tcs->masterfd = open_master_fd(&myhdr)) < 0) | ||
2171 | return false; | ||
2172 | } | ||
2173 | else | ||
2174 | { | ||
2175 | lseek(tcs->masterfd, 0, SEEK_SET); | ||
2176 | read(tcs->masterfd, &myhdr, sizeof(struct tagcache_header)); | ||
2177 | } | ||
2178 | |||
2179 | write(clfd, "## Changelog version 1\n", 23); | ||
2180 | |||
2181 | for (i = 0; i < myhdr.entry_count; i++) | ||
2182 | { | ||
2183 | if (read(tcs->masterfd, &idx, sizeof(struct index_entry)) | ||
2184 | != sizeof(struct index_entry)) | ||
2185 | { | ||
2186 | logf("read error"); | ||
2187 | tagcache_search_finish(tcs); | ||
2188 | close(clfd); | ||
2189 | return false; | ||
2190 | } | ||
2191 | |||
2192 | /* Skip until the entry found has been modified. */ | ||
2193 | if (! (idx.flag & FLAG_DIRTYNUM) ) | ||
2194 | continue; | ||
2195 | |||
2196 | logf("Found!"); | ||
2197 | |||
2198 | /* Now retrieve all tags. */ | ||
2199 | for (j = 0; j < (long)(sizeof(tags) / sizeof(tags[0])); j++) | ||
2200 | { | ||
2201 | if (tagcache_is_numeric_tag(tags[j])) | ||
2202 | { | ||
2203 | snprintf(temp, sizeof temp, "%d", idx.tag_seek[tags[j]]); | ||
2204 | write_tag(clfd, tags_str[j], temp); | ||
2205 | continue; | ||
2206 | } | ||
2207 | |||
2208 | tcs->type = tags[j]; | ||
2209 | tagcache_retrieve(tcs, i, buf, sizeof buf); | ||
2210 | logf("tag: %s", buf); | ||
2211 | write_tag(clfd, tags_str[j], buf); | ||
2212 | } | ||
2213 | |||
2214 | write(clfd, "\n", 1); | ||
2215 | } | ||
2216 | |||
2217 | close(clfd); | ||
2218 | |||
2219 | tagcache_search_finish(tcs); | ||
2220 | |||
2221 | return true; | ||
2222 | } | ||
2223 | |||
2107 | bool tagcache_modify_numeric_entry(struct tagcache_search *tcs, | 2224 | bool tagcache_modify_numeric_entry(struct tagcache_search *tcs, |
2108 | int tag, long data) | 2225 | int tag, long data) |
2109 | { | 2226 | { |
diff --git a/apps/tagcache.h b/apps/tagcache.h index 04f9567936..e655088cc2 100644 --- a/apps/tagcache.h +++ b/apps/tagcache.h | |||
@@ -63,9 +63,10 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title, | |||
63 | #define TAGCACHE_MAX_CLAUSES 10 | 63 | #define TAGCACHE_MAX_CLAUSES 10 |
64 | 64 | ||
65 | /* Tag database files. */ | 65 | /* Tag database files. */ |
66 | #define TAGCACHE_FILE_TEMP ROCKBOX_DIR "/tagcache_tmp.tcd" | 66 | #define TAGCACHE_FILE_TEMP ROCKBOX_DIR "/tagcache_tmp.tcd" |
67 | #define TAGCACHE_FILE_MASTER ROCKBOX_DIR "/tagcache_idx.tcd" | 67 | #define TAGCACHE_FILE_MASTER ROCKBOX_DIR "/tagcache_idx.tcd" |
68 | #define TAGCACHE_FILE_INDEX ROCKBOX_DIR "/tagcache_%d.tcd" | 68 | #define TAGCACHE_FILE_INDEX ROCKBOX_DIR "/tagcache_%d.tcd" |
69 | #define TAGCACHE_FILE_CHANGELOG ROCKBOX_DIR "/tagcache_changelog.txt" | ||
69 | 70 | ||
70 | /* Flags */ | 71 | /* Flags */ |
71 | #define FLAG_DELETED 0x0001 /* Entry has been removed from db */ | 72 | #define FLAG_DELETED 0x0001 /* Entry has been removed from db */ |
@@ -137,6 +138,7 @@ bool tagcache_retrieve(struct tagcache_search *tcs, int idxid, | |||
137 | char *buf, long size); | 138 | char *buf, long size); |
138 | void tagcache_search_finish(struct tagcache_search *tcs); | 139 | void tagcache_search_finish(struct tagcache_search *tcs); |
139 | long tagcache_get_numeric(const struct tagcache_search *tcs, int tag); | 140 | long tagcache_get_numeric(const struct tagcache_search *tcs, int tag); |
141 | bool tagcache_create_changelog(struct tagcache_search *tcs); | ||
140 | bool tagcache_modify_numeric_entry(struct tagcache_search *tcs, | 142 | bool tagcache_modify_numeric_entry(struct tagcache_search *tcs, |
141 | int tag, long data); | 143 | int tag, long data); |
142 | 144 | ||
diff --git a/apps/tagnavi.config b/apps/tagnavi.config index 285f826425..0ad30538ac 100644 --- a/apps/tagnavi.config +++ b/apps/tagnavi.config | |||
@@ -6,6 +6,7 @@ | |||
6 | "Search by artist" artist ? artist ~ "" : album : title = "%02d. %s" tracknum title | 6 | "Search by artist" artist ? artist ~ "" : album : title = "%02d. %s" tracknum title |
7 | "Search by album" album ? album ~ "" : title = "%02d. %s" tracknum title | 7 | "Search by album" album ? album ~ "" : title = "%02d. %s" tracknum title |
8 | "Search by title" title ? title ~ "" | 8 | "Search by title" title ? title ~ "" |
9 | "Search by filename" filename ? filename ~ "" | ||
9 | "Search by year" artist ? year = "" : album : title = "%02d. %s" tracknum title | 10 | "Search by year" artist ? year = "" : album : title = "%02d. %s" tracknum title |
10 | "Search by score" title = "(%3d) %s" autoscore title ? autoscore > "" | 11 | "Search by score" title = "(%3d) %s" autoscore title ? autoscore > "" |
11 | "Most played tracks" title = "(%d) %s" playcount title ? playcount > "1" | 12 | "Most played tracks" title = "(%d) %s" playcount title ? playcount > "1" |
diff --git a/apps/tagtree.c b/apps/tagtree.c index 396248d7ce..f5c100f6ea 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c | |||
@@ -137,6 +137,7 @@ static int get_tag(int *tag) | |||
137 | MATCH(tag, buf, "genre", tag_genre); | 137 | MATCH(tag, buf, "genre", tag_genre); |
138 | MATCH(tag, buf, "length", tag_length); | 138 | MATCH(tag, buf, "length", tag_length); |
139 | MATCH(tag, buf, "title", tag_title); | 139 | MATCH(tag, buf, "title", tag_title); |
140 | MATCH(tag, buf, "filename", tag_filename); | ||
140 | MATCH(tag, buf, "tracknum", tag_tracknumber); | 141 | MATCH(tag, buf, "tracknum", tag_tracknumber); |
141 | MATCH(tag, buf, "year", tag_year); | 142 | MATCH(tag, buf, "year", tag_year); |
142 | MATCH(tag, buf, "playcount", tag_playcount); | 143 | MATCH(tag, buf, "playcount", tag_playcount); |
@@ -415,6 +416,17 @@ static void tagtree_unbuffer_event(struct mp3entry *id3, bool last_track) | |||
415 | tagcache_search_finish(&tcs); | 416 | tagcache_search_finish(&tcs); |
416 | } | 417 | } |
417 | 418 | ||
419 | bool tagtree_export(void) | ||
420 | { | ||
421 | gui_syncsplash(0, true, str(LANG_WAIT)); | ||
422 | if (!tagcache_create_changelog(&tcs)) | ||
423 | { | ||
424 | gui_syncsplash(HZ*2, true, str(LANG_FAILED)); | ||
425 | } | ||
426 | |||
427 | return false; | ||
428 | } | ||
429 | |||
418 | void tagtree_init(void) | 430 | void tagtree_init(void) |
419 | { | 431 | { |
420 | int fd; | 432 | int fd; |
@@ -553,7 +565,7 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, | |||
553 | current_entry_count = 0; | 565 | current_entry_count = 0; |
554 | c->dirfull = false; | 566 | c->dirfull = false; |
555 | 567 | ||
556 | if (tag != tag_title) | 568 | if (tag != tag_title && tag != tag_filename) |
557 | { | 569 | { |
558 | if (offset == 0) | 570 | if (offset == 0) |
559 | { | 571 | { |
@@ -576,7 +588,7 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, | |||
576 | 588 | ||
577 | dptr->newtable = navibrowse; | 589 | dptr->newtable = navibrowse; |
578 | dptr->extraseek = tcs->result_seek; | 590 | dptr->extraseek = tcs->result_seek; |
579 | if (tag == tag_title) | 591 | if (tag == tag_title || tag == tag_filename) |
580 | dptr->newtable = playtrack; | 592 | dptr->newtable = playtrack; |
581 | 593 | ||
582 | if (!tcs->ramsearch || fmt->valid) | 594 | if (!tcs->ramsearch || fmt->valid) |
diff --git a/apps/tagtree.h b/apps/tagtree.h index 81d900bbb6..2129176683 100644 --- a/apps/tagtree.h +++ b/apps/tagtree.h | |||
@@ -30,6 +30,7 @@ struct tagentry { | |||
30 | int extraseek; | 30 | int extraseek; |
31 | }; | 31 | }; |
32 | 32 | ||
33 | bool tagtree_export(void); | ||
33 | void tagtree_init(void); | 34 | void tagtree_init(void); |
34 | int tagtree_enter(struct tree_context* c); | 35 | int tagtree_enter(struct tree_context* c); |
35 | void tagtree_exit(struct tree_context* c); | 36 | void tagtree_exit(struct tree_context* c); |