Moved media file parser to its own module
This commit is contained in:
parent
ddae5e2278
commit
ca64739f36
@ -18,7 +18,7 @@ import de.danoeh.antennapod.R;
|
|||||||
import de.danoeh.antennapod.model.feed.Chapter;
|
import de.danoeh.antennapod.model.feed.Chapter;
|
||||||
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
||||||
import de.danoeh.antennapod.core.util.Converter;
|
import de.danoeh.antennapod.core.util.Converter;
|
||||||
import de.danoeh.antennapod.core.util.EmbeddedChapterImage;
|
import de.danoeh.antennapod.model.feed.EmbeddedChapterImage;
|
||||||
import de.danoeh.antennapod.core.util.IntentUtils;
|
import de.danoeh.antennapod.core.util.IntentUtils;
|
||||||
import de.danoeh.antennapod.ui.common.ThemeUtils;
|
import de.danoeh.antennapod.ui.common.ThemeUtils;
|
||||||
import de.danoeh.antennapod.model.playback.Playable;
|
import de.danoeh.antennapod.model.playback.Playable;
|
||||||
|
@ -51,7 +51,7 @@ import de.danoeh.antennapod.core.feed.util.ImageResourceUtils;
|
|||||||
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
||||||
import de.danoeh.antennapod.core.util.ChapterUtils;
|
import de.danoeh.antennapod.core.util.ChapterUtils;
|
||||||
import de.danoeh.antennapod.core.util.DateFormatter;
|
import de.danoeh.antennapod.core.util.DateFormatter;
|
||||||
import de.danoeh.antennapod.core.util.EmbeddedChapterImage;
|
import de.danoeh.antennapod.model.feed.EmbeddedChapterImage;
|
||||||
import de.danoeh.antennapod.core.util.playback.PlaybackController;
|
import de.danoeh.antennapod.core.util.playback.PlaybackController;
|
||||||
import de.danoeh.antennapod.model.feed.Chapter;
|
import de.danoeh.antennapod.model.feed.Chapter;
|
||||||
import de.danoeh.antennapod.model.playback.Playable;
|
import de.danoeh.antennapod.model.playback.Playable;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</Match>
|
</Match>
|
||||||
<Match>
|
<Match>
|
||||||
<Bug pattern="DM_DEFAULT_ENCODING"/>
|
<Bug pattern="DM_DEFAULT_ENCODING"/>
|
||||||
<Class name="de.danoeh.antennapod.core.util.vorbiscommentreader.VorbisCommentReader"/>
|
<Class name="de.danoeh.antennapod.parser.media.vorbis.VorbisCommentReader"/>
|
||||||
</Match>
|
</Match>
|
||||||
<Match>
|
<Match>
|
||||||
<Bug pattern="HSC_HUGE_SHARED_STRING_CONSTANT"/>
|
<Bug pattern="HSC_HUGE_SHARED_STRING_CONSTANT"/>
|
||||||
|
@ -25,6 +25,7 @@ dependencies {
|
|||||||
implementation project(':net:sync:gpoddernet')
|
implementation project(':net:sync:gpoddernet')
|
||||||
implementation project(':net:sync:model')
|
implementation project(':net:sync:model')
|
||||||
implementation project(':parser:feed')
|
implementation project(':parser:feed')
|
||||||
|
implementation project(':parser:media')
|
||||||
implementation project(':ui:app-start-intent')
|
implementation project(':ui:app-start-intent')
|
||||||
implementation project(':ui:common')
|
implementation project(':ui:common')
|
||||||
implementation project(':ui:png-icons')
|
implementation project(':ui:png-icons')
|
||||||
|
@ -14,7 +14,7 @@ import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory;
|
|||||||
import com.bumptech.glide.load.model.StringLoader;
|
import com.bumptech.glide.load.model.StringLoader;
|
||||||
import com.bumptech.glide.module.AppGlideModule;
|
import com.bumptech.glide.module.AppGlideModule;
|
||||||
|
|
||||||
import de.danoeh.antennapod.core.util.EmbeddedChapterImage;
|
import de.danoeh.antennapod.model.feed.EmbeddedChapterImage;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import com.bumptech.glide.request.RequestOptions;
|
import com.bumptech.glide.request.RequestOptions;
|
||||||
|
@ -10,7 +10,7 @@ import com.bumptech.glide.load.model.ModelLoaderFactory;
|
|||||||
import com.bumptech.glide.load.model.MultiModelLoaderFactory;
|
import com.bumptech.glide.load.model.MultiModelLoaderFactory;
|
||||||
import com.bumptech.glide.signature.ObjectKey;
|
import com.bumptech.glide.signature.ObjectKey;
|
||||||
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
|
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
|
||||||
import de.danoeh.antennapod.core.util.EmbeddedChapterImage;
|
import de.danoeh.antennapod.model.feed.EmbeddedChapterImage;
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
@ -3,10 +3,10 @@ package de.danoeh.antennapod.core.storage.mapper;
|
|||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import de.danoeh.antennapod.model.feed.Chapter;
|
import de.danoeh.antennapod.model.feed.Chapter;
|
||||||
import de.danoeh.antennapod.core.feed.ID3Chapter;
|
|
||||||
import de.danoeh.antennapod.parser.feed.element.SimpleChapter;
|
import de.danoeh.antennapod.parser.feed.element.SimpleChapter;
|
||||||
import de.danoeh.antennapod.core.feed.VorbisCommentChapter;
|
|
||||||
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
||||||
|
import de.danoeh.antennapod.parser.media.id3.ID3Chapter;
|
||||||
|
import de.danoeh.antennapod.parser.media.vorbis.VorbisCommentChapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a {@link Cursor} to a {@link Chapter} object.
|
* Converts a {@link Cursor} to a {@link Chapter} object.
|
||||||
|
@ -11,11 +11,11 @@ import de.danoeh.antennapod.model.feed.FeedMedia;
|
|||||||
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
|
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
|
||||||
import de.danoeh.antennapod.core.storage.DBReader;
|
import de.danoeh.antennapod.core.storage.DBReader;
|
||||||
import de.danoeh.antennapod.core.util.comparator.ChapterStartTimeComparator;
|
import de.danoeh.antennapod.core.util.comparator.ChapterStartTimeComparator;
|
||||||
import de.danoeh.antennapod.core.util.id3reader.ChapterReader;
|
import de.danoeh.antennapod.parser.media.id3.ChapterReader;
|
||||||
import de.danoeh.antennapod.core.util.id3reader.ID3ReaderException;
|
import de.danoeh.antennapod.parser.media.id3.ID3ReaderException;
|
||||||
import de.danoeh.antennapod.model.playback.Playable;
|
import de.danoeh.antennapod.model.playback.Playable;
|
||||||
import de.danoeh.antennapod.core.util.vorbiscommentreader.VorbisCommentChapterReader;
|
import de.danoeh.antennapod.parser.media.vorbis.VorbisCommentChapterReader;
|
||||||
import de.danoeh.antennapod.core.util.vorbiscommentreader.VorbisCommentReaderException;
|
import de.danoeh.antennapod.parser.media.vorbis.VorbisCommentReaderException;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import org.apache.commons.io.input.CountingInputStream;
|
import org.apache.commons.io.input.CountingInputStream;
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
package de.danoeh.antennapod.core.util.id3reader.model;
|
|
||||||
|
|
||||||
public abstract class Header {
|
|
||||||
|
|
||||||
final String id;
|
|
||||||
final int size;
|
|
||||||
|
|
||||||
Header(String id, int size) {
|
|
||||||
super();
|
|
||||||
this.id = id;
|
|
||||||
this.size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSize() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Header [id=" + id + ", size=" + size + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
package de.danoeh.antennapod.core.util.vorbiscommentreader;
|
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
class OggInputStream extends InputStream {
|
|
||||||
private final InputStream input;
|
|
||||||
|
|
||||||
/** True if OggInputStream is currently inside an Ogg page. */
|
|
||||||
private boolean isInPage;
|
|
||||||
private long bytesLeft;
|
|
||||||
|
|
||||||
public OggInputStream(InputStream input) {
|
|
||||||
super();
|
|
||||||
isInPage = false;
|
|
||||||
this.input = input;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read() throws IOException {
|
|
||||||
if (!isInPage) {
|
|
||||||
readOggPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isInPage && bytesLeft > 0) {
|
|
||||||
int result = input.read();
|
|
||||||
bytesLeft -= 1;
|
|
||||||
if (bytesLeft == 0) {
|
|
||||||
isInPage = false;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readOggPage() throws IOException {
|
|
||||||
// find OggS
|
|
||||||
int[] buffer = new int[4];
|
|
||||||
int c;
|
|
||||||
boolean isInOggS = false;
|
|
||||||
while ((c = input.read()) != -1) {
|
|
||||||
switch (c) {
|
|
||||||
case 'O':
|
|
||||||
isInOggS = true;
|
|
||||||
buffer[0] = c;
|
|
||||||
break;
|
|
||||||
case 'g':
|
|
||||||
if (buffer[1] != c) {
|
|
||||||
buffer[1] = c;
|
|
||||||
} else {
|
|
||||||
buffer[2] = c;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'S':
|
|
||||||
buffer[3] = c;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (isInOggS) {
|
|
||||||
Arrays.fill(buffer, 0);
|
|
||||||
isInOggS = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (buffer[0] == 'O' && buffer[1] == 'g' && buffer[2] == 'g'
|
|
||||||
&& buffer[3] == 'S') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// read segments
|
|
||||||
IOUtils.skipFully(input, 22);
|
|
||||||
bytesLeft = 0;
|
|
||||||
int numSegments = input.read();
|
|
||||||
for (int i = 0; i < numSegments; i++) {
|
|
||||||
bytesLeft += input.read();
|
|
||||||
}
|
|
||||||
isInPage = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
package de.danoeh.antennapod.core.util.vorbiscommentreader;
|
|
||||||
class VorbisCommentHeader {
|
|
||||||
private final String vendorString;
|
|
||||||
private final long userCommentLength;
|
|
||||||
|
|
||||||
public VorbisCommentHeader(String vendorString, long userCommentLength) {
|
|
||||||
super();
|
|
||||||
this.vendorString = vendorString;
|
|
||||||
this.userCommentLength = userCommentLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "VorbisCommentHeader [vendorString=" + vendorString
|
|
||||||
+ ", userCommentLength=" + userCommentLength + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getVendorString() {
|
|
||||||
return vendorString;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getUserCommentLength() {
|
|
||||||
return userCommentLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
package de.danoeh.antennapod.core.util;
|
package de.danoeh.antennapod.model.feed;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import de.danoeh.antennapod.model.playback.Playable;
|
import de.danoeh.antennapod.model.playback.Playable;
|
3
parser/media/README.md
Normal file
3
parser/media/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# :parser:media
|
||||||
|
|
||||||
|
This module provides the tag parser for media files. This includes id3 or ogg/vorbis.
|
12
parser/media/build.gradle
Normal file
12
parser/media/build.gradle
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
apply plugin: "com.android.library"
|
||||||
|
apply from: "../../common.gradle"
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation project(':model')
|
||||||
|
|
||||||
|
annotationProcessor "androidx.annotation:annotation:$annotationVersion"
|
||||||
|
|
||||||
|
implementation "commons-io:commons-io:$commonsioVersion"
|
||||||
|
|
||||||
|
testImplementation 'junit:junit:4.13'
|
||||||
|
}
|
1
parser/media/src/main/AndroidManifest.xml
Normal file
1
parser/media/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1 @@
|
|||||||
|
<manifest package="de.danoeh.antennapod.parser.media" />
|
@ -1,12 +1,11 @@
|
|||||||
package de.danoeh.antennapod.core.util.id3reader;
|
package de.danoeh.antennapod.parser.media.id3;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import de.danoeh.antennapod.model.feed.Chapter;
|
import de.danoeh.antennapod.model.feed.Chapter;
|
||||||
import de.danoeh.antennapod.core.feed.ID3Chapter;
|
import de.danoeh.antennapod.model.feed.EmbeddedChapterImage;
|
||||||
import de.danoeh.antennapod.core.util.EmbeddedChapterImage;
|
import de.danoeh.antennapod.parser.media.id3.model.FrameHeader;
|
||||||
import de.danoeh.antennapod.core.util.id3reader.model.FrameHeader;
|
|
||||||
import org.apache.commons.io.input.CountingInputStream;
|
import org.apache.commons.io.input.CountingInputStream;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
@ -1,4 +1,4 @@
|
|||||||
package de.danoeh.antennapod.core.feed;
|
package de.danoeh.antennapod.parser.media.id3;
|
||||||
|
|
||||||
import de.danoeh.antennapod.model.feed.Chapter;
|
import de.danoeh.antennapod.model.feed.Chapter;
|
||||||
|
|
@ -1,9 +1,9 @@
|
|||||||
package de.danoeh.antennapod.core.util.id3reader;
|
package de.danoeh.antennapod.parser.media.id3;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import de.danoeh.antennapod.core.util.id3reader.model.FrameHeader;
|
import de.danoeh.antennapod.parser.media.id3.model.FrameHeader;
|
||||||
import de.danoeh.antennapod.core.util.id3reader.model.TagHeader;
|
import de.danoeh.antennapod.parser.media.id3.model.TagHeader;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.io.input.CountingInputStream;
|
import org.apache.commons.io.input.CountingInputStream;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package de.danoeh.antennapod.core.util.id3reader;
|
package de.danoeh.antennapod.parser.media.id3;
|
||||||
|
|
||||||
public class ID3ReaderException extends Exception {
|
public class ID3ReaderException extends Exception {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
@ -1,4 +1,4 @@
|
|||||||
package de.danoeh.antennapod.core.util.id3reader.model;
|
package de.danoeh.antennapod.parser.media.id3.model;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
@ -15,5 +15,4 @@ public class FrameHeader extends Header {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("FrameHeader [flags=%s, id=%s, size=%s]", Integer.toBinaryString(flags), id, size);
|
return String.format("FrameHeader [flags=%s, id=%s, size=%s]", Integer.toBinaryString(flags), id, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package de.danoeh.antennapod.parser.media.id3.model;
|
||||||
|
|
||||||
|
public abstract class Header {
|
||||||
|
|
||||||
|
final String id;
|
||||||
|
final int size;
|
||||||
|
|
||||||
|
Header(String id, int size) {
|
||||||
|
super();
|
||||||
|
this.id = id;
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Header [id=" + id + ", size=" + size + "]";
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package de.danoeh.antennapod.core.util.id3reader.model;
|
package de.danoeh.antennapod.parser.media.id3.model;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
@ -0,0 +1,81 @@
|
|||||||
|
package de.danoeh.antennapod.parser.media.vorbis;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
class OggInputStream extends InputStream {
|
||||||
|
private final InputStream input;
|
||||||
|
|
||||||
|
/** True if OggInputStream is currently inside an Ogg page. */
|
||||||
|
private boolean isInPage;
|
||||||
|
private long bytesLeft;
|
||||||
|
|
||||||
|
public OggInputStream(InputStream input) {
|
||||||
|
super();
|
||||||
|
isInPage = false;
|
||||||
|
this.input = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
if (!isInPage) {
|
||||||
|
readOggPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInPage && bytesLeft > 0) {
|
||||||
|
int result = input.read();
|
||||||
|
bytesLeft -= 1;
|
||||||
|
if (bytesLeft == 0) {
|
||||||
|
isInPage = false;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readOggPage() throws IOException {
|
||||||
|
// find OggS
|
||||||
|
int[] buffer = new int[4];
|
||||||
|
int c;
|
||||||
|
boolean isInOggS = false;
|
||||||
|
while ((c = input.read()) != -1) {
|
||||||
|
switch (c) {
|
||||||
|
case 'O':
|
||||||
|
isInOggS = true;
|
||||||
|
buffer[0] = c;
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
if (buffer[1] != c) {
|
||||||
|
buffer[1] = c;
|
||||||
|
} else {
|
||||||
|
buffer[2] = c;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
buffer[3] = c;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (isInOggS) {
|
||||||
|
Arrays.fill(buffer, 0);
|
||||||
|
isInOggS = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (buffer[0] == 'O' && buffer[1] == 'g' && buffer[2] == 'g'
|
||||||
|
&& buffer[3] == 'S') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// read segments
|
||||||
|
IOUtils.skipFully(input, 22);
|
||||||
|
bytesLeft = 0;
|
||||||
|
int numSegments = input.read();
|
||||||
|
for (int i = 0; i < numSegments; i++) {
|
||||||
|
bytesLeft += input.read();
|
||||||
|
}
|
||||||
|
isInPage = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,8 +1,7 @@
|
|||||||
package de.danoeh.antennapod.core.feed;
|
package de.danoeh.antennapod.parser.media.vorbis;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import de.danoeh.antennapod.core.util.vorbiscommentreader.VorbisCommentReaderException;
|
|
||||||
import de.danoeh.antennapod.model.feed.Chapter;
|
import de.danoeh.antennapod.model.feed.Chapter;
|
||||||
|
|
||||||
public class VorbisCommentChapter extends Chapter {
|
public class VorbisCommentChapter extends Chapter {
|
@ -1,13 +1,12 @@
|
|||||||
package de.danoeh.antennapod.core.util.vorbiscommentreader;
|
package de.danoeh.antennapod.parser.media.vorbis;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.danoeh.antennapod.core.BuildConfig;
|
|
||||||
import de.danoeh.antennapod.model.feed.Chapter;
|
import de.danoeh.antennapod.model.feed.Chapter;
|
||||||
import de.danoeh.antennapod.core.feed.VorbisCommentChapter;
|
import de.danoeh.antennapod.parser.media.BuildConfig;
|
||||||
|
|
||||||
public class VorbisCommentChapterReader extends VorbisCommentReader {
|
public class VorbisCommentChapterReader extends VorbisCommentReader {
|
||||||
private static final String TAG = "VorbisCommentChptrReadr";
|
private static final String TAG = "VorbisCommentChptrReadr";
|
@ -0,0 +1,27 @@
|
|||||||
|
package de.danoeh.antennapod.parser.media.vorbis;
|
||||||
|
|
||||||
|
class VorbisCommentHeader {
|
||||||
|
private final String vendorString;
|
||||||
|
private final long userCommentLength;
|
||||||
|
|
||||||
|
public VorbisCommentHeader(String vendorString, long userCommentLength) {
|
||||||
|
super();
|
||||||
|
this.vendorString = vendorString;
|
||||||
|
this.userCommentLength = userCommentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "VorbisCommentHeader [vendorString=" + vendorString
|
||||||
|
+ ", userCommentLength=" + userCommentLength + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVendorString() {
|
||||||
|
return vendorString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getUserCommentLength() {
|
||||||
|
return userCommentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package de.danoeh.antennapod.core.util.vorbiscommentreader;
|
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;
|
||||||
@ -9,6 +9,7 @@ import java.io.InputStream;
|
|||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
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. */
|
||||||
@ -67,7 +68,7 @@ public abstract class VorbisCommentReader {
|
|||||||
private void readUserComment(InputStream input) throws VorbisCommentReaderException {
|
private void readUserComment(InputStream input) throws VorbisCommentReaderException {
|
||||||
try {
|
try {
|
||||||
long vectorLength = EndianUtils.readSwappedUnsignedInteger(input);
|
long vectorLength = EndianUtils.readSwappedUnsignedInteger(input);
|
||||||
String key = readContentVectorKey(input, vectorLength).toLowerCase();
|
String key = readContentVectorKey(input, vectorLength).toLowerCase(Locale.US);
|
||||||
boolean readValue = onContentVectorKey(key);
|
boolean readValue = onContentVectorKey(key);
|
||||||
if (readValue) {
|
if (readValue) {
|
||||||
String value = readUtf8String(input, (int) (vectorLength - key.length() - 1));
|
String value = readUtf8String(input, (int) (vectorLength - key.length() - 1));
|
@ -1,4 +1,4 @@
|
|||||||
package de.danoeh.antennapod.core.util.vorbiscommentreader;
|
package de.danoeh.antennapod.parser.media.vorbis;
|
||||||
|
|
||||||
public class VorbisCommentReaderException extends Exception {
|
public class VorbisCommentReaderException extends Exception {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
@ -1,9 +1,8 @@
|
|||||||
package de.danoeh.antennapod.core.util.id3reader;
|
package de.danoeh.antennapod.parser.media.id3;
|
||||||
|
|
||||||
import de.danoeh.antennapod.model.feed.Chapter;
|
import de.danoeh.antennapod.model.feed.Chapter;
|
||||||
import de.danoeh.antennapod.core.feed.ID3Chapter;
|
import de.danoeh.antennapod.model.feed.EmbeddedChapterImage;
|
||||||
import de.danoeh.antennapod.core.util.EmbeddedChapterImage;
|
import de.danoeh.antennapod.parser.media.id3.model.FrameHeader;
|
||||||
import de.danoeh.antennapod.core.util.id3reader.model.FrameHeader;
|
|
||||||
import org.apache.commons.io.input.CountingInputStream;
|
import org.apache.commons.io.input.CountingInputStream;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@ -11,9 +10,6 @@ import java.io.ByteArrayInputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static de.danoeh.antennapod.core.util.id3reader.Id3ReaderTest.concat;
|
|
||||||
import static de.danoeh.antennapod.core.util.id3reader.Id3ReaderTest.generateFrameHeader;
|
|
||||||
import static de.danoeh.antennapod.core.util.id3reader.Id3ReaderTest.generateId3Header;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
public class ChapterReaderTest {
|
public class ChapterReaderTest {
|
||||||
@ -28,11 +24,11 @@ public class ChapterReaderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadFullTagWithChapter() throws IOException, ID3ReaderException {
|
public void testReadFullTagWithChapter() throws IOException, ID3ReaderException {
|
||||||
byte[] chapter = concat(
|
byte[] chapter = Id3ReaderTest.concat(
|
||||||
generateFrameHeader(ChapterReader.FRAME_ID_CHAPTER, CHAPTER_WITHOUT_SUBFRAME.length),
|
Id3ReaderTest.generateFrameHeader(ChapterReader.FRAME_ID_CHAPTER, CHAPTER_WITHOUT_SUBFRAME.length),
|
||||||
CHAPTER_WITHOUT_SUBFRAME);
|
CHAPTER_WITHOUT_SUBFRAME);
|
||||||
byte[] data = concat(
|
byte[] data = Id3ReaderTest.concat(
|
||||||
generateId3Header(chapter.length),
|
Id3ReaderTest.generateId3Header(chapter.length),
|
||||||
chapter);
|
chapter);
|
||||||
CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(data));
|
CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(data));
|
||||||
ChapterReader reader = new ChapterReader(inputStream);
|
ChapterReader reader = new ChapterReader(inputStream);
|
||||||
@ -43,11 +39,11 @@ public class ChapterReaderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadFullTagWithMultipleChapters() throws IOException, ID3ReaderException {
|
public void testReadFullTagWithMultipleChapters() throws IOException, ID3ReaderException {
|
||||||
byte[] chapter = concat(
|
byte[] chapter = Id3ReaderTest.concat(
|
||||||
generateFrameHeader(ChapterReader.FRAME_ID_CHAPTER, CHAPTER_WITHOUT_SUBFRAME.length),
|
Id3ReaderTest.generateFrameHeader(ChapterReader.FRAME_ID_CHAPTER, CHAPTER_WITHOUT_SUBFRAME.length),
|
||||||
CHAPTER_WITHOUT_SUBFRAME);
|
CHAPTER_WITHOUT_SUBFRAME);
|
||||||
byte[] data = concat(
|
byte[] data = Id3ReaderTest.concat(
|
||||||
generateId3Header(2 * chapter.length),
|
Id3ReaderTest.generateId3Header(2 * chapter.length),
|
||||||
chapter,
|
chapter,
|
||||||
chapter);
|
chapter);
|
||||||
CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(data));
|
CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(data));
|
||||||
@ -74,9 +70,9 @@ public class ChapterReaderTest {
|
|||||||
'H', 'e', 'l', 'l', 'o', // Title
|
'H', 'e', 'l', 'l', 'o', // Title
|
||||||
0 // Null-terminated
|
0 // Null-terminated
|
||||||
};
|
};
|
||||||
byte[] chapterData = concat(
|
byte[] chapterData = Id3ReaderTest.concat(
|
||||||
CHAPTER_WITHOUT_SUBFRAME,
|
CHAPTER_WITHOUT_SUBFRAME,
|
||||||
generateFrameHeader(ChapterReader.FRAME_ID_TITLE, title.length),
|
Id3ReaderTest.generateFrameHeader(ChapterReader.FRAME_ID_TITLE, title.length),
|
||||||
title);
|
title);
|
||||||
FrameHeader header = new FrameHeader(ChapterReader.FRAME_ID_CHAPTER, chapterData.length, (short) 0);
|
FrameHeader header = new FrameHeader(ChapterReader.FRAME_ID_CHAPTER, chapterData.length, (short) 0);
|
||||||
CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(chapterData));
|
CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(chapterData));
|
||||||
@ -108,7 +104,7 @@ public class ChapterReaderTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testRealFileUltraschall() throws IOException, ID3ReaderException {
|
public void testRealFileUltraschall() throws IOException, ID3ReaderException {
|
||||||
CountingInputStream inputStream = new CountingInputStream(getClass().getClassLoader()
|
CountingInputStream inputStream = new CountingInputStream(getClass().getClassLoader()
|
||||||
.getResource("media-parser/ultraschall5.mp3").openStream());
|
.getResource("ultraschall5.mp3").openStream());
|
||||||
ChapterReader reader = new ChapterReader(inputStream);
|
ChapterReader reader = new ChapterReader(inputStream);
|
||||||
reader.readInputStream();
|
reader.readInputStream();
|
||||||
List<Chapter> chapters = reader.getChapters();
|
List<Chapter> chapters = reader.getChapters();
|
||||||
@ -135,7 +131,7 @@ public class ChapterReaderTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testRealFileAuphonic() throws IOException, ID3ReaderException {
|
public void testRealFileAuphonic() throws IOException, ID3ReaderException {
|
||||||
CountingInputStream inputStream = new CountingInputStream(getClass().getClassLoader()
|
CountingInputStream inputStream = new CountingInputStream(getClass().getClassLoader()
|
||||||
.getResource("media-parser/auphonic.mp3").openStream());
|
.getResource("auphonic.mp3").openStream());
|
||||||
ChapterReader reader = new ChapterReader(inputStream);
|
ChapterReader reader = new ChapterReader(inputStream);
|
||||||
reader.readInputStream();
|
reader.readInputStream();
|
||||||
List<Chapter> chapters = reader.getChapters();
|
List<Chapter> chapters = reader.getChapters();
|
||||||
@ -166,7 +162,7 @@ public class ChapterReaderTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testRealFileHindenburgJournalistPro() throws IOException, ID3ReaderException {
|
public void testRealFileHindenburgJournalistPro() throws IOException, ID3ReaderException {
|
||||||
CountingInputStream inputStream = new CountingInputStream(getClass().getClassLoader()
|
CountingInputStream inputStream = new CountingInputStream(getClass().getClassLoader()
|
||||||
.getResource("media-parser/hindenburg-journalist-pro.mp3").openStream());
|
.getResource("hindenburg-journalist-pro.mp3").openStream());
|
||||||
ChapterReader reader = new ChapterReader(inputStream);
|
ChapterReader reader = new ChapterReader(inputStream);
|
||||||
reader.readInputStream();
|
reader.readInputStream();
|
||||||
List<Chapter> chapters = reader.getChapters();
|
List<Chapter> chapters = reader.getChapters();
|
||||||
@ -189,7 +185,7 @@ public class ChapterReaderTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testRealFileMp3chapsPy() throws IOException, ID3ReaderException {
|
public void testRealFileMp3chapsPy() throws IOException, ID3ReaderException {
|
||||||
CountingInputStream inputStream = new CountingInputStream(getClass().getClassLoader()
|
CountingInputStream inputStream = new CountingInputStream(getClass().getClassLoader()
|
||||||
.getResource("media-parser/mp3chaps-py.mp3").openStream());
|
.getResource("mp3chaps-py.mp3").openStream());
|
||||||
ChapterReader reader = new ChapterReader(inputStream);
|
ChapterReader reader = new ChapterReader(inputStream);
|
||||||
reader.readInputStream();
|
reader.readInputStream();
|
||||||
List<Chapter> chapters = reader.getChapters();
|
List<Chapter> chapters = reader.getChapters();
|
@ -1,7 +1,7 @@
|
|||||||
package de.danoeh.antennapod.core.util.id3reader;
|
package de.danoeh.antennapod.parser.media.id3;
|
||||||
|
|
||||||
import de.danoeh.antennapod.core.util.id3reader.model.FrameHeader;
|
import de.danoeh.antennapod.parser.media.id3.model.FrameHeader;
|
||||||
import de.danoeh.antennapod.core.util.id3reader.model.TagHeader;
|
import de.danoeh.antennapod.parser.media.id3.model.TagHeader;
|
||||||
import org.apache.commons.io.input.CountingInputStream;
|
import org.apache.commons.io.input.CountingInputStream;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package de.danoeh.antennapod.core.util.vorbiscommentreader;
|
package de.danoeh.antennapod.parser.media.vorbis;
|
||||||
|
|
||||||
import de.danoeh.antennapod.model.feed.Chapter;
|
import de.danoeh.antennapod.model.feed.Chapter;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -13,8 +13,8 @@ public class VorbisCommentChapterReaderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRealFilesAuphonic() throws IOException, VorbisCommentReaderException {
|
public void testRealFilesAuphonic() throws IOException, VorbisCommentReaderException {
|
||||||
testRealFileAuphonic("media-parser/auphonic.ogg");
|
testRealFileAuphonic("auphonic.ogg");
|
||||||
testRealFileAuphonic("media-parser/auphonic.opus");
|
testRealFileAuphonic("auphonic.opus");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRealFileAuphonic(String filename) throws IOException, VorbisCommentReaderException {
|
public void testRealFileAuphonic(String filename) throws IOException, VorbisCommentReaderException {
|
@ -7,6 +7,7 @@ include ':net:sync:gpoddernet'
|
|||||||
include ':net:sync:model'
|
include ':net:sync:model'
|
||||||
|
|
||||||
include ':parser:feed'
|
include ':parser:feed'
|
||||||
|
include ':parser:media'
|
||||||
|
|
||||||
include ':ui:app-start-intent'
|
include ':ui:app-start-intent'
|
||||||
include ':ui:common'
|
include ':ui:common'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user