/* * Created on May 11, 2004 * * To change the template for this generated file go to * Window - Preferences - Java - Code Generation - Code and Comments */ package com.limegroup.gnutella.metadata; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import com.limegroup.gnutella.util.NameValue; import com.limegroup.gnutella.xml.LimeXMLDocument; import com.limegroup.gnutella.xml.LimeXMLUtils; import com.limegroup.gnutella.xml.XMLStringUtils; /** * Encapsulates audio metadata. Subclasses must implement parseFile. */ public abstract class AudioMetaData extends MetaData { private String title ; private String artist; private String album ; private String year; private String comment; private short track = -1; private String genre; private int bitrate = -1; private int length = -1; private short totalTracks =-1; private short disk=-1; private short totalDisks=-1; private String license; private String price; private String licensetype; public static final String ISO_LATIN_1 = "8859_1"; public static final String UNICODE = "Unicode"; public static String schemaURI = "http://www.limewire.com/schemas/audio.xsd"; private static final String DLM = XMLStringUtils.DELIMITER; private static final String KPX = "audios" + DLM + "audio" + DLM; public static final String TRACK_KEY = KPX + "track" + DLM; public static final String ARTIST_KEY = KPX + "artist" + DLM; public static final String ALBUM_KEY = KPX + "album" + DLM; public static final String TITLE_KEY = KPX + "title" + DLM; public static final String GENRE_KEY = KPX + "genre" + DLM; public static final String YEAR_KEY = KPX + "year" + DLM; public static final String COMMENTS_KEY = KPX + "comments" + DLM; public static final String BITRATE_KEY = KPX + "bitrate" + DLM; public static final String SECONDS_KEY = KPX + "seconds" + DLM; public static final String LICENSE_KEY = KPX + "license" + DLM; public static final String PRICE_KEY = KPX + "price" + DLM; public static final String LICENSE_TYPE_KEY = KPX + "licensetype" + DLM; protected AudioMetaData() throws IOException { } public AudioMetaData(File f) throws IOException{ parseFile(f); } public static AudioMetaData parseAudioFile(File f) throws IOException{ if (LimeXMLUtils.isMP3File(f)) return new MP3MetaData(f); if (LimeXMLUtils.isOGGFile(f)) return new OGGMetaData(f); if (LimeXMLUtils.isFLACFile(f)) return new FLACMetaData(f); if (LimeXMLUtils.isM4AFile(f)) return new M4AMetaData(f); if (LimeXMLUtils.isWMAFile(f)) return new WMAMetaData(f); //TODO: add future supported audio types here return null; } public String getSchemaURI() { return schemaURI; } public String toString() { return "ID3Data: title[" + title + "], artist[" + artist + "], album[" + album + "], year[" + year + "], comment[" + comment + "], track[" + track + "], genre[" + genre + "], bitrate[" + bitrate + "], length[" + length + "], license[" + license + "], price[" + price + "], licensetype[" + licensetype + "]"; } public String getTitle() { return title; } public String getArtist() { return artist; } public String getAlbum() { return album; } public String getYear() { return year; } public String getComment() { return comment; } public short getTrack() { return track; } public short getTotalTracks() {return totalTracks;} public short getDisk() {return disk;} public short getTotalDisks() {return totalDisks;} public String getGenre() { return genre; } public int getBitrate() { return bitrate; } public int getLength() { return length; } public String getLicense() { return license; } public String getLicenseType() { return licensetype; } void setPrice(String price) { this.price = price; } void setTitle(String title) { this.title = title; } void setArtist(String artist) { this.artist = artist; } void setAlbum(String album) { this.album = album; } void setYear(String year) { this.year = year; } void setComment(String comment) { this.comment = comment; } void setTrack(short track) { this.track = track; } void setTotalTracks(short total) { totalTracks = total; } void setDisk(short disk) { this.disk =disk; } void setTotalDisks(short total) { totalDisks=total; } void setGenre(String genre) { this.genre = genre; } void setBitrate(int bitrate) { this.bitrate = bitrate; } void setLength(int length) { this.length = length; } void setLicense(String license) { this.license = license; } void setLicenseType(String licensetype) { this.licensetype = licensetype; } /** * Determines if all fields are valid. */ public boolean isComplete() { return isValid(title) && isValid(artist) && isValid(album) && isValid(year) && isValid(comment) && isValid(track) && isValid(genre) && isValid(bitrate) && isValid(length) && isValid(license) && isValid(licensetype); } /** * Writes the data to a NameValue list. */ public List toNameValueList() { List list = new ArrayList(); add(list, title, TITLE_KEY); add(list, artist, ARTIST_KEY); add(list, album, ALBUM_KEY); add(list, year, YEAR_KEY); add(list, comment, COMMENTS_KEY); add(list, track, TRACK_KEY); add(list, genre, GENRE_KEY); add(list, bitrate, BITRATE_KEY); add(list, length, SECONDS_KEY); add(list, license, LICENSE_KEY); add(list, licensetype, LICENSE_TYPE_KEY); return list; } private void add(List list, String value, String key) { if(isValid(value)) list.add(new NameValue(key, value.trim())); } private void add(List list, int value, String key) { if(isValid(value)) list.add(new NameValue(key, "" + value)); } private boolean isValid(String s) { return s != null && !s.trim().equals(""); } private boolean isValid(int i) { return i >= 0; } /** * Appends the key/value & a "\" to the string buffer. */ protected void appendStrings(String key, String value, StringBuffer appendTo) { appendTo.append(key); appendTo.append(value); appendTo.append("\""); } /** * Walks back through the byte array to trim off null characters and * spaces. A helper for read(...) above. * @return the number of bytes with nulls and spaces trimmed. */ protected int getTrimmedLength(byte[] bytes, int includedLength) { int i; for(i = includedLength - 1; (i >= 0) && ((bytes[i] == 0) || (bytes[i] == 32)); i--); //replace the nulls with spaces in the array upto i for(int j=0; j<=i; j++) if(bytes[j]==0) bytes[j]=(byte)32; return i + 1; } /** * Determines whether a LimeXMLDocument was corrupted by * ID3Editor in the past. */ public static boolean isCorrupted(LimeXMLDocument doc) { if(!schemaURI.equals(doc.getSchemaURI())) return false; Set existing = doc.getNameValueSet(); for(Iterator i = existing.iterator(); i.hasNext(); ) { Map.Entry entry = (Map.Entry)i.next(); final String name = (String)entry.getKey(); String value = (String)entry.getValue(); // album & artist were the corrupted fields ... if( name.equals(ALBUM_KEY) || name.equals(ARTIST_KEY) ) { if( value.length() == 30 ) { // if there is a value in the 29th char, but not // in the 28th, it's corrupted. if( value.charAt(29) != ' ' && value.charAt(28) == ' ' ) return true; } } } return false; } /** * Creates a new LimeXMLDocument without corruption. */ public static LimeXMLDocument fixCorruption(LimeXMLDocument oldDoc) { Set existing = oldDoc.getNameValueSet(); List info = new ArrayList(existing.size()); for(Iterator i = existing.iterator(); i.hasNext(); ) { Map.Entry entry = (Map.Entry)i.next(); final String name = (String)entry.getKey(); String value = (String)entry.getValue(); // album & artist were the corrupted fields ... if( name.equals(ALBUM_KEY) || name.equals(ARTIST_KEY) ) { if( value.length() == 30 ) { // if there is a value in the 29th char, but not // in the 28th, it's corrupted erase & trim. if( value.charAt(29) != ' ' && value.charAt(28) == ' ' ) value = value.substring(0, 29).trim(); } } info.add(new NameValue(name, value)); } return new LimeXMLDocument(info, oldDoc.getSchemaURI()); } public static boolean isNonLimeAudioField(String fieldName) { return !fieldName.equals(TRACK_KEY) && !fieldName.equals(ARTIST_KEY) && !fieldName.equals(ALBUM_KEY) && !fieldName.equals(TITLE_KEY) && !fieldName.equals(GENRE_KEY) && !fieldName.equals(YEAR_KEY) && !fieldName.equals(COMMENTS_KEY) && !fieldName.equals(BITRATE_KEY) && !fieldName.equals(SECONDS_KEY) && !fieldName.equals(LICENSE_KEY) && !fieldName.equals(PRICE_KEY) && !fieldName.equals(LICENSE_TYPE_KEY) ; } }