forked from len0rd/rockbox
Initial changelog support (only export, no import yet) and added
an option to search by filename. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10219 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
11e229ffa6
commit
0042201bb3
7 changed files with 156 additions and 7 deletions
|
@ -8557,3 +8557,17 @@
|
||||||
*: "Auto update"
|
*: "Auto update"
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_TAGCACHE_EXPORT
|
||||||
|
desc: in tag cache settings
|
||||||
|
user:
|
||||||
|
<source>
|
||||||
|
*: "Export modifications"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Export modifications"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Export modifications"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
#include "dircache.h"
|
#include "dircache.h"
|
||||||
#include "tagcache.h"
|
#include "tagcache.h"
|
||||||
|
#include "tagtree.h"
|
||||||
#include "rbunicode.h"
|
#include "rbunicode.h"
|
||||||
#include "splash.h"
|
#include "splash.h"
|
||||||
#include "yesno.h"
|
#include "yesno.h"
|
||||||
|
@ -1568,6 +1569,7 @@ static bool tagcache_settings_menu(void)
|
||||||
{ ID2P(LANG_TAGCACHE_FORCE_UPDATE), tagcache_rebuild },
|
{ ID2P(LANG_TAGCACHE_FORCE_UPDATE), tagcache_rebuild },
|
||||||
{ ID2P(LANG_TAGCACHE_UPDATE), tagcache_update },
|
{ ID2P(LANG_TAGCACHE_UPDATE), tagcache_update },
|
||||||
{ ID2P(LANG_RUNTIMEDB_ACTIVE), tagcache_runtimedb },
|
{ ID2P(LANG_RUNTIMEDB_ACTIVE), tagcache_runtimedb },
|
||||||
|
{ ID2P(LANG_TAGCACHE_EXPORT), tagtree_export },
|
||||||
};
|
};
|
||||||
|
|
||||||
m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
|
m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
|
||||||
|
|
121
apps/tagcache.c
121
apps/tagcache.c
|
@ -478,6 +478,7 @@ static bool build_lookup_list(struct tagcache_search *tcs)
|
||||||
{
|
{
|
||||||
struct index_entry *idx = &hdr->indices[i];
|
struct index_entry *idx = &hdr->indices[i];
|
||||||
int seek;
|
int seek;
|
||||||
|
char buf[256];
|
||||||
char *str = NULL;
|
char *str = NULL;
|
||||||
struct tagfile_entry *entry;
|
struct tagfile_entry *entry;
|
||||||
|
|
||||||
|
@ -485,8 +486,16 @@ static bool build_lookup_list(struct tagcache_search *tcs)
|
||||||
|
|
||||||
if (!tagcache_is_numeric_tag(tcs->clause[j]->tag))
|
if (!tagcache_is_numeric_tag(tcs->clause[j]->tag))
|
||||||
{
|
{
|
||||||
entry = (struct tagfile_entry *)&hdr->tags[tcs->clause[j]->tag][seek];
|
if (tcs->clause[j]->tag == tag_filename)
|
||||||
str = entry->tag_data;
|
{
|
||||||
|
tagcache_retrieve(tcs, i, buf, sizeof buf);
|
||||||
|
str = buf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entry = (struct tagfile_entry *)&hdr->tags[tcs->clause[j]->tag][seek];
|
||||||
|
str = entry->tag_data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2104,6 +2113,114 @@ static int open_master_fd(struct tagcache_header *hdr)
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool write_tag(int fd, const char *tagstr, const char *datastr)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
snprintf(buf, sizeof buf, "%s=\"", tagstr);
|
||||||
|
for (i = strlen(buf); i < (long)sizeof(buf)-2; i++)
|
||||||
|
{
|
||||||
|
if (*datastr == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (*datastr == '"')
|
||||||
|
{
|
||||||
|
buf[i] = '\\';
|
||||||
|
*datastr++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[i] = *(datastr++);
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(&buf[i], "\" ");
|
||||||
|
|
||||||
|
write(fd, buf, i + 2);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tagcache_create_changelog(struct tagcache_search *tcs)
|
||||||
|
{
|
||||||
|
static const char *tags_str[] = { "artist", "album", "genre", "title",
|
||||||
|
"filename", "playcount", "playtime", "lastplayed" };
|
||||||
|
static const int tags[] = { tag_artist, tag_album, tag_genre, tag_title,
|
||||||
|
tag_filename, tag_playcount, tag_playtime, tag_lastplayed };
|
||||||
|
struct tagcache_header myhdr;
|
||||||
|
struct index_entry idx;
|
||||||
|
char buf[256];
|
||||||
|
char temp[32];
|
||||||
|
int clfd;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (!tagcache_search(tcs, tag_filename))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Initialize the changelog */
|
||||||
|
clfd = open(TAGCACHE_FILE_CHANGELOG, O_WRONLY | O_CREAT | O_TRUNC);
|
||||||
|
if (clfd < 0)
|
||||||
|
{
|
||||||
|
logf("failure to open changelog");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tcs->masterfd < 0)
|
||||||
|
{
|
||||||
|
if ( (tcs->masterfd = open_master_fd(&myhdr)) < 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lseek(tcs->masterfd, 0, SEEK_SET);
|
||||||
|
read(tcs->masterfd, &myhdr, sizeof(struct tagcache_header));
|
||||||
|
}
|
||||||
|
|
||||||
|
write(clfd, "## Changelog version 1\n", 23);
|
||||||
|
|
||||||
|
for (i = 0; i < myhdr.entry_count; i++)
|
||||||
|
{
|
||||||
|
if (read(tcs->masterfd, &idx, sizeof(struct index_entry))
|
||||||
|
!= sizeof(struct index_entry))
|
||||||
|
{
|
||||||
|
logf("read error");
|
||||||
|
tagcache_search_finish(tcs);
|
||||||
|
close(clfd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip until the entry found has been modified. */
|
||||||
|
if (! (idx.flag & FLAG_DIRTYNUM) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
logf("Found!");
|
||||||
|
|
||||||
|
/* Now retrieve all tags. */
|
||||||
|
for (j = 0; j < (long)(sizeof(tags) / sizeof(tags[0])); j++)
|
||||||
|
{
|
||||||
|
if (tagcache_is_numeric_tag(tags[j]))
|
||||||
|
{
|
||||||
|
snprintf(temp, sizeof temp, "%d", idx.tag_seek[tags[j]]);
|
||||||
|
write_tag(clfd, tags_str[j], temp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcs->type = tags[j];
|
||||||
|
tagcache_retrieve(tcs, i, buf, sizeof buf);
|
||||||
|
logf("tag: %s", buf);
|
||||||
|
write_tag(clfd, tags_str[j], buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
write(clfd, "\n", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(clfd);
|
||||||
|
|
||||||
|
tagcache_search_finish(tcs);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool tagcache_modify_numeric_entry(struct tagcache_search *tcs,
|
bool tagcache_modify_numeric_entry(struct tagcache_search *tcs,
|
||||||
int tag, long data)
|
int tag, long data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -63,9 +63,10 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
|
||||||
#define TAGCACHE_MAX_CLAUSES 10
|
#define TAGCACHE_MAX_CLAUSES 10
|
||||||
|
|
||||||
/* Tag database files. */
|
/* Tag database files. */
|
||||||
#define TAGCACHE_FILE_TEMP ROCKBOX_DIR "/tagcache_tmp.tcd"
|
#define TAGCACHE_FILE_TEMP ROCKBOX_DIR "/tagcache_tmp.tcd"
|
||||||
#define TAGCACHE_FILE_MASTER ROCKBOX_DIR "/tagcache_idx.tcd"
|
#define TAGCACHE_FILE_MASTER ROCKBOX_DIR "/tagcache_idx.tcd"
|
||||||
#define TAGCACHE_FILE_INDEX ROCKBOX_DIR "/tagcache_%d.tcd"
|
#define TAGCACHE_FILE_INDEX ROCKBOX_DIR "/tagcache_%d.tcd"
|
||||||
|
#define TAGCACHE_FILE_CHANGELOG ROCKBOX_DIR "/tagcache_changelog.txt"
|
||||||
|
|
||||||
/* Flags */
|
/* Flags */
|
||||||
#define FLAG_DELETED 0x0001 /* Entry has been removed from db */
|
#define FLAG_DELETED 0x0001 /* Entry has been removed from db */
|
||||||
|
@ -137,6 +138,7 @@ bool tagcache_retrieve(struct tagcache_search *tcs, int idxid,
|
||||||
char *buf, long size);
|
char *buf, long size);
|
||||||
void tagcache_search_finish(struct tagcache_search *tcs);
|
void tagcache_search_finish(struct tagcache_search *tcs);
|
||||||
long tagcache_get_numeric(const struct tagcache_search *tcs, int tag);
|
long tagcache_get_numeric(const struct tagcache_search *tcs, int tag);
|
||||||
|
bool tagcache_create_changelog(struct tagcache_search *tcs);
|
||||||
bool tagcache_modify_numeric_entry(struct tagcache_search *tcs,
|
bool tagcache_modify_numeric_entry(struct tagcache_search *tcs,
|
||||||
int tag, long data);
|
int tag, long data);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
"Search by artist" artist ? artist ~ "" : album : title = "%02d. %s" tracknum title
|
"Search by artist" artist ? artist ~ "" : album : title = "%02d. %s" tracknum title
|
||||||
"Search by album" album ? album ~ "" : title = "%02d. %s" tracknum title
|
"Search by album" album ? album ~ "" : title = "%02d. %s" tracknum title
|
||||||
"Search by title" title ? title ~ ""
|
"Search by title" title ? title ~ ""
|
||||||
|
"Search by filename" filename ? filename ~ ""
|
||||||
"Search by year" artist ? year = "" : album : title = "%02d. %s" tracknum title
|
"Search by year" artist ? year = "" : album : title = "%02d. %s" tracknum title
|
||||||
"Search by score" title = "(%3d) %s" autoscore title ? autoscore > ""
|
"Search by score" title = "(%3d) %s" autoscore title ? autoscore > ""
|
||||||
"Most played tracks" title = "(%d) %s" playcount title ? playcount > "1"
|
"Most played tracks" title = "(%d) %s" playcount title ? playcount > "1"
|
||||||
|
|
|
@ -137,6 +137,7 @@ static int get_tag(int *tag)
|
||||||
MATCH(tag, buf, "genre", tag_genre);
|
MATCH(tag, buf, "genre", tag_genre);
|
||||||
MATCH(tag, buf, "length", tag_length);
|
MATCH(tag, buf, "length", tag_length);
|
||||||
MATCH(tag, buf, "title", tag_title);
|
MATCH(tag, buf, "title", tag_title);
|
||||||
|
MATCH(tag, buf, "filename", tag_filename);
|
||||||
MATCH(tag, buf, "tracknum", tag_tracknumber);
|
MATCH(tag, buf, "tracknum", tag_tracknumber);
|
||||||
MATCH(tag, buf, "year", tag_year);
|
MATCH(tag, buf, "year", tag_year);
|
||||||
MATCH(tag, buf, "playcount", tag_playcount);
|
MATCH(tag, buf, "playcount", tag_playcount);
|
||||||
|
@ -415,6 +416,17 @@ static void tagtree_unbuffer_event(struct mp3entry *id3, bool last_track)
|
||||||
tagcache_search_finish(&tcs);
|
tagcache_search_finish(&tcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tagtree_export(void)
|
||||||
|
{
|
||||||
|
gui_syncsplash(0, true, str(LANG_WAIT));
|
||||||
|
if (!tagcache_create_changelog(&tcs))
|
||||||
|
{
|
||||||
|
gui_syncsplash(HZ*2, true, str(LANG_FAILED));
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void tagtree_init(void)
|
void tagtree_init(void)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -553,7 +565,7 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
|
||||||
current_entry_count = 0;
|
current_entry_count = 0;
|
||||||
c->dirfull = false;
|
c->dirfull = false;
|
||||||
|
|
||||||
if (tag != tag_title)
|
if (tag != tag_title && tag != tag_filename)
|
||||||
{
|
{
|
||||||
if (offset == 0)
|
if (offset == 0)
|
||||||
{
|
{
|
||||||
|
@ -576,7 +588,7 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
|
||||||
|
|
||||||
dptr->newtable = navibrowse;
|
dptr->newtable = navibrowse;
|
||||||
dptr->extraseek = tcs->result_seek;
|
dptr->extraseek = tcs->result_seek;
|
||||||
if (tag == tag_title)
|
if (tag == tag_title || tag == tag_filename)
|
||||||
dptr->newtable = playtrack;
|
dptr->newtable = playtrack;
|
||||||
|
|
||||||
if (!tcs->ramsearch || fmt->valid)
|
if (!tcs->ramsearch || fmt->valid)
|
||||||
|
|
|
@ -30,6 +30,7 @@ struct tagentry {
|
||||||
int extraseek;
|
int extraseek;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool tagtree_export(void);
|
||||||
void tagtree_init(void);
|
void tagtree_init(void);
|
||||||
int tagtree_enter(struct tree_context* c);
|
int tagtree_enter(struct tree_context* c);
|
||||||
void tagtree_exit(struct tree_context* c);
|
void tagtree_exit(struct tree_context* c);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue