Read vorbis description of local files
This commit is contained in:
parent
36a36e4f85
commit
933fde839e
@ -38,6 +38,8 @@ import de.danoeh.antennapod.model.playback.MediaType;
|
|||||||
import de.danoeh.antennapod.parser.feed.util.MimeTypeUtils;
|
import de.danoeh.antennapod.parser.feed.util.MimeTypeUtils;
|
||||||
import de.danoeh.antennapod.parser.media.id3.ID3ReaderException;
|
import de.danoeh.antennapod.parser.media.id3.ID3ReaderException;
|
||||||
import de.danoeh.antennapod.parser.media.id3.Id3MetadataReader;
|
import de.danoeh.antennapod.parser.media.id3.Id3MetadataReader;
|
||||||
|
import de.danoeh.antennapod.parser.media.vorbis.VorbisCommentMetadataReader;
|
||||||
|
import de.danoeh.antennapod.parser.media.vorbis.VorbisCommentReaderException;
|
||||||
import org.apache.commons.io.input.CountingInputStream;
|
import org.apache.commons.io.input.CountingInputStream;
|
||||||
|
|
||||||
public class LocalFeedUpdater {
|
public class LocalFeedUpdater {
|
||||||
@ -209,8 +211,15 @@ public class LocalFeedUpdater {
|
|||||||
reader.readInputStream();
|
reader.readInputStream();
|
||||||
item.setDescriptionIfLonger(reader.getComment());
|
item.setDescriptionIfLonger(reader.getComment());
|
||||||
} catch (IOException | ID3ReaderException e) {
|
} catch (IOException | ID3ReaderException e) {
|
||||||
// Do not flood Logcat with full stack traces
|
|
||||||
Log.d(TAG, "Unable to parse ID3 of " + file.getUri() + ": " + e.getMessage());
|
Log.d(TAG, "Unable to parse ID3 of " + file.getUri() + ": " + e.getMessage());
|
||||||
|
|
||||||
|
try (InputStream inputStream = context.getContentResolver().openInputStream(file.getUri())) {
|
||||||
|
VorbisCommentMetadataReader reader = new VorbisCommentMetadataReader(inputStream);
|
||||||
|
reader.readInputStream();
|
||||||
|
item.setDescriptionIfLonger(reader.getDescription());
|
||||||
|
} catch (IOException | VorbisCommentReaderException e2) {
|
||||||
|
Log.d(TAG, "Unable to parse vorbis comments of " + file.getUri() + ": " + e2.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,8 +171,8 @@ public class ChapterUtils {
|
|||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private static List<Chapter> readOggChaptersFromInputStream(InputStream input) throws VorbisCommentReaderException {
|
private static List<Chapter> readOggChaptersFromInputStream(InputStream input) throws VorbisCommentReaderException {
|
||||||
VorbisCommentChapterReader reader = new VorbisCommentChapterReader();
|
VorbisCommentChapterReader reader = new VorbisCommentChapterReader(input);
|
||||||
reader.readInputStream(input);
|
reader.readInputStream();
|
||||||
List<Chapter> chapters = reader.getChapters();
|
List<Chapter> chapters = reader.getChapters();
|
||||||
if (chapters == null) {
|
if (chapters == null) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
@ -2,6 +2,7 @@ package de.danoeh.antennapod.parser.media.vorbis;
|
|||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -17,25 +18,15 @@ public class VorbisCommentChapterReader extends VorbisCommentReader {
|
|||||||
private static final String CHAPTER_ATTRIBUTE_LINK = "url";
|
private static final String CHAPTER_ATTRIBUTE_LINK = "url";
|
||||||
private static final int CHAPTERXXX_LENGTH = "chapterxxx".length();
|
private static final int CHAPTERXXX_LENGTH = "chapterxxx".length();
|
||||||
|
|
||||||
private List<Chapter> chapters;
|
private final List<Chapter> chapters = new ArrayList<>();
|
||||||
|
|
||||||
public VorbisCommentChapterReader() {
|
public VorbisCommentChapterReader(InputStream input) {
|
||||||
|
super(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onVorbisCommentFound() {
|
public boolean handles(String key) {
|
||||||
System.out.println("Vorbis comment found");
|
return key.matches(CHAPTER_KEY);
|
||||||
}
|
|
||||||
|
|
||||||
@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
|
@Override
|
||||||
@ -68,19 +59,6 @@ public class VorbisCommentChapterReader extends VorbisCommentReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@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) {
|
private Chapter getChapterById(long id) {
|
||||||
for (Chapter c : chapters) {
|
for (Chapter c : chapters) {
|
||||||
if (("" + id).equals(c.getChapterId())) {
|
if (("" + id).equals(c.getChapterId())) {
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
package de.danoeh.antennapod.parser.media.vorbis;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class VorbisCommentMetadataReader extends VorbisCommentReader {
|
||||||
|
private static final String KEY_DESCRIPTION = "description";
|
||||||
|
private static final String KEY_COMMENT = "comment";
|
||||||
|
|
||||||
|
private String description = null;
|
||||||
|
|
||||||
|
public VorbisCommentMetadataReader(InputStream input) {
|
||||||
|
super(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handles(String key) {
|
||||||
|
return KEY_DESCRIPTION.equals(key) || KEY_COMMENT.equals(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onContentVectorValue(String key, String value) {
|
||||||
|
if (KEY_DESCRIPTION.equals(key) || KEY_COMMENT.equals(key)) {
|
||||||
|
if (description == null || value.length() > description.length()) {
|
||||||
|
description = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ package de.danoeh.antennapod.parser.media.vorbis;
|
|||||||
import androidx.annotation.NonNull;
|
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;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -12,51 +13,35 @@ import java.nio.charset.Charset;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
public abstract class VorbisCommentReader {
|
public abstract class VorbisCommentReader {
|
||||||
/** Length of first page in an ogg file in bytes. */
|
private static final String TAG = "VorbisCommentReader";
|
||||||
private static final int FIRST_OGG_PAGE_LENGTH = 58;
|
private static final int FIRST_OGG_PAGE_LENGTH = 58;
|
||||||
private static final int FIRST_OPUS_PAGE_LENGTH = 47;
|
private static final int FIRST_OPUS_PAGE_LENGTH = 47;
|
||||||
private static final int SECOND_PAGE_MAX_LENGTH = 64 * 1024 * 1024;
|
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_IDENTIFICATION = 1;
|
||||||
private static final int PACKET_TYPE_COMMENT = 3;
|
private static final int PACKET_TYPE_COMMENT = 3;
|
||||||
|
|
||||||
/** Called when Reader finds identification header. */
|
private final InputStream input;
|
||||||
protected abstract void onVorbisCommentFound();
|
|
||||||
|
|
||||||
protected abstract void onVorbisCommentHeaderFound(VorbisCommentHeader header);
|
VorbisCommentReader(InputStream input) {
|
||||||
|
this.input = input;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
public void readInputStream() throws VorbisCommentReaderException {
|
||||||
* 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 onEndOfComment();
|
|
||||||
|
|
||||||
protected abstract void onError(VorbisCommentReaderException exception);
|
|
||||||
|
|
||||||
public void readInputStream(InputStream input) throws VorbisCommentReaderException {
|
|
||||||
try {
|
try {
|
||||||
findIdentificationHeader(input);
|
findIdentificationHeader();
|
||||||
onVorbisCommentFound();
|
findOggPage();
|
||||||
findOggPage(input);
|
findCommentHeader();
|
||||||
findCommentHeader(input);
|
VorbisCommentHeader commentHeader = readCommentHeader();
|
||||||
VorbisCommentHeader commentHeader = readCommentHeader(input);
|
Log.d(TAG, commentHeader.toString());
|
||||||
onVorbisCommentHeaderFound(commentHeader);
|
|
||||||
for (int i = 0; i < commentHeader.getUserCommentLength(); i++) {
|
for (int i = 0; i < commentHeader.getUserCommentLength(); i++) {
|
||||||
readUserComment(input);
|
readUserComment();
|
||||||
}
|
}
|
||||||
onEndOfComment();
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
onError(new VorbisCommentReaderException(e));
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void findOggPage(InputStream input) throws IOException {
|
private void findOggPage() throws IOException {
|
||||||
// find OggS
|
// find OggS
|
||||||
byte[] buffer = new byte[4];
|
byte[] buffer = new byte[4];
|
||||||
final byte[] oggPageHeader = {'O', 'g', 'g', 'S'};
|
final byte[] oggPageHeader = {'O', 'g', 'g', 'S'};
|
||||||
@ -76,17 +61,19 @@ public abstract class VorbisCommentReader {
|
|||||||
IOUtils.skipFully(input, numSegments);
|
IOUtils.skipFully(input, numSegments);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readUserComment(InputStream input) throws VorbisCommentReaderException {
|
private void readUserComment() throws VorbisCommentReaderException {
|
||||||
try {
|
try {
|
||||||
long vectorLength = EndianUtils.readSwappedUnsignedInteger(input);
|
long vectorLength = EndianUtils.readSwappedUnsignedInteger(input);
|
||||||
if (vectorLength > 20 * 1024 * 1024) {
|
if (vectorLength > 20 * 1024 * 1024) {
|
||||||
// Avoid reading entire file if it is encoded incorrectly
|
String keyPart = readUtf8String(10);
|
||||||
throw new VorbisCommentReaderException("User comment unrealistically long: " + vectorLength);
|
throw new VorbisCommentReaderException("User comment unrealistically long. "
|
||||||
|
+ "key=" + keyPart + ", length=" + vectorLength);
|
||||||
}
|
}
|
||||||
String key = readContentVectorKey(input, vectorLength).toLowerCase(Locale.US);
|
String key = readContentVectorKey(vectorLength).toLowerCase(Locale.US);
|
||||||
boolean readValue = onContentVectorKey(key);
|
boolean shouldReadValue = handles(key);
|
||||||
if (readValue) {
|
Log.d(TAG, "key=" + key + ", length=" + vectorLength + ", handles=" + shouldReadValue);
|
||||||
String value = readUtf8String(input, vectorLength - key.length() - 1);
|
if (shouldReadValue) {
|
||||||
|
String value = readUtf8String(vectorLength - key.length() - 1);
|
||||||
onContentVectorValue(key, value);
|
onContentVectorValue(key, value);
|
||||||
} else {
|
} else {
|
||||||
IOUtils.skipFully(input, vectorLength - key.length() - 1);
|
IOUtils.skipFully(input, vectorLength - key.length() - 1);
|
||||||
@ -96,7 +83,7 @@ public abstract class VorbisCommentReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String readUtf8String(InputStream input, long length) throws IOException {
|
private String readUtf8String(long length) throws IOException {
|
||||||
byte[] buffer = new byte[(int) length];
|
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");
|
||||||
@ -107,7 +94,7 @@ 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
|
* identification header is found, it will be skipped completely
|
||||||
*/
|
*/
|
||||||
private void findIdentificationHeader(InputStream input) throws IOException {
|
private void findIdentificationHeader() throws IOException {
|
||||||
byte[] buffer = new byte[FIRST_OPUS_PAGE_LENGTH];
|
byte[] buffer = new byte[FIRST_OPUS_PAGE_LENGTH];
|
||||||
IOUtils.readFully(input, buffer);
|
IOUtils.readFully(input, buffer);
|
||||||
final byte[] oggIdentificationHeader = new byte[]{ PACKET_TYPE_IDENTIFICATION, 'v', 'o', 'r', 'b', 'i', 's' };
|
final byte[] oggIdentificationHeader = new byte[]{ PACKET_TYPE_IDENTIFICATION, 'v', 'o', 'r', 'b', 'i', 's' };
|
||||||
@ -122,7 +109,7 @@ public abstract class VorbisCommentReader {
|
|||||||
throw new IOException("No vorbis identification header found");
|
throw new IOException("No vorbis identification header found");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void findCommentHeader(InputStream input) throws IOException {
|
private void findCommentHeader() throws IOException {
|
||||||
byte[] buffer = new byte[64]; // Enough space for some bytes. Used circularly.
|
byte[] buffer = new byte[64]; // Enough space for some bytes. Used circularly.
|
||||||
final byte[] oggCommentHeader = new byte[]{ PACKET_TYPE_COMMENT, 'v', 'o', 'r', 'b', 'i', 's' };
|
final byte[] oggCommentHeader = new byte[]{ PACKET_TYPE_COMMENT, 'v', 'o', 'r', 'b', 'i', 's' };
|
||||||
for (int bytesRead = 0; bytesRead < SECOND_PAGE_MAX_LENGTH; bytesRead++) {
|
for (int bytesRead = 0; bytesRead < SECOND_PAGE_MAX_LENGTH; bytesRead++) {
|
||||||
@ -155,10 +142,10 @@ public abstract class VorbisCommentReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private VorbisCommentHeader readCommentHeader(InputStream input) throws IOException, VorbisCommentReaderException {
|
private VorbisCommentHeader readCommentHeader() throws IOException, VorbisCommentReaderException {
|
||||||
try {
|
try {
|
||||||
long vendorLength = EndianUtils.readSwappedUnsignedInteger(input);
|
long vendorLength = EndianUtils.readSwappedUnsignedInteger(input);
|
||||||
String vendorName = readUtf8String(input, vendorLength);
|
String vendorName = readUtf8String(vendorLength);
|
||||||
long userCommentLength = EndianUtils.readSwappedUnsignedInteger(input);
|
long userCommentLength = EndianUtils.readSwappedUnsignedInteger(input);
|
||||||
return new VorbisCommentHeader(vendorName, userCommentLength);
|
return new VorbisCommentHeader(vendorName, userCommentLength);
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
@ -166,7 +153,7 @@ public abstract class VorbisCommentReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String readContentVectorKey(InputStream input, long vectorLength) throws IOException {
|
private String readContentVectorKey(long vectorLength) 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();
|
||||||
@ -178,4 +165,15 @@ public abstract class VorbisCommentReader {
|
|||||||
}
|
}
|
||||||
return null; // no key found
|
return null; // no key found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 handles(String key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is called if onContentVectorKey returned true for the key.
|
||||||
|
*/
|
||||||
|
protected abstract void onContentVectorValue(String key, String value) throws VorbisCommentReaderException;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
package de.danoeh.antennapod.parser.media.id3;
|
||||||
|
|
||||||
|
import org.apache.commons.io.input.CountingInputStream;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
public class MetadataReaderTest {
|
||||||
|
@Test
|
||||||
|
public void testRealFileUltraschall() throws IOException, ID3ReaderException {
|
||||||
|
CountingInputStream inputStream = new CountingInputStream(getClass().getClassLoader()
|
||||||
|
.getResource("ultraschall5.mp3").openStream());
|
||||||
|
Id3MetadataReader reader = new Id3MetadataReader(inputStream);
|
||||||
|
reader.readInputStream();
|
||||||
|
assertEquals("Description", reader.getComment());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRealFileAuphonic() throws IOException, ID3ReaderException {
|
||||||
|
CountingInputStream inputStream = new CountingInputStream(getClass().getClassLoader()
|
||||||
|
.getResource("auphonic.mp3").openStream());
|
||||||
|
Id3MetadataReader reader = new Id3MetadataReader(inputStream);
|
||||||
|
reader.readInputStream();
|
||||||
|
assertEquals("Summary", reader.getComment());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRealFileHindenburgJournalistPro() throws IOException, ID3ReaderException {
|
||||||
|
CountingInputStream inputStream = new CountingInputStream(getClass().getClassLoader()
|
||||||
|
.getResource("hindenburg-journalist-pro.mp3").openStream());
|
||||||
|
Id3MetadataReader reader = new Id3MetadataReader(inputStream);
|
||||||
|
reader.readInputStream();
|
||||||
|
assertEquals("This is the summary of this podcast episode. This file was made with"
|
||||||
|
+ " Hindenburg Journalist Pro version 1.85, build number 2360.", reader.getComment());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRealFileMp3chapsPy() throws IOException, ID3ReaderException {
|
||||||
|
CountingInputStream inputStream = new CountingInputStream(getClass().getClassLoader()
|
||||||
|
.getResource("mp3chaps-py.mp3").openStream());
|
||||||
|
Id3MetadataReader reader = new Id3MetadataReader(inputStream);
|
||||||
|
reader.readInputStream();
|
||||||
|
assertEquals("2021.08.13", reader.getComment());
|
||||||
|
}
|
||||||
|
}
|
@ -23,8 +23,8 @@ public class VorbisCommentChapterReaderTest {
|
|||||||
public void testRealFileAuphonic(String filename) throws IOException, VorbisCommentReaderException {
|
public void testRealFileAuphonic(String filename) throws IOException, VorbisCommentReaderException {
|
||||||
InputStream inputStream = getClass().getClassLoader()
|
InputStream inputStream = getClass().getClassLoader()
|
||||||
.getResource(filename).openStream();
|
.getResource(filename).openStream();
|
||||||
VorbisCommentChapterReader reader = new VorbisCommentChapterReader();
|
VorbisCommentChapterReader reader = new VorbisCommentChapterReader(inputStream);
|
||||||
reader.readInputStream(inputStream);
|
reader.readInputStream();
|
||||||
List<Chapter> chapters = reader.getChapters();
|
List<Chapter> chapters = reader.getChapters();
|
||||||
|
|
||||||
assertEquals(4, chapters.size());
|
assertEquals(4, chapters.size());
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package de.danoeh.antennapod.parser.media.vorbis;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
public class VorbisCommentMetadataReaderTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRealFilesAuphonic() throws IOException, VorbisCommentReaderException {
|
||||||
|
testRealFileAuphonic("auphonic.ogg");
|
||||||
|
testRealFileAuphonic("auphonic.opus");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRealFileAuphonic(String filename) throws IOException, VorbisCommentReaderException {
|
||||||
|
InputStream inputStream = getClass().getClassLoader()
|
||||||
|
.getResource(filename).openStream();
|
||||||
|
VorbisCommentMetadataReader reader = new VorbisCommentMetadataReader(inputStream);
|
||||||
|
reader.readInputStream();
|
||||||
|
assertEquals("Summary", reader.getDescription());
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user