001 /** 002 * iFish - An iRiver iHP jukebox database creation tool 003 * 004 * Copyright (C) 2009 Richard "Shred" Körber 005 * http://ifish.shredzone.org 006 * 007 * This program is free software: you can redistribute it and/or modify 008 * it under the terms of the GNU General Public License as published by 009 * the Free Software Foundation, either version 3 of the License, or 010 * (at your option) any later version. 011 * 012 * This program is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015 * GNU General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * along with this program. If not, see <http://www.gnu.org/licenses/>. 019 */ 020 package net.shredzone.ifish.db; 021 022 import java.io.*; 023 024 /** 025 * This class represents an Entry which was read from the database. 026 * 027 * @author Richard Körber <dev@shredzone.de> 028 * @version $Id: DbEntry.java 291 2009-04-28 21:29:27Z shred $ 029 */ 030 public class DbEntry extends Entry implements Serializable { 031 private static final long serialVersionUID = 3832905438092932146L; 032 033 private final File base; 034 private final String filename; 035 private final String title; 036 private final String artist; 037 private final String album; 038 private final String genre; 039 040 /** 041 * Create a new Entry from a file database entry. 042 * 043 * @param base Base directory 044 * @param in Input stream within the database file 045 * @param charset Charset to be used for decoding 046 */ 047 public DbEntry( File base, InputStream in, String charset ) 048 throws IOException, UnsupportedEncodingException { 049 this.base = base; 050 int fnl = readLength( in ); 051 int titl = readLength( in ); 052 int artl = readLength( in ); 053 int albl = readLength( in ); 054 int genl = readLength( in ); 055 filename = readString( in, fnl , charset ); 056 title = readString( in, titl, charset ); 057 artist = readString( in, artl, charset ); 058 album = readString( in, albl, charset ); 059 genre = readString( in, genl, charset ); 060 } 061 062 /** 063 * Read the length of a string. This is a 16 bit little endian number. 064 * 065 * @param in InputStream to be read 066 * @param charset Charset the database was written in 067 * @return length read 068 * @throws IOException on errors and EOF 069 */ 070 private int readLength( InputStream in ) 071 throws IOException { 072 byte[] b = new byte[2]; 073 if( 2 != in.read(b) ) 074 throw new IOException( "EOF" ); 075 return ((b[1]&0xFF)<<8) | (b[0]&0xFF); 076 } 077 078 /** 079 * Read a string of a given length. The string encoding of the local 080 * machine will be used. 081 * 082 * @param in InputStream to be read 083 * @param length String length, including 0 termination 084 * @param charset Charset the string was written in 085 * @return String 086 * @throws IOException on errors and EOF 087 * @throws UnsupportedEncodingException Charset not known 088 */ 089 private String readString( InputStream in, int length, String charset ) 090 throws IOException, UnsupportedEncodingException { 091 if( length<=0 ) return ""; 092 byte[] b = new byte[length]; 093 if( length != in.read(b) ) 094 throw new IOException( "EOF" ); 095 096 String str; 097 if( length>=2 && (b[0]&0xFF)==0xFF && (b[1]&0xFF)==0xFE ) { 098 //--- UTF-16SE encoding --- 099 str = new String( b, 2, length-2, "UTF-16LE" ); 100 }else if( length>=2 && (b[0]&0xFF)==0xFE && (b[1]&0xFF)==0xFF ) { 101 //--- UTF-16BE encoding --- 102 str = new String( b, 2, length-2, "UTF-16BE" ); 103 }else { 104 //--- Standard encoding --- 105 str = new String( b, 0, length, charset ); 106 } 107 108 //--- Remove null termination --- 109 while( str.length()>0 && str.charAt(str.length()-1)=='\0' ) 110 str = str.substring( 0, str.length()-1 ); 111 112 return str; 113 } 114 115 /** 116 * Get the file behind this entry. Returns null if there is no matching 117 * file in the file system. 118 * 119 * @return File represented by this entry 120 */ 121 @Override 122 public File getFile() { 123 String fname = getFileName(); 124 125 //--- Convert Windows to this platform's notation --- 126 if( File.separatorChar != '\\' ) { 127 fname = fname.replace( '\\', File.separatorChar ); 128 } 129 130 //--- Remove leading slashes --- 131 if( fname.charAt(0)==File.separatorChar) 132 fname = fname.substring(1); 133 134 //--- Open a File for this file --- 135 return new File( base, fname ); 136 } 137 138 /** 139 * Get the file name of this entry. This is the path and file name 140 * relative to the iHP root directory mount point, and always 141 * using wrongslashes (even on unixoid systems). 142 * 143 * @return File name 144 */ 145 @Override 146 public String getFileName() { 147 return filename; 148 } 149 150 /** 151 * Get the title of the track, as given by the file's tag. Does not 152 * return null. 153 * 154 * @return Title 155 */ 156 @Override 157 public String getTitle() { 158 return title; 159 } 160 161 /** 162 * Get the artist of the track, as given by the file's tag. Does not 163 * return null. 164 * 165 * @return Artist 166 */ 167 @Override 168 public String getArtist() { 169 return artist; 170 } 171 172 /** 173 * Get the album of the track, as given by the file's tag. Does not 174 * return null. 175 * 176 * @return Album 177 */ 178 @Override 179 public String getAlbum() { 180 return album; 181 } 182 183 /** 184 * Get the genre of the track, as given by the file's tag. This is 185 * always a word, not a number. Does not return null. 186 * 187 * @return Genre 188 */ 189 @Override 190 public String getGenre() { 191 return genre; 192 } 193 194 } 195