forked from len0rd/rockbox
(Tag) Database v2. this fixes all bugs in the old songdb.pl, should react like
v1, except this has albums with multiple artists support. *prays nothing breaks* :X git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6347 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
de4ef019b9
commit
d41d44f073
2 changed files with 304 additions and 153 deletions
|
|
@ -57,16 +57,21 @@
|
|||
#define BE32(_x_) _x_
|
||||
#endif
|
||||
|
||||
#define ID3DB_VERSION 1
|
||||
#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
|
||||
|
||||
static int fd;
|
||||
|
||||
static int
|
||||
songstart, albumstart, artiststart,
|
||||
songcount, albumcount, artistcount,
|
||||
songlen, songarraylen,
|
||||
songstart, albumstart, artiststart, filestart,
|
||||
songcount, albumcount, artistcount, filecount,
|
||||
songlen, songarraylen, genrelen, filelen,
|
||||
albumlen, albumarraylen,
|
||||
artistlen, initialized = 0;
|
||||
artistlen, rundbdirty,initialized = 0;
|
||||
|
||||
static int db_play_folder(struct tree_context* c);
|
||||
static int db_search(struct tree_context* c, char* string);
|
||||
|
|
@ -76,7 +81,7 @@ static char searchstring[32];
|
|||
int db_init(void)
|
||||
{
|
||||
unsigned int version;
|
||||
unsigned int buf[12];
|
||||
unsigned int buf[17];
|
||||
unsigned char* ptr = (char*)buf;
|
||||
|
||||
fd = open(ROCKBOX_DIR "/rockbox.id3db", O_RDONLY);
|
||||
|
|
@ -84,7 +89,7 @@ int db_init(void)
|
|||
DEBUGF("Failed opening database\n");
|
||||
return -1;
|
||||
}
|
||||
read(fd, buf, 48);
|
||||
read(fd, buf, 68);
|
||||
|
||||
if (ptr[0] != 'R' ||
|
||||
ptr[1] != 'D' ||
|
||||
|
|
@ -94,29 +99,35 @@ int db_init(void)
|
|||
return -1;
|
||||
}
|
||||
|
||||
version = BE32(buf[0]) & 0xff;
|
||||
version = BE32(buf[0])&0xFF;
|
||||
if (version != ID3DB_VERSION)
|
||||
{
|
||||
splash(HZ,true,"Unsupported database version %d!", version);
|
||||
return -1;
|
||||
}
|
||||
|
||||
songstart = BE32(buf[1]);
|
||||
songcount = BE32(buf[2]);
|
||||
songlen = BE32(buf[3]);
|
||||
artiststart = BE32(buf[1]);
|
||||
albumstart = BE32(buf[2]);
|
||||
songstart = BE32(buf[3]);
|
||||
filestart = BE32(buf[4]);
|
||||
|
||||
albumstart = BE32(buf[4]);
|
||||
albumcount = BE32(buf[5]);
|
||||
albumlen = BE32(buf[6]);
|
||||
songarraylen = BE32(buf[7]);
|
||||
artistcount = BE32(buf[5]);
|
||||
albumcount = BE32(buf[6]);
|
||||
songcount = BE32(buf[7]);
|
||||
filecount = BE32(buf[8]);
|
||||
|
||||
artiststart = BE32(buf[8]);
|
||||
artistcount = BE32(buf[9]);
|
||||
artistlen = BE32(buf[10]);
|
||||
albumarraylen = BE32(buf[11]);
|
||||
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 > albumstart ||
|
||||
albumstart > artiststart)
|
||||
if (songstart > filestart ||
|
||||
albumstart > songstart ||
|
||||
artiststart > albumstart)
|
||||
{
|
||||
splash(HZ,true,"Corrupt ID3 database!");
|
||||
return -1;
|
||||
|
|
@ -150,7 +161,7 @@ int db_load(struct tree_context* c)
|
|||
c->dentry_size = 2;
|
||||
c->dirfull = false;
|
||||
|
||||
DEBUGF("db_load(%d, %x, %d)\n", table, extra, c->firstpos);
|
||||
DEBUGF("db_load() table: %d extra: 0x%x firstpos: %d\n", table, extra, c->firstpos);
|
||||
|
||||
if (!table) {
|
||||
table = root;
|
||||
|
|
@ -166,7 +177,7 @@ int db_load(struct tree_context* c)
|
|||
str(LANG_ID3DB_ALBUMS),
|
||||
str(LANG_ID3DB_SONGS),
|
||||
str(LANG_ID3DB_SEARCH)};
|
||||
|
||||
DEBUGF("dbload table root\n");
|
||||
for (i=0; i < 4; i++) {
|
||||
strcpy(nbuf, labels[i]);
|
||||
dptr[0] = (unsigned long)nbuf;
|
||||
|
|
@ -186,7 +197,7 @@ int db_load(struct tree_context* c)
|
|||
char* labels[] = { str(LANG_ID3DB_SEARCH_ARTISTS),
|
||||
str(LANG_ID3DB_SEARCH_ALBUMS),
|
||||
str(LANG_ID3DB_SEARCH_SONGS)};
|
||||
|
||||
DEBUGF("dbload table search\n");
|
||||
for (i=0; i < 3; i++) {
|
||||
strcpy(nbuf, labels[i]);
|
||||
dptr[0] = (unsigned long)nbuf;
|
||||
|
|
@ -201,6 +212,7 @@ int db_load(struct tree_context* c)
|
|||
case searchartists:
|
||||
case searchalbums:
|
||||
case searchsongs:
|
||||
DEBUGF("dbload table searchsongs/searchartists/searchalbums\n");
|
||||
i = db_search(c, searchstring);
|
||||
c->dirlength = c->filesindir = i;
|
||||
if (c->dirfull) {
|
||||
|
|
@ -214,26 +226,28 @@ int db_load(struct tree_context* c)
|
|||
return i;
|
||||
|
||||
case allsongs:
|
||||
offset = songstart + c->firstpos * (songlen + 12);
|
||||
DEBUGF("dbload table allsongs\n");
|
||||
offset = songstart + c->firstpos * SONGENTRY_SIZE;
|
||||
itemcount = songcount;
|
||||
stringlen = songlen;
|
||||
break;
|
||||
|
||||
case allalbums:
|
||||
offset = albumstart +
|
||||
c->firstpos * (albumlen + 4 + songarraylen * 4);
|
||||
DEBUGF("dbload table allalbums\n");
|
||||
offset = albumstart + c->firstpos * ALBUMENTRY_SIZE;
|
||||
itemcount = albumcount;
|
||||
stringlen = albumlen;
|
||||
break;
|
||||
|
||||
case allartists:
|
||||
offset = artiststart +
|
||||
c->firstpos * (artistlen + albumarraylen * 4);
|
||||
DEBUGF("dbload table allartists\n");
|
||||
offset = artiststart + c->firstpos * ARTISTENTRY_SIZE;
|
||||
itemcount = artistcount;
|
||||
stringlen = artistlen;
|
||||
break;
|
||||
|
||||
case albums4artist:
|
||||
DEBUGF("dbload table albums4artist\n");
|
||||
/* 'extra' is offset to the artist */
|
||||
safeplacelen = albumarraylen * 4;
|
||||
safeplace = (void*)(end_of_nbuf - safeplacelen);
|
||||
|
|
@ -252,6 +266,7 @@ int db_load(struct tree_context* c)
|
|||
break;
|
||||
|
||||
case songs4album:
|
||||
DEBUGF("dbload table songs4album\n");
|
||||
/* 'extra' is offset to the album */
|
||||
safeplacelen = songarraylen * 4;
|
||||
safeplace = (void*)(end_of_nbuf - safeplacelen);
|
||||
|
|
@ -261,8 +276,10 @@ int db_load(struct tree_context* c)
|
|||
return -1;
|
||||
|
||||
#ifdef LITTLE_ENDIAN
|
||||
for (i=0; i<songarraylen; i++)
|
||||
for (i=0; i<songarraylen; i++) {
|
||||
safeplace[i] = BE32(safeplace[i]);
|
||||
DEBUGF("db_load songs4album song %d: 0x%x\n",i,safeplace[i]);
|
||||
}
|
||||
#endif
|
||||
offset = safeplace[0];
|
||||
itemcount = songarraylen;
|
||||
|
|
@ -270,8 +287,9 @@ int db_load(struct tree_context* c)
|
|||
break;
|
||||
|
||||
case songs4artist:
|
||||
DEBUGF("dbload table songs4artist\n");
|
||||
/* 'extra' is offset to the artist, used as filter */
|
||||
offset = songstart + c->firstpos * (songlen + 12);
|
||||
offset = songstart + c->firstpos * SONGENTRY_SIZE;
|
||||
itemcount = songcount;
|
||||
stringlen = songlen;
|
||||
break;
|
||||
|
|
@ -318,13 +336,16 @@ int db_load(struct tree_context* c)
|
|||
case songs4album:
|
||||
case songs4artist:
|
||||
rc = read(fd, intbuf, 12);
|
||||
skip = SONGENTRY_SIZE-stringlen-12; /* skip the rest of the song info */
|
||||
if (rc < 12) {
|
||||
DEBUGF("%d read(%d) returned %d\n", i, 12, rc);
|
||||
return -1;
|
||||
}
|
||||
/* continue to next song if wrong artist */
|
||||
if (table == songs4artist && (int)BE32(intbuf[0]) != extra)
|
||||
if (table == songs4artist && (int)BE32(intbuf[0]) != extra) {
|
||||
lseek(fd, skip, SEEK_CUR);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* save offset of filename */
|
||||
dptr[1] = BE32(intbuf[2]);
|
||||
|
|
@ -400,19 +421,19 @@ static int db_search(struct tree_context* c, char* string)
|
|||
case searchartists:
|
||||
start = artiststart;
|
||||
count = artistcount;
|
||||
size = artistlen + albumarraylen * 4;
|
||||
size = ARTISTENTRY_SIZE;
|
||||
break;
|
||||
|
||||
case searchalbums:
|
||||
start = albumstart;
|
||||
count = albumcount;
|
||||
size = albumlen + 4 + songarraylen * 4;
|
||||
size = ALBUMENTRY_SIZE;
|
||||
break;
|
||||
|
||||
case searchsongs:
|
||||
start = songstart;
|
||||
count = songcount;
|
||||
size = songlen + 12;
|
||||
size = SONGENTRY_SIZE;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -497,7 +518,7 @@ int db_enter(struct tree_context* c)
|
|||
case searchalbums:
|
||||
/* virtual <all albums> entry points to the artist,
|
||||
all normal entries point to the album */
|
||||
if (newextra >= artiststart)
|
||||
if (newextra < albumstart)
|
||||
c->currtable = songs4artist;
|
||||
else
|
||||
c->currtable = songs4album;
|
||||
|
|
|
|||
302
tools/songdb.pl
302
tools/songdb.pl
|
|
@ -12,6 +12,8 @@ my $dir;
|
|||
my $strip;
|
||||
my $verbose;
|
||||
my $help;
|
||||
my $dirisalbum;
|
||||
my $dirisalbumname;
|
||||
|
||||
while($ARGV[0]) {
|
||||
if($ARGV[0] eq "--db") {
|
||||
|
|
@ -33,6 +35,14 @@ while($ARGV[0]) {
|
|||
$verbose = 1;
|
||||
shift @ARGV;
|
||||
}
|
||||
elsif($ARGV[0] eq "--dirisalbum") {
|
||||
$dirisalbum = 1;
|
||||
shift @ARGV;
|
||||
}
|
||||
elsif($ARGV[0] eq "--dirisalbumname") {
|
||||
$dirisalbumname = 1;
|
||||
shift @ARGV;
|
||||
}
|
||||
elsif($ARGV[0] eq "--help" or ($ARGV[0] eq "-h")) {
|
||||
$help = 1;
|
||||
shift @ARGV;
|
||||
|
|
@ -50,11 +60,13 @@ my %filename;
|
|||
my %lcartists;
|
||||
my %lcalbums;
|
||||
|
||||
my $dbver = 1;
|
||||
my %dir2albumname;
|
||||
|
||||
my $dbver = 2;
|
||||
|
||||
if(! -d $dir or $help) {
|
||||
print "'$dir' is not a directory\n" if ($dir ne "" and ! -d $dir);
|
||||
print "songdb --path <dir> [--db <file>] [--strip <path>] [--verbose] [--help]\n";
|
||||
print "songdb --path <dir> [--dirisalbum] [--dirisalbumname] [--db <file>] [--strip <path>] [--verbose] [--help]\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
|
|
@ -140,6 +152,7 @@ sub dodir {
|
|||
# YEAR
|
||||
|
||||
# don't index songs without tags
|
||||
# um. yes we do.
|
||||
if (not defined $$id3{'ARTIST'} and
|
||||
not defined $$id3{'ALBUM'} and
|
||||
not defined $$id3{'TITLE'})
|
||||
|
|
@ -180,8 +193,18 @@ sub dodir {
|
|||
$$id3{'ARTIST'} = "<no artist tag>" if ($$id3{'ARTIST'} eq "");
|
||||
# Fall back on the directory name (not full path dirname),
|
||||
# if no album tag
|
||||
if ($dirisalbum) {
|
||||
if($dir2albumname{$dir} eq "") {
|
||||
$dir2albumname{$dir} = $$id3{'ALBUM'};
|
||||
}
|
||||
elsif($dir2albumname{$dir} ne $$id3{'ALBUM'}) {
|
||||
$dir2albumname{$dir} = (split m[/], $dir)[-1];
|
||||
}
|
||||
}
|
||||
# if no directory
|
||||
if ($dirisalbumname) {
|
||||
$$id3{'ALBUM'} = (split m[/], $dir)[-1] if ($$id3{'ALBUM'} eq "");
|
||||
#if that doesn't work, fall back.
|
||||
}
|
||||
$$id3{'ALBUM'} = "<no album tag>" if ($$id3{'ALBUM'} eq "");
|
||||
# fall back on basename of the file if no title tag.
|
||||
my $base;
|
||||
|
|
@ -190,17 +213,34 @@ sub dodir {
|
|||
|
||||
# Append dirname, to handle multi-artist albums
|
||||
$$id3{'DIR'} = $dir;
|
||||
my $albumid = $id3->{'ALBUM'}."___".$$id3{'DIR'};
|
||||
my $albumid;
|
||||
if ($dirisalbum) {
|
||||
$albumid=$$id3{'DIR'};
|
||||
}
|
||||
else {
|
||||
$albumid= $id3->{'ALBUM'}."___".$$id3{'DIR'};
|
||||
}
|
||||
#printf "album id: %s\n", $albumid;
|
||||
|
||||
if($id3->{'ALBUM'}."___".$id3->{'DIR'} ne "<no album tag>___<no artist tag>") {
|
||||
# if($id3->{'ALBUM'}."___".$id3->{'DIR'} ne "<no album tag>___<no artist tag>") {
|
||||
my $num = ++$albums{$albumid};
|
||||
if($num > $maxsongperalbum) {
|
||||
$maxsongperalbum = $num;
|
||||
$longestalbum = $albumid;
|
||||
}
|
||||
$album2songs{$albumid}{$$id3{TITLE}} = $id3;
|
||||
if($dirisalbum) {
|
||||
$artist2albums{$$id3{ARTIST}}{$$id3{DIR}} = $id3;
|
||||
}
|
||||
else {
|
||||
$artist2albums{$$id3{ARTIST}}{$$id3{ALBUM}} = $id3;
|
||||
}
|
||||
# }
|
||||
}
|
||||
|
||||
if($dirisalbum and $dir2albumname{$dir} eq "") {
|
||||
$dir2albumname{$dir} = (split m[/], $dir)[-1];
|
||||
printf "%s\n", $dir2albumname{$dir};
|
||||
}
|
||||
|
||||
# extractdirs filters out only subdirectories from all given entries
|
||||
|
|
@ -217,17 +257,24 @@ dodir($dir);
|
|||
print "\n";
|
||||
|
||||
print "File name table\n" if ($verbose);
|
||||
my $fc;
|
||||
for(sort keys %entries) {
|
||||
printf(" %s\n", $_) if ($verbose);
|
||||
$fc += length($_)+1;
|
||||
my $l = length($_);
|
||||
if($l > $maxfilelen) {
|
||||
$maxfilelen = $l;
|
||||
$longestfilename = $_;
|
||||
}
|
||||
}
|
||||
$maxfilelen++; # include zero termination byte
|
||||
while($maxfilelen&3) {
|
||||
$maxfilelen++;
|
||||
}
|
||||
|
||||
my $maxsonglen = 0;
|
||||
my $sc;
|
||||
print "\nSong title table\n" if ($verbose);
|
||||
|
||||
for(sort {$entries{$a}->{'TITLE'} cmp $entries{$b}->{'TITLE'}} keys %entries) {
|
||||
for(sort {uc($entries{$a}->{'TITLE'}) cmp uc($entries{$b}->{'TITLE'})} keys %entries) {
|
||||
printf(" %s\n", $entries{$_}->{'TITLE'} ) if ($verbose);
|
||||
my $l = length($entries{$_}->{'TITLE'});
|
||||
if($l > $maxsonglen) {
|
||||
|
|
@ -244,8 +291,8 @@ my $maxartistlen = 0;
|
|||
print "\nArtist table\n" if ($verbose);
|
||||
my $i=0;
|
||||
my %artistcount;
|
||||
for(sort keys %artists) {
|
||||
printf(" %s\n", $_) if ($verbose);
|
||||
for(sort {uc($a) cmp uc($b)} keys %artists) {
|
||||
printf(" %s: %d\n", $_, $i) if ($verbose);
|
||||
$artistcount{$_}=$i++;
|
||||
my $l = length($_);
|
||||
if($l > $maxartistlen) {
|
||||
|
|
@ -256,6 +303,7 @@ for(sort keys %artists) {
|
|||
$l = scalar keys %{$artist2albums{$_}};
|
||||
if ($l > $maxalbumsperartist) {
|
||||
$maxalbumsperartist = $l;
|
||||
$longestartistalbum = $_;
|
||||
}
|
||||
}
|
||||
$maxartistlen++; # include zero termination byte
|
||||
|
|
@ -263,12 +311,22 @@ while($maxartistlen&3) {
|
|||
$maxartistlen++;
|
||||
}
|
||||
|
||||
if ($verbose) {
|
||||
print "\nGenre table\n";
|
||||
for(sort keys %genres) {
|
||||
printf(" %s\n", $_);
|
||||
print "\nGenre table\n" if ($verbose);
|
||||
for(sort keys %genres) {
|
||||
my $l = length($_);
|
||||
if($l > $maxgenrelen) {
|
||||
$maxgenrelen = $l;
|
||||
$longestgenrename = $_;
|
||||
}
|
||||
}
|
||||
|
||||
$maxgenrelen++; #include zero termination byte
|
||||
while($maxgenrelen&3) {
|
||||
$maxgenrelen++;
|
||||
}
|
||||
|
||||
|
||||
if ($verbose) {
|
||||
print "\nYear table\n";
|
||||
for(sort keys %years) {
|
||||
printf(" %s\n", $_);
|
||||
|
|
@ -279,15 +337,33 @@ print "\nAlbum table\n" if ($verbose);
|
|||
my $maxalbumlen = 0;
|
||||
my %albumcount;
|
||||
$i=0;
|
||||
for(sort keys %albums) {
|
||||
my @albumssort;
|
||||
if($dirisalbum) {
|
||||
@albumssort = sort {uc($dir2albumname{$a}) cmp uc($dir2albumname{$b})} keys %albums;
|
||||
}
|
||||
else {
|
||||
@albumssort = sort {uc($a) cmp uc($b)} keys %albums;
|
||||
}
|
||||
for(@albumssort) {
|
||||
my @moo=split(/___/, $_);
|
||||
printf(" %s\n", $moo[0]) if ($verbose);
|
||||
$albumcount{$_} = $i++;
|
||||
my $l = length($moo[0]);
|
||||
my $l;
|
||||
if($dirisalbum) {
|
||||
$l = length($dir2albumname{$_});
|
||||
}
|
||||
else {
|
||||
$l = length($moo[0]);
|
||||
}
|
||||
if($l > $maxalbumlen) {
|
||||
$maxalbumlen = $l;
|
||||
if($dirisalbum) {
|
||||
$longestalbumname = $dir2albumname{$_};
|
||||
}
|
||||
else {
|
||||
$longestalbumname = $moo[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
$maxalbumlen++; # include zero termination byte
|
||||
while($maxalbumlen&3) {
|
||||
|
|
@ -296,6 +372,14 @@ while($maxalbumlen&3) {
|
|||
|
||||
|
||||
|
||||
sub dumpshort {
|
||||
my ($num)=@_;
|
||||
|
||||
# print "int: $num\n";
|
||||
|
||||
print DB pack "n", $num;
|
||||
}
|
||||
|
||||
sub dumpint {
|
||||
my ($num)=@_;
|
||||
|
||||
|
|
@ -311,108 +395,121 @@ if (!scalar keys %entries) {
|
|||
}
|
||||
|
||||
if ($db) {
|
||||
my $songentrysize = $maxsonglen + 12;
|
||||
my $songentrysize = $maxsonglen + 12 + $maxgenrelen+ 4;
|
||||
my $albumentrysize = $maxalbumlen + 4 + $maxsongperalbum*4;
|
||||
my $artistentrysize = $maxartistlen + $maxalbumsperartist*4;
|
||||
my $fileentrysize = $maxfilelen + 12;
|
||||
|
||||
printf "Number of artists : %d\n", scalar keys %artists;
|
||||
printf "Number of albums : %d\n", scalar keys %albums;
|
||||
printf "Number of songs : %d\n", scalar keys %entries;
|
||||
printf "Number of songs / files : %d\n", scalar keys %entries;
|
||||
print "Max artist length : $maxartistlen ($longestartist)\n";
|
||||
print "Max album length : $maxalbumlen ($longestalbumname)\n";
|
||||
print "Max song length : $maxsonglen ($longestsong)\n";
|
||||
print "Max songs per album: $maxsongperalbum ($longestalbum)\n";
|
||||
print "Max songs per album : $maxsongperalbum ($longestalbum)\n";
|
||||
print "Max albums per artist: $maxalbumsperartist ($longestartistalbum)\n";
|
||||
print "Max genre length : $maxgenrelen ($longestgenrename)\n";
|
||||
print "Max file length : $maxfilelen ($longestfilename)\n";
|
||||
print "Database version: $dbver\n" if ($verbose);
|
||||
print "Song Entry Size : $songentrysize ($maxsonglen + 12 + $maxgenrelen + 4)\n" if ($verbose);
|
||||
print "Album Entry Size: $albumentrysize ($maxalbumlen + 4 + $maxsongperalbum * 4)\n" if ($verbose);
|
||||
print "Artist Entry Size: $artistentrysize ($maxartistlen + $maxalbumsperartist * 4)\n" if ($verbose);
|
||||
print "File Entry Size: $fileentrysize ($maxfilelen + 12)\n" if ($verbose);
|
||||
|
||||
|
||||
open(DB, ">$db") || die "couldn't make $db";
|
||||
binmode(DB);
|
||||
printf DB "RDB%c", $dbver;
|
||||
|
||||
$pathindex = 48; # paths always start at index 48
|
||||
$pathindex = 68; # paths always start at index 68
|
||||
|
||||
$songindex = $pathindex + $fc; # fc is size of all paths
|
||||
$songindex++ while ($songindex & 3); # align to 32 bits
|
||||
|
||||
dumpint($songindex); # file position index of song table
|
||||
dumpint(scalar(keys %entries)); # number of songs
|
||||
dumpint($maxsonglen); # length of song name field
|
||||
$artistindex = $pathindex;
|
||||
|
||||
# set total size of song title table
|
||||
$sc = scalar(keys %entries) * $songentrysize;
|
||||
|
||||
$albumindex = $songindex + $sc; # sc is size of all songs
|
||||
dumpint($albumindex); # file position index of album table
|
||||
dumpint(scalar(keys %albums)); # number of albums
|
||||
dumpint($maxalbumlen); # length of album name field
|
||||
dumpint($maxsongperalbum); # number of entries in songs-per-album array
|
||||
|
||||
my $ac = scalar(keys %albums) * $albumentrysize;
|
||||
my $arc = scalar(keys %artists) * $artistentrysize;
|
||||
$albumindex = $artistindex + $arc; # arc is size of all artists
|
||||
$songindex = $albumindex + $ac; # ac is size of all albums
|
||||
my $fileindex = $songindex + $sc; # sc is size of all songs
|
||||
|
||||
$artistindex = $albumindex + $ac; # ac is size of all albums
|
||||
dumpint($artistindex); # file position index of artist table
|
||||
dumpint($albumindex); # file position index of album table
|
||||
dumpint($songindex); # file position index of song table
|
||||
dumpint($fileindex); # file position index of file table
|
||||
dumpint(scalar(keys %artists)); # number of artists
|
||||
dumpint(scalar(keys %albums)); # number of albums
|
||||
dumpint(scalar(keys %entries)); # number of songs
|
||||
dumpint(scalar(keys %entries)); # number of files
|
||||
dumpint($maxartistlen); # length of artist name field
|
||||
dumpint($maxalbumlen); # length of album name field
|
||||
dumpint($maxsonglen); # length of song name field
|
||||
dumpint($maxgenrelen); #length of genre field
|
||||
dumpint($maxfilelen); # length of file field
|
||||
dumpint($maxsongperalbum); # number of entries in songs-per-album array
|
||||
dumpint($maxalbumsperartist); # number of entries in albums-per-artist array
|
||||
dumpint(-1); # rundb dirty
|
||||
|
||||
my $l=0;
|
||||
#### TABLE of artists ###
|
||||
# name of artist1
|
||||
# pointers to albums of artist1
|
||||
|
||||
#### TABLE of file names ###
|
||||
# path1
|
||||
for (sort {uc($a) cmp uc($b)} keys %artists) {
|
||||
my $artist = $_;
|
||||
my $str = $_."\x00" x ($maxartistlen - length($_));
|
||||
print DB $str;
|
||||
|
||||
my %filenamepos;
|
||||
for $f (sort keys %entries) {
|
||||
printf DB ("%s\x00", $f);
|
||||
$filenamepos{$f}= $l;
|
||||
$l += length($f)+1;
|
||||
for (sort keys %{$artist2albums{$artist}}) {
|
||||
my $id3 = $artist2albums{$artist}{$_};
|
||||
my $a;
|
||||
if($dirisalbum) {
|
||||
$a = $albumcount{"$$id3{'DIR'}"} * $albumentrysize;
|
||||
}
|
||||
while ($l & 3) {
|
||||
print DB "\x00";
|
||||
$l++;
|
||||
else {
|
||||
$a = $albumcount{"$$id3{'ALBUM'}___$$id3{'DIR'}"} * $albumentrysize;
|
||||
}
|
||||
dumpint($a + $albumindex);
|
||||
}
|
||||
|
||||
#### TABLE of songs ###
|
||||
# title of song1
|
||||
# pointer to artist of song1
|
||||
# pointer to album of song1
|
||||
# pointer to filename of song1
|
||||
for (scalar keys %{$artist2albums{$artist}} .. $maxalbumsperartist-1) {
|
||||
print DB "\x00\x00\x00\x00";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
### Build song offset info.
|
||||
my $offset = $songindex;
|
||||
for(sort {uc($entries{$a}->{'TITLE'}) cmp uc($entries{$b}->{'TITLE'})} keys %entries) {
|
||||
my $f = $_;
|
||||
my $id3 = $entries{$f};
|
||||
my $t = $id3->{'TITLE'};
|
||||
my $str = $t."\x00" x ($maxsonglen- length($t));
|
||||
|
||||
print DB $str; # title
|
||||
|
||||
my $a = $artistcount{$id3->{'ARTIST'}} * $artistentrysize;
|
||||
dumpint($a + $artistindex); # pointer to artist of this song
|
||||
|
||||
$a = $albumcount{"$$id3{ALBUM}___$$id3{DIR}"} * $albumentrysize;
|
||||
dumpint($a + $albumindex); # pointer to album of this song
|
||||
|
||||
# pointer to filename of this song
|
||||
dumpint($filenamepos{$f} + $pathindex);
|
||||
|
||||
my $id3 = $entries{$_};
|
||||
$$id3{'songoffset'} = $offset;
|
||||
$offset += $songentrysize;
|
||||
}
|
||||
|
||||
|
||||
#### TABLE of albums ###
|
||||
# name of album1
|
||||
# pointers to artists of album1
|
||||
# pointers to songs on album1
|
||||
|
||||
for(sort {uc($a) cmp uc($b)} keys %albums) {
|
||||
for(@albumssort) {
|
||||
my $albumid = $_;
|
||||
my @moo=split(/___/, $_);
|
||||
my $t = $moo[0];
|
||||
my $str = $t."\x00" x ($maxalbumlen - length($t));
|
||||
my $t;
|
||||
my $str;
|
||||
if($dirisalbum) {
|
||||
$t = $dir2albumname{$albumid};
|
||||
}
|
||||
else {
|
||||
$t = $moo[0];
|
||||
}
|
||||
$str = $t."\x00" x ($maxalbumlen - length($t));
|
||||
print DB $str;
|
||||
|
||||
my @songlist = keys %{$album2songs{$albumid}};
|
||||
my $id3 = $album2songs{$albumid}{$songlist[0]};
|
||||
|
||||
#printf "(d) albumid: %s artist: %s\n",$albumid, $id3->{'ARTIST'};
|
||||
|
||||
my $aoffset = $artistcount{$id3->{'ARTIST'}} * $artistentrysize;
|
||||
dumpint($aoffset + $artistindex); # pointer to artist of this album
|
||||
|
||||
|
|
@ -436,25 +533,58 @@ if ($db) {
|
|||
}
|
||||
}
|
||||
|
||||
#### TABLE of artists ###
|
||||
# name of artist1
|
||||
# pointers to albums of artist1
|
||||
#### Build filename offset info
|
||||
my $l=$fileindex;
|
||||
my %filenamepos;
|
||||
for $f (sort keys %entries) {
|
||||
$filenamepos{$f}= $l;
|
||||
$l += $fileentrysize;
|
||||
}
|
||||
|
||||
for (sort {uc($a) cmp uc($b)} keys %artists) {
|
||||
my $artist = $_;
|
||||
my $str = $_."\x00" x ($maxartistlen - length($_));
|
||||
#### TABLE of songs ###
|
||||
# title of song1
|
||||
# pointer to artist of song1
|
||||
# pointer to album of song1
|
||||
# pointer to filename of song1
|
||||
|
||||
for(sort {uc($entries{$a}->{'TITLE'}) cmp uc($entries{$b}->{'TITLE'})} keys %entries) {
|
||||
my $f = $_;
|
||||
my $id3 = $entries{$f};
|
||||
my $t = $id3->{'TITLE'};
|
||||
my $g = $id3->{'GENRE'};
|
||||
my $str = $t."\x00" x ($maxsonglen- length($t));
|
||||
|
||||
print DB $str; # title
|
||||
$str = $g."\x00" x ($maxgenrelen - length($g));
|
||||
|
||||
my $a = $artistcount{$id3->{'ARTIST'}} * $artistentrysize;
|
||||
dumpint($a + $artistindex); # pointer to artist of this song
|
||||
|
||||
if($dirisalbum) {
|
||||
$a = $albumcount{"$$id3{DIR}"} * $albumentrysize;
|
||||
}
|
||||
else {
|
||||
$a = $albumcount{"$$id3{ALBUM}___$$id3{DIR}"} * $albumentrysize;
|
||||
}
|
||||
dumpint($a + $albumindex); # pointer to album of this song
|
||||
|
||||
# pointer to filename of this song
|
||||
dumpint($filenamepos{$f});
|
||||
print DB $str; #genre
|
||||
dumpshort(-1);
|
||||
dumpshort($id3->{'YEAR'});
|
||||
}
|
||||
|
||||
#### TABLE of file names ###
|
||||
# path1
|
||||
|
||||
for $f (sort keys %entries) {
|
||||
my $str = $f."\x00" x ($maxfilelen- length($f));
|
||||
my $id3 = $entries{$f};
|
||||
print DB $str;
|
||||
|
||||
for (sort keys %{$artist2albums{$artist}}) {
|
||||
my $id3 = $artist2albums{$artist}{$_};
|
||||
my $a = $albumcount{"$$id3{'ALBUM'}___$$id3{'DIR'}"} * $albumentrysize;
|
||||
dumpint($a + $albumindex);
|
||||
}
|
||||
|
||||
for (scalar keys %{$artist2albums{$artist}} .. $maxalbumsperartist-1) {
|
||||
print DB "\x00\x00\x00\x00";
|
||||
}
|
||||
|
||||
dumpint(0);
|
||||
dumpint($id3->{'songoffset'});
|
||||
dumpint(-1);
|
||||
}
|
||||
|
||||
close(DB);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue