2005-01-17 11:39:46 +00:00
|
|
|
|
/***************************************************************************
|
|
|
|
|
* __________ __ ___.
|
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
|
* \/ \/ \/ \/ \/
|
|
|
|
|
* $Id$
|
|
|
|
|
*
|
2005-01-17 16:06:07 +00:00
|
|
|
|
* Copyright (C) 2005 by Bj<EFBFBD>rn Stenberg
|
2005-01-17 11:39:46 +00:00
|
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
****************************************************************************/
|
2005-01-27 22:21:08 +00:00
|
|
|
|
#define _GNU_SOURCE
|
2005-01-17 11:39:46 +00:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include "file.h"
|
|
|
|
|
#include "screens.h"
|
|
|
|
|
#include "kernel.h"
|
|
|
|
|
#include "tree.h"
|
|
|
|
|
#include "lcd.h"
|
|
|
|
|
#include "font.h"
|
|
|
|
|
#include "settings.h"
|
|
|
|
|
#include "icons.h"
|
|
|
|
|
#include "status.h"
|
|
|
|
|
#include "debug.h"
|
|
|
|
|
#include "button.h"
|
|
|
|
|
#include "menu.h"
|
|
|
|
|
#include "main_menu.h"
|
|
|
|
|
#include "mpeg.h"
|
|
|
|
|
#include "misc.h"
|
|
|
|
|
#include "ata.h"
|
|
|
|
|
#include "wps.h"
|
|
|
|
|
#include "filetypes.h"
|
|
|
|
|
#include "applimits.h"
|
|
|
|
|
#include "dbtree.h"
|
|
|
|
|
#include "icons.h"
|
2005-01-19 15:01:31 +00:00
|
|
|
|
#include "lang.h"
|
2005-01-27 22:21:08 +00:00
|
|
|
|
#include "keyboard.h"
|
2005-01-17 11:39:46 +00:00
|
|
|
|
|
2005-01-29 06:43:44 +00:00
|
|
|
|
/* workaround for cygwin not defining endian macros */
|
|
|
|
|
#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) && defined(_X86_)
|
|
|
|
|
#define LITTLE_ENDIAN
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef LITTLE_ENDIAN
|
2005-01-28 23:04:19 +00:00
|
|
|
|
#define BE32(_x_) (((_x_ & 0xff000000) >> 24) | \
|
|
|
|
|
((_x_ & 0x00ff0000) >> 8) | \
|
|
|
|
|
((_x_ & 0x0000ff00) << 8) | \
|
|
|
|
|
((_x_ & 0x000000ff) << 24))
|
2005-01-17 11:39:46 +00:00
|
|
|
|
#else
|
|
|
|
|
#define BE32(_x_) _x_
|
|
|
|
|
#endif
|
|
|
|
|
|
2005-04-25 18:19:59 +00:00
|
|
|
|
#define SONGENTRY_SIZE (songlen+12+genrelen+4)
|
|
|
|
|
#define FILEENTRY_SIZE (filelen+12)
|
|
|
|
|
#define ALBUMENTRY_SIZE (albumlen+4+songarraylen*4)
|
|
|
|
|
#define ARTISTENTRY_SIZE (artistlen+albumarraylen*4)
|
|
|
|
|
|
|
|
|
|
#define ID3DB_VERSION 2
|
2005-01-17 15:34:43 +00:00
|
|
|
|
|
2005-04-26 19:23:47 +00:00
|
|
|
|
static int fd = -1;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
|
|
|
|
|
static int
|
2005-04-25 18:19:59 +00:00
|
|
|
|
songstart, albumstart, artiststart, filestart,
|
|
|
|
|
songcount, albumcount, artistcount, filecount,
|
|
|
|
|
songlen, songarraylen, genrelen, filelen,
|
2005-01-17 11:39:46 +00:00
|
|
|
|
albumlen, albumarraylen,
|
2005-04-26 19:23:47 +00:00
|
|
|
|
artistlen, rundbdirty, initialized = 0;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
|
2005-01-20 16:24:26 +00:00
|
|
|
|
static int db_play_folder(struct tree_context* c);
|
2005-01-27 22:21:08 +00:00
|
|
|
|
static int db_search(struct tree_context* c, char* string);
|
|
|
|
|
|
|
|
|
|
static char searchstring[32];
|
2005-01-20 16:24:26 +00:00
|
|
|
|
|
2005-01-17 11:39:46 +00:00
|
|
|
|
int db_init(void)
|
|
|
|
|
{
|
|
|
|
|
unsigned int version;
|
2005-04-25 18:19:59 +00:00
|
|
|
|
unsigned int buf[17];
|
2005-01-17 15:34:43 +00:00
|
|
|
|
unsigned char* ptr = (char*)buf;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
|
|
|
|
|
fd = open(ROCKBOX_DIR "/rockbox.id3db", O_RDONLY);
|
|
|
|
|
if (fd < 0) {
|
|
|
|
|
DEBUGF("Failed opening database\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2005-04-25 18:19:59 +00:00
|
|
|
|
read(fd, buf, 68);
|
2005-01-17 11:39:46 +00:00
|
|
|
|
|
2005-01-17 15:34:43 +00:00
|
|
|
|
if (ptr[0] != 'R' ||
|
|
|
|
|
ptr[1] != 'D' ||
|
|
|
|
|
ptr[2] != 'B')
|
|
|
|
|
{
|
2005-01-27 22:21:08 +00:00
|
|
|
|
splash(HZ,true,"Not a rockbox ID3 database!");
|
2005-01-17 15:34:43 +00:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2005-04-25 18:19:59 +00:00
|
|
|
|
version = BE32(buf[0])&0xFF;
|
2005-01-17 15:34:43 +00:00
|
|
|
|
if (version != ID3DB_VERSION)
|
|
|
|
|
{
|
2005-01-27 22:21:08 +00:00
|
|
|
|
splash(HZ,true,"Unsupported database version %d!", version);
|
2005-01-17 15:34:43 +00:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
2005-01-17 11:39:46 +00:00
|
|
|
|
|
2005-04-25 18:19:59 +00:00
|
|
|
|
artiststart = BE32(buf[1]);
|
|
|
|
|
albumstart = BE32(buf[2]);
|
|
|
|
|
songstart = BE32(buf[3]);
|
|
|
|
|
filestart = BE32(buf[4]);
|
|
|
|
|
|
|
|
|
|
artistcount = BE32(buf[5]);
|
|
|
|
|
albumcount = BE32(buf[6]);
|
|
|
|
|
songcount = BE32(buf[7]);
|
|
|
|
|
filecount = BE32(buf[8]);
|
|
|
|
|
|
|
|
|
|
artistlen = BE32(buf[9]);
|
|
|
|
|
albumlen = BE32(buf[10]);
|
|
|
|
|
songlen = BE32(buf[11]);
|
|
|
|
|
genrelen = BE32(buf[12]);
|
|
|
|
|
filelen = BE32(buf[13]);
|
|
|
|
|
songarraylen = BE32(buf[14]);
|
|
|
|
|
albumarraylen = BE32(buf[15]);
|
|
|
|
|
rundbdirty = BE32(buf[16]);
|
|
|
|
|
|
|
|
|
|
if (songstart > filestart ||
|
|
|
|
|
albumstart > songstart ||
|
|
|
|
|
artiststart > albumstart)
|
2005-01-17 15:34:43 +00:00
|
|
|
|
{
|
2005-01-27 22:21:08 +00:00
|
|
|
|
splash(HZ,true,"Corrupt ID3 database!");
|
2005-01-17 15:34:43 +00:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
initialized = 1;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2005-04-26 19:23:47 +00:00
|
|
|
|
void db_shutdown(void)
|
|
|
|
|
{
|
|
|
|
|
if (fd >= 0)
|
|
|
|
|
close(fd);
|
|
|
|
|
initialized = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-18 22:45:00 +00:00
|
|
|
|
int db_load(struct tree_context* c)
|
2005-01-17 11:39:46 +00:00
|
|
|
|
{
|
2005-01-18 22:45:00 +00:00
|
|
|
|
int i, offset, rc;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
int dcachesize = global_settings.max_files_in_dir * sizeof(struct entry);
|
2005-02-01 14:22:27 +00:00
|
|
|
|
int itemcount, stringlen, hits=0;
|
2005-02-12 12:29:41 +00:00
|
|
|
|
unsigned long* nptr = (void*) c->name_buffer;
|
|
|
|
|
unsigned long* dptr = c->dircache;
|
|
|
|
|
unsigned long* safeplace = NULL;
|
2005-01-18 22:45:00 +00:00
|
|
|
|
int safeplacelen = 0;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
|
|
|
|
|
int table = c->currtable;
|
|
|
|
|
int extra = c->currextra;
|
2005-01-17 15:34:43 +00:00
|
|
|
|
|
2005-01-18 22:45:00 +00:00
|
|
|
|
char* end_of_nbuf = c->name_buffer + c->name_buffer_size;
|
|
|
|
|
|
2005-01-17 15:34:43 +00:00
|
|
|
|
if (!initialized) {
|
|
|
|
|
DEBUGF("ID3 database is not initialized.\n");
|
2005-01-17 22:48:03 +00:00
|
|
|
|
c->filesindir = 0;
|
2005-01-17 15:34:43 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-20 16:24:26 +00:00
|
|
|
|
c->dentry_size = 2;
|
2005-01-18 22:45:00 +00:00
|
|
|
|
c->dirfull = false;
|
|
|
|
|
|
2005-04-25 18:19:59 +00:00
|
|
|
|
DEBUGF("db_load() table: %d extra: 0x%x firstpos: %d\n", table, extra, c->firstpos);
|
2005-01-17 11:39:46 +00:00
|
|
|
|
|
|
|
|
|
if (!table) {
|
2005-01-19 15:01:31 +00:00
|
|
|
|
table = root;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
c->currtable = table;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (table) {
|
2005-01-19 15:01:31 +00:00
|
|
|
|
case root: {
|
2005-01-27 22:21:08 +00:00
|
|
|
|
static const int tables[] = {allartists, allalbums, allsongs,
|
|
|
|
|
search };
|
2005-01-19 15:01:31 +00:00
|
|
|
|
char* nbuf = (char*)nptr;
|
2005-01-20 16:24:26 +00:00
|
|
|
|
char* labels[] = { str(LANG_ID3DB_ARTISTS),
|
|
|
|
|
str(LANG_ID3DB_ALBUMS),
|
2005-01-27 22:21:08 +00:00
|
|
|
|
str(LANG_ID3DB_SONGS),
|
|
|
|
|
str(LANG_ID3DB_SEARCH)};
|
2005-04-25 18:19:59 +00:00
|
|
|
|
DEBUGF("dbload table root\n");
|
2005-01-27 22:21:08 +00:00
|
|
|
|
for (i=0; i < 4; i++) {
|
|
|
|
|
strcpy(nbuf, labels[i]);
|
2005-02-12 12:29:41 +00:00
|
|
|
|
dptr[0] = (unsigned long)nbuf;
|
2005-01-27 22:21:08 +00:00
|
|
|
|
dptr[1] = tables[i];
|
|
|
|
|
nbuf += strlen(nbuf) + 1;
|
|
|
|
|
dptr += 2;
|
|
|
|
|
}
|
|
|
|
|
c->dirlength = c->filesindir = i;
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case search: {
|
|
|
|
|
static const int tables[] = {searchartists,
|
|
|
|
|
searchalbums,
|
|
|
|
|
searchsongs};
|
|
|
|
|
char* nbuf = (char*)nptr;
|
|
|
|
|
char* labels[] = { str(LANG_ID3DB_SEARCH_ARTISTS),
|
|
|
|
|
str(LANG_ID3DB_SEARCH_ALBUMS),
|
|
|
|
|
str(LANG_ID3DB_SEARCH_SONGS)};
|
2005-04-25 18:19:59 +00:00
|
|
|
|
DEBUGF("dbload table search\n");
|
2005-01-19 15:01:31 +00:00
|
|
|
|
for (i=0; i < 3; i++) {
|
|
|
|
|
strcpy(nbuf, labels[i]);
|
2005-02-12 12:29:41 +00:00
|
|
|
|
dptr[0] = (unsigned long)nbuf;
|
2005-01-19 15:01:31 +00:00
|
|
|
|
dptr[1] = tables[i];
|
|
|
|
|
nbuf += strlen(nbuf) + 1;
|
|
|
|
|
dptr += 2;
|
|
|
|
|
}
|
|
|
|
|
c->dirlength = c->filesindir = i;
|
|
|
|
|
return i;
|
|
|
|
|
}
|
2005-01-27 22:21:08 +00:00
|
|
|
|
|
|
|
|
|
case searchartists:
|
|
|
|
|
case searchalbums:
|
|
|
|
|
case searchsongs:
|
2005-04-25 18:19:59 +00:00
|
|
|
|
DEBUGF("dbload table searchsongs/searchartists/searchalbums\n");
|
2005-01-27 22:21:08 +00:00
|
|
|
|
i = db_search(c, searchstring);
|
|
|
|
|
c->dirlength = c->filesindir = i;
|
|
|
|
|
if (c->dirfull) {
|
|
|
|
|
splash(HZ, true, "%s %s",
|
|
|
|
|
str(LANG_SHOWDIR_ERROR_BUFFER),
|
|
|
|
|
str(LANG_SHOWDIR_ERROR_FULL));
|
|
|
|
|
c->dirfull = false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
splash(HZ, true, str(LANG_ID3DB_MATCHES), i);
|
|
|
|
|
return i;
|
|
|
|
|
|
2005-01-17 11:39:46 +00:00
|
|
|
|
case allsongs:
|
2005-04-25 18:19:59 +00:00
|
|
|
|
DEBUGF("dbload table allsongs\n");
|
|
|
|
|
offset = songstart + c->firstpos * SONGENTRY_SIZE;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
itemcount = songcount;
|
|
|
|
|
stringlen = songlen;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case allalbums:
|
2005-04-25 18:19:59 +00:00
|
|
|
|
DEBUGF("dbload table allalbums\n");
|
|
|
|
|
offset = albumstart + c->firstpos * ALBUMENTRY_SIZE;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
itemcount = albumcount;
|
|
|
|
|
stringlen = albumlen;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case allartists:
|
2005-04-25 18:19:59 +00:00
|
|
|
|
DEBUGF("dbload table allartists\n");
|
|
|
|
|
offset = artiststart + c->firstpos * ARTISTENTRY_SIZE;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
itemcount = artistcount;
|
|
|
|
|
stringlen = artistlen;
|
|
|
|
|
break;
|
|
|
|
|
|
2005-01-18 22:45:00 +00:00
|
|
|
|
case albums4artist:
|
2005-04-25 18:19:59 +00:00
|
|
|
|
DEBUGF("dbload table albums4artist\n");
|
2005-01-17 11:39:46 +00:00
|
|
|
|
/* 'extra' is offset to the artist */
|
2005-01-18 22:45:00 +00:00
|
|
|
|
safeplacelen = albumarraylen * 4;
|
|
|
|
|
safeplace = (void*)(end_of_nbuf - safeplacelen);
|
2005-01-17 11:39:46 +00:00
|
|
|
|
lseek(fd, extra + artistlen, SEEK_SET);
|
2005-01-18 22:45:00 +00:00
|
|
|
|
rc = read(fd, safeplace, safeplacelen);
|
|
|
|
|
if (rc < safeplacelen)
|
2005-01-17 11:39:46 +00:00
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
#ifdef LITTLE_ENDIAN
|
|
|
|
|
for (i=0; i<albumarraylen; i++)
|
|
|
|
|
safeplace[i] = BE32(safeplace[i]);
|
|
|
|
|
#endif
|
|
|
|
|
offset = safeplace[0];
|
|
|
|
|
itemcount = albumarraylen;
|
|
|
|
|
stringlen = albumlen;
|
|
|
|
|
break;
|
|
|
|
|
|
2005-01-18 22:45:00 +00:00
|
|
|
|
case songs4album:
|
2005-04-25 18:19:59 +00:00
|
|
|
|
DEBUGF("dbload table songs4album\n");
|
2005-01-17 11:39:46 +00:00
|
|
|
|
/* 'extra' is offset to the album */
|
2005-01-18 22:45:00 +00:00
|
|
|
|
safeplacelen = songarraylen * 4;
|
|
|
|
|
safeplace = (void*)(end_of_nbuf - safeplacelen);
|
2005-01-17 11:39:46 +00:00
|
|
|
|
lseek(fd, extra + albumlen + 4, SEEK_SET);
|
2005-01-18 22:45:00 +00:00
|
|
|
|
rc = read(fd, safeplace, safeplacelen);
|
|
|
|
|
if (rc < safeplacelen)
|
2005-01-17 11:39:46 +00:00
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
#ifdef LITTLE_ENDIAN
|
2005-04-25 18:19:59 +00:00
|
|
|
|
for (i=0; i<songarraylen; i++) {
|
2005-01-17 11:39:46 +00:00
|
|
|
|
safeplace[i] = BE32(safeplace[i]);
|
2005-04-25 18:19:59 +00:00
|
|
|
|
DEBUGF("db_load songs4album song %d: 0x%x\n",i,safeplace[i]);
|
|
|
|
|
}
|
2005-01-17 11:39:46 +00:00
|
|
|
|
#endif
|
|
|
|
|
offset = safeplace[0];
|
|
|
|
|
itemcount = songarraylen;
|
|
|
|
|
stringlen = songlen;
|
|
|
|
|
break;
|
|
|
|
|
|
2005-02-01 14:22:27 +00:00
|
|
|
|
case songs4artist:
|
2005-04-25 18:19:59 +00:00
|
|
|
|
DEBUGF("dbload table songs4artist\n");
|
2005-02-01 14:22:27 +00:00
|
|
|
|
/* 'extra' is offset to the artist, used as filter */
|
2005-04-25 18:19:59 +00:00
|
|
|
|
offset = songstart + c->firstpos * SONGENTRY_SIZE;
|
2005-02-01 14:22:27 +00:00
|
|
|
|
itemcount = songcount;
|
|
|
|
|
stringlen = songlen;
|
|
|
|
|
break;
|
|
|
|
|
|
2005-01-17 11:39:46 +00:00
|
|
|
|
default:
|
|
|
|
|
DEBUGF("Unsupported table %d\n", table);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2005-01-18 22:45:00 +00:00
|
|
|
|
end_of_nbuf -= safeplacelen;
|
|
|
|
|
|
|
|
|
|
c->dirlength = itemcount;
|
|
|
|
|
itemcount -= c->firstpos;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
|
2005-02-01 14:22:27 +00:00
|
|
|
|
if (!safeplace)
|
2005-01-17 11:39:46 +00:00
|
|
|
|
lseek(fd, offset, SEEK_SET);
|
|
|
|
|
|
|
|
|
|
/* name_buffer (nptr) contains only names, null terminated.
|
|
|
|
|
the first word of dcache (dptr) is a pointer to the name,
|
|
|
|
|
the rest is table specific. see below. */
|
|
|
|
|
|
2005-02-01 14:22:27 +00:00
|
|
|
|
for ( i=0; i < itemcount; i++ ) {
|
2005-01-17 11:39:46 +00:00
|
|
|
|
int rc, skip=0;
|
2005-01-20 16:24:26 +00:00
|
|
|
|
int intbuf[4];
|
2005-01-17 11:39:46 +00:00
|
|
|
|
|
|
|
|
|
if (safeplace) {
|
2005-01-18 22:45:00 +00:00
|
|
|
|
if (!safeplace[i]) {
|
|
|
|
|
c->dirlength = i;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
break;
|
2005-01-18 22:45:00 +00:00
|
|
|
|
}
|
2005-01-17 11:39:46 +00:00
|
|
|
|
lseek(fd, safeplace[i], SEEK_SET);
|
|
|
|
|
offset = safeplace[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* read name */
|
|
|
|
|
rc = read(fd, nptr, stringlen);
|
|
|
|
|
if (rc < stringlen)
|
|
|
|
|
{
|
|
|
|
|
DEBUGF("%d read(%d) returned %d\n", i, stringlen, rc);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (table) {
|
|
|
|
|
case allsongs:
|
2005-01-18 22:45:00 +00:00
|
|
|
|
case songs4album:
|
2005-02-01 14:22:27 +00:00
|
|
|
|
case songs4artist:
|
2005-01-20 16:24:26 +00:00
|
|
|
|
rc = read(fd, intbuf, 12);
|
2005-04-25 18:19:59 +00:00
|
|
|
|
skip = SONGENTRY_SIZE-stringlen-12; /* skip the rest of the song info */
|
2005-01-20 16:24:26 +00:00
|
|
|
|
if (rc < 12) {
|
|
|
|
|
DEBUGF("%d read(%d) returned %d\n", i, 12, rc);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2005-02-01 14:22:27 +00:00
|
|
|
|
/* continue to next song if wrong artist */
|
2005-04-25 18:19:59 +00:00
|
|
|
|
if (table == songs4artist && (int)BE32(intbuf[0]) != extra) {
|
|
|
|
|
lseek(fd, skip, SEEK_CUR);
|
2005-02-01 14:22:27 +00:00
|
|
|
|
continue;
|
2005-04-25 18:19:59 +00:00
|
|
|
|
}
|
2005-02-01 14:22:27 +00:00
|
|
|
|
|
2005-01-20 16:24:26 +00:00
|
|
|
|
/* save offset of filename */
|
2005-01-27 22:21:08 +00:00
|
|
|
|
dptr[1] = BE32(intbuf[2]);
|
2005-01-17 11:39:46 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case allalbums:
|
2005-01-18 22:45:00 +00:00
|
|
|
|
case albums4artist:
|
2005-01-17 11:39:46 +00:00
|
|
|
|
/* save offset of this album */
|
|
|
|
|
skip = songarraylen * 4 + 4;
|
|
|
|
|
dptr[1] = offset;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case allartists:
|
|
|
|
|
/* save offset of this artist */
|
|
|
|
|
skip = albumarraylen * 4;
|
|
|
|
|
dptr[1] = offset;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-01 14:22:27 +00:00
|
|
|
|
/* store name pointer in dir cache */
|
2005-02-12 12:29:41 +00:00
|
|
|
|
dptr[0] = (unsigned long)nptr;
|
2005-02-01 14:22:27 +00:00
|
|
|
|
|
2005-01-17 11:39:46 +00:00
|
|
|
|
if (skip)
|
|
|
|
|
lseek(fd, skip, SEEK_CUR);
|
2005-02-01 14:22:27 +00:00
|
|
|
|
|
|
|
|
|
hits++;
|
2005-04-25 22:36:23 +00:00
|
|
|
|
|
|
|
|
|
if(table==songs4artist)
|
|
|
|
|
c->dirlength=hits;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
|
|
|
|
|
/* next name is stored immediately after this */
|
|
|
|
|
nptr = (void*)nptr + strlen((char*)nptr) + 1;
|
2005-01-19 12:19:58 +00:00
|
|
|
|
if ((void*)nptr + stringlen > (void*)end_of_nbuf) {
|
2005-01-18 22:45:00 +00:00
|
|
|
|
c->dirfull = true;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2005-02-01 14:22:27 +00:00
|
|
|
|
|
|
|
|
|
/* limit dir buffer */
|
2005-01-20 16:24:26 +00:00
|
|
|
|
dptr = (void*)dptr + c->dentry_size * sizeof(int);
|
2005-02-01 14:22:27 +00:00
|
|
|
|
if ((void*)(dptr + c->dentry_size) >
|
|
|
|
|
(void*)(c->dircache + dcachesize))
|
|
|
|
|
{
|
|
|
|
|
c->dirfull = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2005-01-17 11:39:46 +00:00
|
|
|
|
|
|
|
|
|
if (!safeplace)
|
|
|
|
|
offset += stringlen + skip;
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-01 14:22:27 +00:00
|
|
|
|
if (c->currtable == albums4artist && !c->dirfull) {
|
|
|
|
|
strcpy((char*)nptr, str(LANG_ID3DB_ALL_SONGS));
|
2005-02-12 12:29:41 +00:00
|
|
|
|
dptr[0] = (unsigned long)nptr;
|
2005-02-01 14:22:27 +00:00
|
|
|
|
dptr[1] = extra; /* offset to artist */
|
|
|
|
|
hits++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c->filesindir = hits;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
|
2005-02-01 14:22:27 +00:00
|
|
|
|
return hits;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-01-27 22:21:08 +00:00
|
|
|
|
static int db_search(struct tree_context* c, char* string)
|
|
|
|
|
{
|
|
|
|
|
int i, count, size, hits=0;
|
|
|
|
|
long start;
|
|
|
|
|
|
|
|
|
|
char* nptr = c->name_buffer;
|
|
|
|
|
const char* end_of_nbuf = nptr + c->name_buffer_size;
|
|
|
|
|
|
|
|
|
|
unsigned long* dptr = c->dircache;
|
|
|
|
|
const long dcachesize = global_settings.max_files_in_dir *
|
|
|
|
|
sizeof(struct entry);
|
|
|
|
|
|
|
|
|
|
switch (c->currtable) {
|
|
|
|
|
case searchartists:
|
|
|
|
|
start = artiststart;
|
|
|
|
|
count = artistcount;
|
2005-04-25 18:19:59 +00:00
|
|
|
|
size = ARTISTENTRY_SIZE;
|
2005-01-27 22:21:08 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case searchalbums:
|
|
|
|
|
start = albumstart;
|
|
|
|
|
count = albumcount;
|
2005-04-25 18:19:59 +00:00
|
|
|
|
size = ALBUMENTRY_SIZE;
|
2005-01-27 22:21:08 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case searchsongs:
|
|
|
|
|
start = songstart;
|
|
|
|
|
count = songcount;
|
2005-04-25 18:19:59 +00:00
|
|
|
|
size = SONGENTRY_SIZE;
|
2005-01-27 22:21:08 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
DEBUGF("Invalid table %d\n", c->currtable);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lseek(fd, start, SEEK_SET);
|
|
|
|
|
|
|
|
|
|
for (i=0; i<count; i++) {
|
|
|
|
|
if (read(fd, nptr, size) < size) {
|
|
|
|
|
DEBUGF("Short read(%d) in db_search()\n",size);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (strcasestr(nptr, string)) {
|
|
|
|
|
hits++;
|
|
|
|
|
|
|
|
|
|
dptr[0] = (unsigned long)nptr;
|
|
|
|
|
if (c->currtable == searchsongs) {
|
|
|
|
|
/* store offset of filename */
|
|
|
|
|
dptr[1] = BE32(*((long*)(nptr + songlen + 8)));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
/* store offset of database record */
|
|
|
|
|
dptr[1] = start + i * size;
|
|
|
|
|
|
|
|
|
|
dptr += 2;
|
|
|
|
|
|
|
|
|
|
/* limit dir buffer */
|
|
|
|
|
if ((void*)(dptr + c->dentry_size) >
|
|
|
|
|
(void*)(c->dircache + dcachesize))
|
|
|
|
|
{
|
|
|
|
|
c->dirfull = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nptr += strlen(nptr) + 1;
|
|
|
|
|
while ((unsigned long)nptr & 3)
|
|
|
|
|
nptr++;
|
|
|
|
|
|
|
|
|
|
/* limit name buffer */
|
|
|
|
|
if ((void*)nptr + size > (void*)end_of_nbuf) {
|
|
|
|
|
c->dirfull = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return hits;
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-20 16:24:26 +00:00
|
|
|
|
int db_enter(struct tree_context* c)
|
2005-01-17 11:39:46 +00:00
|
|
|
|
{
|
2005-01-20 16:24:26 +00:00
|
|
|
|
int rc = 0;
|
2005-01-27 22:21:08 +00:00
|
|
|
|
int offset = (c->dircursor + c->dirstart) * c->dentry_size + 1;
|
|
|
|
|
int newextra = ((int*)c->dircache)[offset];
|
2005-01-19 15:01:31 +00:00
|
|
|
|
|
2005-01-27 22:21:08 +00:00
|
|
|
|
if (c->dirlevel >= MAX_DIR_LEVELS)
|
|
|
|
|
return 0;
|
|
|
|
|
|
2005-01-19 15:01:31 +00:00
|
|
|
|
c->dirpos[c->dirlevel] = c->dirstart;
|
|
|
|
|
c->cursorpos[c->dirlevel] = c->dircursor;
|
|
|
|
|
c->table_history[c->dirlevel] = c->currtable;
|
|
|
|
|
c->extra_history[c->dirlevel] = c->currextra;
|
|
|
|
|
c->pos_history[c->dirlevel] = c->firstpos;
|
|
|
|
|
c->dirlevel++;
|
|
|
|
|
|
2005-01-17 11:39:46 +00:00
|
|
|
|
switch (c->currtable) {
|
2005-01-19 15:01:31 +00:00
|
|
|
|
case root:
|
|
|
|
|
c->currtable = newextra;
|
|
|
|
|
c->currextra = newextra;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
break;
|
2005-01-19 15:01:31 +00:00
|
|
|
|
|
2005-01-17 11:39:46 +00:00
|
|
|
|
case allartists:
|
2005-01-27 22:21:08 +00:00
|
|
|
|
case searchartists:
|
2005-01-18 22:45:00 +00:00
|
|
|
|
c->currtable = albums4artist;
|
2005-01-19 15:01:31 +00:00
|
|
|
|
c->currextra = newextra;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2005-01-19 15:01:31 +00:00
|
|
|
|
case allalbums:
|
2005-01-18 22:45:00 +00:00
|
|
|
|
case albums4artist:
|
2005-01-27 22:21:08 +00:00
|
|
|
|
case searchalbums:
|
2005-02-01 14:22:27 +00:00
|
|
|
|
/* virtual <all albums> entry points to the artist,
|
|
|
|
|
all normal entries point to the album */
|
2005-04-25 18:19:59 +00:00
|
|
|
|
if (newextra < albumstart)
|
2005-02-01 14:22:27 +00:00
|
|
|
|
c->currtable = songs4artist;
|
|
|
|
|
else
|
|
|
|
|
c->currtable = songs4album;
|
|
|
|
|
|
2005-01-19 15:01:31 +00:00
|
|
|
|
c->currextra = newextra;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2005-01-19 15:01:31 +00:00
|
|
|
|
case allsongs:
|
2005-01-20 16:24:26 +00:00
|
|
|
|
case songs4album:
|
2005-02-02 09:07:24 +00:00
|
|
|
|
case songs4artist:
|
2005-01-27 22:21:08 +00:00
|
|
|
|
case searchsongs:
|
2005-01-19 15:01:31 +00:00
|
|
|
|
c->dirlevel--;
|
2005-01-20 16:24:26 +00:00
|
|
|
|
if (db_play_folder(c) >= 0)
|
|
|
|
|
rc = 3;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
break;
|
2005-01-27 22:21:08 +00:00
|
|
|
|
|
|
|
|
|
case search:
|
|
|
|
|
rc = kbd_input(searchstring, sizeof(searchstring));
|
|
|
|
|
if (rc == -1 || !searchstring[0])
|
|
|
|
|
c->dirlevel--;
|
|
|
|
|
else
|
|
|
|
|
c->currtable = newextra;
|
|
|
|
|
break;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
|
|
|
|
|
default:
|
2005-01-27 22:21:08 +00:00
|
|
|
|
c->dirlevel--;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-18 22:45:00 +00:00
|
|
|
|
c->dirstart = c->dircursor = c->firstpos = 0;
|
2005-01-20 16:24:26 +00:00
|
|
|
|
|
|
|
|
|
return rc;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void db_exit(struct tree_context* c)
|
|
|
|
|
{
|
|
|
|
|
c->dirlevel--;
|
|
|
|
|
c->dirstart = c->dirpos[c->dirlevel];
|
|
|
|
|
c->dircursor = c->cursorpos[c->dirlevel];
|
|
|
|
|
c->currtable = c->table_history[c->dirlevel];
|
|
|
|
|
c->currextra = c->extra_history[c->dirlevel];
|
2005-01-18 22:45:00 +00:00
|
|
|
|
c->firstpos = c->pos_history[c->dirlevel];
|
2005-01-17 11:39:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-01-20 16:24:26 +00:00
|
|
|
|
static int db_play_folder(struct tree_context* c)
|
|
|
|
|
{
|
|
|
|
|
char buf[MAX_PATH];
|
|
|
|
|
int rc, i;
|
|
|
|
|
int filenum = c->dircursor + c->dirstart;
|
|
|
|
|
|
|
|
|
|
if (playlist_create(NULL, NULL) < 0) {
|
|
|
|
|
DEBUGF("Failed creating playlist\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* TODO: add support for very long tables */
|
|
|
|
|
|
|
|
|
|
for (i=0; i < c->filesindir; i++) {
|
2005-01-27 22:21:08 +00:00
|
|
|
|
int pathoffset = ((int*)c->dircache)[i * c->dentry_size + 1];
|
2005-01-20 16:24:26 +00:00
|
|
|
|
lseek(fd, pathoffset, SEEK_SET);
|
|
|
|
|
rc = read(fd, buf, sizeof(buf));
|
|
|
|
|
if (rc < songlen) {
|
2005-02-12 12:29:41 +00:00
|
|
|
|
DEBUGF("short path read(%ld) = %d\n", sizeof(buf), rc);
|
2005-01-20 16:24:26 +00:00
|
|
|
|
return -2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
playlist_insert_track(NULL, buf, PLAYLIST_INSERT, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (global_settings.playlist_shuffle)
|
|
|
|
|
filenum = playlist_shuffle(current_tick, filenum);
|
|
|
|
|
if (!global_settings.play_selected)
|
|
|
|
|
filenum = 0;
|
|
|
|
|
|
|
|
|
|
playlist_start(filenum,0);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-17 11:39:46 +00:00
|
|
|
|
#ifdef HAVE_LCD_BITMAP
|
|
|
|
|
const char* db_get_icon(struct tree_context* c)
|
2005-01-27 22:21:08 +00:00
|
|
|
|
#else
|
|
|
|
|
int db_get_icon(struct tree_context* c)
|
|
|
|
|
#endif
|
2005-01-17 11:39:46 +00:00
|
|
|
|
{
|
|
|
|
|
int icon;
|
|
|
|
|
|
|
|
|
|
switch (c->currtable)
|
|
|
|
|
{
|
|
|
|
|
case allsongs:
|
2005-01-18 22:45:00 +00:00
|
|
|
|
case songs4album:
|
2005-02-01 14:22:27 +00:00
|
|
|
|
case songs4artist:
|
2005-01-27 22:21:08 +00:00
|
|
|
|
case searchsongs:
|
2005-01-17 11:39:46 +00:00
|
|
|
|
icon = File;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
icon = Folder;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-27 22:21:08 +00:00
|
|
|
|
#ifdef HAVE_LCD_BITMAP
|
2005-01-17 11:39:46 +00:00
|
|
|
|
return bitmap_icons_6x8[icon];
|
|
|
|
|
#else
|
2005-01-18 00:04:08 +00:00
|
|
|
|
return icon;
|
2005-01-17 11:39:46 +00:00
|
|
|
|
#endif
|
2005-01-27 22:21:08 +00:00
|
|
|
|
}
|