forked from len0rd/rockbox
Initial version of tagcache! There are still some bugs in the engine
and much more problems with the UI. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9256 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
50d40ea434
commit
7c4e0c8730
23 changed files with 2698 additions and 64 deletions
|
@ -25,8 +25,7 @@ status.c
|
||||||
talk.c
|
talk.c
|
||||||
#endif
|
#endif
|
||||||
tree.c
|
tree.c
|
||||||
dbtree.c
|
tagtree.c
|
||||||
database.c
|
|
||||||
filetree.c
|
filetree.c
|
||||||
|
|
||||||
screen_access.c
|
screen_access.c
|
||||||
|
@ -69,7 +68,6 @@ recorder/recording.c
|
||||||
#if CONFIG_CODEC == SWCODEC
|
#if CONFIG_CODEC == SWCODEC
|
||||||
pcmbuf.c
|
pcmbuf.c
|
||||||
playback.c
|
playback.c
|
||||||
metadata.c
|
|
||||||
codecs.c
|
codecs.c
|
||||||
dsp.c
|
dsp.c
|
||||||
eq.c
|
eq.c
|
||||||
|
@ -81,3 +79,5 @@ eq_arm.S
|
||||||
#endif
|
#endif
|
||||||
eq_menu.c
|
eq_menu.c
|
||||||
#endif
|
#endif
|
||||||
|
metadata.c
|
||||||
|
tagcache.c
|
||||||
|
|
|
@ -177,12 +177,6 @@ struct codec_api ci = {
|
||||||
audio_flush_and_reload_tracks,
|
audio_flush_and_reload_tracks,
|
||||||
audio_get_file_pos,
|
audio_get_file_pos,
|
||||||
|
|
||||||
/* tag database */
|
|
||||||
&tagdbheader,
|
|
||||||
&tagdb_fd,
|
|
||||||
&tagdb_initialized,
|
|
||||||
tagdb_init,
|
|
||||||
|
|
||||||
/* misc */
|
/* misc */
|
||||||
srand,
|
srand,
|
||||||
rand,
|
rand,
|
||||||
|
|
|
@ -85,12 +85,12 @@
|
||||||
#define CODEC_MAGIC 0x52434F44 /* RCOD */
|
#define CODEC_MAGIC 0x52434F44 /* RCOD */
|
||||||
|
|
||||||
/* increase this every time the api struct changes */
|
/* increase this every time the api struct changes */
|
||||||
#define CODEC_API_VERSION 5
|
#define CODEC_API_VERSION 6
|
||||||
|
|
||||||
/* update this to latest version if a change to the api struct breaks
|
/* update this to latest version if a change to the api struct breaks
|
||||||
backwards compatibility (and please take the opportunity to sort in any
|
backwards compatibility (and please take the opportunity to sort in any
|
||||||
new function which are "waiting" at the end of the function table) */
|
new function which are "waiting" at the end of the function table) */
|
||||||
#define CODEC_MIN_API_VERSION 5
|
#define CODEC_MIN_API_VERSION 6
|
||||||
|
|
||||||
/* codec return codes */
|
/* codec return codes */
|
||||||
enum codec_status {
|
enum codec_status {
|
||||||
|
@ -248,12 +248,6 @@ struct codec_api {
|
||||||
void (*audio_flush_and_reload_tracks)(void);
|
void (*audio_flush_and_reload_tracks)(void);
|
||||||
int (*audio_get_file_pos)(void);
|
int (*audio_get_file_pos)(void);
|
||||||
|
|
||||||
/* tag database */
|
|
||||||
struct tagdb_header *tagdbheader;
|
|
||||||
int *tagdb_fd;
|
|
||||||
int *tagdb_initialized;
|
|
||||||
int (*tagdb_init) (void);
|
|
||||||
|
|
||||||
/* misc */
|
/* misc */
|
||||||
void (*srand)(unsigned int seed);
|
void (*srand)(unsigned int seed);
|
||||||
int (*rand)(void);
|
int (*rand)(void);
|
||||||
|
|
|
@ -49,6 +49,8 @@
|
||||||
#include "screens.h"
|
#include "screens.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "splash.h"
|
#include "splash.h"
|
||||||
|
#include "dircache.h"
|
||||||
|
#include "tagcache.h"
|
||||||
#include "lcd-remote.h"
|
#include "lcd-remote.h"
|
||||||
|
|
||||||
#ifdef HAVE_LCD_BITMAP
|
#ifdef HAVE_LCD_BITMAP
|
||||||
|
@ -1855,6 +1857,10 @@ static bool dbg_dircache_info(void)
|
||||||
dircache_get_build_ticks() / HZ);
|
dircache_get_build_ticks() / HZ);
|
||||||
lcd_puts(0, line++, buf);
|
lcd_puts(0, line++, buf);
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "Entry count: %d",
|
||||||
|
dircache_get_entry_count());
|
||||||
|
lcd_puts(0, line++, buf);
|
||||||
|
|
||||||
lcd_update();
|
lcd_update();
|
||||||
|
|
||||||
switch (button_get_w_tmo(HZ/2))
|
switch (button_get_w_tmo(HZ/2))
|
||||||
|
@ -1871,6 +1877,38 @@ static bool dbg_dircache_info(void)
|
||||||
|
|
||||||
#endif /* HAVE_DIRCACHE */
|
#endif /* HAVE_DIRCACHE */
|
||||||
|
|
||||||
|
static bool dbg_tagcache_info(void)
|
||||||
|
{
|
||||||
|
bool done = false;
|
||||||
|
int line;
|
||||||
|
char buf[32];
|
||||||
|
|
||||||
|
lcd_setmargins(0, 0);
|
||||||
|
lcd_setfont(FONT_SYSFIXED);
|
||||||
|
|
||||||
|
while (!done)
|
||||||
|
{
|
||||||
|
line = 0;
|
||||||
|
|
||||||
|
lcd_clear_display();
|
||||||
|
snprintf(buf, sizeof(buf), "Current progress: %d%%",
|
||||||
|
tagcache_get_progress());
|
||||||
|
lcd_puts(0, line++, buf);
|
||||||
|
|
||||||
|
lcd_update();
|
||||||
|
|
||||||
|
switch (button_get_w_tmo(HZ/2))
|
||||||
|
{
|
||||||
|
case SETTINGS_OK:
|
||||||
|
case SETTINGS_CANCEL:
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#if CONFIG_CPU == SH7034
|
#if CONFIG_CPU == SH7034
|
||||||
bool dbg_save_roms(void)
|
bool dbg_save_roms(void)
|
||||||
{
|
{
|
||||||
|
@ -2014,6 +2052,7 @@ bool debug_menu(void)
|
||||||
#ifdef HAVE_DIRCACHE
|
#ifdef HAVE_DIRCACHE
|
||||||
{ "View dircache info", dbg_dircache_info },
|
{ "View dircache info", dbg_dircache_info },
|
||||||
#endif
|
#endif
|
||||||
|
{ "View tagcache info", dbg_tagcache_info },
|
||||||
#ifdef HAVE_LCD_BITMAP
|
#ifdef HAVE_LCD_BITMAP
|
||||||
{ "View audio thread", dbg_audio_thread },
|
{ "View audio thread", dbg_audio_thread },
|
||||||
#ifdef PM_DEBUG
|
#ifdef PM_DEBUG
|
||||||
|
|
|
@ -3838,3 +3838,45 @@ desc: Backlight behaviour setting
|
||||||
eng: "First keypress enables backlight only"
|
eng: "First keypress enables backlight only"
|
||||||
voice: "First keypress enables backlight only"
|
voice: "First keypress enables backlight only"
|
||||||
new:
|
new:
|
||||||
|
|
||||||
|
id: LANG_ID3DB_GENRES
|
||||||
|
desc: in tag cache
|
||||||
|
eng: "Genres"
|
||||||
|
voice: "Genres"
|
||||||
|
new:
|
||||||
|
|
||||||
|
id: LANG_TAGCACHE
|
||||||
|
desc: in tag cache settings
|
||||||
|
eng: "Tag cache"
|
||||||
|
voice: "Tag cache"
|
||||||
|
new:
|
||||||
|
|
||||||
|
id: LANG_TAGCACHE_INIT
|
||||||
|
desc: while initializing tagcache on boot
|
||||||
|
eng: "Committing tagcache"
|
||||||
|
voice:
|
||||||
|
new:
|
||||||
|
|
||||||
|
id: LANG_TAGCACHE_DISK
|
||||||
|
desc: in tag cache settings
|
||||||
|
eng: "Keep on disk"
|
||||||
|
voice: "Keep on disk"
|
||||||
|
new:
|
||||||
|
|
||||||
|
id: LANG_TAGCACHE_RAM
|
||||||
|
desc: in tag cache settings
|
||||||
|
eng: "Load to ram"
|
||||||
|
voice: "Load to ram"
|
||||||
|
new:
|
||||||
|
|
||||||
|
id: LANG_TAGCACHE_FORCE_UPDATE
|
||||||
|
desc: in tag cache settings
|
||||||
|
eng: "Force tag cache update"
|
||||||
|
voice: "Force tag cache update"
|
||||||
|
new:
|
||||||
|
|
||||||
|
id: LANG_TAGCACHE_FORCE_UPDATE_SPLASH
|
||||||
|
desc: in tag cache settings
|
||||||
|
eng: "Updating in background"
|
||||||
|
voice: "Updating in background"
|
||||||
|
new:
|
||||||
|
|
27
apps/main.c
27
apps/main.c
|
@ -60,6 +60,7 @@
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
#include "dircache.h"
|
#include "dircache.h"
|
||||||
|
#include "tagcache.h"
|
||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "splash.h"
|
#include "splash.h"
|
||||||
|
@ -138,6 +139,29 @@ void init_dircache(void)
|
||||||
# define init_dircache(...)
|
# define init_dircache(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void init_tagcache(void)
|
||||||
|
{
|
||||||
|
int font_w, font_h;
|
||||||
|
|
||||||
|
#ifdef HAVE_LCD_BITMAP
|
||||||
|
/* Print "Scanning disk..." to the display. */
|
||||||
|
lcd_getstringsize("A", &font_w, &font_h);
|
||||||
|
lcd_putsxy((LCD_WIDTH/2) - ((strlen(str(LANG_TAGCACHE_INIT))*font_w)/2),
|
||||||
|
LCD_HEIGHT-font_h*3, str(LANG_TAGCACHE_INIT));
|
||||||
|
lcd_update();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tagcache_init();
|
||||||
|
|
||||||
|
#ifdef HAVE_LCD_BITMAP
|
||||||
|
/* Clean the text when we are done. */
|
||||||
|
lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
||||||
|
lcd_fillrect(0, LCD_HEIGHT-font_h*3, LCD_WIDTH, font_h);
|
||||||
|
lcd_set_drawmode(DRMODE_SOLID);
|
||||||
|
lcd_update();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef SIMULATOR
|
#ifdef SIMULATOR
|
||||||
|
|
||||||
void init(void)
|
void init(void)
|
||||||
|
@ -162,6 +186,7 @@ void init(void)
|
||||||
gui_sync_wps_init();
|
gui_sync_wps_init();
|
||||||
settings_apply();
|
settings_apply();
|
||||||
init_dircache();
|
init_dircache();
|
||||||
|
init_tagcache();
|
||||||
sleep(HZ/2);
|
sleep(HZ/2);
|
||||||
tree_init();
|
tree_init();
|
||||||
playlist_init();
|
playlist_init();
|
||||||
|
@ -350,6 +375,7 @@ void init(void)
|
||||||
|
|
||||||
|
|
||||||
init_dircache();
|
init_dircache();
|
||||||
|
init_tagcache();
|
||||||
gui_sync_wps_init();
|
gui_sync_wps_init();
|
||||||
settings_apply();
|
settings_apply();
|
||||||
|
|
||||||
|
@ -379,7 +405,6 @@ void init(void)
|
||||||
#endif
|
#endif
|
||||||
talk_init();
|
talk_init();
|
||||||
/* runtime database has to be initialized after audio_init() */
|
/* runtime database has to be initialized after audio_init() */
|
||||||
rundb_init();
|
|
||||||
cpu_boost(false);
|
cpu_boost(false);
|
||||||
|
|
||||||
#ifdef AUTOROCK
|
#ifdef AUTOROCK
|
||||||
|
|
|
@ -68,6 +68,7 @@ static const struct format_list formats[] =
|
||||||
{ AFMT_MPA_L2, "mp2" },
|
{ AFMT_MPA_L2, "mp2" },
|
||||||
{ AFMT_MPA_L2, "mpa" },
|
{ AFMT_MPA_L2, "mpa" },
|
||||||
{ AFMT_MPA_L3, "mp3" },
|
{ AFMT_MPA_L3, "mp3" },
|
||||||
|
#if CONFIG_CODEC == SWCODEC
|
||||||
{ AFMT_OGG_VORBIS, "ogg" },
|
{ AFMT_OGG_VORBIS, "ogg" },
|
||||||
{ AFMT_PCM_WAV, "wav" },
|
{ AFMT_PCM_WAV, "wav" },
|
||||||
{ AFMT_FLAC, "flac" },
|
{ AFMT_FLAC, "flac" },
|
||||||
|
@ -80,8 +81,10 @@ static const struct format_list formats[] =
|
||||||
{ AFMT_SHN, "shn" },
|
{ AFMT_SHN, "shn" },
|
||||||
{ AFMT_AIFF, "aif" },
|
{ AFMT_AIFF, "aif" },
|
||||||
{ AFMT_AIFF, "aiff" },
|
{ AFMT_AIFF, "aiff" },
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if CONFIG_CODEC == SWCODEC
|
||||||
static const unsigned short a52_bitrates[] =
|
static const unsigned short a52_bitrates[] =
|
||||||
{
|
{
|
||||||
32, 40, 48, 56, 64, 80, 96, 112, 128, 160,
|
32, 40, 48, 56, 64, 80, 96, 112, 128, 160,
|
||||||
|
@ -1246,6 +1249,7 @@ static bool get_musepack_metadata(int fd, struct mp3entry *id3)
|
||||||
id3->bitrate = id3->filesize*8/id3->length;
|
id3->bitrate = id3->filesize*8/id3->length;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_CODEC == SWCODEC */
|
||||||
|
|
||||||
static bool get_aiff_metadata(int fd, struct mp3entry* id3)
|
static bool get_aiff_metadata(int fd, struct mp3entry* id3)
|
||||||
{
|
{
|
||||||
|
@ -1318,7 +1322,7 @@ static bool get_aiff_metadata(int fd, struct mp3entry* id3)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Simple file type probing by looking at the filename extension. */
|
/* Simple file type probing by looking at the filename extension. */
|
||||||
static unsigned int probe_file_format(const char *filename)
|
unsigned int probe_file_format(const char *filename)
|
||||||
{
|
{
|
||||||
char *suffix;
|
char *suffix;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
@ -1349,9 +1353,11 @@ static unsigned int probe_file_format(const char *filename)
|
||||||
bool get_metadata(struct track_info* track, int fd, const char* trackname,
|
bool get_metadata(struct track_info* track, int fd, const char* trackname,
|
||||||
bool v1first)
|
bool v1first)
|
||||||
{
|
{
|
||||||
|
#if CONFIG_CODEC == SWCODEC
|
||||||
unsigned char* buf;
|
unsigned char* buf;
|
||||||
unsigned long totalsamples;
|
unsigned long totalsamples;
|
||||||
int i;
|
int i;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Take our best guess at the codec type based on file extension */
|
/* Take our best guess at the codec type based on file extension */
|
||||||
track->id3.codectype = probe_file_format(trackname);
|
track->id3.codectype = probe_file_format(trackname);
|
||||||
|
@ -1369,6 +1375,7 @@ bool get_metadata(struct track_info* track, int fd, const char* trackname,
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if CONFIG_CODEC == SWCODEC
|
||||||
case AFMT_FLAC:
|
case AFMT_FLAC:
|
||||||
if (!get_flac_metadata(fd, &(track->id3)))
|
if (!get_flac_metadata(fd, &(track->id3)))
|
||||||
{
|
{
|
||||||
|
@ -1519,6 +1526,7 @@ bool get_metadata(struct track_info* track, int fd, const char* trackname,
|
||||||
}
|
}
|
||||||
/* TODO: read the id3v2 header if it exists */
|
/* TODO: read the id3v2 header if it exists */
|
||||||
break;
|
break;
|
||||||
|
#endif /* CONFIG_CODEC == SWCODEC */
|
||||||
|
|
||||||
case AFMT_AIFF:
|
case AFMT_AIFF:
|
||||||
if (!get_aiff_metadata(fd, &(track->id3)))
|
if (!get_aiff_metadata(fd, &(track->id3)))
|
||||||
|
@ -1543,3 +1551,4 @@ bool get_metadata(struct track_info* track, int fd, const char* trackname,
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include "playback.h"
|
#include "playback.h"
|
||||||
|
|
||||||
|
unsigned int probe_file_format(const char *filename);
|
||||||
bool get_metadata(struct track_info* track, int fd, const char* trackname,
|
bool get_metadata(struct track_info* track, int fd, const char* trackname,
|
||||||
bool v1first);
|
bool v1first);
|
||||||
|
|
||||||
|
|
|
@ -820,12 +820,12 @@ int onplay(char* file, int attr, int from)
|
||||||
items[i].desc = ID2P(LANG_MENU_SHOW_ID3_INFO);
|
items[i].desc = ID2P(LANG_MENU_SHOW_ID3_INFO);
|
||||||
items[i].function = browse_id3;
|
items[i].function = browse_id3;
|
||||||
i++;
|
i++;
|
||||||
if(rundb_initialized)
|
/* if(rundb_initialized)
|
||||||
{
|
{
|
||||||
items[i].desc = ID2P(LANG_MENU_SET_RATING);
|
items[i].desc = ID2P(LANG_MENU_SET_RATING);
|
||||||
items[i].function = set_rating;
|
items[i].function = set_rating;
|
||||||
i++;
|
i++;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_MULTIVOLUME
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
|
|
@ -333,16 +333,6 @@ static const struct plugin_api rockbox_api = {
|
||||||
#endif
|
#endif
|
||||||
#endif /* !SIMULATOR && CONFIG_CODEC != SWCODEC */
|
#endif /* !SIMULATOR && CONFIG_CODEC != SWCODEC */
|
||||||
|
|
||||||
/* tag database */
|
|
||||||
&tagdbheader,
|
|
||||||
&tagdb_fd,
|
|
||||||
&tagdb_initialized,
|
|
||||||
tagdb_init,
|
|
||||||
/* runtime database */
|
|
||||||
&rundbheader,
|
|
||||||
&rundb_fd,
|
|
||||||
&rundb_initialized,
|
|
||||||
|
|
||||||
/* menu */
|
/* menu */
|
||||||
menu_init,
|
menu_init,
|
||||||
menu_exit,
|
menu_exit,
|
||||||
|
|
|
@ -99,12 +99,12 @@
|
||||||
#define PLUGIN_MAGIC 0x526F634B /* RocK */
|
#define PLUGIN_MAGIC 0x526F634B /* RocK */
|
||||||
|
|
||||||
/* increase this every time the api struct changes */
|
/* increase this every time the api struct changes */
|
||||||
#define PLUGIN_API_VERSION 13
|
#define PLUGIN_API_VERSION 14
|
||||||
|
|
||||||
/* update this to latest version if a change to the api struct breaks
|
/* update this to latest version if a change to the api struct breaks
|
||||||
backwards compatibility (and please take the opportunity to sort in any
|
backwards compatibility (and please take the opportunity to sort in any
|
||||||
new function which are "waiting" at the end of the function table) */
|
new function which are "waiting" at the end of the function table) */
|
||||||
#define PLUGIN_MIN_API_VERSION 13
|
#define PLUGIN_MIN_API_VERSION 14
|
||||||
|
|
||||||
/* plugin return codes */
|
/* plugin return codes */
|
||||||
enum plugin_status {
|
enum plugin_status {
|
||||||
|
@ -387,16 +387,6 @@ struct plugin_api {
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* tag database */
|
|
||||||
struct tagdb_header *tagdbheader;
|
|
||||||
int *tagdb_fd;
|
|
||||||
int *tagdb_initialized;
|
|
||||||
int (*tagdb_init) (void);
|
|
||||||
/* runtime database */
|
|
||||||
struct rundb_header *rundbheader;
|
|
||||||
int *rundb_fd;
|
|
||||||
int *rundb_initialized;
|
|
||||||
|
|
||||||
/* menu */
|
/* menu */
|
||||||
int (*menu_init)(const struct menu_item* mitems, int count,
|
int (*menu_init)(const struct menu_item* mitems, int count,
|
||||||
int (*callback)(int, int),
|
int (*callback)(int, int),
|
||||||
|
|
|
@ -60,7 +60,8 @@ DIRS = .
|
||||||
# Subdirs containing multi-file plugins
|
# Subdirs containing multi-file plugins
|
||||||
|
|
||||||
#for all targets
|
#for all targets
|
||||||
SUBDIRS += searchengine databox
|
# SUBDIRS += searchengine databox
|
||||||
|
SUBDIRS += databox
|
||||||
|
|
||||||
#for any recorder, iRiver or iPod model
|
#for any recorder, iRiver or iPod model
|
||||||
ifneq (,$(strip $(foreach tgt,RECORDER IRIVER IPOD_COLOR IPOD_VIDEO GIGABEAT,$(findstring $(tgt),$(TARGET)))))
|
ifneq (,$(strip $(foreach tgt,RECORDER IRIVER IPOD_COLOR IPOD_VIDEO GIGABEAT,$(findstring $(tgt),$(TARGET)))))
|
||||||
|
|
|
@ -15,7 +15,7 @@ metronome.c
|
||||||
#endif
|
#endif
|
||||||
mosaique.c
|
mosaique.c
|
||||||
rockbox_flash.c
|
rockbox_flash.c
|
||||||
search.c
|
/* search.c */
|
||||||
snow.c
|
snow.c
|
||||||
sort.c
|
sort.c
|
||||||
stats.c
|
stats.c
|
||||||
|
|
|
@ -565,6 +565,11 @@ static const struct bit_entry hd_bits[] =
|
||||||
{LCD_DEPTH,S_O(fg_color),LCD_DEFAULT_FG,"foreground color","rgb"},
|
{LCD_DEPTH,S_O(fg_color),LCD_DEFAULT_FG,"foreground color","rgb"},
|
||||||
{LCD_DEPTH,S_O(bg_color),LCD_DEFAULT_BG,"background color","rgb"},
|
{LCD_DEPTH,S_O(bg_color),LCD_DEFAULT_BG,"background color","rgb"},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_DIRCACHE
|
||||||
|
{1, S_O(tagcache_ram), 0, "tagcache_ram", off_on },
|
||||||
|
#endif
|
||||||
|
|
||||||
/* If values are just added to the end, no need to bump the version. */
|
/* If values are just added to the end, no need to bump the version. */
|
||||||
/* new stuff to be added at the end */
|
/* new stuff to be added at the end */
|
||||||
|
|
||||||
|
|
|
@ -419,6 +419,7 @@ struct user_settings
|
||||||
#ifdef HAVE_DIRCACHE
|
#ifdef HAVE_DIRCACHE
|
||||||
bool dircache; /* enable directory cache */
|
bool dircache; /* enable directory cache */
|
||||||
int dircache_size; /* directory cache structure last size, 22 bits */
|
int dircache_size; /* directory cache structure last size, 22 bits */
|
||||||
|
bool tagcache_ram; /* tag cache mode (0=disabled,1=disk,2=ram) */
|
||||||
#endif
|
#endif
|
||||||
int default_codepage; /* set default codepage for tag conversion */
|
int default_codepage; /* set default codepage for tag conversion */
|
||||||
#ifdef HAVE_REMOTE_LCD
|
#ifdef HAVE_REMOTE_LCD
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
#include "dircache.h"
|
#include "dircache.h"
|
||||||
|
#include "tagcache.h"
|
||||||
#include "rbunicode.h"
|
#include "rbunicode.h"
|
||||||
#include "splash.h"
|
#include "splash.h"
|
||||||
#include "yesno.h"
|
#include "yesno.h"
|
||||||
|
@ -1259,15 +1260,15 @@ static bool next_folder(void)
|
||||||
static bool runtimedb(void)
|
static bool runtimedb(void)
|
||||||
{
|
{
|
||||||
bool rc;
|
bool rc;
|
||||||
bool old = global_settings.runtimedb;
|
// bool old = global_settings.runtimedb;
|
||||||
|
|
||||||
rc = set_bool( str(LANG_RUNTIMEDB_ACTIVE),
|
rc = set_bool( str(LANG_RUNTIMEDB_ACTIVE),
|
||||||
&global_settings.runtimedb );
|
&global_settings.runtimedb );
|
||||||
if (old && !global_settings.runtimedb)
|
/* if (old && !global_settings.runtimedb)
|
||||||
rundb_shutdown();
|
rundb_shutdown();
|
||||||
if (!old && global_settings.runtimedb)
|
if (!old && global_settings.runtimedb)
|
||||||
rundb_init();
|
rundb_init();
|
||||||
|
*/
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1479,6 +1480,7 @@ static bool beep(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_DIRCACHE
|
#ifdef HAVE_DIRCACHE
|
||||||
static bool dircache(void)
|
static bool dircache(void)
|
||||||
{
|
{
|
||||||
|
@ -1497,6 +1499,16 @@ static bool dircache(void)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tagcache_ram(void)
|
||||||
|
{
|
||||||
|
bool result = set_bool_options(str(LANG_TAGCACHE),
|
||||||
|
&global_settings.tagcache_ram,
|
||||||
|
STR(LANG_TAGCACHE_RAM),
|
||||||
|
STR(LANG_TAGCACHE_DISK),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
#endif /* HAVE_DIRCACHE */
|
#endif /* HAVE_DIRCACHE */
|
||||||
|
|
||||||
static bool playback_settings_menu(void)
|
static bool playback_settings_menu(void)
|
||||||
|
@ -1523,6 +1535,10 @@ static bool playback_settings_menu(void)
|
||||||
#endif
|
#endif
|
||||||
{ ID2P(LANG_ID3_ORDER), id3_order },
|
{ ID2P(LANG_ID3_ORDER), id3_order },
|
||||||
{ ID2P(LANG_NEXT_FOLDER), next_folder },
|
{ ID2P(LANG_NEXT_FOLDER), next_folder },
|
||||||
|
#ifdef HAVE_DIRCACHE
|
||||||
|
{ ID2P(LANG_TAGCACHE), tagcache_ram },
|
||||||
|
#endif
|
||||||
|
{ ID2P(LANG_TAGCACHE_FORCE_UPDATE), tagcache_force_update },
|
||||||
{ ID2P(LANG_RUNTIMEDB_ACTIVE), runtimedb },
|
{ ID2P(LANG_RUNTIMEDB_ACTIVE), runtimedb },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
1868
apps/tagcache.c
Normal file
1868
apps/tagcache.c
Normal file
File diff suppressed because it is too large
Load diff
78
apps/tagcache.h
Normal file
78
apps/tagcache.h
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 by Miika Pekkarinen
|
||||||
|
*
|
||||||
|
* All files in this archive are subject to the GNU General Public License.
|
||||||
|
* See the file COPYING in the source tree root for full license agreement.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef _TAGCACHE_H
|
||||||
|
#define _TAGCACHE_H
|
||||||
|
|
||||||
|
#include "id3.h"
|
||||||
|
|
||||||
|
enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
|
||||||
|
tag_filename/*, tag_checksum*/ };
|
||||||
|
#define TAG_COUNT 5
|
||||||
|
|
||||||
|
#ifdef HAVE_DIRCACHE
|
||||||
|
#define HAVE_TC_RAMCACHE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Allow a little drift to the filename ordering. */
|
||||||
|
#define POS_HISTORY_COUNT 4
|
||||||
|
|
||||||
|
/* How many entries we can create in one tag file (for sorting). */
|
||||||
|
#define TAGFILE_MAX_ENTRIES 20000
|
||||||
|
|
||||||
|
#define SEEK_LIST_SIZE 50
|
||||||
|
#define TAGCACHE_MAX_FILTERS 3
|
||||||
|
|
||||||
|
struct tagcache_search {
|
||||||
|
/* For internal use only. */
|
||||||
|
int fd;
|
||||||
|
long seek_list[SEEK_LIST_SIZE];
|
||||||
|
long filter_tag[TAGCACHE_MAX_FILTERS];
|
||||||
|
long filter_seek[TAGCACHE_MAX_FILTERS];
|
||||||
|
int filter_count;
|
||||||
|
int seek_list_count;
|
||||||
|
int seek_pos;
|
||||||
|
long position;
|
||||||
|
int entry_count;
|
||||||
|
bool valid;
|
||||||
|
|
||||||
|
/* Exported variables. */
|
||||||
|
bool ramsearch;
|
||||||
|
int type;
|
||||||
|
char *result;
|
||||||
|
int result_len;
|
||||||
|
long result_seek;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool tagcache_fill_tags(struct mp3entry *id3, const char *filename);
|
||||||
|
bool tagcache_search(struct tagcache_search *tcs, int tag);
|
||||||
|
bool tagcache_search_add_filter(struct tagcache_search *tcs,
|
||||||
|
int tag, int seek);
|
||||||
|
bool tagcache_get_next(struct tagcache_search *tcs);
|
||||||
|
void tagcache_search_finish(struct tagcache_search *tcs);
|
||||||
|
|
||||||
|
int tagcache_get_progress(void);
|
||||||
|
#ifdef HAVE_TC_RAMCACHE
|
||||||
|
bool tagcache_is_ramcache(void);
|
||||||
|
#endif
|
||||||
|
void tagcache_init(void);
|
||||||
|
void tagcache_start_scan(void);
|
||||||
|
void tagcache_stop_scan(void);
|
||||||
|
bool tagcache_force_update(void);
|
||||||
|
|
||||||
|
#endif
|
536
apps/tagtree.c
Normal file
536
apps/tagtree.c
Normal file
|
@ -0,0 +1,536 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 by Miika Pekkarinen
|
||||||
|
*
|
||||||
|
* All files in this archive are subject to the GNU General Public License.
|
||||||
|
* See the file COPYING in the source tree root for full license agreement.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic structure on this file was copied from dbtree.c and modified to
|
||||||
|
* support the tag cache interface.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "system.h"
|
||||||
|
#include "kernel.h"
|
||||||
|
#include "splash.h"
|
||||||
|
#include "icons.h"
|
||||||
|
#include "tree.h"
|
||||||
|
#include "settings.h"
|
||||||
|
#include "tagcache.h"
|
||||||
|
#include "tagtree.h"
|
||||||
|
#include "lang.h"
|
||||||
|
#include "logf.h"
|
||||||
|
#include "playlist.h"
|
||||||
|
#include "keyboard.h"
|
||||||
|
#include "gui/list.h"
|
||||||
|
|
||||||
|
#define CHUNKED_NEXT -2
|
||||||
|
|
||||||
|
static int tagtree_play_folder(struct tree_context* c);
|
||||||
|
static int tagtree_search(struct tree_context* c, char* string);
|
||||||
|
|
||||||
|
static char searchstring[32];
|
||||||
|
struct tagentry {
|
||||||
|
char *name;
|
||||||
|
int newtable;
|
||||||
|
int extraseek;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct tagcache_search tcs;
|
||||||
|
|
||||||
|
int tagtree_load(struct tree_context* c)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int namebufused = 0;
|
||||||
|
struct tagentry *dptr = (struct tagentry *)c->dircache;
|
||||||
|
|
||||||
|
int table = c->currtable;
|
||||||
|
int extra = c->currextra;
|
||||||
|
int extra2 = c->currextra2;
|
||||||
|
|
||||||
|
c->dentry_size = sizeof(struct tagentry);
|
||||||
|
|
||||||
|
if (!table)
|
||||||
|
{
|
||||||
|
c->dirfull = false;
|
||||||
|
table = root;
|
||||||
|
c->currtable = table;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->dirfull)
|
||||||
|
table = chunked_next;
|
||||||
|
|
||||||
|
switch (table) {
|
||||||
|
case root: {
|
||||||
|
static const int tables[] = {allartists, allalbums, allgenres, allsongs,
|
||||||
|
search };
|
||||||
|
unsigned char* labels[] = { str(LANG_ID3DB_ARTISTS),
|
||||||
|
str(LANG_ID3DB_ALBUMS),
|
||||||
|
str(LANG_ID3DB_GENRES),
|
||||||
|
str(LANG_ID3DB_SONGS),
|
||||||
|
str(LANG_ID3DB_SEARCH)};
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++) {
|
||||||
|
dptr->name = &c->name_buffer[namebufused];
|
||||||
|
dptr->newtable = tables[i];
|
||||||
|
strcpy(dptr->name, (char *)labels[i]);
|
||||||
|
namebufused += strlen(dptr->name) + 1;
|
||||||
|
dptr++;
|
||||||
|
}
|
||||||
|
c->dirlength = c->filesindir = i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
case search: {
|
||||||
|
static const int tables[] = {searchartists,
|
||||||
|
searchalbums,
|
||||||
|
searchsongs};
|
||||||
|
unsigned char* labels[] = { str(LANG_ID3DB_SEARCH_ARTISTS),
|
||||||
|
str(LANG_ID3DB_SEARCH_ALBUMS),
|
||||||
|
str(LANG_ID3DB_SEARCH_SONGS)};
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
dptr->name = &c->name_buffer[namebufused];
|
||||||
|
dptr->newtable = tables[i];
|
||||||
|
strcpy(dptr->name, (char *)labels[i]);
|
||||||
|
namebufused += strlen(dptr->name) + 1;
|
||||||
|
dptr++;
|
||||||
|
}
|
||||||
|
c->dirlength = c->filesindir = i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
case searchartists:
|
||||||
|
case searchalbums:
|
||||||
|
case searchsongs:
|
||||||
|
i = tagtree_search(c, searchstring);
|
||||||
|
c->dirlength = c->filesindir = i;
|
||||||
|
if (c->dirfull) {
|
||||||
|
gui_syncsplash(HZ, true, (unsigned char *)"%s %s",
|
||||||
|
str(LANG_SHOWDIR_ERROR_BUFFER),
|
||||||
|
str(LANG_SHOWDIR_ERROR_FULL));
|
||||||
|
c->dirfull = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gui_syncsplash(HZ, true, str(LANG_ID3DB_MATCHES), i);
|
||||||
|
return i;
|
||||||
|
|
||||||
|
case allsongs:
|
||||||
|
logf("songs..");
|
||||||
|
tagcache_search(&tcs, tag_title);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case allgenres:
|
||||||
|
logf("genres..");
|
||||||
|
tagcache_search(&tcs, tag_genre);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case allalbums:
|
||||||
|
logf("albums..");
|
||||||
|
tagcache_search(&tcs, tag_album);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case allartists:
|
||||||
|
logf("artists..");
|
||||||
|
tagcache_search(&tcs, tag_artist);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case artist4genres:
|
||||||
|
logf("artist4genres..");
|
||||||
|
tagcache_search(&tcs, tag_artist);
|
||||||
|
tagcache_search_add_filter(&tcs, tag_genre, extra);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case albums4artist:
|
||||||
|
logf("albums4artist..");
|
||||||
|
tagcache_search(&tcs, tag_album);
|
||||||
|
tagcache_search_add_filter(&tcs, tag_artist, extra);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case songs4album:
|
||||||
|
logf("songs4album..");
|
||||||
|
tagcache_search(&tcs, tag_title);
|
||||||
|
tagcache_search_add_filter(&tcs, tag_album, extra);
|
||||||
|
if (extra2 > 0)
|
||||||
|
tagcache_search_add_filter(&tcs, tag_artist, extra2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case songs4artist:
|
||||||
|
logf("songs4artist..");
|
||||||
|
tagcache_search(&tcs, tag_title);
|
||||||
|
tagcache_search_add_filter(&tcs, tag_artist, extra);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case chunked_next:
|
||||||
|
logf("chunked next...");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
logf("Unsupported table %d\n", table);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
namebufused = 0;
|
||||||
|
c->dirfull = false;
|
||||||
|
while (tagcache_get_next(&tcs))
|
||||||
|
{
|
||||||
|
dptr->newtable = tcs.result_seek;
|
||||||
|
if (!tcs.ramsearch)
|
||||||
|
{
|
||||||
|
dptr->name = &c->name_buffer[namebufused];
|
||||||
|
namebufused += tcs.result_len;
|
||||||
|
if (namebufused > c->name_buffer_size)
|
||||||
|
{
|
||||||
|
logf("buffer full, 1 entry missed.");
|
||||||
|
c->dirfull = true;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
strcpy(dptr->name, tcs.result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dptr->name = tcs.result;
|
||||||
|
dptr++;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Estimate when we are running out of space so we can stop
|
||||||
|
* and enabled chunked browsing without missing entries.
|
||||||
|
*/
|
||||||
|
if (i >= global_settings.max_files_in_dir - 1
|
||||||
|
|| namebufused + 200 > c->name_buffer_size)
|
||||||
|
{
|
||||||
|
c->dirfull = true;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->dirfull)
|
||||||
|
{
|
||||||
|
dptr->name = "===>";
|
||||||
|
dptr->newtable = chunked_next;
|
||||||
|
dptr++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tagcache_search_finish(&tcs);
|
||||||
|
|
||||||
|
c->dirlength = c->filesindir = i;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tagtree_search(struct tree_context* c, char* string)
|
||||||
|
{
|
||||||
|
struct tagentry *dptr = (struct tagentry *)c->dircache;
|
||||||
|
int hits = 0;
|
||||||
|
int namebufused = 0;
|
||||||
|
|
||||||
|
switch (c->currtable) {
|
||||||
|
case searchartists:
|
||||||
|
tagcache_search(&tcs, tag_artist);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case searchalbums:
|
||||||
|
tagcache_search(&tcs, tag_album);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case searchsongs:
|
||||||
|
tagcache_search(&tcs, tag_title);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
logf("Invalid table %d\n", c->currtable);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (tagcache_get_next(&tcs))
|
||||||
|
{
|
||||||
|
if (!strcasestr(tcs.result, string))
|
||||||
|
continue ;
|
||||||
|
|
||||||
|
if (!tcs.ramsearch)
|
||||||
|
{
|
||||||
|
dptr->name = &c->name_buffer[namebufused];
|
||||||
|
namebufused += tcs.result_len;
|
||||||
|
strcpy(dptr->name, tcs.result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dptr->name = tcs.result;
|
||||||
|
|
||||||
|
dptr->newtable = tcs.result_seek;
|
||||||
|
dptr++;
|
||||||
|
hits++;
|
||||||
|
}
|
||||||
|
|
||||||
|
tagcache_search_finish(&tcs);
|
||||||
|
|
||||||
|
return hits;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tagtree_enter(struct tree_context* c)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
struct tagentry *dptr = (struct tagentry *)c->dircache;
|
||||||
|
int newextra;
|
||||||
|
|
||||||
|
dptr += c->selected_item;
|
||||||
|
|
||||||
|
if (dptr->newtable == chunked_next)
|
||||||
|
{
|
||||||
|
c->selected_item=0;
|
||||||
|
gui_synclist_select_item(&tree_lists, c->selected_item);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->dirfull = false;
|
||||||
|
newextra = dptr->newtable;
|
||||||
|
|
||||||
|
if (c->dirlevel >= MAX_DIR_LEVELS)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
c->selected_item_history[c->dirlevel]=c->selected_item;
|
||||||
|
c->table_history[c->dirlevel] = c->currtable;
|
||||||
|
c->extra_history[c->dirlevel] = c->currextra;
|
||||||
|
c->pos_history[c->dirlevel] = c->firstpos;
|
||||||
|
c->dirlevel++;
|
||||||
|
|
||||||
|
switch (c->currtable) {
|
||||||
|
case root:
|
||||||
|
c->currtable = newextra;
|
||||||
|
c->currextra = newextra;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case allartists:
|
||||||
|
case searchartists:
|
||||||
|
c->currtable = albums4artist;
|
||||||
|
c->currextra = newextra;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case allgenres:
|
||||||
|
c->currtable = artist4genres;
|
||||||
|
c->currextra = newextra;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case artist4genres:
|
||||||
|
c->currtable = albums4artist;
|
||||||
|
c->currextra = newextra;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case allalbums:
|
||||||
|
c->currtable = songs4album;
|
||||||
|
c->currextra = newextra;
|
||||||
|
c->currextra2 = -1;
|
||||||
|
break;
|
||||||
|
case albums4artist:
|
||||||
|
case searchalbums:
|
||||||
|
c->currtable = songs4album;
|
||||||
|
c->currextra2 = c->currextra;
|
||||||
|
c->currextra = newextra;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case allsongs:
|
||||||
|
case songs4album:
|
||||||
|
case songs4artist:
|
||||||
|
case searchsongs:
|
||||||
|
c->dirlevel--;
|
||||||
|
if (tagtree_play_folder(c) >= 0)
|
||||||
|
rc = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case search:
|
||||||
|
rc = kbd_input(searchstring, sizeof(searchstring));
|
||||||
|
if (rc == -1 || !searchstring[0])
|
||||||
|
c->dirlevel--;
|
||||||
|
else
|
||||||
|
c->currtable = newextra;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
c->dirlevel--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c->selected_item=0;
|
||||||
|
gui_synclist_select_item(&tree_lists, c->selected_item);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tagtree_exit(struct tree_context* c)
|
||||||
|
{
|
||||||
|
c->dirfull = false;
|
||||||
|
c->dirlevel--;
|
||||||
|
c->selected_item=c->selected_item_history[c->dirlevel];
|
||||||
|
gui_synclist_select_item(&tree_lists, c->selected_item);
|
||||||
|
c->currtable = c->table_history[c->dirlevel];
|
||||||
|
c->currextra = c->extra_history[c->dirlevel];
|
||||||
|
c->firstpos = c->pos_history[c->dirlevel];
|
||||||
|
|
||||||
|
/* Just to be sure when chunked browsing is used. */
|
||||||
|
tagcache_search_finish(&tcs);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tagtree_get_filename(struct tree_context* c, char *buf, int buflen)
|
||||||
|
{
|
||||||
|
struct tagentry *entry = (struct tagentry *)c->dircache;
|
||||||
|
|
||||||
|
entry += c->selected_item;
|
||||||
|
|
||||||
|
tagcache_search(&tcs, tag_filename);
|
||||||
|
tagcache_search_add_filter(&tcs, tag_title, entry->newtable);
|
||||||
|
|
||||||
|
if (!tagcache_get_next(&tcs))
|
||||||
|
{
|
||||||
|
tagcache_search_finish(&tcs);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(buf, tcs.result, buflen-1);
|
||||||
|
tagcache_search_finish(&tcs);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
bool tagtree_rename_tag(struct tree_context *c, const char *newtext)
|
||||||
|
{
|
||||||
|
struct tagentry *dptr = (struct tagentry *)c->dircache;
|
||||||
|
int extra, extra2;
|
||||||
|
int type;
|
||||||
|
|
||||||
|
dptr += c->selected_item;
|
||||||
|
extra = dptr->newtable;
|
||||||
|
extra2 = dptr->extraseek;
|
||||||
|
|
||||||
|
switch (c->currtable) {
|
||||||
|
case allgenres:
|
||||||
|
tagcache_search(&tcs, tag_title);
|
||||||
|
tagcache_search_add_filter(&tcs, tag_genre, extra);
|
||||||
|
type = tag_genre;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case allalbums:
|
||||||
|
tagcache_search(&tcs, tag_title);
|
||||||
|
tagcache_search_add_filter(&tcs, tag_album, extra);
|
||||||
|
type = tag_album;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case allartists:
|
||||||
|
tagcache_search(&tcs, tag_title);
|
||||||
|
tagcache_search_add_filter(&tcs, tag_artist, extra);
|
||||||
|
type = tag_artist;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case artist4genres:
|
||||||
|
tagcache_search(&tcs, tag_title);
|
||||||
|
tagcache_search_add_filter(&tcs, tag_genre, extra);
|
||||||
|
type = tag_artist;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case albums4artist:
|
||||||
|
tagcache_search(&tcs, tag_title);
|
||||||
|
tagcache_search_add_filter(&tcs, tag_album, extra);
|
||||||
|
tagcache_search_add_filter(&tcs, tag_artist, extra2);
|
||||||
|
type = tag_album;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
logf("wrong table");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (tagcache_get_next(&tcs))
|
||||||
|
{
|
||||||
|
// tagcache_modify(&tcs, type, newtext);
|
||||||
|
}
|
||||||
|
|
||||||
|
tagcache_search_finish(&tcs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int tagtree_play_folder(struct tree_context* c)
|
||||||
|
{
|
||||||
|
struct tagentry *entry = (struct tagentry *)c->dircache;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (playlist_create(NULL, NULL) < 0) {
|
||||||
|
logf("Failed creating playlist\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||||
|
cpu_boost(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i=0; i < c->filesindir; i++) {
|
||||||
|
tagcache_search(&tcs, tag_filename);
|
||||||
|
tagcache_search_add_filter(&tcs, tag_title, entry[i].newtable);
|
||||||
|
|
||||||
|
if (!tagcache_get_next(&tcs))
|
||||||
|
{
|
||||||
|
tagcache_search_finish(&tcs);
|
||||||
|
continue ;
|
||||||
|
}
|
||||||
|
playlist_insert_track(NULL, tcs.result, PLAYLIST_INSERT, false);
|
||||||
|
tagcache_search_finish(&tcs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||||
|
cpu_boost(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (global_settings.playlist_shuffle)
|
||||||
|
c->selected_item = playlist_shuffle(current_tick, c->selected_item);
|
||||||
|
if (!global_settings.play_selected)
|
||||||
|
c->selected_item = 0;
|
||||||
|
gui_synclist_select_item(&tree_lists, c->selected_item);
|
||||||
|
|
||||||
|
playlist_start(c->selected_item,0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LCD_BITMAP
|
||||||
|
const char* tagtree_get_icon(struct tree_context* c)
|
||||||
|
#else
|
||||||
|
int tagtree_get_icon(struct tree_context* c)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
int icon;
|
||||||
|
|
||||||
|
switch (c->currtable)
|
||||||
|
{
|
||||||
|
case allsongs:
|
||||||
|
case songs4album:
|
||||||
|
case songs4artist:
|
||||||
|
case searchsongs:
|
||||||
|
icon = Icon_Audio;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
icon = Icon_Folder;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LCD_BITMAP
|
||||||
|
return (char *)bitmap_icons_6x8[icon];
|
||||||
|
#else
|
||||||
|
return icon;
|
||||||
|
#endif
|
||||||
|
}
|
41
apps/tagtree.h
Normal file
41
apps/tagtree.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 by Miika Pekkarinen
|
||||||
|
*
|
||||||
|
* All files in this archive are subject to the GNU General Public License.
|
||||||
|
* See the file COPYING in the source tree root for full license agreement.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef _TAGTREE_H
|
||||||
|
#define _TAGTREE_H
|
||||||
|
|
||||||
|
#include "tagcache.h"
|
||||||
|
#include "tree.h"
|
||||||
|
|
||||||
|
enum table { invalid, root, allsongs, allalbums, allartists, allgenres,
|
||||||
|
albums4artist, songs4album, songs4artist, artist4genres,
|
||||||
|
search, searchartists, searchalbums, searchsongs,
|
||||||
|
chunked_next };
|
||||||
|
|
||||||
|
int tagtree_enter(struct tree_context* c);
|
||||||
|
void tagtree_exit(struct tree_context* c);
|
||||||
|
int tagtree_load(struct tree_context* c);
|
||||||
|
#ifdef HAVE_LCD_BITMAP
|
||||||
|
const char* tagtree_get_icon(struct tree_context* c);
|
||||||
|
#else
|
||||||
|
int tagtree_get_icon(struct tree_context* c);
|
||||||
|
#endif
|
||||||
|
int tagtree_get_filename(struct tree_context* c, char *buf, int buflen);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
31
apps/tree.c
31
apps/tree.c
|
@ -57,10 +57,11 @@
|
||||||
#include "filetypes.h"
|
#include "filetypes.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "filetree.h"
|
#include "filetree.h"
|
||||||
#include "dbtree.h"
|
#include "tagtree.h"
|
||||||
#include "recorder/recording.h"
|
#include "recorder/recording.h"
|
||||||
#include "rtc.h"
|
#include "rtc.h"
|
||||||
#include "dircache.h"
|
#include "dircache.h"
|
||||||
|
#include "tagcache.h"
|
||||||
#include "yesno.h"
|
#include "yesno.h"
|
||||||
|
|
||||||
/* gui api */
|
/* gui api */
|
||||||
|
@ -164,7 +165,8 @@ char * tree_get_filename(int selected_item, void * data, char *buffer)
|
||||||
bool id3db = *(local_tc->dirfilter) == SHOW_ID3DB;
|
bool id3db = *(local_tc->dirfilter) == SHOW_ID3DB;
|
||||||
|
|
||||||
if (id3db) {
|
if (id3db) {
|
||||||
name = ((char**)local_tc->dircache)[selected_item * local_tc->dentry_size];
|
char **buf = local_tc->dircache;
|
||||||
|
name = buf[selected_item * (local_tc->dentry_size/sizeof(int))];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
struct entry* dc = local_tc->dircache;
|
struct entry* dc = local_tc->dircache;
|
||||||
|
@ -189,7 +191,7 @@ void tree_get_fileicon(int selected_item, void * data, ICON * icon)
|
||||||
struct tree_context * local_tc=(struct tree_context *)data;
|
struct tree_context * local_tc=(struct tree_context *)data;
|
||||||
bool id3db = *(local_tc->dirfilter) == SHOW_ID3DB;
|
bool id3db = *(local_tc->dirfilter) == SHOW_ID3DB;
|
||||||
if (id3db) {
|
if (id3db) {
|
||||||
*icon = (ICON)db_get_icon(&tc);
|
*icon = (ICON)tagtree_get_icon(&tc);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
struct entry* dc = local_tc->dircache;
|
struct entry* dc = local_tc->dircache;
|
||||||
|
@ -267,6 +269,7 @@ struct tree_context* tree_get_context(void)
|
||||||
int tree_get_file_position(char * filename)
|
int tree_get_file_position(char * filename)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* use lastfile to determine the selected item (default=0) */
|
/* use lastfile to determine the selected item (default=0) */
|
||||||
for (i=0; i < tc.filesindir; i++)
|
for (i=0; i < tc.filesindir; i++)
|
||||||
{
|
{
|
||||||
|
@ -292,7 +295,7 @@ static int update_dir(void)
|
||||||
tc.currextra != lastextra ||
|
tc.currextra != lastextra ||
|
||||||
tc.firstpos != lastfirstpos)
|
tc.firstpos != lastfirstpos)
|
||||||
{
|
{
|
||||||
if (db_load(&tc) < 0)
|
if (tagtree_load(&tc) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
lasttable = tc.currtable;
|
lasttable = tc.currtable;
|
||||||
|
@ -494,7 +497,7 @@ static bool check_changed_id3mode(bool currmode)
|
||||||
currmode = global_settings.dirfilter == SHOW_ID3DB;
|
currmode = global_settings.dirfilter == SHOW_ID3DB;
|
||||||
if (currmode) {
|
if (currmode) {
|
||||||
curr_context=CONTEXT_ID3DB;
|
curr_context=CONTEXT_ID3DB;
|
||||||
db_load(&tc);
|
tagtree_load(&tc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -600,7 +603,7 @@ static bool dirbrowse(void)
|
||||||
if ( numentries == 0 )
|
if ( numentries == 0 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
switch (id3db?db_enter(&tc):ft_enter(&tc))
|
switch (id3db?tagtree_enter(&tc):ft_enter(&tc))
|
||||||
{
|
{
|
||||||
case 1: reload_dir = true; break;
|
case 1: reload_dir = true; break;
|
||||||
case 2: start_wps = true; break;
|
case 2: start_wps = true; break;
|
||||||
|
@ -624,7 +627,7 @@ static bool dirbrowse(void)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (id3db)
|
if (id3db)
|
||||||
db_exit(&tc);
|
tagtree_exit(&tc);
|
||||||
else
|
else
|
||||||
if (ft_exit(&tc) == 3)
|
if (ft_exit(&tc) == 3)
|
||||||
exit_func = true;
|
exit_func = true;
|
||||||
|
@ -732,6 +735,7 @@ static bool dirbrowse(void)
|
||||||
restore = true;
|
restore = true;
|
||||||
|
|
||||||
id3db = check_changed_id3mode(id3db);
|
id3db = check_changed_id3mode(id3db);
|
||||||
|
reload_dir = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -772,7 +776,7 @@ static bool dirbrowse(void)
|
||||||
case songs4artist:
|
case songs4artist:
|
||||||
case searchsongs:
|
case searchsongs:
|
||||||
attr=TREE_ATTR_MPA;
|
attr=TREE_ATTR_MPA;
|
||||||
db_get_filename(&tc, buf, sizeof(buf));
|
tagtree_get_filename(&tc, buf, sizeof(buf));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -906,6 +910,7 @@ static bool dirbrowse(void)
|
||||||
lastextra = -1;
|
lastextra = -1;
|
||||||
reload_root = false;
|
reload_root = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! reload_dir )
|
if (! reload_dir )
|
||||||
{
|
{
|
||||||
gui_synclist_select_item(&tree_lists, 0);
|
gui_synclist_select_item(&tree_lists, 0);
|
||||||
|
@ -935,6 +940,7 @@ static bool dirbrowse(void)
|
||||||
need_update = true;
|
need_update = true;
|
||||||
reload_dir = false;
|
reload_dir = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(need_update) {
|
if(need_update) {
|
||||||
tc.selected_item = gui_synclist_get_sel_pos(&tree_lists);
|
tc.selected_item = gui_synclist_get_sel_pos(&tree_lists);
|
||||||
need_update=false;
|
need_update=false;
|
||||||
|
@ -1177,8 +1183,6 @@ void tree_init(void)
|
||||||
memset(&tc, 0, sizeof(tc));
|
memset(&tc, 0, sizeof(tc));
|
||||||
tc.dirfilter = &global_settings.dirfilter;
|
tc.dirfilter = &global_settings.dirfilter;
|
||||||
|
|
||||||
tagdb_init();
|
|
||||||
|
|
||||||
tc.name_buffer_size = AVERAGE_FILENAME_LENGTH * max_files;
|
tc.name_buffer_size = AVERAGE_FILENAME_LENGTH * max_files;
|
||||||
tc.name_buffer = buffer_alloc(tc.name_buffer_size);
|
tc.name_buffer = buffer_alloc(tc.name_buffer_size);
|
||||||
|
|
||||||
|
@ -1331,9 +1335,9 @@ void ft_play_filename(char *dir, char *file)
|
||||||
/* These two functions are called by the USB and shutdown handlers */
|
/* These two functions are called by the USB and shutdown handlers */
|
||||||
void tree_flush(void)
|
void tree_flush(void)
|
||||||
{
|
{
|
||||||
rundb_shutdown();
|
tagcache_stop_scan();
|
||||||
tagdb_shutdown();
|
|
||||||
playlist_shutdown();
|
playlist_shutdown();
|
||||||
|
|
||||||
#ifdef HAVE_DIRCACHE
|
#ifdef HAVE_DIRCACHE
|
||||||
if (global_settings.dircache)
|
if (global_settings.dircache)
|
||||||
{
|
{
|
||||||
|
@ -1351,8 +1355,6 @@ void tree_flush(void)
|
||||||
|
|
||||||
void tree_restore(void)
|
void tree_restore(void)
|
||||||
{
|
{
|
||||||
tagdb_init();
|
|
||||||
rundb_init();
|
|
||||||
#ifdef HAVE_DIRCACHE
|
#ifdef HAVE_DIRCACHE
|
||||||
if (global_settings.dircache)
|
if (global_settings.dircache)
|
||||||
{
|
{
|
||||||
|
@ -1376,5 +1378,6 @@ void tree_restore(void)
|
||||||
gui_textarea_clear(&screens[i]);
|
gui_textarea_clear(&screens[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tagcache_start_scan();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,6 +213,7 @@ struct tree_context {
|
||||||
int extra_history[MAX_DIR_LEVELS]; /* db use */
|
int extra_history[MAX_DIR_LEVELS]; /* db use */
|
||||||
int currtable; /* db use */
|
int currtable; /* db use */
|
||||||
int currextra; /* db use */
|
int currextra; /* db use */
|
||||||
|
int currextra2; /* db use */
|
||||||
/* A big buffer with plenty of entry structs,
|
/* A big buffer with plenty of entry structs,
|
||||||
* contains all files and dirs in the current
|
* contains all files and dirs in the current
|
||||||
* dir (with filters applied) */
|
* dir (with filters applied) */
|
||||||
|
|
|
@ -84,8 +84,8 @@ static struct dircache_entry* allocate_entry(void)
|
||||||
/* Make sure the entry is long aligned. */
|
/* Make sure the entry is long aligned. */
|
||||||
if ((long)next_entry & 0x03)
|
if ((long)next_entry & 0x03)
|
||||||
{
|
{
|
||||||
next_entry = (struct dircache_entry *)(((long)next_entry & ~0x03) + 0x04);
|
|
||||||
dircache_size += 4 - ((long)next_entry & 0x03);
|
dircache_size += 4 - ((long)next_entry & 0x03);
|
||||||
|
next_entry = (struct dircache_entry *)(((long)next_entry & ~0x03) + 0x04);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
next_entry->name_len = 0;
|
next_entry->name_len = 0;
|
||||||
|
@ -95,7 +95,6 @@ static struct dircache_entry* allocate_entry(void)
|
||||||
next_entry->next = NULL;
|
next_entry->next = NULL;
|
||||||
|
|
||||||
dircache_size += sizeof(struct dircache_entry);
|
dircache_size += sizeof(struct dircache_entry);
|
||||||
entry_count++;
|
|
||||||
|
|
||||||
return next_entry;
|
return next_entry;
|
||||||
}
|
}
|
||||||
|
@ -186,6 +185,7 @@ static int dircache_scan(struct travel_data *td)
|
||||||
td->ce->wrttime = td->entry.wrttime;
|
td->ce->wrttime = td->entry.wrttime;
|
||||||
memcpy(td->ce->d_name, td->entry.name, td->ce->name_len);
|
memcpy(td->ce->d_name, td->entry.name, td->ce->name_len);
|
||||||
dircache_size += td->ce->name_len;
|
dircache_size += td->ce->name_len;
|
||||||
|
entry_count++;
|
||||||
|
|
||||||
if (td->entry.attr & FAT_ATTR_DIRECTORY)
|
if (td->entry.attr & FAT_ATTR_DIRECTORY)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue