Reformatted vorbis reader for readability

This commit is contained in:
ByteHamster 2020-02-12 23:26:30 +01:00
parent 9db5450243
commit 246a2e650c
2 changed files with 221 additions and 242 deletions

View File

@ -38,10 +38,10 @@ public class VorbisCommentChapterReader extends VorbisCommentReader {
} }
@Override @Override
public void onContentVectorValue(String key, String value) public void onContentVectorValue(String key, String value) throws VorbisCommentReaderException {
throws VorbisCommentReaderException { if (BuildConfig.DEBUG) {
if (BuildConfig.DEBUG)
Log.d(TAG, "Key: " + key + ", value: " + value); Log.d(TAG, "Key: " + key + ", value: " + value);
}
String attribute = VorbisCommentChapter.getAttributeTypeFromKey(key); String attribute = VorbisCommentChapter.getAttributeTypeFromKey(key);
int id = VorbisCommentChapter.getIDFromKey(key); int id = VorbisCommentChapter.getIDFromKey(key);
Chapter chapter = getChapterById(id); Chapter chapter = getChapterById(id);
@ -53,9 +53,7 @@ public class VorbisCommentChapterReader extends VorbisCommentReader {
chapter.setStart(start); chapter.setStart(start);
chapters.add(chapter); chapters.add(chapter);
} else { } else {
throw new VorbisCommentReaderException( throw new VorbisCommentReaderException("Found chapter with duplicate ID (" + key + ", " + value + ")");
"Found chapter with duplicate ID (" + key + ", "
+ value + ")");
} }
} else if (attribute.equals(CHAPTER_ATTRIBUTE_TITLE)) { } else if (attribute.equals(CHAPTER_ATTRIBUTE_TITLE)) {
if (chapter != null) { if (chapter != null) {

View File

@ -1,5 +1,6 @@
package de.danoeh.antennapod.core.util.vorbiscommentreader; package de.danoeh.antennapod.core.util.vorbiscommentreader;
import androidx.annotation.NonNull;
import org.apache.commons.io.EndianUtils; import org.apache.commons.io.EndianUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
@ -10,7 +11,6 @@ import java.nio.ByteBuffer;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Arrays; import java.util.Arrays;
public abstract class VorbisCommentReader { public abstract class VorbisCommentReader {
/** Length of first page in an ogg file in bytes. */ /** Length of first page in an ogg file in bytes. */
private static final int FIRST_PAGE_LENGTH = 58; private static final int FIRST_PAGE_LENGTH = 58;
@ -31,11 +31,8 @@ public abstract class VorbisCommentReader {
/** /**
* Is called if onContentVectorKey returned true for the key. * Is called if onContentVectorKey returned true for the key.
*
* @throws VorbisCommentReaderException
*/ */
protected abstract void onContentVectorValue(String key, String value) protected abstract void onContentVectorValue(String key, String value) throws VorbisCommentReaderException;
throws VorbisCommentReaderException;
protected abstract void onNoVorbisCommentFound(); protected abstract void onNoVorbisCommentFound();
@ -43,45 +40,21 @@ public abstract class VorbisCommentReader {
protected abstract void onError(VorbisCommentReaderException exception); protected abstract void onError(VorbisCommentReaderException exception);
public void readInputStream(InputStream input) public void readInputStream(InputStream input) throws VorbisCommentReaderException {
throws VorbisCommentReaderException {
try { try {
// look for identification header // look for identification header
if (findIdentificationHeader(input)) { if (findIdentificationHeader(input)) {
onVorbisCommentFound(); onVorbisCommentFound();
input = new OggInputStream(input); input = new OggInputStream(input);
if (findCommentHeader(input)) { if (findCommentHeader(input)) {
VorbisCommentHeader commentHeader = readCommentHeader(input); VorbisCommentHeader commentHeader = readCommentHeader(input);
if (commentHeader != null) {
onVorbisCommentHeaderFound(commentHeader); onVorbisCommentHeaderFound(commentHeader);
for (int i = 0; i < commentHeader for (int i = 0; i < commentHeader.getUserCommentLength(); i++) {
.getUserCommentLength(); i++) { readUserComment(input);
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(); onEndOfComment();
}
} else { } else {
onError(new VorbisCommentReaderException( onError(new VorbisCommentReaderException("No comment header found"));
"No comment header found"));
} }
} else { } else {
onNoVorbisCommentFound(); onNoVorbisCommentFound();
@ -91,10 +64,24 @@ public abstract class VorbisCommentReader {
} }
} }
private String readUTF8String(InputStream input, long length) private void readUserComment(InputStream input) throws VorbisCommentReaderException {
throws IOException { try {
byte[] buffer = new byte[(int) length]; 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); IOUtils.readFully(input, buffer);
Charset charset = Charset.forName("UTF-8"); Charset charset = Charset.forName("UTF-8");
return charset.newDecoder().decode(ByteBuffer.wrap(buffer)).toString(); return charset.newDecoder().decode(ByteBuffer.wrap(buffer)).toString();
@ -104,15 +91,11 @@ public abstract class VorbisCommentReader {
* Looks for an identification header in the first page of the file. If an * 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 * identification header is found, it will be skipped completely and the
* method will return true, otherwise false. * method will return true, otherwise false.
*
* @throws IOException
*/ */
private boolean findIdentificationHeader(InputStream input) private boolean findIdentificationHeader(InputStream input) throws IOException {
throws IOException {
byte[] buffer = new byte[FIRST_PAGE_LENGTH]; byte[] buffer = new byte[FIRST_PAGE_LENGTH];
IOUtils.readFully(input, buffer); IOUtils.readFully(input, buffer);
int i; for (int i = 6; i < buffer.length; i++) {
for (i = 6; i < buffer.length; i++) {
if (buffer[i - 5] == 'v' && buffer[i - 4] == 'o' if (buffer[i - 5] == 'v' && buffer[i - 4] == 'o'
&& buffer[i - 3] == 'r' && buffer[i - 2] == 'b' && buffer[i - 3] == 'r' && buffer[i - 2] == 'b'
&& buffer[i - 1] == 'i' && buffer[i] == 's' && buffer[i - 1] == 'i' && buffer[i] == 's'
@ -165,21 +148,19 @@ public abstract class VorbisCommentReader {
return false; return false;
} }
private VorbisCommentHeader readCommentHeader(InputStream input) @NonNull
throws IOException, VorbisCommentReaderException { private VorbisCommentHeader readCommentHeader(InputStream input) throws IOException, VorbisCommentReaderException {
try { try {
long vendorLength = EndianUtils.readSwappedUnsignedInteger(input); long vendorLength = EndianUtils.readSwappedUnsignedInteger(input);
String vendorName = readUTF8String(input, vendorLength); String vendorName = readUtf8String(input, vendorLength);
long userCommentLength = EndianUtils long userCommentLength = EndianUtils.readSwappedUnsignedInteger(input);
.readSwappedUnsignedInteger(input);
return new VorbisCommentHeader(vendorName, userCommentLength); return new VorbisCommentHeader(vendorName, userCommentLength);
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
throw new VorbisCommentReaderException(e); throw new VorbisCommentReaderException(e);
} }
} }
private String readContentVectorKey(InputStream input, long vectorLength) private String readContentVectorKey(InputStream input, long vectorLength) throws IOException {
throws IOException {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for (int i = 0; i < vectorLength; i++) { for (int i = 0; i < vectorLength; i++) {
char c = (char) input.read(); char c = (char) input.read();