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 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(); } }