diff options
author | daniel oeh <daniel.oeh@gmail.com> | 2013-06-25 19:27:26 +0200 |
---|---|---|
committer | daniel oeh <daniel.oeh@gmail.com> | 2013-06-25 19:27:26 +0200 |
commit | 62961d6594687eb34e36adaeba55a90c99e2dd4e (patch) | |
tree | 12ab392df2803ec3d0a5526ac132f7926252f2aa /src/de/danoeh/antennapod/util/id3reader | |
parent | 4707139def5500f1039de669e53822d47855008c (diff) | |
parent | ddf77913bc7b0c4549ab1ea4b4aa462bf80ac406 (diff) | |
download | AntennaPod-62961d6594687eb34e36adaeba55a90c99e2dd4e.zip |
Merge branch 'develop'
Diffstat (limited to 'src/de/danoeh/antennapod/util/id3reader')
3 files changed, 99 insertions, 31 deletions
diff --git a/src/de/danoeh/antennapod/util/id3reader/ChapterReader.java b/src/de/danoeh/antennapod/util/id3reader/ChapterReader.java index e1cafe85d..f897f886c 100644 --- a/src/de/danoeh/antennapod/util/id3reader/ChapterReader.java +++ b/src/de/danoeh/antennapod/util/id3reader/ChapterReader.java @@ -2,18 +2,24 @@ package de.danoeh.antennapod.util.id3reader; import java.io.IOException; import java.io.InputStream; +import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; +import android.util.Log; + +import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.feed.Chapter; import de.danoeh.antennapod.feed.ID3Chapter; import de.danoeh.antennapod.util.id3reader.model.FrameHeader; import de.danoeh.antennapod.util.id3reader.model.TagHeader; public class ChapterReader extends ID3Reader { + private static final String TAG = "ID3ChapterReader"; private static final String FRAME_ID_CHAPTER = "CHAP"; private static final String FRAME_ID_TITLE = "TIT2"; + private static final String FRAME_ID_LINK = "WXXX"; private List<Chapter> chapters; private ID3Chapter currentChapter; @@ -33,27 +39,45 @@ public class ChapterReader extends ID3Reader { if (currentChapter != null) { if (!hasId3Chapter(currentChapter)) { chapters.add(currentChapter); - System.out.println("Found chapter: " + currentChapter); + if (AppConfig.DEBUG) Log.d(TAG, "Found chapter: " + currentChapter); currentChapter = null; } } - String elementId = readISOString(input, Integer.MAX_VALUE); + StringBuffer elementId = new StringBuffer(); + readISOString(elementId, input, Integer.MAX_VALUE); char[] startTimeSource = readBytes(input, 4); long startTime = ((int) startTimeSource[0] << 24) | ((int) startTimeSource[1] << 16) | ((int) startTimeSource[2] << 8) | startTimeSource[3]; - currentChapter = new ID3Chapter(elementId, startTime); + currentChapter = new ID3Chapter(elementId.toString(), startTime); skipBytes(input, 12); return ID3Reader.ACTION_DONT_SKIP; } else if (header.getId().equals(FRAME_ID_TITLE)) { if (currentChapter != null && currentChapter.getTitle() == null) { + StringBuffer title = new StringBuffer(); + readString(title, input, header.getSize()); currentChapter - .setTitle(readString(input, header.getSize())); - System.out.println("Found title: " + currentChapter.getTitle()); + .setTitle(title.toString()); + if (AppConfig.DEBUG) Log.d(TAG, "Found title: " + currentChapter.getTitle()); return ID3Reader.ACTION_DONT_SKIP; } - } + } else if (header.getId().equals(FRAME_ID_LINK)) { + if (currentChapter != null) { + // skip description + int descriptionLength = readString(null, input, header.getSize()); + StringBuffer link = new StringBuffer(); + readISOString(link, input, header.getSize() - descriptionLength); + String decodedLink = URLDecoder.decode(link.toString(), "UTF-8"); + + currentChapter.setLink(decodedLink); + + if (AppConfig.DEBUG) Log.d(TAG, "Found link: " + currentChapter.getLink()); + return ID3Reader.ACTION_DONT_SKIP; + } + } else if (header.getId().equals("APIC")) { + Log.d(TAG, header.toString()); + } return super.onStartFrameHeader(header, input); } diff --git a/src/de/danoeh/antennapod/util/id3reader/ID3Reader.java b/src/de/danoeh/antennapod/util/id3reader/ID3Reader.java index dff6d77e8..92f817363 100644 --- a/src/de/danoeh/antennapod/util/id3reader/ID3Reader.java +++ b/src/de/danoeh/antennapod/util/id3reader/ID3Reader.java @@ -24,7 +24,11 @@ public class ID3Reader { protected int readerPosition; - private static final byte ENCODING_UNICODE = 1; + private static final byte ENCODING_UTF16_WITH_BOM = 1; + private static final byte ENCODING_UTF16_WITHOUT_BOM = 2; + private static final byte ENCODING_UTF8 = 3; + + private TagHeader tagHeader; public ID3Reader() { } @@ -34,7 +38,7 @@ public class ID3Reader { int rc; readerPosition = 0; char[] tagHeaderSource = readBytes(input, HEADER_LENGTH); - TagHeader tagHeader = createTagHeader(tagHeaderSource); + tagHeader = createTagHeader(tagHeaderSource); if (tagHeader == null) { onNoTagHeaderFound(); } else { @@ -124,12 +128,12 @@ public class ID3Reader { + HEADER_LENGTH); } if (hasTag) { - String id = null; - id = new String(source, 0, ID3_LENGTH); + String id = new String(source, 0, ID3_LENGTH); char version = (char) ((source[3] << 8) | source[4]); byte flags = (byte) source[5]; int size = (source[6] << 24) | (source[7] << 16) | (source[8] << 8) | source[9]; + size = unsynchsafe(size); return new TagHeader(id, size, version, flags); } else { return null; @@ -142,48 +146,89 @@ public class ID3Reader { throw new ID3ReaderException("Length of header must be " + HEADER_LENGTH); } - String id = null; - id = new String(source, 0, FRAME_ID_LENGTH); - int size = (((int) source[4]) << 24) | (((int) source[5]) << 16) - | (((int) source[6]) << 8) | source[7]; + String id = new String(source, 0, FRAME_ID_LENGTH); + + int size = (((int) source[4]) << 24) | (((int) source[5]) << 16) + | (((int) source[6]) << 8) | source[7]; + if (tagHeader != null && tagHeader.getVersion() >= 0x0400) { + size = unsynchsafe(size); + } char flags = (char) ((source[8] << 8) | source[9]); return new FrameHeader(id, size, flags); } - protected String readString(InputStream input, int max) throws IOException, + private int unsynchsafe(int in) { + int out = 0; + int mask = 0x7F000000; + + while (mask != 0) { + out >>= 1; + out |= in & mask; + mask >>= 8; + } + + return out; + } + + protected int readString(StringBuffer buffer, InputStream input, int max) throws IOException, ID3ReaderException { if (max > 0) { char[] encoding = readBytes(input, 1); max--; - if (encoding[0] == ENCODING_UNICODE) { - return readUnicodeString(input, max); - } else { - return readISOString(input, max); + if (encoding[0] == ENCODING_UTF16_WITH_BOM || encoding[0] == ENCODING_UTF16_WITHOUT_BOM) { + return readUnicodeString(buffer, input, max, Charset.forName("UTF-16")) + 1; // take encoding byte into account + } else if (encoding[0] == ENCODING_UTF8) { + return readUnicodeString(buffer, input, max, Charset.forName("UTF-8")) + 1; // take encoding byte into account + } else { + return readISOString(buffer, input, max) + 1; // take encoding byte into account } } else { - return ""; + if (buffer != null) { + buffer.append(""); + } + return 0; } } - protected String readISOString(InputStream input, int max) + protected int readISOString(StringBuffer buffer, InputStream input, int max) throws IOException, ID3ReaderException { int bytesRead = 0; - StringBuilder builder = new StringBuilder(); char c; while (++bytesRead <= max && (c = (char) input.read()) > 0) { - builder.append(c); + if (buffer != null) { + buffer.append(c); + } } - return builder.toString(); + return bytesRead; } - private String readUnicodeString(InputStream input, int max) + private int readUnicodeString(StringBuffer strBuffer, InputStream input, int max, Charset charset) throws IOException, ID3ReaderException { byte[] buffer = new byte[max]; - IOUtils.readFully(input, buffer); - Charset charset = Charset.forName("UTF-16"); - return charset.newDecoder().decode(ByteBuffer.wrap(buffer)).toString(); + int c, cZero = -1; + int i = 0; + for (; i < max; i++) { + c = input.read(); + if (c == -1) { + break; + } else if (c == 0) { + if (cZero == 0) { + // termination character found + break; + } else { + cZero = 0; + } + } else { + buffer[i] = (byte) c; + cZero = -1; + } + } + if (strBuffer != null) { + strBuffer.append(charset.newDecoder().decode(ByteBuffer.wrap(buffer)).toString()); + } + return i; } public int onStartTagHeader(TagHeader header) { diff --git a/src/de/danoeh/antennapod/util/id3reader/model/FrameHeader.java b/src/de/danoeh/antennapod/util/id3reader/model/FrameHeader.java index 2c0d8e5ba..df73393a5 100644 --- a/src/de/danoeh/antennapod/util/id3reader/model/FrameHeader.java +++ b/src/de/danoeh/antennapod/util/id3reader/model/FrameHeader.java @@ -11,8 +11,7 @@ public class FrameHeader extends Header { @Override public String toString() { - return "FrameHeader [flags=" + Integer.toString(flags) + ", id=" + id + ", size=" + size - + "]"; - } + return String.format("FrameHeader [flags=%s, id=%s, size=%s]", Integer.toBinaryString(flags), id, Integer.toBinaryString(size)); + } } |