377 lines
9.7 KiB
Java
377 lines
9.7 KiB
Java
|
import java.util.*;
|
||
|
import java.io.*;
|
||
|
import java.lang.reflect.Array;
|
||
|
|
||
|
/*
|
||
|
TreeSet for runtimedatabase with entry hash used in compareto
|
||
|
fix commandline interface.
|
||
|
*/
|
||
|
|
||
|
public class TagDatabase {
|
||
|
protected static TagDatabase instance=null;
|
||
|
protected TreeMap songs;
|
||
|
protected TreeMap files;
|
||
|
protected TreeMap filehashes;
|
||
|
protected TreeMap albums;
|
||
|
protected TreeMap artists;
|
||
|
protected int artiststart,albumstart,songstart,filestart;
|
||
|
protected int artistcount,albumcount,songcount,filecount;
|
||
|
public int artistlen,albumlen,songlen,genrelen,filelen,songarraylen,albumarraylen;
|
||
|
public String strip,add;
|
||
|
public boolean haveOldDatabase,dirisalbum,dirisalbumname,showduplicates;
|
||
|
protected Vector sortedsongs,sortedfiles,sortedalbums,sortedartists;
|
||
|
|
||
|
protected TagDatabase() {
|
||
|
songs=new TreeMap();
|
||
|
files=new TreeMap();
|
||
|
filehashes=new TreeMap();
|
||
|
albums=new TreeMap();
|
||
|
artists=new TreeMap();
|
||
|
strip=null;
|
||
|
add=null;
|
||
|
haveOldDatabase=false;
|
||
|
dirisalbum=false;
|
||
|
dirisalbumname=true;
|
||
|
showduplicates=true;
|
||
|
}
|
||
|
|
||
|
public static TagDatabase getInstance() {
|
||
|
if(instance==null)
|
||
|
instance=new TagDatabase();
|
||
|
return instance;
|
||
|
}
|
||
|
|
||
|
public void removeFileEntry(File file) {
|
||
|
String key = file.getAbsolutePath();
|
||
|
files.remove(key);
|
||
|
}
|
||
|
|
||
|
public FileEntry getFileEntry(File file) throws FileNotFoundException, IOException {
|
||
|
String key = file.getAbsolutePath();
|
||
|
if(!files.containsKey(key)) {
|
||
|
FileEntry f = new FileEntry(file);
|
||
|
files.put(key,f);
|
||
|
return f;
|
||
|
}
|
||
|
else
|
||
|
return (FileEntry)files.get(key);
|
||
|
}
|
||
|
|
||
|
public ArtistEntry getArtistEntry(String name) {
|
||
|
String key = name.toLowerCase();
|
||
|
if(!artists.containsKey(key)) {
|
||
|
ArtistEntry a = new ArtistEntry(name);
|
||
|
artists.put(key,a);
|
||
|
return a;
|
||
|
}
|
||
|
else
|
||
|
return (ArtistEntry)artists.get(key);
|
||
|
}
|
||
|
|
||
|
public String getAlbumKey(String name, String directory) {
|
||
|
if(dirisalbum)
|
||
|
return directory;
|
||
|
else
|
||
|
return name.toLowerCase()+"___"+directory;
|
||
|
}
|
||
|
|
||
|
public AlbumEntry getAlbumEntry(String name,String directory) {
|
||
|
String key = getAlbumKey(name,directory);
|
||
|
if(!albums.containsKey(key)) {
|
||
|
AlbumEntry a = new AlbumEntry(name);
|
||
|
albums.put(key,a);
|
||
|
return a;
|
||
|
}
|
||
|
else
|
||
|
return (AlbumEntry)albums.get(key);
|
||
|
}
|
||
|
|
||
|
public void removeSongEntry(FileEntry file) {
|
||
|
String key = file.getFilename();
|
||
|
songs.remove(key);
|
||
|
file.setSongEntry(null);
|
||
|
}
|
||
|
|
||
|
public SongEntry getSongEntry(FileEntry file) {
|
||
|
String key = file.getFilename();
|
||
|
if(!songs.containsKey(key)) {
|
||
|
SongEntry s = new SongEntry(file);
|
||
|
songs.put(key,s);
|
||
|
return s;
|
||
|
}
|
||
|
else
|
||
|
return (SongEntry)songs.get(key);
|
||
|
}
|
||
|
|
||
|
private class SongFilter implements FileFilter {
|
||
|
public boolean accept(File f) {
|
||
|
if(f.isDirectory()) // always accept directories.
|
||
|
return true;
|
||
|
String name=f.getName();
|
||
|
return name.endsWith(".mp3")||name.endsWith(".ogg");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void add(File f) {
|
||
|
if(!f.isDirectory()) {
|
||
|
if(f.isFile()) {
|
||
|
addSong(f);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
File[] files = f.listFiles(new SongFilter());
|
||
|
int length=Array.getLength(files);
|
||
|
System.out.println(FileEntry.convertPath(f.getAbsolutePath()));
|
||
|
for(int i=0;i<length;i++) {
|
||
|
add(files[i]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected FileEntry addSong(File f) {
|
||
|
FileEntry file = null;
|
||
|
try {
|
||
|
file = getFileEntry(f);
|
||
|
}
|
||
|
catch(Exception e) {
|
||
|
return null;
|
||
|
}
|
||
|
SongEntry song = getSongEntry(file);
|
||
|
if(!song.gotTagInfo()) {
|
||
|
removeSongEntry(file);
|
||
|
return null;
|
||
|
}
|
||
|
ArtistEntry artist = getArtistEntry(song.getArtistTag());
|
||
|
AlbumEntry album = getAlbumEntry(song.getAlbumTag(),f.getParent());
|
||
|
album.setArtist(artist);
|
||
|
album.addSong(song);
|
||
|
return file;
|
||
|
}
|
||
|
|
||
|
protected int align(int len) {
|
||
|
while((len&3)!=0) len++;
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
protected void calcLimits() {
|
||
|
ArtistEntry longartist=null,longalbumarray=null;
|
||
|
AlbumEntry longalbum=null, longsongarray=null;
|
||
|
SongEntry longsong=null,longgenre=null;
|
||
|
FileEntry longfile=null;
|
||
|
Iterator i;
|
||
|
artistlen=0;
|
||
|
albumarraylen=0;
|
||
|
i=sortedartists.iterator();
|
||
|
while(i.hasNext()) {
|
||
|
ArtistEntry artist = (ArtistEntry) i.next();
|
||
|
int length=artist.getName().length();
|
||
|
int albumcount=artist.size();
|
||
|
if(length > artistlen) {
|
||
|
artistlen=align(length);
|
||
|
longartist=artist;
|
||
|
}
|
||
|
if(albumcount> albumarraylen) {
|
||
|
albumarraylen=albumcount;
|
||
|
longalbumarray=artist;
|
||
|
}
|
||
|
}
|
||
|
artistcount=sortedartists.size();
|
||
|
if(longartist!=null)
|
||
|
System.out.println("Artist with longest name ("+artistlen+") :"+longartist.getName());
|
||
|
if(longalbumarray!=null)
|
||
|
System.out.println("Artist with most albums ("+albumarraylen+") :"+longalbumarray.getName());
|
||
|
albumlen=0;
|
||
|
songarraylen=0;
|
||
|
i=sortedalbums.iterator();
|
||
|
while(i.hasNext()) {
|
||
|
AlbumEntry album = (AlbumEntry) i.next();
|
||
|
int length=album.getName().length();
|
||
|
int songcount=album.size();
|
||
|
if(length > albumlen) {
|
||
|
albumlen=align(length);
|
||
|
longalbum=album;
|
||
|
}
|
||
|
if(songcount> songarraylen) {
|
||
|
songarraylen=songcount;
|
||
|
longsongarray=album;
|
||
|
}
|
||
|
}
|
||
|
albumcount=sortedalbums.size();
|
||
|
if(longalbum!=null)
|
||
|
System.out.println("Album with longest name ("+albumlen+") :"+longalbum.getName());
|
||
|
if(longsongarray!=null)
|
||
|
System.out.println("Album with most songs ("+songarraylen+") :"+longsongarray.getName());
|
||
|
filelen=0;
|
||
|
i=sortedfiles.iterator();
|
||
|
while(i.hasNext()) {
|
||
|
FileEntry file = (FileEntry) i.next();
|
||
|
int length=file.getFilename().length();
|
||
|
if(length> filelen) {
|
||
|
filelen=align(length);
|
||
|
longfile=file;
|
||
|
}
|
||
|
}
|
||
|
filecount=sortedfiles.size();
|
||
|
if(longfile!=null)
|
||
|
System.out.println("File with longest filename ("+filelen+") :"+longfile.getFilename());
|
||
|
songlen=0;
|
||
|
genrelen=0;
|
||
|
i=sortedsongs.iterator();
|
||
|
while(i.hasNext()) {
|
||
|
SongEntry song = (SongEntry) i.next();
|
||
|
int tlength=song.getName().length();
|
||
|
int glength=song.getGenreTag().length();
|
||
|
if(tlength> songlen) {
|
||
|
songlen=align(tlength);
|
||
|
longsong=song;
|
||
|
}
|
||
|
if(glength> genrelen) {
|
||
|
genrelen=align(glength);
|
||
|
longgenre=song;
|
||
|
}
|
||
|
}
|
||
|
songcount=sortedsongs.size();
|
||
|
if(longsong!=null)
|
||
|
System.out.println("Song with longest name ("+songlen+") :"+longsong.getName());
|
||
|
if(longsong!=null)
|
||
|
System.out.println("Song with longest genre ("+genrelen+") :"+longgenre.getGenreTag());
|
||
|
System.out.println("Artistcount: "+artistcount);
|
||
|
System.out.println("Albumcount : "+albumcount);
|
||
|
System.out.println("Songcount : "+songcount);
|
||
|
System.out.println("Filecount : "+filecount);
|
||
|
artiststart=68;
|
||
|
albumstart=artiststart+artistcount*ArtistEntry.entrySize();
|
||
|
songstart=albumstart+albumcount*AlbumEntry.entrySize();
|
||
|
filestart=songstart+songcount*SongEntry.entrySize();
|
||
|
}
|
||
|
|
||
|
protected void calcOffsets() {
|
||
|
Iterator i;
|
||
|
int offset=artiststart;
|
||
|
i=sortedartists.iterator();
|
||
|
while(i.hasNext()) {
|
||
|
Entry e = (Entry) i.next();
|
||
|
e.setOffset(offset);
|
||
|
offset+=ArtistEntry.entrySize();
|
||
|
}
|
||
|
// assert(offset==albumstart);
|
||
|
i=sortedalbums.iterator();
|
||
|
while(i.hasNext()) {
|
||
|
Entry e = (Entry) i.next();
|
||
|
e.setOffset(offset);
|
||
|
offset+=AlbumEntry.entrySize();
|
||
|
}
|
||
|
// assert(offset==songstart);
|
||
|
i=sortedsongs.iterator();
|
||
|
while(i.hasNext()) {
|
||
|
Entry e = (Entry) i.next();
|
||
|
e.setOffset(offset);
|
||
|
offset+=SongEntry.entrySize();
|
||
|
}
|
||
|
// assert(offset==filestart);
|
||
|
i=sortedfiles.iterator();
|
||
|
while(i.hasNext()) {
|
||
|
Entry e = (Entry) i.next();
|
||
|
e.setOffset(offset);
|
||
|
offset+=FileEntry.entrySize();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected void calcHashes() {
|
||
|
Iterator i;
|
||
|
i=sortedfiles.iterator();
|
||
|
while(i.hasNext()) {
|
||
|
FileEntry file = (FileEntry) i.next();
|
||
|
Integer key = new Integer(file.getHash());
|
||
|
if(!filehashes.containsKey(key))
|
||
|
filehashes.put(key,file);
|
||
|
else {
|
||
|
System.out.println("Duplicate hash:");
|
||
|
System.out.println(((FileEntry)filehashes.get(key)).getFilename());
|
||
|
System.out.println(file.getFilename());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected void writeHeader(DataOutputStream w) throws IOException {
|
||
|
w.write('R');
|
||
|
w.write('D');
|
||
|
w.write('B');
|
||
|
w.write(0x3);
|
||
|
w.writeInt(artiststart);
|
||
|
w.writeInt(albumstart);
|
||
|
w.writeInt(songstart);
|
||
|
w.writeInt(filestart);
|
||
|
w.writeInt(artistcount);
|
||
|
w.writeInt(albumcount);
|
||
|
w.writeInt(songcount);
|
||
|
w.writeInt(filecount);
|
||
|
w.writeInt(artistlen);
|
||
|
w.writeInt(albumlen);
|
||
|
w.writeInt(songlen);
|
||
|
w.writeInt(genrelen);
|
||
|
w.writeInt(filelen);
|
||
|
w.writeInt(songarraylen);
|
||
|
w.writeInt(albumarraylen);
|
||
|
w.writeInt(RuntimeDatabase.getInstance().isDirty());
|
||
|
}
|
||
|
|
||
|
public void prepareWrite() {
|
||
|
System.out.println("Sorting artists..");
|
||
|
sortedartists=new Vector();
|
||
|
sortedartists.addAll(artists.values());
|
||
|
Collections.sort(sortedartists);
|
||
|
System.out.println("Sorting albums..");
|
||
|
sortedalbums=new Vector();
|
||
|
sortedalbums.addAll(albums.values());
|
||
|
Collections.sort(sortedalbums);
|
||
|
System.out.println("Sorting songs..");
|
||
|
sortedsongs=new Vector();
|
||
|
sortedsongs.addAll(songs.values());
|
||
|
Collections.sort(sortedsongs);
|
||
|
System.out.println("Sorting files..");
|
||
|
sortedfiles=new Vector();
|
||
|
sortedfiles.addAll(files.values());
|
||
|
Collections.sort(sortedfiles);
|
||
|
System.out.println("Calculating tag database limits..");
|
||
|
calcLimits();
|
||
|
System.out.println("Calculating tag database offsets..");
|
||
|
calcOffsets();
|
||
|
if(showduplicates) {
|
||
|
System.out.println("Comparing file hashes..");
|
||
|
calcHashes();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void writeDatabase(File f) throws IOException {
|
||
|
int x;
|
||
|
Iterator i;
|
||
|
DataOutputStream w = new DataOutputStream(new FileOutputStream(f));
|
||
|
System.out.println("Writing tag database..");
|
||
|
writeHeader(w);
|
||
|
|
||
|
i=sortedartists.iterator();
|
||
|
while(i.hasNext()) {
|
||
|
Entry e = (Entry) i.next();
|
||
|
e.write(w);
|
||
|
}
|
||
|
i=sortedalbums.iterator();
|
||
|
while(i.hasNext()) {
|
||
|
Entry e = (Entry) i.next();
|
||
|
e.write(w);
|
||
|
}
|
||
|
i=sortedsongs.iterator();
|
||
|
while(i.hasNext()) {
|
||
|
Entry e = (Entry) i.next();
|
||
|
e.write(w);
|
||
|
}
|
||
|
i=sortedfiles.iterator();
|
||
|
while(i.hasNext()) {
|
||
|
Entry e = (Entry) i.next();
|
||
|
e.write(w);
|
||
|
}
|
||
|
// done...
|
||
|
w.flush();
|
||
|
w.close();
|
||
|
}
|
||
|
}
|