package com.frostwire.mp3; import java.util.Arrays; public class ID3v1Tag implements ID3v1 { public static final int TAG_LENGTH = 128; private static final String VERSION_0 = "0"; private static final String VERSION_1 = "1"; private static final String TAG = "TAG"; private static final int TITLE_OFFSET = 3; private static final int TITLE_LENGTH = 30; private static final int ARTIST_OFFSET = 33; private static final int ARTIST_LENGTH = 30; private static final int ALBUM_OFFSET = 63; private static final int ALBUM_LENGTH = 30; private static final int YEAR_OFFSET = 93; private static final int YEAR_LENGTH = 4; private static final int COMMENT_OFFSET = 97; private static final int COMMENT_LENGTH_V1_0 = 30; private static final int COMMENT_LENGTH_V1_1 = 28; private static final int TRACK_MARKER_OFFSET = 125; private static final int TRACK_OFFSET = 126; private static final int GENRE_OFFSET = 127; private String track = null; private String artist = null; private String title = null; private String album = null; private String year = null; private int genre = -1; private String comment = null; public ID3v1Tag() { } public ID3v1Tag(byte[] bytes) throws NoSuchTagException { unpackTag(bytes); } private void unpackTag(byte[] bytes) throws NoSuchTagException { sanityCheckTag(bytes); title = BufferTools.trimStringRight(BufferTools.byteBufferToString(bytes, TITLE_OFFSET, TITLE_LENGTH)); artist = BufferTools.trimStringRight(BufferTools.byteBufferToString(bytes, ARTIST_OFFSET, ARTIST_LENGTH)); album = BufferTools.trimStringRight(BufferTools.byteBufferToString(bytes, ALBUM_OFFSET, ALBUM_LENGTH)); year = BufferTools.trimStringRight(BufferTools.byteBufferToString(bytes, YEAR_OFFSET, YEAR_LENGTH)); genre = bytes[GENRE_OFFSET] & 0xFF; if (genre == 0xFF) { genre = -1; } if (bytes[TRACK_MARKER_OFFSET] != 0) { comment = BufferTools.trimStringRight(BufferTools.byteBufferToString(bytes, COMMENT_OFFSET, COMMENT_LENGTH_V1_0)); track = null; } else { comment = BufferTools.trimStringRight(BufferTools.byteBufferToString(bytes, COMMENT_OFFSET, COMMENT_LENGTH_V1_1)); int trackInt = bytes[TRACK_OFFSET]; if (trackInt == 0) { track = ""; } else { track = Integer.toString(trackInt); } } } private void sanityCheckTag(byte[] bytes) throws NoSuchTagException { if (bytes.length != TAG_LENGTH) { throw new NoSuchTagException("Buffer length wrong"); } if (! TAG.equals(BufferTools.byteBufferToString(bytes, 0, TAG.length()))) { throw new NoSuchTagException(); } } public byte[] toBytes() { byte[] bytes = new byte[TAG_LENGTH]; packTag(bytes); return bytes; } public void toBytes(byte[] bytes) { packTag(bytes); } public void packTag(byte[] bytes) { Arrays.fill(bytes, (byte)0); BufferTools.stringIntoByteBuffer(TAG, 0, 3, bytes, 0); packField(bytes, title, TITLE_LENGTH, TITLE_OFFSET); packField(bytes, artist, ARTIST_LENGTH, ARTIST_OFFSET); packField(bytes, album, ALBUM_LENGTH, ALBUM_OFFSET); packField(bytes, year, YEAR_LENGTH, YEAR_OFFSET); if (genre < 128) { bytes[GENRE_OFFSET] = (byte)genre; } else { bytes[GENRE_OFFSET] = (byte)(genre - 256); } if (track == null) { packField(bytes, comment, COMMENT_LENGTH_V1_0, COMMENT_OFFSET); } else { packField(bytes, comment, COMMENT_LENGTH_V1_1, COMMENT_OFFSET); String trackTemp = numericsOnly(track); if (trackTemp.length() > 0) { int trackInt = Integer.parseInt(trackTemp.toString()); if (trackInt < 128) { bytes[TRACK_OFFSET] = (byte)trackInt; } else { bytes[TRACK_OFFSET] = (byte)(trackInt - 256); } } } } private void packField(byte[] bytes, String value, int maxLength, int offset) { if (value != null) { BufferTools.stringIntoByteBuffer(value, 0, Math.min(value.length(), maxLength), bytes, offset); } } private String numericsOnly(String s) { StringBuffer stringBuffer = new StringBuffer(); for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if (ch >= '0' && ch <= '9') { stringBuffer.append(ch); } else { break; } } return stringBuffer.toString(); } public String getVersion() { if (track == null) { return VERSION_0; } else { return VERSION_1; } } public String getTrack() { return track; } public void setTrack(String track) { this.track = track; } public String getArtist() { return artist; } public void setArtist(String artist) { this.artist = artist; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getAlbum() { return album; } public void setAlbum(String album) { this.album = album; } public String getYear() { return year; } public void setYear(String year) { this.year = year; } public int getGenre() { return genre; } public void setGenre(int genre) { this.genre = genre; } public String getGenreDescription() { try { return ID3v1Genres.GENRES[genre]; } catch (ArrayIndexOutOfBoundsException e) { return "Unknown"; } } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } public boolean equals(Object obj) { if (! (obj instanceof ID3v1Tag)) return false; if (super.equals(obj)) return true; ID3v1Tag other = (ID3v1Tag) obj; if (genre != other.genre) return false; if (track == null) { if (other.track != null) return false; } else if (other.track == null) return false; else if (! track.equals(other.track)) return false; if (artist == null) { if (other.artist != null) return false; } else if (other.artist == null) return false; else if (! artist.equals(other.artist)) return false; if (title == null) { if (other.title != null) return false; } else if (other.title == null) return false; else if (! title.equals(other.title)) return false; if (album == null) { if (other.album != null) return false; } else if (other.album == null) return false; else if (! album.equals(other.album)) return false; if (year == null) { if (other.year != null) return false; } else if (other.year == null) return false; else if (! year.equals(other.year)) return false; if (comment == null) { if (other.comment != null) return false; } else if (other.comment == null) return false; else if (! comment.equals(other.comment)) return false; return true; } }