summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java3
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java35
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java13
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java93
-rw-r--r--app/src/main/res/layout/external_player_fragment.xml8
-rw-r--r--app/src/main/res/layout/mediaplayerinfo_activity.xml18
-rw-r--r--app/src/main/res/layout/simplechapter_item.xml9
-rw-r--r--app/src/main/res/layout/videoplayer_activity.xml8
-rw-r--r--app/src/main/res/xml/preferences.xml2
-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/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/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/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.java16
-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_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_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_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_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_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_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_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_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/layout/player_widget.xml6
-rw-r--r--core/src/main/res/values/attrs.xml7
-rw-r--r--core/src/main/res/values/styles.xml30
117 files changed, 1059 insertions, 754 deletions
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java b/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java
index ebf59fea7..840a7d01f 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java
@@ -58,7 +58,8 @@ class DBTestUtils {
List<Chapter> chapters = new ArrayList<>();
item.setChapters(chapters);
for (int k = 0; k < numChapters; k++) {
- chapters.add(new SimpleChapter(k, "item " + j + " chapter " + k, item, "http://example.com"));
+ chapters.add(new SimpleChapter(k, "item " + j + " chapter " + k,
+ "http://example.com", "http://example.com/image.png"));
}
}
f.getItems().add(item);
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java
index 3e84e090a..cb74bb169 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java
@@ -1,6 +1,7 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
+import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -9,10 +10,15 @@ import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.request.RequestOptions;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.Chapter;
+import de.danoeh.antennapod.core.feed.util.ImageResourceUtils;
+import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.util.ChapterUtils;
import de.danoeh.antennapod.core.util.Converter;
+import de.danoeh.antennapod.core.util.EmbeddedChapterImage;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.ThemeUtils;
import de.danoeh.antennapod.core.util.playback.Playable;
@@ -23,6 +29,7 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
private Playable media;
private final Callback callback;
private int currentChapterIndex = -1;
+ private boolean hasImages = false;
public ChaptersListAdapter(Context context, int textViewResourceId, Callback callback) {
super(context, textViewResourceId);
@@ -31,6 +38,15 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
public void setMedia(Playable media) {
this.media = media;
+ hasImages = false;
+ if (media.getChapters() != null) {
+ for (Chapter chapter : media.getChapters()) {
+ if (!ignoreChapter(chapter) && !TextUtils.isEmpty(chapter.getImageUrl())) {
+ hasImages = true;
+ }
+ }
+ }
+ notifyDataSetChanged();
}
@NonNull
@@ -51,6 +67,7 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
holder.title = convertView.findViewById(R.id.txtvTitle);
holder.start = convertView.findViewById(R.id.txtvStart);
holder.link = convertView.findViewById(R.id.txtvLink);
+ holder.image = convertView.findViewById(R.id.imgvCover);
holder.duration = convertView.findViewById(R.id.txtvDuration);
holder.secondaryActionButton = convertView.findViewById(R.id.secondaryActionButton);
holder.secondaryActionIcon = convertView.findViewById(R.id.secondaryActionIcon);
@@ -94,6 +111,23 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
holder.view.setBackgroundColor(ContextCompat.getColor(getContext(), android.R.color.transparent));
}
+ if (hasImages) {
+ holder.image.setVisibility(View.VISIBLE);
+ if (TextUtils.isEmpty(sc.getImageUrl())) {
+ Glide.with(getContext()).clear(holder.image);
+ } else {
+ Glide.with(getContext())
+ .load(EmbeddedChapterImage.getModelFor(media, position))
+ .apply(new RequestOptions()
+ .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
+ .dontAnimate()
+ .fitCenter())
+ .into(holder.image);
+ }
+ } else {
+ holder.image.setVisibility(View.GONE);
+ }
+
return convertView;
}
@@ -103,6 +137,7 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
TextView start;
TextView link;
TextView duration;
+ ImageView image;
View secondaryActionButton;
ImageView secondaryActionIcon;
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java
index 386b760b1..9940ccbdd 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java
@@ -6,6 +6,7 @@ import android.util.Log;
import android.view.View;
import android.widget.ListView;
+import de.danoeh.antennapod.core.util.ChapterUtils;
import java.util.List;
import java.util.ListIterator;
@@ -104,18 +105,10 @@ public class ChaptersFragment extends ListFragment {
}
private int getCurrentChapter(Playable media) {
- if (media == null || media.getChapters() == null || media.getChapters().size() == 0 || controller == null) {
+ if (controller == null) {
return -1;
}
- int currentPosition = controller.getPosition();
-
- List<Chapter> chapters = media.getChapters();
- for (int i = 0; i < chapters.size(); i++) {
- if (chapters.get(i).getStart() > currentPosition) {
- return i - 1;
- }
- }
- return chapters.size() - 1;
+ return ChapterUtils.getCurrentChapterIndex(media, controller.getPosition());
}
private void loadMediaInfo() {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java
index 79e88679e..fc540e223 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java
@@ -1,29 +1,36 @@
package de.danoeh.antennapod.fragment;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.fragment.app.Fragment;
+import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
-
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
import com.bumptech.glide.Glide;
-
import com.bumptech.glide.load.resource.bitmap.FitCenter;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
+import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.request.RequestOptions;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.core.glide.ApGlideSettings;
+import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.feed.util.ImageResourceUtils;
+import de.danoeh.antennapod.core.glide.ApGlideSettings;
+import de.danoeh.antennapod.core.util.ChapterUtils;
+import de.danoeh.antennapod.core.util.EmbeddedChapterImage;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import io.reactivex.Maybe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
/**
* Displays the cover and the title of a FeedItem.
@@ -38,6 +45,8 @@ public class CoverFragment extends Fragment {
private ImageView imgvCover;
private PlaybackController controller;
private Disposable disposable;
+ private int displayedChapterIndex = -2;
+ private Playable media;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -55,31 +64,26 @@ public class CoverFragment extends Fragment {
if (disposable != null) {
disposable.dispose();
}
- disposable = Maybe.create(emitter -> {
- Playable media = controller.getMedia();
- if (media != null) {
- emitter.onSuccess(media);
- } else {
- emitter.onComplete();
- }
- })
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(media -> displayMediaInfo((Playable) media),
- error -> Log.e(TAG, Log.getStackTraceString(error)));
+ disposable = Maybe.<Playable>create(emitter -> {
+ Playable media = controller.getMedia();
+ if (media != null) {
+ emitter.onSuccess(media);
+ } else {
+ emitter.onComplete();
+ }
+ })
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(media -> {
+ this.media = media;
+ displayMediaInfo(media);
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
private void displayMediaInfo(@NonNull Playable media) {
txtvPodcastTitle.setText(media.getFeedTitle());
txtvEpisodeTitle.setText(media.getEpisodeTitle());
- Glide.with(this)
- .load(ImageResourceUtils.getImageLocation(media))
- .apply(new RequestOptions()
- .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
- .dontAnimate()
- .transforms(new FitCenter(),
- new RoundedCorners((int) (16 * getResources().getDisplayMetrics().density))))
- .into(imgvCover);
+ displayCoverImage(media.getPosition());
}
@Override
@@ -102,6 +106,7 @@ public class CoverFragment extends Fragment {
};
controller.init();
loadMediaInfo();
+ EventBus.getDefault().register(this);
}
@Override
@@ -109,6 +114,44 @@ public class CoverFragment extends Fragment {
super.onStop();
controller.release();
controller = null;
+ EventBus.getDefault().unregister(this);
+ }
+
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ public void onEventMainThread(PlaybackPositionEvent event) {
+ if (controller == null) {
+ return;
+ }
+ displayCoverImage(event.getPosition());
+ }
+
+ private void displayCoverImage(int position) {
+ int chapter = ChapterUtils.getCurrentChapterIndex(media, position);
+ if (chapter != displayedChapterIndex) {
+ displayedChapterIndex = chapter;
+
+ RequestBuilder<Drawable> cover = Glide.with(this)
+ .load(ImageResourceUtils.getImageLocation(media))
+ .apply(new RequestOptions()
+ .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
+ .dontAnimate()
+ .transforms(new FitCenter(),
+ new RoundedCorners((int) (16 * getResources().getDisplayMetrics().density))));
+ if (chapter == -1 || TextUtils.isEmpty(media.getChapters().get(chapter).getImageUrl())) {
+ cover.into(imgvCover);
+ } else {
+ Glide.with(this)
+ .load(EmbeddedChapterImage.getModelFor(media, chapter))
+ .apply(new RequestOptions()
+ .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
+ .dontAnimate()
+ .transforms(new FitCenter(),
+ new RoundedCorners((int) (16 * getResources().getDisplayMetrics().density))))
+ .thumbnail(cover)
+ .error(cover)
+ .into(imgvCover);
+ }
+ }
}
@Override
diff --git a/app/src/main/res/layout/external_player_fragment.xml b/app/src/main/res/layout/external_player_fragment.xml
index dc890807c..3e2efe47e 100644
--- a/app/src/main/res/layout/external_player_fragment.xml
+++ b/app/src/main/res/layout/external_player_fragment.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/fragmentLayout"
android:layout_width="match_parent"
android:layout_height="@dimen/external_player_height"
@@ -44,7 +44,9 @@
android:layout_centerVertical="true"
android:contentDescription="@string/pause_label"
android:background="?attr/selectableItemBackground"
- android:src="?attr/av_play_big"
+ app:srcCompat="?attr/av_play"
+ android:scaleType="fitCenter"
+ android:padding="8dp"
tools:src="@drawable/ic_play_arrow_white_36dp"/>
<TextView
diff --git a/app/src/main/res/layout/mediaplayerinfo_activity.xml b/app/src/main/res/layout/mediaplayerinfo_activity.xml
index 00c912d2c..08d29c8e1 100644
--- a/app/src/main/res/layout/mediaplayerinfo_activity.xml
+++ b/app/src/main/res/layout/mediaplayerinfo_activity.xml
@@ -119,9 +119,9 @@
android:layout_centerHorizontal="true"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/pause_label"
- android:src="?attr/av_play"
+ app:srcCompat="?attr/av_play"
android:scaleType="fitCenter"
- tools:src="@drawable/ic_play_arrow_white_24dp"
+ tools:src="@drawable/ic_av_play_white_24dp"
tools:background="@android:color/holo_green_dark" />
<ImageButton
@@ -134,9 +134,9 @@
android:layout_marginStart="16dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/rewind_label"
- android:src="?attr/av_rew_big"
+ app:srcCompat="?attr/av_rewind"
android:scaleType="fitCenter"
- tools:src="@drawable/ic_fast_rewind_white_36dp"
+ tools:src="@drawable/ic_av_fast_rewind_white_48dp"
tools:background="@android:color/holo_blue_dark" />
<TextView
@@ -163,7 +163,7 @@
android:layout_toStartOf="@id/butRev"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/set_playback_speed_label"
- android:src="?attr/av_speed"
+ app:srcCompat="?attr/av_speed"
android:scaleType="fitCenter"
tools:src="@drawable/ic_playback_speed_white_48dp"
tools:visibility="gone"
@@ -210,9 +210,9 @@
android:layout_marginEnd="16dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/fast_forward_label"
- android:src="?attr/av_ff_big"
+ app:srcCompat="?attr/av_fast_forward"
android:scaleType="fitCenter"
- tools:src="@drawable/ic_fast_forward_white_36dp"
+ tools:src="@drawable/ic_av_fast_forward_white_48dp"
tools:background="@android:color/holo_blue_dark" />
<TextView
@@ -239,9 +239,9 @@
android:layout_toEndOf="@id/butFF"
android:background="?attr/selectableItemBackgroundBorderless"
android:scaleType="fitCenter"
- android:src="?attr/av_skip_big"
+ app:srcCompat="?attr/av_skip"
android:contentDescription="@string/skip_episode_label"
- tools:src="@drawable/ic_skip_white_36dp"
+ tools:src="@drawable/ic_av_skip_white_48dp"
tools:background="@android:color/holo_green_dark" />
</RelativeLayout>
diff --git a/app/src/main/res/layout/simplechapter_item.xml b/app/src/main/res/layout/simplechapter_item.xml
index 86927f32c..54c607d71 100644
--- a/app/src/main/res/layout/simplechapter_item.xml
+++ b/app/src/main/res/layout/simplechapter_item.xml
@@ -10,6 +10,15 @@
android:baselineAligned="false"
android:descendantFocusability="blocksDescendants">
+ <ImageView
+ android:id="@+id/imgvCover"
+ android:layout_width="@dimen/thumbnail_length_queue_item"
+ android:layout_height="@dimen/thumbnail_length_queue_item"
+ android:contentDescription="@string/cover_label"
+ android:layout_marginLeft="16dp"
+ android:layout_marginStart="16dp"
+ tools:src="@tools:sample/avatars"/>
+
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
diff --git a/app/src/main/res/layout/videoplayer_activity.xml b/app/src/main/res/layout/videoplayer_activity.xml
index b26ef304c..42484ea1b 100644
--- a/app/src/main/res/layout/videoplayer_activity.xml
+++ b/app/src/main/res/layout/videoplayer_activity.xml
@@ -27,6 +27,8 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layoutDirection="ltr"
+ android:background="@android:color/transparent"
+ android:padding="16dp"
android:orientation="horizontal">
<ImageButton
@@ -34,7 +36,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
- android:background="@android:color/transparent"
+ android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/rewind_label"
app:srcCompat="@drawable/ic_av_fast_rewind_white_80dp" />
@@ -43,7 +45,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
- android:background="@android:color/transparent"
+ android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/pause_label"
app:srcCompat="@drawable/ic_av_pause_white_80dp" />
@@ -52,7 +54,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
- android:background="@android:color/transparent"
+ android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/fast_forward_label"
app:srcCompat="@drawable/ic_av_fast_forward_white_80dp" />
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index 6e734f789..1ca3a8088 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -19,7 +19,7 @@
android:key="prefScreenPlayback"
android:title="@string/playback_pref"
android:summary="@string/playback_pref_sum"
- android:icon="?attr/av_play" />
+ android:icon="?attr/ic_settings_playback" />
<Preference
android:key="prefScreenNetwork"
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/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/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/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..d9567e1e1 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;
@@ -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_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_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_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_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_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_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_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_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/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/attrs.xml b/core/src/main/res/values/attrs.xml
index 77dd1fe47..44c79567c 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"/>
@@ -32,11 +33,7 @@
<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/styles.xml b/core/src/main/res/values/styles.xml
index 33b736089..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>
@@ -49,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>
@@ -108,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>
@@ -137,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>