summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/lang/english.lang14
-rw-r--r--apps/settings_menu.c2
-rw-r--r--apps/tagcache.c121
-rw-r--r--apps/tagcache.h8
-rw-r--r--apps/tagnavi.config1
-rw-r--r--apps/tagtree.c16
-rw-r--r--apps/tagtree.h1
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
2116static 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
2144bool 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
2107bool tagcache_modify_numeric_entry(struct tagcache_search *tcs, 2224bool 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);
138void tagcache_search_finish(struct tagcache_search *tcs); 139void tagcache_search_finish(struct tagcache_search *tcs);
139long tagcache_get_numeric(const struct tagcache_search *tcs, int tag); 140long tagcache_get_numeric(const struct tagcache_search *tcs, int tag);
141bool tagcache_create_changelog(struct tagcache_search *tcs);
140bool tagcache_modify_numeric_entry(struct tagcache_search *tcs, 142bool 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
419bool 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
418void tagtree_init(void) 430void 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
33bool tagtree_export(void);
33void tagtree_init(void); 34void tagtree_init(void);
34int tagtree_enter(struct tree_context* c); 35int tagtree_enter(struct tree_context* c);
35void tagtree_exit(struct tree_context* c); 36void tagtree_exit(struct tree_context* c);