summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java159
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/ID3Chapter.java62
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/SimpleChapter.java27
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/VorbisCommentChapter.java181
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java111
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java24
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java7
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/handler/PostDownloaderTask.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java11
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java13
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java8
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java20
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java9
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSSimpleChapters.java9
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java36
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/EmbeddedChapterImage.java73
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java7
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java238
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java18
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java18
-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.java334
-rw-r--r--core/src/main/res/drawable-hdpi/ic_fast_forward_grey600_24dp.pngbin256 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_fast_forward_grey600_36dp.pngbin324 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_fast_forward_white_24dp.pngbin253 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_fast_forward_white_36dp.pngbin315 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_fast_rewind_grey600_24dp.pngbin267 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_fast_rewind_grey600_36dp.pngbin331 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_fast_rewind_white_24dp.pngbin261 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_fast_rewind_white_36dp.pngbin321 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_hearing_grey600_18dp.pngbin478 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_hearing_white_18dp.pngbin449 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_pause_grey600_24dp.pngbin103 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_pause_grey600_36dp.pngbin126 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_pause_white_24dp.pngbin103 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_pause_white_36dp.pngbin124 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_play_arrow_grey600_24dp.pngbin195 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_play_arrow_grey600_36dp.pngbin235 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.pngbin194 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_play_arrow_white_36dp.pngbin232 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_remove_red_eye_grey600_18dp.pngbin380 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_remove_red_eye_white_18dp.pngbin358 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_skip_grey600_36dp.pngbin256 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_skip_white_36dp.pngbin251 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_fast_forward_grey600_24dp.pngbin162 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_fast_forward_grey600_36dp.pngbin256 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_fast_forward_white_24dp.pngbin163 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_fast_forward_white_36dp.pngbin253 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_fast_rewind_grey600_24dp.pngbin167 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_fast_rewind_grey600_36dp.pngbin267 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_fast_rewind_white_24dp.pngbin162 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_fast_rewind_white_36dp.pngbin261 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_hearing_grey600_18dp.pngbin324 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_hearing_white_18dp.pngbin301 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_pause_grey600_24dp.pngbin84 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_pause_grey600_36dp.pngbin103 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_pause_white_24dp.pngbin83 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_pause_white_36dp.pngbin103 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_play_arrow_grey600_24dp.pngbin151 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_play_arrow_grey600_36dp.pngbin195 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_play_arrow_white_24dp.pngbin154 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_play_arrow_white_36dp.pngbin194 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_remove_red_eye_grey600_18dp.pngbin265 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_remove_red_eye_white_18dp.pngbin259 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_skip_grey600_36dp.pngbin183 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_skip_white_36dp.pngbin183 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_fast_forward_grey600_24dp.pngbin252 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_fast_forward_grey600_36dp.pngbin332 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_fast_forward_white_24dp.pngbin253 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_fast_forward_white_36dp.pngbin327 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_fast_rewind_grey600_24dp.pngbin279 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_fast_rewind_grey600_36dp.pngbin348 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_fast_rewind_white_24dp.pngbin263 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_fast_rewind_white_36dp.pngbin331 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_hearing_grey600_18dp.pngbin621 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_hearing_white_18dp.pngbin588 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_pause_grey600_24dp.pngbin105 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_pause_grey600_36dp.pngbin109 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_pause_white_24dp.pngbin90 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_pause_white_36dp.pngbin92 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_play_arrow_grey600_24dp.pngbin211 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_play_arrow_grey600_36dp.pngbin270 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.pngbin206 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.pngbin270 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_remove_red_eye_grey600_18dp.pngbin492 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_remove_red_eye_white_18dp.pngbin472 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_skip_grey600_36dp.pngbin285 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_skip_white_36dp.pngbin285 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_fast_forward_grey600_24dp.pngbin332 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_fast_forward_grey600_36dp.pngbin520 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_fast_forward_white_24dp.pngbin327 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_fast_forward_white_36dp.pngbin518 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_fast_rewind_grey600_24dp.pngbin348 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_fast_rewind_grey600_36dp.pngbin547 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_fast_rewind_white_24dp.pngbin331 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_fast_rewind_white_36dp.pngbin548 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_hearing_grey600_18dp.pngbin885 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_hearing_white_18dp.pngbin840 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_pause_grey600_24dp.pngbin109 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_pause_grey600_36dp.pngbin143 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_pause_white_24dp.pngbin92 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.pngbin143 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_play_arrow_grey600_24dp.pngbin270 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_play_arrow_grey600_36dp.pngbin367 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.pngbin270 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_play_arrow_white_36dp.pngbin351 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_grey600_18dp.pngbin697 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_white_18dp.pngbin669 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_skip_grey600_36dp.pngbin369 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_skip_white_36dp.pngbin361 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxxhdpi/ic_skip_grey600_36dp.pngbin443 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxxhdpi/ic_skip_white_36dp.pngbin433 -> 0 bytes
-rw-r--r--core/src/main/res/drawable/ic_av_fast_forward_dark_48dp.xml7
-rw-r--r--core/src/main/res/drawable/ic_av_fast_forward_white_48dp.xml7
-rw-r--r--core/src/main/res/drawable/ic_av_fast_rewind_dark_48dp.xml7
-rw-r--r--core/src/main/res/drawable/ic_av_fast_rewind_white_48dp.xml7
-rw-r--r--core/src/main/res/drawable/ic_av_pause_dark_48dp.xml7
-rw-r--r--core/src/main/res/drawable/ic_av_pause_white_48dp.xml7
-rw-r--r--core/src/main/res/drawable/ic_av_play_dark_24dp.xml7
-rw-r--r--core/src/main/res/drawable/ic_av_play_dark_48dp.xml7
-rw-r--r--core/src/main/res/drawable/ic_av_play_white_24dp.xml7
-rw-r--r--core/src/main/res/drawable/ic_av_play_white_48dp.xml7
-rw-r--r--core/src/main/res/drawable/ic_av_skip_dark_48dp.xml7
-rw-r--r--core/src/main/res/drawable/ic_av_skip_white_48dp.xml7
-rw-r--r--core/src/main/res/drawable/ic_notification_cast_off.xml4
-rw-r--r--core/src/main/res/drawable/ic_notification_fast_forward.xml4
-rw-r--r--core/src/main/res/drawable/ic_notification_fast_rewind.xml4
-rw-r--r--core/src/main/res/drawable/ic_notification_pause.xml4
-rw-r--r--core/src/main/res/drawable/ic_notification_play.xml4
-rw-r--r--core/src/main/res/drawable/ic_notification_skip.xml4
-rw-r--r--core/src/main/res/drawable/ic_videocam_grey600_24dp.xml8
-rw-r--r--core/src/main/res/drawable/ic_videocam_white_24dp.xml8
-rw-r--r--core/src/main/res/layout/player_widget.xml6
-rw-r--r--core/src/main/res/values-large/dimens.xml2
-rw-r--r--core/src/main/res/values/attrs.xml8
-rw-r--r--core/src/main/res/values/colors.xml4
-rw-r--r--core/src/main/res/values/dimens.xml6
-rw-r--r--core/src/main/res/values/strings.xml1
-rw-r--r--core/src/main/res/values/styles.xml38
142 files changed, 1003 insertions, 736 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java
index f3dfdfdb6..08a531d17 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java
@@ -6,81 +6,92 @@ import de.danoeh.antennapod.core.storage.PodDBAdapter;
public abstract class Chapter extends FeedComponent {
- /** Defines starting point in milliseconds. */
+ /** Defines starting point in milliseconds. */
long start;
- String title;
- String link;
-
- Chapter() {
- }
-
- Chapter(long start) {
- super();
- this.start = start;
- }
-
- Chapter(long start, String title, FeedItem item, String link) {
- super();
- this.start = start;
- this.title = title;
- this.link = link;
- }
-
- public static Chapter fromCursor(Cursor cursor, FeedItem item) {
- int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID);
- int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_TITLE);
- int indexStart = cursor.getColumnIndex(PodDBAdapter.KEY_START);
- int indexLink = cursor.getColumnIndex(PodDBAdapter.KEY_LINK);
- int indexChapterType = cursor.getColumnIndex(PodDBAdapter.KEY_CHAPTER_TYPE);
-
- long id = cursor.getLong(indexId);
- String title = cursor.getString(indexTitle);
- long start = cursor.getLong(indexStart);
- String link = cursor.getString(indexLink);
- int chapterType = cursor.getInt(indexChapterType);
-
- Chapter chapter = null;
- switch (chapterType) {
- case SimpleChapter.CHAPTERTYPE_SIMPLECHAPTER:
- chapter = new SimpleChapter(start, title, item, link);
- break;
- case ID3Chapter.CHAPTERTYPE_ID3CHAPTER:
- chapter = new ID3Chapter(start, title, item, link);
- break;
- case VorbisCommentChapter.CHAPTERTYPE_VORBISCOMMENT_CHAPTER:
- chapter = new VorbisCommentChapter(start, title, item, link);
- break;
- }
- chapter.setId(id);
- return chapter;
- }
-
-
- public abstract int getChapterType();
-
- public long getStart() {
- return start;
- }
-
- public String getTitle() {
- return title;
- }
-
- public String getLink() {
- return link;
- }
-
- public void setStart(long start) {
- this.start = start;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public void setLink(String link) {
- this.link = link;
- }
+ String title;
+ String link;
+ String imageUrl;
+
+ Chapter() {
+ }
+
+ Chapter(long start) {
+ super();
+ this.start = start;
+ }
+
+ Chapter(long start, String title, String link, String imageUrl) {
+ super();
+ this.start = start;
+ this.title = title;
+ this.link = link;
+ this.imageUrl = imageUrl;
+ }
+
+ public static Chapter fromCursor(Cursor cursor) {
+ int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID);
+ int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_TITLE);
+ int indexStart = cursor.getColumnIndex(PodDBAdapter.KEY_START);
+ int indexLink = cursor.getColumnIndex(PodDBAdapter.KEY_LINK);
+ int indexImage = cursor.getColumnIndex(PodDBAdapter.KEY_IMAGE_URL);
+ int indexChapterType = cursor.getColumnIndex(PodDBAdapter.KEY_CHAPTER_TYPE);
+
+ long id = cursor.getLong(indexId);
+ String title = cursor.getString(indexTitle);
+ long start = cursor.getLong(indexStart);
+ String link = cursor.getString(indexLink);
+ String imageUrl = cursor.getString(indexImage);
+ int chapterType = cursor.getInt(indexChapterType);
+
+ Chapter chapter = null;
+ switch (chapterType) {
+ case SimpleChapter.CHAPTERTYPE_SIMPLECHAPTER:
+ chapter = new SimpleChapter(start, title, link, imageUrl);
+ break;
+ case ID3Chapter.CHAPTERTYPE_ID3CHAPTER:
+ chapter = new ID3Chapter(start, title, link, imageUrl);
+ break;
+ case VorbisCommentChapter.CHAPTERTYPE_VORBISCOMMENT_CHAPTER:
+ chapter = new VorbisCommentChapter(start, title, link, imageUrl);
+ break;
+ }
+ chapter.setId(id);
+ return chapter;
+ }
+
+ public abstract int getChapterType();
+
+ public long getStart() {
+ return start;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getLink() {
+ return link;
+ }
+
+ public void setStart(long start) {
+ this.start = start;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public void setLink(String link) {
+ this.link = link;
+ }
+
+ public String getImageUrl() {
+ return imageUrl;
+ }
+
+ public void setImageUrl(String imageUrl) {
+ this.imageUrl = imageUrl;
+ }
@Override
public String getHumanReadableIdentifier() {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/ID3Chapter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/ID3Chapter.java
index f0ff03a93..b69d537fb 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/ID3Chapter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/ID3Chapter.java
@@ -1,36 +1,36 @@
package de.danoeh.antennapod.core.feed;
public class ID3Chapter extends Chapter {
- public static final int CHAPTERTYPE_ID3CHAPTER = 2;
-
- /**
- * Identifies the chapter in its ID3 tag. This attribute does not have to be
- * store in the DB and is only used for parsing.
- */
- private String id3ID;
-
- public ID3Chapter(String id3ID, long start) {
- super(start);
- this.id3ID = id3ID;
- }
-
- public ID3Chapter(long start, String title, FeedItem item, String link) {
- super(start, title, item, link);
- }
-
- @Override
- public String toString() {
- return "ID3Chapter [id3ID=" + id3ID + ", title=" + title + ", start="
- + start + ", url=" + link + "]";
- }
-
- @Override
- public int getChapterType() {
- return CHAPTERTYPE_ID3CHAPTER;
- }
-
- public String getId3ID() {
- return id3ID;
- }
+ public static final int CHAPTERTYPE_ID3CHAPTER = 2;
+
+ /**
+ * Identifies the chapter in its ID3 tag. This attribute does not have to be
+ * store in the DB and is only used for parsing.
+ */
+ private String id3ID;
+
+ public ID3Chapter(String id3ID, long start) {
+ super(start);
+ this.id3ID = id3ID;
+ }
+
+ public ID3Chapter(long start, String title, String link, String imageUrl) {
+ super(start, title, link, imageUrl);
+ }
+
+ @Override
+ public String toString() {
+ return "ID3Chapter [id3ID=" + id3ID + ", title=" + title + ", start="
+ + start + ", url=" + link + "]";
+ }
+
+ @Override
+ public int getChapterType() {
+ return CHAPTERTYPE_ID3CHAPTER;
+ }
+
+ public String getId3ID() {
+ return id3ID;
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/SimpleChapter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/SimpleChapter.java
index 2dadd3ec8..45c71a014 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/SimpleChapter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/SimpleChapter.java
@@ -1,25 +1,14 @@
package de.danoeh.antennapod.core.feed;
public class SimpleChapter extends Chapter {
- public static final int CHAPTERTYPE_SIMPLECHAPTER = 0;
-
- public SimpleChapter(long start, String title, FeedItem item, String link) {
- super(start, title, item, link);
- }
+ public static final int CHAPTERTYPE_SIMPLECHAPTER = 0;
- @Override
- public int getChapterType() {
- return CHAPTERTYPE_SIMPLECHAPTER;
- }
+ public SimpleChapter(long start, String title, String link, String imageUrl) {
+ super(start, title, link, imageUrl);
+ }
- public void updateFromOther(SimpleChapter other) {
- super.updateFromOther(other);
- start = other.start;
- if (other.title != null) {
- title = other.title;
- }
- if (other.link != null) {
- link = other.link;
- }
- }
+ @Override
+ public int getChapterType() {
+ return CHAPTERTYPE_SIMPLECHAPTER;
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/VorbisCommentChapter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/VorbisCommentChapter.java
index 5ab9868a6..eac50aed8 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/VorbisCommentChapter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/VorbisCommentChapter.java
@@ -5,105 +5,84 @@ import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.core.util.vorbiscommentreader.VorbisCommentReaderException;
public class VorbisCommentChapter extends Chapter {
- public static final int CHAPTERTYPE_VORBISCOMMENT_CHAPTER = 3;
-
- private static final int CHAPTERXXX_LENGTH = "chapterxxx".length();
-
- private int vorbisCommentId;
-
- public VorbisCommentChapter(int vorbisCommentId) {
- this.vorbisCommentId = vorbisCommentId;
- }
-
- public VorbisCommentChapter(long start, String title, FeedItem item,
- String link) {
- super(start, title, item, link);
- }
-
- @Override
- public String toString() {
- return "VorbisCommentChapter [id=" + id + ", title=" + title
- + ", link=" + link + ", start=" + start + "]";
- }
-
- public static long getStartTimeFromValue(String value)
- throws VorbisCommentReaderException {
- String[] parts = value.split(":");
- if (parts.length >= 3) {
- try {
- long hours = TimeUnit.MILLISECONDS.convert(
- Long.parseLong(parts[0]), TimeUnit.HOURS);
- long minutes = TimeUnit.MILLISECONDS.convert(
- Long.parseLong(parts[1]), TimeUnit.MINUTES);
- if (parts[2].contains("-->")) {
- parts[2] = parts[2].substring(0, parts[2].indexOf("-->"));
- }
- long seconds = TimeUnit.MILLISECONDS.convert(
- ((long) Float.parseFloat(parts[2])), TimeUnit.SECONDS);
- return hours + minutes + seconds;
- } catch (NumberFormatException e) {
- throw new VorbisCommentReaderException(e);
- }
- } else {
- throw new VorbisCommentReaderException("Invalid time string");
- }
- }
-
- /**
- * Return the id of a vorbiscomment chapter from a string like CHAPTERxxx*
- *
- * @return the id of the chapter key or -1 if the id couldn't be read.
- * @throws VorbisCommentReaderException
- * */
- public static int getIDFromKey(String key)
- throws VorbisCommentReaderException {
- if (key.length() >= CHAPTERXXX_LENGTH) { // >= CHAPTERxxx
- try {
- String strId = key.substring(8, 10);
- return Integer.parseInt(strId);
- } catch (NumberFormatException e) {
- throw new VorbisCommentReaderException(e);
- }
- }
- throw new VorbisCommentReaderException("key is too short (" + key + ")");
- }
-
- /**
- * Get the string that comes after 'CHAPTERxxx', for example 'name' or
- * 'url'.
- */
- public static String getAttributeTypeFromKey(String key) {
- if (key.length() > CHAPTERXXX_LENGTH) {
- return key.substring(CHAPTERXXX_LENGTH, key.length());
- }
- return null;
- }
-
- @Override
- public int getChapterType() {
- return CHAPTERTYPE_VORBISCOMMENT_CHAPTER;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public void setLink(String link) {
- this.link = link;
- }
-
- public void setStart(long start) {
- this.start = start;
- }
-
- public int getVorbisCommentId() {
- return vorbisCommentId;
- }
-
- public void setVorbisCommentId(int vorbisCommentId) {
- this.vorbisCommentId = vorbisCommentId;
- }
-
-
-
+ public static final int CHAPTERTYPE_VORBISCOMMENT_CHAPTER = 3;
+
+ private static final int CHAPTERXXX_LENGTH = "chapterxxx".length();
+
+ private int vorbisCommentId;
+
+ public VorbisCommentChapter(int vorbisCommentId) {
+ this.vorbisCommentId = vorbisCommentId;
+ }
+
+ public VorbisCommentChapter(long start, String title, String link, String imageUrl) {
+ super(start, title, link, imageUrl);
+ }
+
+ @Override
+ public String toString() {
+ return "VorbisCommentChapter [id=" + id + ", title=" + title
+ + ", link=" + link + ", start=" + start + "]";
+ }
+
+ public static long getStartTimeFromValue(String value)
+ throws VorbisCommentReaderException {
+ String[] parts = value.split(":");
+ if (parts.length >= 3) {
+ try {
+ long hours = TimeUnit.MILLISECONDS.convert(
+ Long.parseLong(parts[0]), TimeUnit.HOURS);
+ long minutes = TimeUnit.MILLISECONDS.convert(
+ Long.parseLong(parts[1]), TimeUnit.MINUTES);
+ if (parts[2].contains("-->")) {
+ parts[2] = parts[2].substring(0, parts[2].indexOf("-->"));
+ }
+ long seconds = TimeUnit.MILLISECONDS.convert(
+ ((long) Float.parseFloat(parts[2])), TimeUnit.SECONDS);
+ return hours + minutes + seconds;
+ } catch (NumberFormatException e) {
+ throw new VorbisCommentReaderException(e);
+ }
+ } else {
+ throw new VorbisCommentReaderException("Invalid time string");
+ }
+ }
+
+ /**
+ * Return the id of a vorbiscomment chapter from a string like CHAPTERxxx*
+ *
+ * @return the id of the chapter key or -1 if the id couldn't be read.
+ * @throws VorbisCommentReaderException
+ * */
+ public static int getIDFromKey(String key) throws VorbisCommentReaderException {
+ if (key.length() >= CHAPTERXXX_LENGTH) { // >= CHAPTERxxx
+ try {
+ String strId = key.substring(8, 10);
+ return Integer.parseInt(strId);
+ } catch (NumberFormatException e) {
+ throw new VorbisCommentReaderException(e);
+ }
+ }
+ throw new VorbisCommentReaderException("key is too short (" + key + ")");
+ }
+
+ /**
+ * Get the string that comes after 'CHAPTERxxx', for example 'name' or
+ * 'url'.
+ */
+ public static String getAttributeTypeFromKey(String key) {
+ if (key.length() > CHAPTERXXX_LENGTH) {
+ return key.substring(CHAPTERXXX_LENGTH);
+ }
+ return null;
+ }
+
+ @Override
+ public int getChapterType() {
+ return CHAPTERTYPE_VORBISCOMMENT_CHAPTER;
+ }
+
+ public int getVorbisCommentId() {
+ return vorbisCommentId;
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java
index b2c809e90..50511526f 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java
@@ -11,10 +11,12 @@ import com.bumptech.glide.load.DecodeFormat;
import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory;
import com.bumptech.glide.module.AppGlideModule;
+import de.danoeh.antennapod.core.util.EmbeddedChapterImage;
import java.io.InputStream;
import com.bumptech.glide.request.RequestOptions;
import de.danoeh.antennapod.core.preferences.UserPreferences;
+import java.nio.ByteBuffer;
/**
* {@see com.bumptech.glide.integration.okhttp.OkHttpGlideModule}
@@ -32,5 +34,6 @@ public class ApGlideModule extends AppGlideModule {
@Override
public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
registry.replace(String.class, InputStream.class, new ApOkHttpUrlLoader.Factory());
+ registry.append(EmbeddedChapterImage.class, ByteBuffer.class, new ChapterImageModelLoader.Factory());
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java
new file mode 100644
index 000000000..bc0a06a07
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java
@@ -0,0 +1,111 @@
+package de.danoeh.antennapod.core.glide;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import com.bumptech.glide.Priority;
+import com.bumptech.glide.load.DataSource;
+import com.bumptech.glide.load.Options;
+import com.bumptech.glide.load.data.DataFetcher;
+import com.bumptech.glide.load.model.ModelLoader;
+import com.bumptech.glide.load.model.ModelLoaderFactory;
+import com.bumptech.glide.load.model.MultiModelLoaderFactory;
+import com.bumptech.glide.signature.ObjectKey;
+import de.danoeh.antennapod.core.ClientConfig;
+import de.danoeh.antennapod.core.feed.Chapter;
+import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
+import de.danoeh.antennapod.core.util.EmbeddedChapterImage;
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import org.apache.commons.io.IOUtils;
+
+public final class ChapterImageModelLoader implements ModelLoader<EmbeddedChapterImage, ByteBuffer> {
+
+ public static class Factory implements ModelLoaderFactory<EmbeddedChapterImage, ByteBuffer> {
+ @Override
+ public ModelLoader<EmbeddedChapterImage, ByteBuffer> build(MultiModelLoaderFactory unused) {
+ return new ChapterImageModelLoader();
+ }
+
+ @Override
+ public void teardown() {
+ // Do nothing.
+ }
+ }
+
+ @Nullable
+ @Override
+ public LoadData<ByteBuffer> buildLoadData(EmbeddedChapterImage model, int width, int height, Options options) {
+ return new LoadData<>(new ObjectKey(model), new EmbeddedImageFetcher(model));
+ }
+
+ @Override
+ public boolean handles(EmbeddedChapterImage model) {
+ return true;
+ }
+
+ static class EmbeddedImageFetcher implements DataFetcher<ByteBuffer> {
+ private final EmbeddedChapterImage image;
+
+ public EmbeddedImageFetcher(EmbeddedChapterImage image) {
+ this.image = image;
+ }
+
+ @Override
+ public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super ByteBuffer> callback) {
+
+ BufferedInputStream stream = null;
+ try {
+ if (image.getMedia().localFileAvailable()) {
+ File localFile = new File(image.getMedia().getLocalMediaUrl());
+ stream = new BufferedInputStream(new FileInputStream(localFile));
+ stream.skip(image.getPosition());
+ byte[] imageContent = new byte[image.getLength()];
+ stream.read(imageContent, 0, image.getLength());
+ callback.onDataReady(ByteBuffer.wrap(imageContent));
+ } else {
+ Request.Builder httpReq = new Request.Builder();
+ httpReq.header("User-Agent", ClientConfig.USER_AGENT);
+ // Skipping would download the whole file
+ httpReq.header("Range", "bytes=" + image.getPosition()
+ + "-" + (image.getPosition() + image.getLength()));
+ httpReq.url(image.getMedia().getStreamUrl());
+ Response response = AntennapodHttpClient.getHttpClient().newCall(httpReq.build()).execute();
+ if (!response.isSuccessful() || response.body() == null) {
+ throw new IOException("Invalid response: " + response.code() + " " + response.message());
+ }
+ callback.onDataReady(ByteBuffer.wrap(response.body().bytes()));
+ }
+ } catch (IOException e) {
+ callback.onLoadFailed(e);
+ } finally {
+ IOUtils.closeQuietly(stream);
+ }
+ }
+
+ @Override public void cleanup() {
+ // nothing to clean up
+ }
+ @Override public void cancel() {
+ // cannot cancel
+ }
+
+ @NonNull
+ @Override
+ public Class<ByteBuffer> getDataClass() {
+ return ByteBuffer.class;
+ }
+
+ @NonNull
+ @Override
+ public DataSource getDataSource() {
+ return DataSource.LOCAL;
+ }
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java
index 3cc906b7f..d2d9e5947 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java
@@ -14,19 +14,15 @@ public class FastBlurTransformation extends BitmapTransformation {
private static final String TAG = FastBlurTransformation.class.getSimpleName();
- private static final int STACK_BLUR_RADIUS = 1;
- private static final int BLUR_IMAGE_WIDTH = 150;
+ private static final int STACK_BLUR_RADIUS = 5;
public FastBlurTransformation() {
super();
}
@Override
- protected Bitmap transform(BitmapPool pool, Bitmap source,
- int outWidth, int outHeight) {
- int targetWidth = BLUR_IMAGE_WIDTH;
- int targetHeight = (int) (1.0 * outHeight * targetWidth / outWidth);
- Bitmap resized = ThumbnailUtils.extractThumbnail(source, targetWidth, targetHeight);
+ protected Bitmap transform(BitmapPool pool, Bitmap source, int outWidth, int outHeight) {
+ Bitmap resized = ThumbnailUtils.extractThumbnail(source, outWidth / 3, outHeight / 3);
Bitmap result = fastBlur(resized, STACK_BLUR_RADIUS);
if (result == null) {
Log.w(TAG, "result was null");
@@ -80,9 +76,9 @@ public class FastBlurTransformation extends BitmapTransformation {
int wh = w * h;
int div = radius + radius + 1;
- int r[] = new int[wh];
- int g[] = new int[wh];
- int b[] = new int[wh];
+ int[] r = new int[wh];
+ int[] g = new int[wh];
+ int[] b = new int[wh];
int rsum;
int gsum;
int bsum;
@@ -93,11 +89,11 @@ public class FastBlurTransformation extends BitmapTransformation {
int yp;
int yi;
int yw;
- int vmin[] = new int[Math.max(w, h)];
+ int[] vmin = new int[Math.max(w, h)];
int divsum = (div + 1) >> 1;
divsum *= divsum;
- int dv[] = new int[256 * divsum];
+ int[] dv = new int[256 * divsum];
for (i = 0; i < 256 * divsum; i++) {
dv[i] = (i / divsum);
}
@@ -225,8 +221,8 @@ public class FastBlurTransformation extends BitmapTransformation {
yi = x;
stackpointer = radius;
for (y = 0; y < h; y++) {
- // Preserve alpha channel: ( 0xff000000 & pix[yi] )
- pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
+ // Set alpha to 1
+ pix[yi] = 0xff000000 | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
rsum -= routsum;
gsum -= goutsum;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java b/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java
index e6f2176f7..4562f1393 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java
@@ -8,7 +8,6 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
-import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import androidx.annotation.NonNull;
@@ -158,10 +157,10 @@ public class PlayerWidgetJobService extends SafeJobIntentService {
}
if (status == PlayerStatus.PLAYING) {
- views.setImageViewResource(R.id.butPlay, R.drawable.ic_pause_white_24dp);
+ views.setImageViewResource(R.id.butPlay, R.drawable.ic_av_pause_white_48dp);
views.setContentDescription(R.id.butPlay, getString(R.string.pause_label));
} else {
- views.setImageViewResource(R.id.butPlay, R.drawable.ic_play_arrow_white_24dp);
+ views.setImageViewResource(R.id.butPlay, R.drawable.ic_av_play_white_48dp);
views.setContentDescription(R.id.butPlay, getString(R.string.play_label));
}
views.setOnClickPendingIntent(R.id.butPlay, createMediaButtonIntent());
@@ -177,7 +176,7 @@ public class PlayerWidgetJobService extends SafeJobIntentService {
views.setViewVisibility(R.id.txtvTitle, View.GONE);
views.setViewVisibility(R.id.txtNoPlaying, View.VISIBLE);
views.setImageViewResource(R.id.imgvCover, R.mipmap.ic_launcher_foreground);
- views.setImageViewResource(R.id.butPlay, R.drawable.ic_play_arrow_white_24dp);
+ views.setImageViewResource(R.id.butPlay, R.drawable.ic_av_play_white_48dp);
}
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java
index 40be2895c..9ecabd14b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java
@@ -6,6 +6,7 @@ import android.util.Log;
import androidx.annotation.NonNull;
+import java.io.File;
import java.util.concurrent.ExecutionException;
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
@@ -50,6 +51,7 @@ public class MediaDownloadedHandler implements Runnable {
boolean broadcastUnreadStateUpdate = media.getItem() != null && media.getItem().isNew();
media.setDownloaded(true);
media.setFile_url(request.getDestination());
+ media.setSize(new File(request.getDestination()).length());
media.checkEmbeddedPicture(); // enforce check
// check if file has chapters
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/PostDownloaderTask.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/PostDownloaderTask.java
index 5d2c48679..7c998146d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/PostDownloaderTask.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/PostDownloaderTask.java
@@ -2,6 +2,7 @@ package de.danoeh.antennapod.core.service.download.handler;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.service.download.Downloader;
+import de.danoeh.antennapod.core.storage.DownloadRequester;
import org.greenrobot.eventbus.EventBus;
import java.util.ArrayList;
@@ -23,6 +24,7 @@ public class PostDownloaderTask implements Runnable {
runningDownloads.add(downloader);
}
}
+ DownloadRequester.getInstance().updateProgress(downloads);
List<Downloader> list = Collections.unmodifiableList(runningDownloads);
EventBus.getDefault().postSticky(DownloadEvent.refresh(list));
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
index fbd8d65d8..bf59b0ffd 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
@@ -573,6 +573,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
mediaPlayer.prepare();
} else if (mediaPlayer.getPlayable() == null) {
startPlayingFromPreferences();
+ } else {
+ return false;
}
taskManager.restartSleepTimer();
return true;
@@ -584,18 +586,19 @@ public class PlaybackService extends MediaBrowserServiceCompat {
mediaPlayer.prepare();
} else if (mediaPlayer.getPlayable() == null) {
startPlayingFromPreferences();
+ } else {
+ return false;
}
taskManager.restartSleepTimer();
return true;
case KeyEvent.KEYCODE_MEDIA_PAUSE:
if (status == PlayerStatus.PLAYING) {
mediaPlayer.pause(!UserPreferences.isPersistNotify(), false);
+ return true;
}
-
- return true;
+ return false;
case KeyEvent.KEYCODE_MEDIA_NEXT:
- if (notificationButton ||
- UserPreferences.shouldHardwareButtonSkip()) {
+ if (notificationButton || UserPreferences.shouldHardwareButtonSkip()) {
// assume the skip command comes from a notification or the lockscreen
// a >| skip button should actually skip
mediaPlayer.skip();
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java
index 4f4ee4721..e818f3072 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java
@@ -795,9 +795,7 @@ public final class DBReader {
}
private static void loadChaptersOfFeedItem(PodDBAdapter adapter, FeedItem item) {
- Cursor cursor = null;
- try {
- cursor = adapter.getSimpleChaptersOfFeedItemCursor(item);
+ try (Cursor cursor = adapter.getSimpleChaptersOfFeedItemCursor(item)) {
int chaptersCount = cursor.getCount();
if (chaptersCount == 0) {
item.setChapters(null);
@@ -805,14 +803,7 @@ public final class DBReader {
}
item.setChapters(new ArrayList<>(chaptersCount));
while (cursor.moveToNext()) {
- Chapter chapter = Chapter.fromCursor(cursor, item);
- if (chapter != null) {
- item.getChapters().add(chapter);
- }
- }
- } finally {
- if (cursor != null) {
- cursor.close();
+ item.getChapters().add(Chapter.fromCursor(cursor));
}
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java
index 234ce8367..ee31c8cc4 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java
@@ -95,7 +95,7 @@ class DBUpgrader {
+ " ADD COLUMN " + PodDBAdapter.KEY_PASSWORD
+ " TEXT");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " ADD COLUMN " + PodDBAdapter.KEY_IMAGE
+ + " ADD COLUMN image"
+ " INTEGER");
}
if (oldVersion <= 12) {
@@ -280,13 +280,13 @@ class DBUpgrader {
+ " SELECT " + PodDBAdapter.KEY_DOWNLOAD_URL
+ " FROM " + PodDBAdapter.TABLE_NAME_FEED_IMAGES
+ " WHERE " + PodDBAdapter.TABLE_NAME_FEED_IMAGES + "." + PodDBAdapter.KEY_ID
- + " = " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_IMAGE + ")");
+ + " = " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + ".image)");
db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + " SET " + PodDBAdapter.KEY_IMAGE_URL + " = ("
+ " SELECT " + PodDBAdapter.KEY_DOWNLOAD_URL
+ " FROM " + PodDBAdapter.TABLE_NAME_FEED_IMAGES
+ " WHERE " + PodDBAdapter.TABLE_NAME_FEED_IMAGES + "." + PodDBAdapter.KEY_ID
- + " = " + PodDBAdapter.TABLE_NAME_FEEDS + "." + PodDBAdapter.KEY_IMAGE + ")");
+ + " = " + PodDBAdapter.TABLE_NAME_FEEDS + ".image)");
db.execSQL("DROP TABLE " + PodDBAdapter.TABLE_NAME_FEED_IMAGES);
}
@@ -301,6 +301,8 @@ class DBUpgrader {
if (oldVersion < 1090000) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + PodDBAdapter.KEY_FEED_VOLUME_ADAPTION + " INTEGER DEFAULT 0");
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
+ + " ADD COLUMN " + PodDBAdapter.KEY_IMAGE_URL + " TEXT DEFAULT NULL");
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java
index 3d4ee443b..8bd9afe38 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java
@@ -12,6 +12,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.core.content.ContextCompat;
+import de.danoeh.antennapod.core.service.download.Downloader;
import org.apache.commons.io.FilenameUtils;
import java.io.File;
@@ -344,6 +345,16 @@ public class DownloadRequester implements DownloadStateProvider {
}
/**
+ * Get the downloader for this item.
+ */
+ public synchronized DownloadRequest getRequestFor(FeedFile item) {
+ if (isDownloadingFile(item)) {
+ return downloads.get(item.getDownload_url());
+ }
+ return null;
+ }
+
+ /**
* Checks if feedfile with the given download url is in the downloads list
*/
public synchronized boolean isDownloadingFile(String downloadUrl) {
@@ -428,4 +439,13 @@ public class DownloadRequester implements DownloadStateProvider {
}
return filename;
}
+
+ public void updateProgress(List<Downloader> newDownloads) {
+ for (Downloader downloader : newDownloads) {
+ DownloadRequest request = downloader.getDownloadRequest();
+ if (downloads.containsKey(request.getSource())) {
+ downloads.put(request.getSource(), request);
+ }
+ }
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java
index bbe8b26f1..77c8d3b7f 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java
@@ -35,11 +35,12 @@ public class FeedSearcher {
final List<FeedComponent> result = new ArrayList<>();
try {
FutureTask<List<FeedItem>> itemSearchTask = DBTasks.searchFeedItems(context, selectedFeed, query);
- FutureTask<List<Feed>> feedSearchTask = DBTasks.searchFeeds(context, query);
itemSearchTask.run();
- feedSearchTask.run();
-
- result.addAll(feedSearchTask.get());
+ if (selectedFeed == 0) {
+ FutureTask<List<Feed>> feedSearchTask = DBTasks.searchFeeds(context, query);
+ feedSearchTask.run();
+ result.addAll(feedSearchTask.get());
+ }
result.addAll(itemSearchTask.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
index 4e2588f22..af6a8ef81 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
@@ -69,7 +69,6 @@ public class PodDBAdapter {
public static final String KEY_POSITION = "position";
public static final String KEY_SIZE = "filesize";
public static final String KEY_MIME_TYPE = "mime_type";
- public static final String KEY_IMAGE = "image";
public static final String KEY_IMAGE_URL = "image_url";
public static final String KEY_FEED = "feed";
public static final String KEY_MEDIA = "media";
@@ -183,7 +182,7 @@ public class PodDBAdapter {
private static final String CREATE_TABLE_SIMPLECHAPTERS = "CREATE TABLE "
+ TABLE_NAME_SIMPLECHAPTERS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE
+ " TEXT," + KEY_START + " INTEGER," + KEY_FEEDITEM + " INTEGER,"
- + KEY_LINK + " TEXT," + KEY_CHAPTER_TYPE + " INTEGER)";
+ + KEY_LINK + " TEXT," + KEY_IMAGE_URL + " TEXT," + KEY_CHAPTER_TYPE + " INTEGER)";
// SQL Statements for creating indexes
static final String CREATE_INDEX_FEEDITEMS_FEED = "CREATE INDEX "
@@ -674,6 +673,7 @@ public class PodDBAdapter {
values.put(KEY_START, chapter.getStart());
values.put(KEY_FEEDITEM, item.getId());
values.put(KEY_LINK, chapter.getLink());
+ values.put(KEY_IMAGE_URL, chapter.getImageUrl());
values.put(KEY_CHAPTER_TYPE, chapter.getChapterType());
if (chapter.getId() == 0) {
chapter.setId(db.insert(TABLE_NAME_SIMPLECHAPTERS, null, values));
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSSimpleChapters.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSSimpleChapters.java
index 45266569a..5761f37c8 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSSimpleChapters.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSSimpleChapters.java
@@ -22,12 +22,12 @@ public class NSSimpleChapters extends Namespace {
private static final String START = "start";
private static final String TITLE = "title";
private static final String HREF = "href";
+ private static final String IMAGE = "image";
@Override
- public SyndElement handleElementStart(String localName, HandlerState state,
- Attributes attributes) {
+ public SyndElement handleElementStart(String localName, HandlerState state, Attributes attributes) {
FeedItem currentItem = state.getCurrentItem();
- if(currentItem != null) {
+ if (currentItem != null) {
if (localName.equals(CHAPTERS)) {
currentItem.setChapters(new ArrayList<>());
} else if (localName.equals(CHAPTER)) {
@@ -35,7 +35,8 @@ public class NSSimpleChapters extends Namespace {
long start = DateUtils.parseTimeString(attributes.getValue(START));
String title = attributes.getValue(TITLE);
String link = attributes.getValue(HREF);
- SimpleChapter chapter = new SimpleChapter(start, title, currentItem, link);
+ String imageUrl = attributes.getValue(IMAGE);
+ SimpleChapter chapter = new SimpleChapter(start, title, link, imageUrl);
currentItem.getChapters().add(chapter);
} catch (NumberFormatException e) {
Log.e(TAG, "Unable to read chapter", e);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java
index 300e0038a..b75887154 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java
@@ -4,6 +4,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.Log;
+import java.util.zip.CheckedOutputStream;
import org.apache.commons.io.IOUtils;
import java.io.BufferedInputStream;
@@ -23,6 +24,7 @@ import de.danoeh.antennapod.core.util.id3reader.ID3ReaderException;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.vorbiscommentreader.VorbisCommentChapterReader;
import de.danoeh.antennapod.core.util.vorbiscommentreader.VorbisCommentReaderException;
+import org.apache.commons.io.input.CountingInputStream;
/**
* Utility class for getting chapter data from media files.
@@ -34,24 +36,17 @@ public class ChapterUtils {
private ChapterUtils() {
}
- @Nullable
- public static Chapter getCurrentChapter(Playable media) {
- if (media.getChapters() == null) {
- return null;
+ public static int getCurrentChapterIndex(Playable media, int position) {
+ if (media == null || media.getChapters() == null || media.getChapters().size() == 0) {
+ return -1;
}
List<Chapter> chapters = media.getChapters();
- if (chapters == null) {
- return null;
- }
- Chapter current = chapters.get(0);
- for (Chapter sc : chapters) {
- if (sc.getStart() > media.getPosition()) {
- break;
- } else {
- current = sc;
+ for (int i = 0; i < chapters.size(); i++) {
+ if (chapters.get(i).getStart() > position) {
+ return i - 1;
}
}
- return current;
+ return chapters.size() - 1;
}
public static void loadChaptersFromStreamUrl(Playable media) {
@@ -82,13 +77,12 @@ public class ChapterUtils {
return;
}
Log.d(TAG, "Reading id3 chapters from item " + p.getEpisodeTitle());
- InputStream in = null;
+ CountingInputStream in = null;
try {
URL url = new URL(p.getStreamUrl());
-
- in = url.openStream();
+ in = new CountingInputStream(url.openStream());
List<Chapter> chapters = readChaptersFrom(in);
- if(!chapters.isEmpty()) {
+ if (!chapters.isEmpty()) {
p.setChapters(chapters);
}
Log.i(TAG, "Chapters loaded");
@@ -114,9 +108,9 @@ public class ChapterUtils {
return;
}
- InputStream in = null;
+ CountingInputStream in = null;
try {
- in = new BufferedInputStream(new FileInputStream(source));
+ in = new CountingInputStream(new BufferedInputStream(new FileInputStream(source)));
List<Chapter> chapters = readChaptersFrom(in);
if (!chapters.isEmpty()) {
p.setChapters(chapters);
@@ -130,7 +124,7 @@ public class ChapterUtils {
}
@NonNull
- private static List<Chapter> readChaptersFrom(InputStream in) throws IOException, ID3ReaderException {
+ private static List<Chapter> readChaptersFrom(CountingInputStream in) throws IOException, ID3ReaderException {
ChapterReader reader = new ChapterReader();
reader.readInputStream(in);
List<Chapter> chapters = reader.getChapters();
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/EmbeddedChapterImage.java b/core/src/main/java/de/danoeh/antennapod/core/util/EmbeddedChapterImage.java
new file mode 100644
index 000000000..deeba9238
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/EmbeddedChapterImage.java
@@ -0,0 +1,73 @@
+package de.danoeh.antennapod.core.util;
+
+import android.text.TextUtils;
+import de.danoeh.antennapod.core.util.playback.Playable;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class EmbeddedChapterImage {
+ private static final Pattern EMBEDDED_IMAGE_MATCHER = Pattern.compile("embedded-image://(\\d+)/(\\d+)");
+
+ private final int position;
+ private final int length;
+ private final String imageUrl;
+ private final Playable media;
+
+ public EmbeddedChapterImage(Playable media, String imageUrl) {
+ this.media = media;
+ this.imageUrl = imageUrl;
+ Matcher m = EMBEDDED_IMAGE_MATCHER.matcher(imageUrl);
+ if (m.find()) {
+ this.position = Integer.parseInt(m.group(1));
+ this.length = Integer.parseInt(m.group(2));
+ } else {
+ throw new IllegalArgumentException("Not an embedded chapter");
+ }
+ }
+
+ public static String makeUrl(int position, int length) {
+ return "embedded-image://" + position + "/" + length;
+ }
+
+ public int getPosition() {
+ return position;
+ }
+
+ public int getLength() {
+ return length;
+ }
+
+ public Playable getMedia() {
+ return media;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ EmbeddedChapterImage that = (EmbeddedChapterImage) o;
+ return TextUtils.equals(imageUrl, that.imageUrl);
+ }
+
+ @Override
+ public int hashCode() {
+ return imageUrl.hashCode();
+ }
+
+ private static boolean isEmbeddedChapterImage(String imageUrl) {
+ return EMBEDDED_IMAGE_MATCHER.matcher(imageUrl).matches();
+ }
+
+ public static Object getModelFor(Playable media, int chapter) {
+ String imageUrl = media.getChapters().get(chapter).getImageUrl();
+ if (isEmbeddedChapterImage(imageUrl)) {
+ return new EmbeddedChapterImage(media, imageUrl);
+ } else {
+ return imageUrl;
+ }
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java
index eabaaa828..44b31f0be 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java
@@ -4,6 +4,7 @@ import android.content.Context;
import androidx.annotation.AttrRes;
import androidx.annotation.ColorInt;
import android.util.TypedValue;
+import androidx.annotation.DrawableRes;
public class ThemeUtils {
private ThemeUtils() {
@@ -15,4 +16,10 @@ public class ThemeUtils {
context.getTheme().resolveAttribute(attr, typedValue, true);
return typedValue.data;
}
+
+ public static @DrawableRes int getDrawableFromAttr(Context context, @AttrRes int attr) {
+ TypedValue typedValue = new TypedValue();
+ context.getTheme().resolveAttribute(attr, typedValue, true);
+ return typedValue.resourceId;
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java
index a3f747e09..ce3577a9e 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java
@@ -1,124 +1,154 @@
package de.danoeh.antennapod.core.util.id3reader;
+import android.text.TextUtils;
import android.util.Log;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.ID3Chapter;
+import de.danoeh.antennapod.core.util.EmbeddedChapterImage;
import de.danoeh.antennapod.core.util.id3reader.model.FrameHeader;
import de.danoeh.antennapod.core.util.id3reader.model.TagHeader;
import java.io.IOException;
-import java.io.InputStream;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
+import org.apache.commons.io.input.CountingInputStream;
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_CHAPTER = "CHAP";
+ private static final String FRAME_ID_TITLE = "TIT2";
private static final String FRAME_ID_LINK = "WXXX";
+ private static final String FRAME_ID_PICTURE = "APIC";
+ private static final int IMAGE_TYPE_COVER = 3;
- private List<Chapter> chapters;
- private ID3Chapter currentChapter;
-
- @Override
- public int onStartTagHeader(TagHeader header) {
- chapters = new ArrayList<>();
- Log.d(TAG, "header: " + header);
- return ID3Reader.ACTION_DONT_SKIP;
- }
-
- @Override
- public int onStartFrameHeader(FrameHeader header, InputStream input)
- throws IOException, ID3ReaderException {
- Log.d(TAG, "header: " + header);
- switch (header.getId()) {
- case FRAME_ID_CHAPTER:
- if (currentChapter != null) {
- if (!hasId3Chapter(currentChapter)) {
- chapters.add(currentChapter);
- Log.d(TAG, "Found chapter: " + currentChapter);
- currentChapter = null;
- }
- }
- StringBuilder elementId = new StringBuilder();
- 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.toString(), startTime);
- skipBytes(input, 12);
- return ID3Reader.ACTION_DONT_SKIP;
- case FRAME_ID_TITLE:
- if (currentChapter != null && currentChapter.getTitle() == null) {
- StringBuilder title = new StringBuilder();
- readString(title, input, header.getSize());
- currentChapter
- .setTitle(title.toString());
- Log.d(TAG, "Found title: " + currentChapter.getTitle());
-
- return ID3Reader.ACTION_DONT_SKIP;
- }
- break;
- case FRAME_ID_LINK:
- if (currentChapter != null) {
- // skip description
- int descriptionLength = readString(null, input, header.getSize());
- StringBuilder link = new StringBuilder();
- readISOString(link, input, header.getSize() - descriptionLength);
- try {
- String decodedLink = URLDecoder.decode(link.toString(), "UTF-8");
- currentChapter.setLink(decodedLink);
- Log.d(TAG, "Found link: " + currentChapter.getLink());
- } catch (IllegalArgumentException iae) {
- Log.w(TAG, "Bad URL found in ID3 data");
- }
-
- return ID3Reader.ACTION_DONT_SKIP;
- }
- break;
- case "APIC":
- Log.d(TAG, header.toString());
- break;
- }
-
- return super.onStartFrameHeader(header, input);
- }
-
- private boolean hasId3Chapter(ID3Chapter chapter) {
- for (Chapter c : chapters) {
- if (((ID3Chapter) c).getId3ID().equals(chapter.getId3ID())) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public void onEndTag() {
- if (currentChapter != null) {
- if (!hasId3Chapter(currentChapter)) {
- chapters.add(currentChapter);
- }
- }
- Log.d(TAG, "Reached end of tag");
- if (chapters != null) {
- for (Chapter c : chapters) {
- Log.d(TAG, "chapter: " + c);
- }
- }
- }
-
- @Override
- public void onNoTagHeaderFound() {
- Log.d(TAG, "No tag header found");
- super.onNoTagHeaderFound();
- }
-
- public List<Chapter> getChapters() {
- return chapters;
- }
+ private List<Chapter> chapters;
+ private ID3Chapter currentChapter;
+
+ @Override
+ public int onStartTagHeader(TagHeader header) {
+ chapters = new ArrayList<>();
+ Log.d(TAG, "header: " + header);
+ return ID3Reader.ACTION_DONT_SKIP;
+ }
+
+ @Override
+ public int onStartFrameHeader(FrameHeader header, CountingInputStream input) throws IOException, ID3ReaderException {
+ Log.d(TAG, "header: " + header);
+ switch (header.getId()) {
+ case FRAME_ID_CHAPTER:
+ if (currentChapter != null) {
+ if (!hasId3Chapter(currentChapter)) {
+ chapters.add(currentChapter);
+ Log.d(TAG, "Found chapter: " + currentChapter);
+ currentChapter = null;
+ }
+ }
+ StringBuilder elementId = new StringBuilder();
+ readISOString(elementId, input, Integer.MAX_VALUE);
+ char[] startTimeSource = readChars(input, 4);
+ long startTime = ((int) startTimeSource[0] << 24)
+ | ((int) startTimeSource[1] << 16)
+ | ((int) startTimeSource[2] << 8) | startTimeSource[3];
+ currentChapter = new ID3Chapter(elementId.toString(), startTime);
+ skipBytes(input, 12);
+ return ID3Reader.ACTION_DONT_SKIP;
+ case FRAME_ID_TITLE:
+ if (currentChapter != null && currentChapter.getTitle() == null) {
+ StringBuilder title = new StringBuilder();
+ readString(title, input, header.getSize());
+ currentChapter
+ .setTitle(title.toString());
+ Log.d(TAG, "Found title: " + currentChapter.getTitle());
+
+ return ID3Reader.ACTION_DONT_SKIP;
+ }
+ break;
+ case FRAME_ID_LINK:
+ if (currentChapter != null) {
+ // skip description
+ int descriptionLength = readString(null, input, header.getSize());
+ StringBuilder link = new StringBuilder();
+ readISOString(link, input, header.getSize() - descriptionLength);
+ try {
+ String decodedLink = URLDecoder.decode(link.toString(), "UTF-8");
+ currentChapter.setLink(decodedLink);
+ Log.d(TAG, "Found link: " + currentChapter.getLink());
+ } catch (IllegalArgumentException iae) {
+ Log.w(TAG, "Bad URL found in ID3 data");
+ }
+
+ return ID3Reader.ACTION_DONT_SKIP;
+ }
+ break;
+ case FRAME_ID_PICTURE:
+ if (currentChapter != null) {
+ Log.d(TAG, header.toString());
+ StringBuilder mime = new StringBuilder();
+ int read = readString(mime, input, header.getSize());
+ byte type = (byte) readChars(input, 1)[0];
+ read++;
+ StringBuilder description = new StringBuilder();
+ read += readISOString(description, input, header.getSize()); // Should use same encoding as mime
+
+ Log.d(TAG, "Found apic: " + mime + "," + description);
+ if (mime.toString().equals("-->")) {
+ // Data contains a link to a picture
+ StringBuilder link = new StringBuilder();
+ readISOString(link, input, header.getSize());
+ Log.d(TAG, "link: " + link.toString());
+ if (TextUtils.isEmpty(currentChapter.getImageUrl()) || type == IMAGE_TYPE_COVER) {
+ currentChapter.setImageUrl(link.toString());
+ }
+ } else {
+ // Data contains the picture
+ int length = header.getSize() - read;
+ if (TextUtils.isEmpty(currentChapter.getImageUrl()) || type == IMAGE_TYPE_COVER) {
+ currentChapter.setImageUrl(EmbeddedChapterImage.makeUrl(input.getCount(), length));
+ }
+ skipBytes(input, length);
+ }
+ return ID3Reader.ACTION_DONT_SKIP;
+ }
+ break;
+ }
+
+ return super.onStartFrameHeader(header, input);
+ }
+
+ private boolean hasId3Chapter(ID3Chapter chapter) {
+ for (Chapter c : chapters) {
+ if (((ID3Chapter) c).getId3ID().equals(chapter.getId3ID())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void onEndTag() {
+ if (currentChapter != null) {
+ if (!hasId3Chapter(currentChapter)) {
+ chapters.add(currentChapter);
+ }
+ }
+ Log.d(TAG, "Reached end of tag");
+ if (chapters != null) {
+ for (Chapter c : chapters) {
+ Log.d(TAG, "chapter: " + c);
+ }
+ }
+ }
+
+ @Override
+ public void onNoTagHeaderFound() {
+ Log.d(TAG, "No tag header found");
+ super.onNoTagHeaderFound();
+ }
+
+ public List<Chapter> getChapters() {
+ return chapters;
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java
index 3f5993700..dfc21a5f2 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java
@@ -9,6 +9,7 @@ import java.nio.charset.Charset;
import de.danoeh.antennapod.core.util.id3reader.model.FrameHeader;
import de.danoeh.antennapod.core.util.id3reader.model.TagHeader;
+import org.apache.commons.io.input.CountingInputStream;
/**
* Reads the ID3 Tag of a given file. In order to use this class, you should
@@ -33,11 +34,10 @@ public class ID3Reader {
ID3Reader() {
}
- public final void readInputStream(InputStream input) throws IOException,
- ID3ReaderException {
+ public final void readInputStream(CountingInputStream input) throws IOException, ID3ReaderException {
int rc;
readerPosition = 0;
- char[] tagHeaderSource = readBytes(input, HEADER_LENGTH);
+ char[] tagHeaderSource = readChars(input, HEADER_LENGTH);
tagHeader = createTagHeader(tagHeaderSource);
if (tagHeader == null) {
onNoTagHeaderFound();
@@ -47,7 +47,7 @@ public class ID3Reader {
onEndTag();
} else {
while (readerPosition < tagHeader.getSize()) {
- FrameHeader frameHeader = createFrameHeader(readBytes(input, HEADER_LENGTH));
+ FrameHeader frameHeader = createFrameHeader(readChars(input, HEADER_LENGTH));
if (checkForNullString(frameHeader.getId())) {
break;
}
@@ -84,11 +84,10 @@ public class ID3Reader {
}
/**
- * Read a certain number of bytes from the given input stream. This method
+ * Read a certain number of chars from the given input stream. This method
* changes the readerPosition-attribute.
*/
- char[] readBytes(InputStream input, int number)
- throws IOException, ID3ReaderException {
+ char[] readChars(InputStream input, int number) throws IOException, ID3ReaderException {
char[] header = new char[number];
for (int i = 0; i < number; i++) {
int b = input.read();
@@ -168,7 +167,7 @@ public class ID3Reader {
protected int readString(StringBuilder buffer, InputStream input, int max) throws IOException,
ID3ReaderException {
if (max > 0) {
- char[] encoding = readBytes(input, 1);
+ char[] encoding = readChars(input, 1);
max--;
if (encoding[0] == ENCODING_UTF16_WITH_BOM || encoding[0] == ENCODING_UTF16_WITHOUT_BOM) {
@@ -230,8 +229,7 @@ public class ID3Reader {
return ACTION_SKIP;
}
- int onStartFrameHeader(FrameHeader header, InputStream input)
- throws IOException, ID3ReaderException {
+ int onStartFrameHeader(FrameHeader header, CountingInputStream input) throws IOException, ID3ReaderException {
return ACTION_SKIP;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
index cb22fbcc9..5cc2bbc64 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
@@ -21,6 +21,7 @@ import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
+import de.danoeh.antennapod.core.util.ThemeUtils;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import de.danoeh.antennapod.core.R;
@@ -397,12 +398,10 @@ public class PlaybackController {
final CharSequence playText = activity.getString(R.string.play_label);
final CharSequence pauseText = activity.getString(R.string.pause_label);
- if (PlaybackService.getCurrentMediaType() == MediaType.AUDIO ||
- PlaybackService.isCasting()) {
- TypedArray res = activity.obtainStyledAttributes(new int[]{
- R.attr.av_play_big, R.attr.av_pause_big});
- playResource = res.getResourceId(0, R.drawable.ic_play_arrow_grey600_36dp);
- pauseResource = res.getResourceId(1, R.drawable.ic_pause_grey600_36dp);
+ if (PlaybackService.getCurrentMediaType() == MediaType.AUDIO || PlaybackService.isCasting()) {
+ TypedArray res = activity.obtainStyledAttributes(new int[]{ R.attr.av_play, R.attr.av_pause});
+ playResource = res.getResourceId(0, R.drawable.ic_av_play_dark_48dp);
+ pauseResource = res.getResourceId(1, R.drawable.ic_av_pause_dark_48dp);
res.recycle();
} else {
playResource = R.drawable.ic_av_play_white_80dp;
@@ -547,7 +546,7 @@ public class PlaybackController {
*/
public void onSeekBarStopTrackingTouch(SeekBar seekBar, float prog) {
if (playbackService != null && media != null) {
- playbackService.seekTo((int) (prog * media.getDuration()));
+ seekTo((int) (prog * getDuration()));
}
}
@@ -779,11 +778,8 @@ public class PlaybackController {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(media -> {
if (media.getMediaType() == MediaType.AUDIO) {
- TypedArray res = activity.obtainStyledAttributes(new int[]{
- de.danoeh.antennapod.core.R.attr.av_play_big});
getPlayButton().setImageResource(
- res.getResourceId(0, de.danoeh.antennapod.core.R.drawable.ic_play_arrow_grey600_36dp));
- res.recycle();
+ ThemeUtils.getDrawableFromAttr(activity, de.danoeh.antennapod.core.R.attr.av_play));
} else {
getPlayButton().setImageResource(R.drawable.ic_av_play_white_80dp);
}
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..e910e2be4 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;
@@ -8,187 +9,158 @@ import java.io.InputStream;
import java.io.UnsupportedEncodingException;
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_OGG_PAGE_LENGTH = 58;
+ private static final int FIRST_OPUS_PAGE_LENGTH = 47;
+ 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_OPUS_PAGE_LENGTH];
+ IOUtils.readFully(input, buffer);
+ final byte[] oggIdentificationHeader = new byte[]{ PACKET_TYPE_IDENTIFICATION, 'v', 'o', 'r', 'b', 'i', 's' };
+ for (int i = 6; i < buffer.length; i++) {
+ if (bufferMatches(buffer, oggIdentificationHeader, i)) {
+ IOUtils.skip(input, FIRST_OGG_PAGE_LENGTH - FIRST_OPUS_PAGE_LENGTH);
+ return true;
+ } else if (bufferMatches(buffer, "OpusHead".getBytes(), i)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean findCommentHeader(InputStream input) throws IOException {
+ 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' };
+ for (int bytesRead = 0; bytesRead < SECOND_PAGE_MAX_LENGTH; bytesRead++) {
+ buffer[bytesRead % buffer.length] = (byte) input.read();
+ if (bufferMatches(buffer, oggCommentHeader, bytesRead)) {
+ return true;
+ } else if (bufferMatches(buffer, "OpusTags".getBytes(), bytesRead)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Reads backwards in haystack, starting at position. Checks if the bytes match needle.
+ * Uses haystack circularly, so when reading at (-1), it reads at (length - 1).
+ */
+ boolean bufferMatches(byte[] haystack, byte[] needle, int position) {
+ for (int i = 0; i < needle.length; i++) {
+ int posInHaystack = position - i;
+ while (posInHaystack < 0) {
+ posInHaystack += haystack.length;
+ }
+ posInHaystack = posInHaystack % haystack.length;
+ if (haystack[posInHaystack] != needle[needle.length - 1 - i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @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
+ }
}
diff --git a/core/src/main/res/drawable-hdpi/ic_fast_forward_grey600_24dp.png b/core/src/main/res/drawable-hdpi/ic_fast_forward_grey600_24dp.png
deleted file mode 100644
index df9e662c1..000000000
--- a/core/src/main/res/drawable-hdpi/ic_fast_forward_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_fast_forward_grey600_36dp.png b/core/src/main/res/drawable-hdpi/ic_fast_forward_grey600_36dp.png
deleted file mode 100644
index 59ae40266..000000000
--- a/core/src/main/res/drawable-hdpi/ic_fast_forward_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_fast_forward_white_24dp.png b/core/src/main/res/drawable-hdpi/ic_fast_forward_white_24dp.png
deleted file mode 100644
index 2d61b31f1..000000000
--- a/core/src/main/res/drawable-hdpi/ic_fast_forward_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_fast_forward_white_36dp.png b/core/src/main/res/drawable-hdpi/ic_fast_forward_white_36dp.png
deleted file mode 100644
index e5ae251d3..000000000
--- a/core/src/main/res/drawable-hdpi/ic_fast_forward_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_fast_rewind_grey600_24dp.png b/core/src/main/res/drawable-hdpi/ic_fast_rewind_grey600_24dp.png
deleted file mode 100644
index f661ca723..000000000
--- a/core/src/main/res/drawable-hdpi/ic_fast_rewind_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_fast_rewind_grey600_36dp.png b/core/src/main/res/drawable-hdpi/ic_fast_rewind_grey600_36dp.png
deleted file mode 100644
index d36891a8d..000000000
--- a/core/src/main/res/drawable-hdpi/ic_fast_rewind_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_fast_rewind_white_24dp.png b/core/src/main/res/drawable-hdpi/ic_fast_rewind_white_24dp.png
deleted file mode 100644
index ab8b48ec3..000000000
--- a/core/src/main/res/drawable-hdpi/ic_fast_rewind_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_fast_rewind_white_36dp.png b/core/src/main/res/drawable-hdpi/ic_fast_rewind_white_36dp.png
deleted file mode 100644
index 75796d7a9..000000000
--- a/core/src/main/res/drawable-hdpi/ic_fast_rewind_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_hearing_grey600_18dp.png b/core/src/main/res/drawable-hdpi/ic_hearing_grey600_18dp.png
deleted file mode 100644
index 2452cfa92..000000000
--- a/core/src/main/res/drawable-hdpi/ic_hearing_grey600_18dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_hearing_white_18dp.png b/core/src/main/res/drawable-hdpi/ic_hearing_white_18dp.png
deleted file mode 100644
index 96a06141a..000000000
--- a/core/src/main/res/drawable-hdpi/ic_hearing_white_18dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_pause_grey600_24dp.png b/core/src/main/res/drawable-hdpi/ic_pause_grey600_24dp.png
deleted file mode 100644
index 7281f37e1..000000000
--- a/core/src/main/res/drawable-hdpi/ic_pause_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_pause_grey600_36dp.png b/core/src/main/res/drawable-hdpi/ic_pause_grey600_36dp.png
deleted file mode 100644
index dde9bb25c..000000000
--- a/core/src/main/res/drawable-hdpi/ic_pause_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_pause_white_24dp.png b/core/src/main/res/drawable-hdpi/ic_pause_white_24dp.png
deleted file mode 100644
index 1701f34b0..000000000
--- a/core/src/main/res/drawable-hdpi/ic_pause_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_pause_white_36dp.png b/core/src/main/res/drawable-hdpi/ic_pause_white_36dp.png
deleted file mode 100644
index 1d024393a..000000000
--- a/core/src/main/res/drawable-hdpi/ic_pause_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_play_arrow_grey600_24dp.png b/core/src/main/res/drawable-hdpi/ic_play_arrow_grey600_24dp.png
deleted file mode 100644
index b540e4a63..000000000
--- a/core/src/main/res/drawable-hdpi/ic_play_arrow_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_play_arrow_grey600_36dp.png b/core/src/main/res/drawable-hdpi/ic_play_arrow_grey600_36dp.png
deleted file mode 100644
index a12b921e4..000000000
--- a/core/src/main/res/drawable-hdpi/ic_play_arrow_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png b/core/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png
deleted file mode 100644
index f77ad6b57..000000000
--- a/core/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_play_arrow_white_36dp.png b/core/src/main/res/drawable-hdpi/ic_play_arrow_white_36dp.png
deleted file mode 100644
index 2b8e3513f..000000000
--- a/core/src/main/res/drawable-hdpi/ic_play_arrow_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_remove_red_eye_grey600_18dp.png b/core/src/main/res/drawable-hdpi/ic_remove_red_eye_grey600_18dp.png
deleted file mode 100644
index 4f1af39ab..000000000
--- a/core/src/main/res/drawable-hdpi/ic_remove_red_eye_grey600_18dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_remove_red_eye_white_18dp.png b/core/src/main/res/drawable-hdpi/ic_remove_red_eye_white_18dp.png
deleted file mode 100644
index abc338d51..000000000
--- a/core/src/main/res/drawable-hdpi/ic_remove_red_eye_white_18dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_skip_grey600_36dp.png b/core/src/main/res/drawable-hdpi/ic_skip_grey600_36dp.png
deleted file mode 100644
index 6e1dffc93..000000000
--- a/core/src/main/res/drawable-hdpi/ic_skip_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_skip_white_36dp.png b/core/src/main/res/drawable-hdpi/ic_skip_white_36dp.png
deleted file mode 100644
index 760ec9987..000000000
--- a/core/src/main/res/drawable-hdpi/ic_skip_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_fast_forward_grey600_24dp.png b/core/src/main/res/drawable-mdpi/ic_fast_forward_grey600_24dp.png
deleted file mode 100644
index c67fc25f1..000000000
--- a/core/src/main/res/drawable-mdpi/ic_fast_forward_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_fast_forward_grey600_36dp.png b/core/src/main/res/drawable-mdpi/ic_fast_forward_grey600_36dp.png
deleted file mode 100644
index df9e662c1..000000000
--- a/core/src/main/res/drawable-mdpi/ic_fast_forward_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_fast_forward_white_24dp.png b/core/src/main/res/drawable-mdpi/ic_fast_forward_white_24dp.png
deleted file mode 100644
index fceffcb7b..000000000
--- a/core/src/main/res/drawable-mdpi/ic_fast_forward_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_fast_forward_white_36dp.png b/core/src/main/res/drawable-mdpi/ic_fast_forward_white_36dp.png
deleted file mode 100644
index 2d61b31f1..000000000
--- a/core/src/main/res/drawable-mdpi/ic_fast_forward_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_fast_rewind_grey600_24dp.png b/core/src/main/res/drawable-mdpi/ic_fast_rewind_grey600_24dp.png
deleted file mode 100644
index de04575da..000000000
--- a/core/src/main/res/drawable-mdpi/ic_fast_rewind_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_fast_rewind_grey600_36dp.png b/core/src/main/res/drawable-mdpi/ic_fast_rewind_grey600_36dp.png
deleted file mode 100644
index f661ca723..000000000
--- a/core/src/main/res/drawable-mdpi/ic_fast_rewind_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_fast_rewind_white_24dp.png b/core/src/main/res/drawable-mdpi/ic_fast_rewind_white_24dp.png
deleted file mode 100644
index bfb476b4a..000000000
--- a/core/src/main/res/drawable-mdpi/ic_fast_rewind_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_fast_rewind_white_36dp.png b/core/src/main/res/drawable-mdpi/ic_fast_rewind_white_36dp.png
deleted file mode 100644
index ab8b48ec3..000000000
--- a/core/src/main/res/drawable-mdpi/ic_fast_rewind_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_hearing_grey600_18dp.png b/core/src/main/res/drawable-mdpi/ic_hearing_grey600_18dp.png
deleted file mode 100644
index ea44e3f07..000000000
--- a/core/src/main/res/drawable-mdpi/ic_hearing_grey600_18dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_hearing_white_18dp.png b/core/src/main/res/drawable-mdpi/ic_hearing_white_18dp.png
deleted file mode 100644
index 78e98fe8d..000000000
--- a/core/src/main/res/drawable-mdpi/ic_hearing_white_18dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_pause_grey600_24dp.png b/core/src/main/res/drawable-mdpi/ic_pause_grey600_24dp.png
deleted file mode 100644
index 126ee03ef..000000000
--- a/core/src/main/res/drawable-mdpi/ic_pause_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_pause_grey600_36dp.png b/core/src/main/res/drawable-mdpi/ic_pause_grey600_36dp.png
deleted file mode 100644
index 7281f37e1..000000000
--- a/core/src/main/res/drawable-mdpi/ic_pause_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_pause_white_24dp.png b/core/src/main/res/drawable-mdpi/ic_pause_white_24dp.png
deleted file mode 100644
index 2272d478c..000000000
--- a/core/src/main/res/drawable-mdpi/ic_pause_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_pause_white_36dp.png b/core/src/main/res/drawable-mdpi/ic_pause_white_36dp.png
deleted file mode 100644
index 1701f34b0..000000000
--- a/core/src/main/res/drawable-mdpi/ic_pause_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_play_arrow_grey600_24dp.png b/core/src/main/res/drawable-mdpi/ic_play_arrow_grey600_24dp.png
deleted file mode 100644
index 9c8f2c555..000000000
--- a/core/src/main/res/drawable-mdpi/ic_play_arrow_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_play_arrow_grey600_36dp.png b/core/src/main/res/drawable-mdpi/ic_play_arrow_grey600_36dp.png
deleted file mode 100644
index b540e4a63..000000000
--- a/core/src/main/res/drawable-mdpi/ic_play_arrow_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_play_arrow_white_24dp.png b/core/src/main/res/drawable-mdpi/ic_play_arrow_white_24dp.png
deleted file mode 100644
index 172c211ab..000000000
--- a/core/src/main/res/drawable-mdpi/ic_play_arrow_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_play_arrow_white_36dp.png b/core/src/main/res/drawable-mdpi/ic_play_arrow_white_36dp.png
deleted file mode 100644
index f77ad6b57..000000000
--- a/core/src/main/res/drawable-mdpi/ic_play_arrow_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_remove_red_eye_grey600_18dp.png b/core/src/main/res/drawable-mdpi/ic_remove_red_eye_grey600_18dp.png
deleted file mode 100644
index daa8e568e..000000000
--- a/core/src/main/res/drawable-mdpi/ic_remove_red_eye_grey600_18dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_remove_red_eye_white_18dp.png b/core/src/main/res/drawable-mdpi/ic_remove_red_eye_white_18dp.png
deleted file mode 100644
index a6b4ff0da..000000000
--- a/core/src/main/res/drawable-mdpi/ic_remove_red_eye_white_18dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_skip_grey600_36dp.png b/core/src/main/res/drawable-mdpi/ic_skip_grey600_36dp.png
deleted file mode 100644
index 229eeca47..000000000
--- a/core/src/main/res/drawable-mdpi/ic_skip_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_skip_white_36dp.png b/core/src/main/res/drawable-mdpi/ic_skip_white_36dp.png
deleted file mode 100644
index 9032328d4..000000000
--- a/core/src/main/res/drawable-mdpi/ic_skip_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_fast_forward_grey600_24dp.png b/core/src/main/res/drawable-xhdpi/ic_fast_forward_grey600_24dp.png
deleted file mode 100644
index 6f8b42221..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_fast_forward_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_fast_forward_grey600_36dp.png b/core/src/main/res/drawable-xhdpi/ic_fast_forward_grey600_36dp.png
deleted file mode 100644
index 521f7490b..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_fast_forward_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_fast_forward_white_24dp.png b/core/src/main/res/drawable-xhdpi/ic_fast_forward_white_24dp.png
deleted file mode 100644
index 2b34fb82d..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_fast_forward_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_fast_forward_white_36dp.png b/core/src/main/res/drawable-xhdpi/ic_fast_forward_white_36dp.png
deleted file mode 100644
index 2d9a7e3c9..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_fast_forward_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_fast_rewind_grey600_24dp.png b/core/src/main/res/drawable-xhdpi/ic_fast_rewind_grey600_24dp.png
deleted file mode 100644
index 9468020b7..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_fast_rewind_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_fast_rewind_grey600_36dp.png b/core/src/main/res/drawable-xhdpi/ic_fast_rewind_grey600_36dp.png
deleted file mode 100644
index ea5493251..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_fast_rewind_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_fast_rewind_white_24dp.png b/core/src/main/res/drawable-xhdpi/ic_fast_rewind_white_24dp.png
deleted file mode 100644
index f4182f174..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_fast_rewind_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_fast_rewind_white_36dp.png b/core/src/main/res/drawable-xhdpi/ic_fast_rewind_white_36dp.png
deleted file mode 100644
index de9ec1d90..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_fast_rewind_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_hearing_grey600_18dp.png b/core/src/main/res/drawable-xhdpi/ic_hearing_grey600_18dp.png
deleted file mode 100644
index d014684e1..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_hearing_grey600_18dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_hearing_white_18dp.png b/core/src/main/res/drawable-xhdpi/ic_hearing_white_18dp.png
deleted file mode 100644
index 91adb4437..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_hearing_white_18dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_pause_grey600_24dp.png b/core/src/main/res/drawable-xhdpi/ic_pause_grey600_24dp.png
deleted file mode 100644
index 6708b4161..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_pause_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_pause_grey600_36dp.png b/core/src/main/res/drawable-xhdpi/ic_pause_grey600_36dp.png
deleted file mode 100644
index aeb13ebc4..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_pause_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_pause_white_24dp.png b/core/src/main/res/drawable-xhdpi/ic_pause_white_24dp.png
deleted file mode 100644
index f49aed757..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_pause_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png b/core/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png
deleted file mode 100644
index 7192ad487..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_play_arrow_grey600_24dp.png b/core/src/main/res/drawable-xhdpi/ic_play_arrow_grey600_24dp.png
deleted file mode 100644
index 6874b8236..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_play_arrow_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_play_arrow_grey600_36dp.png b/core/src/main/res/drawable-xhdpi/ic_play_arrow_grey600_36dp.png
deleted file mode 100644
index dabd252ee..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_play_arrow_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png b/core/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png
deleted file mode 100644
index 5b0110454..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png b/core/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png
deleted file mode 100644
index fff3e1f56..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_grey600_18dp.png b/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_grey600_18dp.png
deleted file mode 100644
index 2039d9ce8..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_grey600_18dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_white_18dp.png b/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_white_18dp.png
deleted file mode 100644
index 6dd240bca..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_white_18dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_skip_grey600_36dp.png b/core/src/main/res/drawable-xhdpi/ic_skip_grey600_36dp.png
deleted file mode 100644
index 31aa09ca2..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_skip_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_skip_white_36dp.png b/core/src/main/res/drawable-xhdpi/ic_skip_white_36dp.png
deleted file mode 100644
index e664f607c..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_skip_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_fast_forward_grey600_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_fast_forward_grey600_24dp.png
deleted file mode 100644
index 521f7490b..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_fast_forward_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_fast_forward_grey600_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_fast_forward_grey600_36dp.png
deleted file mode 100644
index 644645c8b..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_fast_forward_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_fast_forward_white_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_fast_forward_white_24dp.png
deleted file mode 100644
index 2d9a7e3c9..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_fast_forward_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_fast_forward_white_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_fast_forward_white_36dp.png
deleted file mode 100644
index 76c94c3ba..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_fast_forward_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_grey600_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_grey600_24dp.png
deleted file mode 100644
index ea5493251..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_grey600_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_grey600_36dp.png
deleted file mode 100644
index 831fda2ab..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_white_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_white_24dp.png
deleted file mode 100644
index de9ec1d90..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_white_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_white_36dp.png
deleted file mode 100644
index 8e11ac89e..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_hearing_grey600_18dp.png b/core/src/main/res/drawable-xxhdpi/ic_hearing_grey600_18dp.png
deleted file mode 100644
index 19456de04..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_hearing_grey600_18dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_hearing_white_18dp.png b/core/src/main/res/drawable-xxhdpi/ic_hearing_white_18dp.png
deleted file mode 100644
index 82de8bb65..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_hearing_white_18dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_pause_grey600_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_pause_grey600_24dp.png
deleted file mode 100644
index aeb13ebc4..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_pause_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_pause_grey600_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_pause_grey600_36dp.png
deleted file mode 100644
index 8753d9c50..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_pause_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_pause_white_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_pause_white_24dp.png
deleted file mode 100644
index 7192ad487..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_pause_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.png
deleted file mode 100644
index fb63ddc5a..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_play_arrow_grey600_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_play_arrow_grey600_24dp.png
deleted file mode 100644
index dabd252ee..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_play_arrow_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_play_arrow_grey600_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_play_arrow_grey600_36dp.png
deleted file mode 100644
index 9fcf99558..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_play_arrow_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png
deleted file mode 100644
index fff3e1f56..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_play_arrow_white_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_play_arrow_white_36dp.png
deleted file mode 100644
index 9b31e2d19..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_play_arrow_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_grey600_18dp.png b/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_grey600_18dp.png
deleted file mode 100644
index 16cdc31c1..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_grey600_18dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_white_18dp.png b/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_white_18dp.png
deleted file mode 100644
index 695eb950e..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_white_18dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_skip_grey600_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_skip_grey600_36dp.png
deleted file mode 100644
index 75a4a9545..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_skip_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_skip_white_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_skip_white_36dp.png
deleted file mode 100644
index a31299c81..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_skip_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxxhdpi/ic_skip_grey600_36dp.png b/core/src/main/res/drawable-xxxhdpi/ic_skip_grey600_36dp.png
deleted file mode 100644
index b599c2207..000000000
--- a/core/src/main/res/drawable-xxxhdpi/ic_skip_grey600_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxxhdpi/ic_skip_white_36dp.png b/core/src/main/res/drawable-xxxhdpi/ic_skip_white_36dp.png
deleted file mode 100644
index a0dd670c3..000000000
--- a/core/src/main/res/drawable-xxxhdpi/ic_skip_white_36dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable/ic_av_fast_forward_dark_48dp.xml b/core/src/main/res/drawable/ic_av_fast_forward_dark_48dp.xml
new file mode 100644
index 000000000..cf0faa33e
--- /dev/null
+++ b/core/src/main/res/drawable/ic_av_fast_forward_dark_48dp.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path android:fillColor="#FF757575" android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_av_fast_forward_white_48dp.xml b/core/src/main/res/drawable/ic_av_fast_forward_white_48dp.xml
new file mode 100644
index 000000000..aca5bcf29
--- /dev/null
+++ b/core/src/main/res/drawable/ic_av_fast_forward_white_48dp.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path android:fillColor="#FFFFFFFF" android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_av_fast_rewind_dark_48dp.xml b/core/src/main/res/drawable/ic_av_fast_rewind_dark_48dp.xml
new file mode 100644
index 000000000..47d1189cb
--- /dev/null
+++ b/core/src/main/res/drawable/ic_av_fast_rewind_dark_48dp.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path android:fillColor="#FF757575" android:pathData="M11,18L11,6l-8.5,6 8.5,6zM11.5,12l8.5,6L20,6l-8.5,6z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_av_fast_rewind_white_48dp.xml b/core/src/main/res/drawable/ic_av_fast_rewind_white_48dp.xml
new file mode 100644
index 000000000..ba2b8ae4f
--- /dev/null
+++ b/core/src/main/res/drawable/ic_av_fast_rewind_white_48dp.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path android:fillColor="#FFFFFFFF" android:pathData="M11,18L11,6l-8.5,6 8.5,6zM11.5,12l8.5,6L20,6l-8.5,6z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_av_pause_dark_48dp.xml b/core/src/main/res/drawable/ic_av_pause_dark_48dp.xml
new file mode 100644
index 000000000..61fdd4b5b
--- /dev/null
+++ b/core/src/main/res/drawable/ic_av_pause_dark_48dp.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path android:fillColor="#FF757575" android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_av_pause_white_48dp.xml b/core/src/main/res/drawable/ic_av_pause_white_48dp.xml
new file mode 100644
index 000000000..3512563ec
--- /dev/null
+++ b/core/src/main/res/drawable/ic_av_pause_white_48dp.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path android:fillColor="#FFFFFFFF" android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_av_play_dark_24dp.xml b/core/src/main/res/drawable/ic_av_play_dark_24dp.xml
new file mode 100644
index 000000000..5bc12c0e1
--- /dev/null
+++ b/core/src/main/res/drawable/ic_av_play_dark_24dp.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path android:fillColor="#FF757575" android:pathData="M8,5v14l11,-7z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_av_play_dark_48dp.xml b/core/src/main/res/drawable/ic_av_play_dark_48dp.xml
new file mode 100644
index 000000000..dbe5e7104
--- /dev/null
+++ b/core/src/main/res/drawable/ic_av_play_dark_48dp.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path android:fillColor="#FF757575" android:pathData="M8,5v14l11,-7z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_av_play_white_24dp.xml b/core/src/main/res/drawable/ic_av_play_white_24dp.xml
new file mode 100644
index 000000000..0e896a8d4
--- /dev/null
+++ b/core/src/main/res/drawable/ic_av_play_white_24dp.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path android:fillColor="#FFFFFFFF" android:pathData="M8,5v14l11,-7z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_av_play_white_48dp.xml b/core/src/main/res/drawable/ic_av_play_white_48dp.xml
new file mode 100644
index 000000000..bf94a000b
--- /dev/null
+++ b/core/src/main/res/drawable/ic_av_play_white_48dp.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path android:fillColor="#FFFFFFFF" android:pathData="M8,5v14l11,-7z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_av_skip_dark_48dp.xml b/core/src/main/res/drawable/ic_av_skip_dark_48dp.xml
new file mode 100644
index 000000000..2552f8d73
--- /dev/null
+++ b/core/src/main/res/drawable/ic_av_skip_dark_48dp.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path android:fillColor="#FF757575" android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_av_skip_white_48dp.xml b/core/src/main/res/drawable/ic_av_skip_white_48dp.xml
new file mode 100644
index 000000000..7e0073e88
--- /dev/null
+++ b/core/src/main/res/drawable/ic_av_skip_white_48dp.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path android:fillColor="#FFFFFFFF" android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_notification_cast_off.xml b/core/src/main/res/drawable/ic_notification_cast_off.xml
index 63a21fbe2..3e3accd0b 100644
--- a/core/src/main/res/drawable/ic_notification_cast_off.xml
+++ b/core/src/main/res/drawable/ic_notification_cast_off.xml
@@ -1,5 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp" android:viewportHeight="24.0"
- android:viewportWidth="24.0" android:width="24dp">
+ android:height="30dp" android:viewportHeight="24.0"
+ android:viewportWidth="24.0" android:width="30dp">
<path android:fillColor="#FFFFFFFF" android:pathData="M1.6,1.27L0.25,2.75L1.41,3.8C1.16,4.13 1,4.55 1,5V8H3V5.23L18.2,19H14V21H20.41L22.31,22.72L23.65,21.24M6.5,3L8.7,5H21V16.14L23,17.95V5C23,3.89 22.1,3 21,3M1,10V12A9,9 0 0,1 10,21H12C12,14.92 7.08,10 1,10M1,14V16A5,5 0 0,1 6,21H8A7,7 0 0,0 1,14M1,18V21H4A3,3 0 0,0 1,18Z" />
</vector> \ No newline at end of file
diff --git a/core/src/main/res/drawable/ic_notification_fast_forward.xml b/core/src/main/res/drawable/ic_notification_fast_forward.xml
index bf564977c..8ee82f4ed 100644
--- a/core/src/main/res/drawable/ic_notification_fast_forward.xml
+++ b/core/src/main/res/drawable/ic_notification_fast_forward.xml
@@ -1,5 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp" android:viewportHeight="24.0"
- android:viewportWidth="24.0" android:width="24dp">
+ android:height="30dp" android:viewportHeight="24.0"
+ android:viewportWidth="24.0" android:width="30dp">
<path android:fillColor="#FFFFFFFF" android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z"/>
</vector>
diff --git a/core/src/main/res/drawable/ic_notification_fast_rewind.xml b/core/src/main/res/drawable/ic_notification_fast_rewind.xml
index 847159cc5..261ed7e6f 100644
--- a/core/src/main/res/drawable/ic_notification_fast_rewind.xml
+++ b/core/src/main/res/drawable/ic_notification_fast_rewind.xml
@@ -1,5 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp" android:viewportHeight="24.0"
- android:viewportWidth="24.0" android:width="24dp">
+ android:height="30dp" android:viewportHeight="24.0"
+ android:viewportWidth="24.0" android:width="30dp">
<path android:fillColor="#FFFFFFFF" android:pathData="M11,18L11,6l-8.5,6 8.5,6zM11.5,12l8.5,6L20,6l-8.5,6z"/>
</vector>
diff --git a/core/src/main/res/drawable/ic_notification_pause.xml b/core/src/main/res/drawable/ic_notification_pause.xml
index d46efb2f5..16ebd4eab 100644
--- a/core/src/main/res/drawable/ic_notification_pause.xml
+++ b/core/src/main/res/drawable/ic_notification_pause.xml
@@ -1,5 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp" android:viewportHeight="24.0"
- android:viewportWidth="24.0" android:width="24dp">
+ android:height="30dp" android:viewportHeight="24.0"
+ android:viewportWidth="24.0" android:width="30dp">
<path android:fillColor="#FFFFFFFF" android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z"/>
</vector>
diff --git a/core/src/main/res/drawable/ic_notification_play.xml b/core/src/main/res/drawable/ic_notification_play.xml
index d571460c6..eb4acd983 100644
--- a/core/src/main/res/drawable/ic_notification_play.xml
+++ b/core/src/main/res/drawable/ic_notification_play.xml
@@ -1,5 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp" android:viewportHeight="24.0"
- android:viewportWidth="24.0" android:width="24dp">
+ android:height="30dp" android:viewportHeight="24.0"
+ android:viewportWidth="24.0" android:width="30dp">
<path android:fillColor="#FFFFFFFF" android:pathData="M8,5v14l11,-7z"/>
</vector>
diff --git a/core/src/main/res/drawable/ic_notification_skip.xml b/core/src/main/res/drawable/ic_notification_skip.xml
index 0c65448cc..6bf03002a 100644
--- a/core/src/main/res/drawable/ic_notification_skip.xml
+++ b/core/src/main/res/drawable/ic_notification_skip.xml
@@ -1,5 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp" android:viewportHeight="24.0"
- android:viewportWidth="24.0" android:width="24dp">
+ android:height="30dp" android:viewportHeight="24.0"
+ android:viewportWidth="24.0" android:width="30dp">
<path android:fillColor="#FFFFFFFF" android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z"/>
</vector>
diff --git a/core/src/main/res/drawable/ic_videocam_grey600_24dp.xml b/core/src/main/res/drawable/ic_videocam_grey600_24dp.xml
new file mode 100644
index 000000000..40c893883
--- /dev/null
+++ b/core/src/main/res/drawable/ic_videocam_grey600_24dp.xml
@@ -0,0 +1,8 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:width="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path android:fillColor="#FF757575"
+ android:pathData="M17,10.5V7c0,-0.55 -0.45,-1 -1,-1H4c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1v-3.5l4,4v-11l-4,4z"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_videocam_white_24dp.xml b/core/src/main/res/drawable/ic_videocam_white_24dp.xml
new file mode 100644
index 000000000..a8cfd71e3
--- /dev/null
+++ b/core/src/main/res/drawable/ic_videocam_white_24dp.xml
@@ -0,0 +1,8 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:width="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path android:fillColor="#FFFFFFFF"
+ android:pathData="M17,10.5V7c0,-0.55 -0.45,-1 -1,-1H4c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1v-3.5l4,4v-11l-4,4z"/>
+</vector>
diff --git a/core/src/main/res/layout/player_widget.xml b/core/src/main/res/layout/player_widget.xml
index 5f49fb7ef..b0e5e0fd8 100644
--- a/core/src/main/res/layout/player_widget.xml
+++ b/core/src/main/res/layout/player_widget.xml
@@ -19,8 +19,10 @@
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_margin="12dp"
- android:background="@android:color/transparent"
- android:src="@drawable/ic_play_arrow_white_24dp" />
+ android:background="?android:attr/selectableItemBackground"
+ android:scaleType="fitCenter"
+ android:padding="8dp"
+ android:src="@drawable/ic_av_play_white_24dp" />
<LinearLayout
android:id="@+id/layout_left"
diff --git a/core/src/main/res/values-large/dimens.xml b/core/src/main/res/values-large/dimens.xml
index 2d107eef0..27e269099 100644
--- a/core/src/main/res/values-large/dimens.xml
+++ b/core/src/main/res/values-large/dimens.xml
@@ -2,6 +2,4 @@
<resources>
<dimen name="thumbnail_length">170dp</dimen>
- <dimen name="thumbnail_length_queue_item">64dp</dimen>
- <dimen name="thumbnail_length_downloaded_item">64dp</dimen>
</resources> \ No newline at end of file
diff --git a/core/src/main/res/values/attrs.xml b/core/src/main/res/values/attrs.xml
index 53cf7b211..1147f015d 100644
--- a/core/src/main/res/values/attrs.xml
+++ b/core/src/main/res/values/attrs.xml
@@ -9,6 +9,7 @@
<attr name="av_fast_forward" format="reference"/>
<attr name="av_pause" format="reference"/>
<attr name="av_play" format="reference"/>
+ <attr name="av_skip" format="reference"/>
<attr name="av_speed" format="reference"/>
<attr name="av_rewind" format="reference"/>
<attr name="content_discard" format="reference"/>
@@ -26,18 +27,13 @@
<attr name="social_share" format="reference"/>
<attr name="stat_playlist" format="reference"/>
<attr name="ic_folder" format="reference"/>
- <attr name="type_audio" format="reference"/>
<attr name="type_video" format="reference"/>
<attr name="overlay_drawable" format="reference"/>
<attr name="dragview_background" format="reference"/>
<attr name="dragview_float_background" format="reference"/>
<attr name="ic_new" format="reference"/>
<attr name="ic_history" format="reference"/>
- <attr name="av_play_big" format="reference"/>
- <attr name="av_pause_big" format="reference"/>
- <attr name="av_ff_big" format="reference"/>
- <attr name="av_rew_big" format="reference"/>
- <attr name="av_skip_big" format="reference"/>
+ <attr name="ic_settings_playback" format="reference"/>
<attr name="ic_settings" format="reference"/>
<attr name="ic_lock_open" format="reference"/>
<attr name="ic_lock_closed" format="reference"/>
diff --git a/core/src/main/res/values/colors.xml b/core/src/main/res/values/colors.xml
index fea7da4a4..b162038cf 100644
--- a/core/src/main/res/values/colors.xml
+++ b/core/src/main/res/values/colors.xml
@@ -7,8 +7,8 @@
<color name="black">#000000</color>
<color name="holo_blue_light">#33B5E5</color>
<color name="holo_blue_dark">#0099CC</color>
- <color name="download_success_green">#669900</color>
- <color name="download_failed_red">#CC0000</color>
+ <color name="download_success_green">#248800</color>
+ <color name="download_failed_red">#B00020</color>
<color name="status_progress">#E033B5E5</color>
<color name="overlay_dark">#2C2C2C</color>
<color name="overlay_light">#FFFFFF</color>
diff --git a/core/src/main/res/values/dimens.xml b/core/src/main/res/values/dimens.xml
index 02c398b62..34cbe1b72 100644
--- a/core/src/main/res/values/dimens.xml
+++ b/core/src/main/res/values/dimens.xml
@@ -10,8 +10,8 @@
<dimen name="text_size_navdrawer">16sp</dimen>
<dimen name="text_size_medium">18sp</dimen>
<dimen name="text_size_large">22sp</dimen>
- <dimen name="thumbnail_length_itemlist">64dp</dimen>
- <dimen name="thumbnail_length_queue_item">64dp</dimen>
+ <dimen name="thumbnail_length_itemlist">56dp</dimen>
+ <dimen name="thumbnail_length_queue_item">56dp</dimen>
<dimen name="thumbnail_length_downloaded_item">64dp</dimen>
<dimen name="thumbnail_length_onlinefeedview">100dp</dimen>
<dimen name="feeditemlist_header_height">132dp</dimen>
@@ -23,7 +23,7 @@
<dimen name="listitem_threeline_textleftpadding">16dp</dimen>
<dimen name="listitem_threeline_textrightpadding">8dp</dimen>
- <dimen name="listitem_threeline_verticalpadding">16dp</dimen>
+ <dimen name="listitem_threeline_verticalpadding">8dp</dimen>
<dimen name="listitem_threeline_horizontalpadding">16dp</dimen>
<dimen name="list_vertical_padding">8dp</dimen>
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index e5d8247bc..8cb9f7b84 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -102,6 +102,7 @@
<string name="feed_volume_reduction_light">Light</string>
<string name="feed_volume_reduction_heavy">Heavy</string>
<string name="parallel_downloads_suffix">\u0020parallel downloads</string>
+ <string name="download_queued">Download queued</string>
<string name="feed_auto_download_global">Global default</string>
<string name="feed_auto_download_always">Always</string>
<string name="feed_auto_download_never">Never</string>
diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml
index 5656ca0e9..f6c31f652 100644
--- a/core/src/main/res/values/styles.xml
+++ b/core/src/main/res/values/styles.xml
@@ -20,12 +20,13 @@
<item name="action_search">@drawable/ic_search_grey600_24dp</item>
<item name="action_stream">@drawable/ic_stream_grey600</item>
<item name="av_download">@drawable/ic_file_download_grey600_24dp</item>
- <item name="av_fast_forward">@drawable/ic_fast_forward_grey600_24dp</item>
- <item name="av_pause">@drawable/ic_pause_grey600_24dp</item>
- <item name="av_play">@drawable/ic_play_arrow_grey600_24dp</item>
+ <item name="av_pause">@drawable/ic_av_pause_dark_48dp</item>
+ <item name="av_play">@drawable/ic_av_play_dark_48dp</item>
+ <item name="av_rewind">@drawable/ic_av_fast_rewind_dark_48dp</item>
+ <item name="av_fast_forward">@drawable/ic_av_fast_forward_dark_48dp</item>
+ <item name="av_skip">@drawable/ic_av_skip_dark_48dp</item>
<item name="av_speed">@drawable/ic_playback_speed_dark_48dp</item>
<item name="ic_settings_speed">@drawable/ic_playback_speed_dark_24dp</item>
- <item name="av_rewind">@drawable/ic_fast_rewind_grey600_24dp</item>
<item name="content_discard">@drawable/ic_delete_grey600_24dp</item>
<item name="content_new">@drawable/ic_add_grey600_24dp</item>
<item name="content_remove_from_queue">@drawable/ic_remove_grey600</item>
@@ -38,8 +39,7 @@
<item name="navigation_up">@drawable/navigation_up</item>
<item name="social_share">@drawable/ic_share_grey600_24dp</item>
<item name="stat_playlist">@drawable/ic_list_grey600_24dp</item>
- <item name="type_audio">@drawable/ic_hearing_grey600_18dp</item>
- <item name="type_video">@drawable/ic_remove_red_eye_grey600_18dp</item>
+ <item name="type_video">@drawable/ic_videocam_grey600_24dp</item>
<item name="non_transparent_background">@color/white</item>
<item name="overlay_background">@color/overlay_light</item>
<item name="overlay_drawable">@drawable/overlay_drawable</item>
@@ -50,11 +50,7 @@
<item name="ic_new">@drawable/ic_new_releases_grey600_24dp</item>
<item name="ic_history">@drawable/ic_history_grey600_24dp</item>
<item name="ic_folder">@drawable/ic_folder_grey600_24dp</item>
- <item name="av_play_big">@drawable/ic_play_arrow_grey600_36dp</item>
- <item name="av_pause_big">@drawable/ic_pause_grey600_36dp</item>
- <item name="av_ff_big">@drawable/ic_fast_forward_grey600_36dp</item>
- <item name="av_rew_big">@drawable/ic_fast_rewind_grey600_36dp</item>
- <item name="av_skip_big">@drawable/ic_skip_grey600_36dp</item>
+ <item name="ic_settings_playback">@drawable/ic_av_play_dark_24dp</item>
<item name="ic_fav">@drawable/ic_star_border_grey600_24dp</item>
<item name="ic_unfav">@drawable/ic_star_grey600_24dp</item>
<item name="ic_settings">@drawable/ic_settings_grey600_24dp</item>
@@ -109,12 +105,13 @@
<item name="action_search">@drawable/ic_search_white_24dp</item>
<item name="action_stream">@drawable/ic_stream_white</item>
<item name="av_download">@drawable/ic_file_download_white_24dp</item>
- <item name="av_fast_forward">@drawable/ic_fast_forward_white_24dp</item>
- <item name="av_pause">@drawable/ic_pause_white_24dp</item>
- <item name="av_play">@drawable/ic_play_arrow_white_24dp</item>
+ <item name="av_rewind">@drawable/ic_av_fast_rewind_white_48dp</item>
+ <item name="av_fast_forward">@drawable/ic_av_fast_forward_white_48dp</item>
+ <item name="av_pause">@drawable/ic_av_pause_white_48dp</item>
+ <item name="av_play">@drawable/ic_av_play_white_48dp</item>
+ <item name="av_skip">@drawable/ic_av_skip_white_48dp</item>
<item name="av_speed">@drawable/ic_playback_speed_white_48dp</item>
<item name="ic_settings_speed">@drawable/ic_playback_speed_white_24dp</item>
- <item name="av_rewind">@drawable/ic_fast_rewind_white_24dp</item>
<item name="content_discard">@drawable/ic_delete_white_24dp</item>
<item name="content_new">@drawable/ic_add_white_24dp</item>
<item name="content_remove_from_queue">@drawable/ic_remove_white</item>
@@ -127,8 +124,7 @@
<item name="navigation_up">@drawable/navigation_up_dark</item>
<item name="social_share">@drawable/ic_share_white_24dp</item>
<item name="stat_playlist">@drawable/ic_list_white_24dp</item>
- <item name="type_audio">@drawable/ic_hearing_white_18dp</item>
- <item name="type_video">@drawable/ic_remove_red_eye_white_18dp</item>
+ <item name="type_video">@drawable/ic_videocam_white_24dp</item>
<item name="non_transparent_background">@color/black</item>
<item name="overlay_background">@color/overlay_dark</item>
<item name="overlay_drawable">@drawable/overlay_drawable_dark</item>
@@ -139,11 +135,7 @@
<item name="ic_new">@drawable/ic_new_releases_white_24dp</item>
<item name="ic_history">@drawable/ic_history_white_24dp</item>
<item name="ic_folder">@drawable/ic_folder_white_24dp</item>
- <item name="av_play_big">@drawable/ic_play_arrow_white_36dp</item>
- <item name="av_pause_big">@drawable/ic_pause_white_36dp</item>
- <item name="av_ff_big">@drawable/ic_fast_forward_white_36dp</item>
- <item name="av_rew_big">@drawable/ic_fast_rewind_white_36dp</item>
- <item name="av_skip_big">@drawable/ic_skip_white_36dp</item>
+ <item name="ic_settings_playback">@drawable/ic_av_play_white_24dp</item>
<item name="ic_fav">@drawable/ic_star_border_white_24dp</item>
<item name="ic_unfav">@drawable/ic_star_white_24dp</item>
<item name="ic_settings">@drawable/ic_settings_white_24dp</item>
@@ -291,7 +283,7 @@
<style name="AntennaPod.TextView.ListItemPrimaryTitle" parent="@android:style/TextAppearance.Small">
<item name="android:textSize">16sp</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
- <item name="android:lines">2</item>
+ <item name="android:maxLines">2</item>
<item name="android:ellipsize">end</item>
</style>