summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorByteHamster <info@bytehamster.com>2020-02-12 23:26:30 +0100
committerByteHamster <info@bytehamster.com>2020-02-12 23:26:30 +0100
commit246a2e650cedc25afe705d7b5422774b02c623e1 (patch)
tree497916fbdfc9b5f032442d1fac905ff5d8e0bbc6
parent9db54502434ef375414be9148a6de3b7d4a1f300 (diff)
downloadAntennaPod-246a2e650cedc25afe705d7b5422774b02c623e1.zip
Reformatted vorbis reader for readability
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentChapterReader.java174
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentReader.java341
2 files changed, 247 insertions, 268 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentChapterReader.java b/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentChapterReader.java
index 569ff3438..c4fe76780 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentChapterReader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentChapterReader.java
@@ -10,93 +10,91 @@ import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.VorbisCommentChapter;
public class VorbisCommentChapterReader extends VorbisCommentReader {
- private static final String TAG = "VorbisCommentChptrReadr";
-
- private static final String CHAPTER_KEY = "chapter\\d\\d\\d.*";
- private static final String CHAPTER_ATTRIBUTE_TITLE = "name";
- private static final String CHAPTER_ATTRIBUTE_LINK = "url";
-
- private List<Chapter> chapters;
-
- public VorbisCommentChapterReader() {
- }
-
- @Override
- public void onVorbisCommentFound() {
- System.out.println("Vorbis comment found");
- }
-
- @Override
- public void onVorbisCommentHeaderFound(VorbisCommentHeader header) {
- chapters = new ArrayList<>();
- System.out.println(header.toString());
- }
-
- @Override
- public boolean onContentVectorKey(String content) {
- return content.matches(CHAPTER_KEY);
- }
-
- @Override
- public void onContentVectorValue(String key, String value)
- throws VorbisCommentReaderException {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Key: " + key + ", value: " + value);
- String attribute = VorbisCommentChapter.getAttributeTypeFromKey(key);
- int id = VorbisCommentChapter.getIDFromKey(key);
- Chapter chapter = getChapterById(id);
- if (attribute == null) {
- if (getChapterById(id) == null) {
- // new chapter
- long start = VorbisCommentChapter.getStartTimeFromValue(value);
- chapter = new VorbisCommentChapter(id);
- chapter.setStart(start);
- chapters.add(chapter);
- } else {
- throw new VorbisCommentReaderException(
- "Found chapter with duplicate ID (" + key + ", "
- + value + ")");
- }
- } else if (attribute.equals(CHAPTER_ATTRIBUTE_TITLE)) {
- if (chapter != null) {
- chapter.setTitle(value);
- }
- } else if (attribute.equals(CHAPTER_ATTRIBUTE_LINK)) {
- if (chapter != null) {
- chapter.setLink(value);
- }
- }
- }
-
- @Override
- public void onNoVorbisCommentFound() {
- System.out.println("No vorbis comment found");
- }
-
- @Override
- public void onEndOfComment() {
- System.out.println("End of comment");
- for (Chapter c : chapters) {
- System.out.println(c.toString());
- }
- }
-
- @Override
- public void onError(VorbisCommentReaderException exception) {
- exception.printStackTrace();
- }
-
- private Chapter getChapterById(long id) {
- for (Chapter c : chapters) {
- if (((VorbisCommentChapter) c).getVorbisCommentId() == id) {
- return c;
- }
- }
- return null;
- }
-
- public List<Chapter> getChapters() {
- return chapters;
- }
+ private static final String TAG = "VorbisCommentChptrReadr";
+
+ private static final String CHAPTER_KEY = "chapter\\d\\d\\d.*";
+ private static final String CHAPTER_ATTRIBUTE_TITLE = "name";
+ private static final String CHAPTER_ATTRIBUTE_LINK = "url";
+
+ private List<Chapter> chapters;
+
+ public VorbisCommentChapterReader() {
+ }
+
+ @Override
+ public void onVorbisCommentFound() {
+ System.out.println("Vorbis comment found");
+ }
+
+ @Override
+ public void onVorbisCommentHeaderFound(VorbisCommentHeader header) {
+ chapters = new ArrayList<>();
+ System.out.println(header.toString());
+ }
+
+ @Override
+ public boolean onContentVectorKey(String content) {
+ return content.matches(CHAPTER_KEY);
+ }
+
+ @Override
+ public void onContentVectorValue(String key, String value) throws VorbisCommentReaderException {
+ if (BuildConfig.DEBUG) {
+ Log.d(TAG, "Key: " + key + ", value: " + value);
+ }
+ String attribute = VorbisCommentChapter.getAttributeTypeFromKey(key);
+ int id = VorbisCommentChapter.getIDFromKey(key);
+ Chapter chapter = getChapterById(id);
+ if (attribute == null) {
+ if (getChapterById(id) == null) {
+ // new chapter
+ long start = VorbisCommentChapter.getStartTimeFromValue(value);
+ chapter = new VorbisCommentChapter(id);
+ chapter.setStart(start);
+ chapters.add(chapter);
+ } else {
+ throw new VorbisCommentReaderException("Found chapter with duplicate ID (" + key + ", " + value + ")");
+ }
+ } else if (attribute.equals(CHAPTER_ATTRIBUTE_TITLE)) {
+ if (chapter != null) {
+ chapter.setTitle(value);
+ }
+ } else if (attribute.equals(CHAPTER_ATTRIBUTE_LINK)) {
+ if (chapter != null) {
+ chapter.setLink(value);
+ }
+ }
+ }
+
+ @Override
+ public void onNoVorbisCommentFound() {
+ System.out.println("No vorbis comment found");
+ }
+
+ @Override
+ public void onEndOfComment() {
+ System.out.println("End of comment");
+ for (Chapter c : chapters) {
+ System.out.println(c.toString());
+ }
+ }
+
+ @Override
+ public void onError(VorbisCommentReaderException exception) {
+ exception.printStackTrace();
+ }
+
+ private Chapter getChapterById(long id) {
+ for (Chapter c : chapters) {
+ if (((VorbisCommentChapter) c).getVorbisCommentId() == id) {
+ return c;
+ }
+ }
+ return null;
+ }
+
+ public List<Chapter> getChapters() {
+ return chapters;
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentReader.java b/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentReader.java
index 55498afcb..e5924b1ab 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentReader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentReader.java
@@ -1,5 +1,6 @@
package de.danoeh.antennapod.core.util.vorbiscommentreader;
+import androidx.annotation.NonNull;
import org.apache.commons.io.EndianUtils;
import org.apache.commons.io.IOUtils;
@@ -10,185 +11,165 @@ import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Arrays;
-
public abstract class VorbisCommentReader {
- /** Length of first page in an ogg file in bytes. */
- private static final int FIRST_PAGE_LENGTH = 58;
- private static final int SECOND_PAGE_MAX_LENGTH = 64 * 1024 * 1024;
- private static final int PACKET_TYPE_IDENTIFICATION = 1;
- private static final int PACKET_TYPE_COMMENT = 3;
-
- /** Called when Reader finds identification header. */
- protected abstract void onVorbisCommentFound();
-
- protected abstract void onVorbisCommentHeaderFound(VorbisCommentHeader header);
-
- /**
- * Is called every time the Reader finds a content vector. The handler
- * should return true if it wants to handle the content vector.
- */
- protected abstract boolean onContentVectorKey(String content);
-
- /**
- * Is called if onContentVectorKey returned true for the key.
- *
- * @throws VorbisCommentReaderException
- */
- protected abstract void onContentVectorValue(String key, String value)
- throws VorbisCommentReaderException;
-
- protected abstract void onNoVorbisCommentFound();
-
- protected abstract void onEndOfComment();
-
- protected abstract void onError(VorbisCommentReaderException exception);
-
- public void readInputStream(InputStream input)
- throws VorbisCommentReaderException {
- try {
- // look for identification header
- if (findIdentificationHeader(input)) {
-
- onVorbisCommentFound();
- input = new OggInputStream(input);
- if (findCommentHeader(input)) {
- VorbisCommentHeader commentHeader = readCommentHeader(input);
- if (commentHeader != null) {
- onVorbisCommentHeaderFound(commentHeader);
- for (int i = 0; i < commentHeader
- .getUserCommentLength(); i++) {
- try {
- long vectorLength = EndianUtils
- .readSwappedUnsignedInteger(input);
- String key = readContentVectorKey(input,
- vectorLength).toLowerCase();
- boolean readValue = onContentVectorKey(key);
- if (readValue) {
- String value = readUTF8String(
- input,
- (int) (vectorLength - key.length() - 1));
- onContentVectorValue(key, value);
- } else {
- IOUtils.skipFully(input,
- vectorLength - key.length() - 1);
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- onEndOfComment();
- }
-
- } else {
- onError(new VorbisCommentReaderException(
- "No comment header found"));
- }
- } else {
- onNoVorbisCommentFound();
- }
- } catch (IOException e) {
- onError(new VorbisCommentReaderException(e));
- }
- }
-
- private String readUTF8String(InputStream input, long length)
- throws IOException {
- byte[] buffer = new byte[(int) length];
-
- IOUtils.readFully(input, buffer);
- Charset charset = Charset.forName("UTF-8");
- return charset.newDecoder().decode(ByteBuffer.wrap(buffer)).toString();
- }
-
- /**
- * Looks for an identification header in the first page of the file. If an
- * identification header is found, it will be skipped completely and the
- * method will return true, otherwise false.
- *
- * @throws IOException
- */
- private boolean findIdentificationHeader(InputStream input)
- throws IOException {
- byte[] buffer = new byte[FIRST_PAGE_LENGTH];
- IOUtils.readFully(input, buffer);
- int i;
- for (i = 6; i < buffer.length; i++) {
- if (buffer[i - 5] == 'v' && buffer[i - 4] == 'o'
- && buffer[i - 3] == 'r' && buffer[i - 2] == 'b'
- && buffer[i - 1] == 'i' && buffer[i] == 's'
- && buffer[i - 6] == PACKET_TYPE_IDENTIFICATION) {
- return true;
- }
- }
- return false;
- }
-
- private boolean findCommentHeader(InputStream input) throws IOException {
- char[] buffer = new char["vorbis".length() + 1];
- for (int bytesRead = 0; bytesRead < SECOND_PAGE_MAX_LENGTH; bytesRead++) {
- char c = (char) input.read();
- int dest = -1;
- switch (c) {
- case PACKET_TYPE_COMMENT:
- dest = 0;
- break;
- case 'v':
- dest = 1;
- break;
- case 'o':
- dest = 2;
- break;
- case 'r':
- dest = 3;
- break;
- case 'b':
- dest = 4;
- break;
- case 'i':
- dest = 5;
- break;
- case 's':
- dest = 6;
- break;
- }
- if (dest >= 0) {
- buffer[dest] = c;
- if (buffer[1] == 'v' && buffer[2] == 'o' && buffer[3] == 'r'
- && buffer[4] == 'b' && buffer[5] == 'i'
- && buffer[6] == 's' && buffer[0] == PACKET_TYPE_COMMENT) {
- return true;
- }
- } else {
- Arrays.fill(buffer, (char) 0);
- }
- }
- return false;
- }
-
- private VorbisCommentHeader readCommentHeader(InputStream input)
- throws IOException, VorbisCommentReaderException {
- try {
- long vendorLength = EndianUtils.readSwappedUnsignedInteger(input);
- String vendorName = readUTF8String(input, vendorLength);
- long userCommentLength = EndianUtils
- .readSwappedUnsignedInteger(input);
- return new VorbisCommentHeader(vendorName, userCommentLength);
- } catch (UnsupportedEncodingException e) {
- throw new VorbisCommentReaderException(e);
- }
- }
-
- private String readContentVectorKey(InputStream input, long vectorLength)
- throws IOException {
- StringBuilder builder = new StringBuilder();
- for (int i = 0; i < vectorLength; i++) {
- char c = (char) input.read();
- if (c == '=') {
- return builder.toString();
- } else {
- builder.append(c);
- }
- }
- return null; // no key found
- }
+ /** Length of first page in an ogg file in bytes. */
+ private static final int FIRST_PAGE_LENGTH = 58;
+ private static final int SECOND_PAGE_MAX_LENGTH = 64 * 1024 * 1024;
+ private static final int PACKET_TYPE_IDENTIFICATION = 1;
+ private static final int PACKET_TYPE_COMMENT = 3;
+
+ /** Called when Reader finds identification header. */
+ protected abstract void onVorbisCommentFound();
+
+ protected abstract void onVorbisCommentHeaderFound(VorbisCommentHeader header);
+
+ /**
+ * Is called every time the Reader finds a content vector. The handler
+ * should return true if it wants to handle the content vector.
+ */
+ protected abstract boolean onContentVectorKey(String content);
+
+ /**
+ * Is called if onContentVectorKey returned true for the key.
+ */
+ protected abstract void onContentVectorValue(String key, String value) throws VorbisCommentReaderException;
+
+ protected abstract void onNoVorbisCommentFound();
+
+ protected abstract void onEndOfComment();
+
+ protected abstract void onError(VorbisCommentReaderException exception);
+
+ public void readInputStream(InputStream input) throws VorbisCommentReaderException {
+ try {
+ // look for identification header
+ if (findIdentificationHeader(input)) {
+ onVorbisCommentFound();
+ input = new OggInputStream(input);
+ if (findCommentHeader(input)) {
+ VorbisCommentHeader commentHeader = readCommentHeader(input);
+ onVorbisCommentHeaderFound(commentHeader);
+ for (int i = 0; i < commentHeader.getUserCommentLength(); i++) {
+ readUserComment(input);
+ }
+ onEndOfComment();
+ } else {
+ onError(new VorbisCommentReaderException("No comment header found"));
+ }
+ } else {
+ onNoVorbisCommentFound();
+ }
+ } catch (IOException e) {
+ onError(new VorbisCommentReaderException(e));
+ }
+ }
+
+ private void readUserComment(InputStream input) throws VorbisCommentReaderException {
+ try {
+ long vectorLength = EndianUtils.readSwappedUnsignedInteger(input);
+ String key = readContentVectorKey(input, vectorLength).toLowerCase();
+ boolean readValue = onContentVectorKey(key);
+ if (readValue) {
+ String value = readUtf8String(input, (int) (vectorLength - key.length() - 1));
+ onContentVectorValue(key, value);
+ } else {
+ IOUtils.skipFully(input, vectorLength - key.length() - 1);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private String readUtf8String(InputStream input, long length) throws IOException {
+ byte[] buffer = new byte[(int) length];
+ IOUtils.readFully(input, buffer);
+ Charset charset = Charset.forName("UTF-8");
+ return charset.newDecoder().decode(ByteBuffer.wrap(buffer)).toString();
+ }
+
+ /**
+ * Looks for an identification header in the first page of the file. If an
+ * identification header is found, it will be skipped completely and the
+ * method will return true, otherwise false.
+ */
+ private boolean findIdentificationHeader(InputStream input) throws IOException {
+ byte[] buffer = new byte[FIRST_PAGE_LENGTH];
+ IOUtils.readFully(input, buffer);
+ for (int i = 6; i < buffer.length; i++) {
+ if (buffer[i - 5] == 'v' && buffer[i - 4] == 'o'
+ && buffer[i - 3] == 'r' && buffer[i - 2] == 'b'
+ && buffer[i - 1] == 'i' && buffer[i] == 's'
+ && buffer[i - 6] == PACKET_TYPE_IDENTIFICATION) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean findCommentHeader(InputStream input) throws IOException {
+ char[] buffer = new char["vorbis".length() + 1];
+ for (int bytesRead = 0; bytesRead < SECOND_PAGE_MAX_LENGTH; bytesRead++) {
+ char c = (char) input.read();
+ int dest = -1;
+ switch (c) {
+ case PACKET_TYPE_COMMENT:
+ dest = 0;
+ break;
+ case 'v':
+ dest = 1;
+ break;
+ case 'o':
+ dest = 2;
+ break;
+ case 'r':
+ dest = 3;
+ break;
+ case 'b':
+ dest = 4;
+ break;
+ case 'i':
+ dest = 5;
+ break;
+ case 's':
+ dest = 6;
+ break;
+ }
+ if (dest >= 0) {
+ buffer[dest] = c;
+ if (buffer[1] == 'v' && buffer[2] == 'o' && buffer[3] == 'r'
+ && buffer[4] == 'b' && buffer[5] == 'i'
+ && buffer[6] == 's' && buffer[0] == PACKET_TYPE_COMMENT) {
+ return true;
+ }
+ } else {
+ Arrays.fill(buffer, (char) 0);
+ }
+ }
+ return false;
+ }
+
+ @NonNull
+ private VorbisCommentHeader readCommentHeader(InputStream input) throws IOException, VorbisCommentReaderException {
+ try {
+ long vendorLength = EndianUtils.readSwappedUnsignedInteger(input);
+ String vendorName = readUtf8String(input, vendorLength);
+ long userCommentLength = EndianUtils.readSwappedUnsignedInteger(input);
+ return new VorbisCommentHeader(vendorName, userCommentLength);
+ } catch (UnsupportedEncodingException e) {
+ throw new VorbisCommentReaderException(e);
+ }
+ }
+
+ private String readContentVectorKey(InputStream input, long vectorLength) throws IOException {
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < vectorLength; i++) {
+ char c = (char) input.read();
+ if (c == '=') {
+ return builder.toString();
+ } else {
+ builder.append(c);
+ }
+ }
+ return null; // no key found
+ }
}