summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorTony Tam <engineer.tonytam@pm.me>2020-04-21 14:20:22 -0700
committerGitHub <noreply@github.com>2020-04-21 23:20:22 +0200
commit92eb1d669ba14318b90ad4da4cd925279007fa3a (patch)
tree07924bd7b28104f581e8b715749587dd3cab94a9 /core
parent3a86745e8144baa6d0a2cdc88aa0e29d1fd6e66c (diff)
downloadAntennaPod-92eb1d669ba14318b90ad4da4cd925279007fa3a.zip
Skip intro and ending per feed (#3975)
Diffstat (limited to 'core')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/settings/SkipIntroEndingChangedEvent.java25
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java41
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java84
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java6
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java14
-rw-r--r--core/src/main/res/values/strings.xml6
6 files changed, 170 insertions, 6 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/settings/SkipIntroEndingChangedEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/settings/SkipIntroEndingChangedEvent.java
new file mode 100644
index 000000000..583f7b13f
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/event/settings/SkipIntroEndingChangedEvent.java
@@ -0,0 +1,25 @@
+package de.danoeh.antennapod.core.event.settings;
+
+public class SkipIntroEndingChangedEvent {
+ private final int skipIntro;
+ private final int skipEnding;
+ private final long feedId;
+
+ public SkipIntroEndingChangedEvent(int skipIntro, int skipEnding, long feedId) {
+ this.skipIntro= skipIntro;
+ this.skipEnding = skipEnding;
+ this.feedId = feedId;
+ }
+
+ public int getSkipIntro() {
+ return skipIntro;
+ }
+
+ public int getSkipEnding() {
+ return skipEnding;
+ }
+
+ public long getFeedId() {
+ return feedId;
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java
index b24c52266..2a2568f28 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java
@@ -34,12 +34,18 @@ public class FeedPreferences {
private String username;
private String password;
private float feedPlaybackSpeed;
+ private int feedSkipIntro;
+ private int feedSkipEnding;
public FeedPreferences(long feedID, boolean autoDownload, AutoDeleteAction auto_delete_action, VolumeAdaptionSetting volumeAdaptionSetting, String username, String password) {
this(feedID, autoDownload, true, auto_delete_action, volumeAdaptionSetting, username, password, new FeedFilter(), SPEED_USE_GLOBAL);
}
private FeedPreferences(long feedID, boolean autoDownload, boolean keepUpdated, AutoDeleteAction auto_delete_action, VolumeAdaptionSetting volumeAdaptionSetting, String username, String password, @NonNull FeedFilter filter, float feedPlaybackSpeed) {
+ this(feedID, autoDownload, true, auto_delete_action, volumeAdaptionSetting, username, password, new FeedFilter(), feedPlaybackSpeed, 0, 0);
+ }
+
+ private FeedPreferences(long feedID, boolean autoDownload, boolean keepUpdated, AutoDeleteAction auto_delete_action, VolumeAdaptionSetting volumeAdaptionSetting, String username, String password, @NonNull FeedFilter filter, float feedPlaybackSpeed, int feedSkipIntro, int feedSkipEnding) {
this.feedID = feedID;
this.autoDownload = autoDownload;
this.keepUpdated = keepUpdated;
@@ -49,6 +55,8 @@ public class FeedPreferences {
this.password = password;
this.filter = filter;
this.feedPlaybackSpeed = feedPlaybackSpeed;
+ this.feedSkipIntro = feedSkipIntro;
+ this.feedSkipEnding = feedSkipEnding;
}
public static FeedPreferences fromCursor(Cursor cursor) {
@@ -62,6 +70,8 @@ public class FeedPreferences {
int indexIncludeFilter = cursor.getColumnIndex(PodDBAdapter.KEY_INCLUDE_FILTER);
int indexExcludeFilter = cursor.getColumnIndex(PodDBAdapter.KEY_EXCLUDE_FILTER);
int indexFeedPlaybackSpeed = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_PLAYBACK_SPEED);
+ int indexAutoSkipIntro = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_SKIP_INTRO);
+ int indexAutoSkipEnding = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_SKIP_ENDING);
long feedId = cursor.getLong(indexId);
boolean autoDownload = cursor.getInt(indexAutoDownload) > 0;
@@ -75,7 +85,20 @@ public class FeedPreferences {
String includeFilter = cursor.getString(indexIncludeFilter);
String excludeFilter = cursor.getString(indexExcludeFilter);
float feedPlaybackSpeed = cursor.getFloat(indexFeedPlaybackSpeed);
- return new FeedPreferences(feedId, autoDownload, autoRefresh, autoDeleteAction, volumeAdaptionSetting, username, password, new FeedFilter(includeFilter, excludeFilter), feedPlaybackSpeed);
+ int feedAutoSkipIntro = cursor.getInt(indexAutoSkipIntro);
+ int feedAutoSkipEnding = cursor.getInt(indexAutoSkipEnding);
+ return new FeedPreferences(feedId,
+ autoDownload,
+ autoRefresh,
+ autoDeleteAction,
+ volumeAdaptionSetting,
+ username,
+ password,
+ new FeedFilter(includeFilter, excludeFilter),
+ feedPlaybackSpeed,
+ feedAutoSkipIntro,
+ feedAutoSkipEnding
+ );
}
/**
@@ -204,4 +227,20 @@ public class FeedPreferences {
public void setFeedPlaybackSpeed(float playbackSpeed) {
feedPlaybackSpeed = playbackSpeed;
}
+
+ public void setFeedSkipIntro(int skipIntro) {
+ feedSkipIntro = skipIntro;
+ }
+
+ public int getFeedSkipIntro() {
+ return feedSkipIntro;
+ }
+
+ public void setFeedSkipEnding(int skipEnding) {
+ feedSkipEnding = skipEnding;
+ }
+
+ public int getFeedSkipEnding() {
+ return feedSkipEnding;
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
index 2679a93d4..a83e50506 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
@@ -51,12 +51,14 @@ import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.event.MessageEvent;
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.event.ServiceEvent;
+import de.danoeh.antennapod.core.event.settings.SkipIntroEndingChangedEvent;
import de.danoeh.antennapod.core.event.settings.SpeedPresetChangedEvent;
import de.danoeh.antennapod.core.event.settings.VolumeAdaptionChangedEvent;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
+import de.danoeh.antennapod.core.feed.FeedPreferences;
import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
@@ -211,6 +213,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
private Disposable positionEventTimer;
private PlaybackServiceNotificationBuilder notificationBuilder;
+ private long autoSkippedFeedMediaId = -1;
+
/**
* Used for Lollipop notifications, Android Wear, and Android Auto.
*/
@@ -507,6 +511,30 @@ public class PlaybackService extends MediaBrowserServiceCompat {
return Service.START_NOT_STICKY;
}
+ private void skipIntro(Playable playable) {
+ if (! (playable instanceof FeedMedia)) {
+ return;
+ }
+
+ FeedMedia feedMedia = (FeedMedia) playable;
+ FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences();
+ int skipIntro = preferences.getFeedSkipIntro();
+
+ Context context = getApplicationContext();
+ if (skipIntro > 0 && playable.getPosition() < skipIntro * 1000) {
+ int duration = getDuration();
+ if (skipIntro * 1000 < duration) {
+ Log.d(TAG, "skipIntro " + playable.getEpisodeTitle());
+ mediaPlayer.seekTo(skipIntro * 1000);
+ String skipIntroMesg = context.getString(R.string.pref_feed_skip_intro_toast,
+ skipIntro);
+ Toast toast = Toast.makeText(context, skipIntroMesg,
+ Toast.LENGTH_LONG);
+ toast.show();
+ }
+ }
+ }
+
private void displayStreamingNotAllowedNotification(Intent originalIntent) {
Intent intentAllowThisTime = new Intent(originalIntent);
intentAllowThisTime.setAction(EXTRA_ALLOW_STREAM_THIS_TIME);
@@ -758,7 +786,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
case PLAYING:
PlaybackPreferences.writePlayerStatus(mediaPlayer.getPlayerStatus());
setupNotification(newInfo);
- setupPositionUpdater();
+ setupPositionObserver();
stateManager.validStartCommandWasReceived();
// set sleep timer if auto-enabled
if (newInfo.oldPlayerStatus != null && newInfo.oldPlayerStatus != PlayerStatus.SEEKING
@@ -849,6 +877,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
taskManager.startWidgetUpdater();
if (position != PlaybackServiceMediaPlayer.INVALID_TIME) {
playable.setPosition(position);
+ } else {
+ skipIntro(playable);
}
playable.onPlaybackStart();
taskManager.startPositionSaver();
@@ -1000,6 +1030,10 @@ public class PlaybackService extends MediaBrowserServiceCompat {
media.onPlaybackPause(getApplicationContext());
}
+ if (autoSkippedFeedMediaId >= 0 && autoSkippedFeedMediaId == media.getId()) {
+ ended = true;
+ }
+
if (item != null) {
if (ended || smartMarkAsPlayed
|| (skipped && !UserPreferences.shouldSkipKeepEpisode())) {
@@ -1040,6 +1074,33 @@ public class PlaybackService extends MediaBrowserServiceCompat {
sendBroadcast(intent);
}
+ private void skipEndingIfNecessary() {
+ Playable playable = mediaPlayer.getPlayable();
+ if (! (playable instanceof FeedMedia)) {
+ return;
+ }
+
+ int duration = getDuration();
+ int remainingTime = duration - getCurrentPosition();
+
+ FeedMedia feedMedia = (FeedMedia) playable;
+ FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences();
+ int skipEnd = preferences.getFeedSkipEnding();
+ if (skipEnd > 0
+ && skipEnd < playable.getDuration()
+ && (remainingTime - (skipEnd * 1000) > 0)
+ && ((remainingTime - skipEnd * 1000) < (getCurrentPlaybackSpeed() * 1000))) {
+ Log.d(TAG, "skipEndingIfNecessary: Skipping the remaining " + remainingTime + " " + skipEnd * 1000 + " speed " + getCurrentPlaybackSpeed());
+ Context context = getApplicationContext();
+ String skipMesg = context.getString(R.string.pref_feed_skip_ending_toast, skipEnd);
+ Toast toast = Toast.makeText(context, skipMesg, Toast.LENGTH_LONG);
+ toast.show();
+
+ this.autoSkippedFeedMediaId = feedMedia.getItem().getId();
+ mediaPlayer.skip();
+ }
+ }
+
/**
* Updates the Media Session for the corresponding status.
*
@@ -1451,12 +1512,14 @@ public class PlaybackService extends MediaBrowserServiceCompat {
};
@Subscribe(threadMode = ThreadMode.MAIN)
+ @SuppressWarnings("unused")
public void volumeAdaptionChanged(VolumeAdaptionChangedEvent event) {
PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater();
playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, event.getFeedId(), event.getVolumeAdaptionSetting());
}
@Subscribe(threadMode = ThreadMode.MAIN)
+ @SuppressWarnings("unused")
public void speedPresetChanged(SpeedPresetChangedEvent event) {
if (getPlayable() instanceof FeedMedia) {
if (((FeedMedia) getPlayable()).getItem().getFeed().getId() == event.getFeedId()) {
@@ -1469,6 +1532,22 @@ public class PlaybackService extends MediaBrowserServiceCompat {
}
}
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ @SuppressWarnings("unused")
+ public void skipIntroEndingPresetChanged(SkipIntroEndingChangedEvent event) {
+ if (getPlayable() instanceof FeedMedia) {
+ if (((FeedMedia) getPlayable()).getItem().getFeed().getId() == event.getFeedId()) {
+ if (event.getSkipEnding() != 0) {
+ FeedPreferences feedPreferences
+ = ((FeedMedia) getPlayable()).getItem().getFeed().getPreferences();
+ feedPreferences.setFeedSkipIntro(event.getSkipIntro());
+ feedPreferences.setFeedSkipEnding(event.getSkipEnding());
+
+ }
+ }
+ }
+ }
+
public static MediaType getCurrentMediaType() {
return currentMediaType;
}
@@ -1613,7 +1692,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
return mediaPlayer.getVideoSize();
}
- private void setupPositionUpdater() {
+ private void setupPositionObserver() {
if (positionEventTimer != null) {
positionEventTimer.dispose();
}
@@ -1629,6 +1708,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
}
+ skipEndingIfNecessary();
});
}
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 ee31c8cc4..8574ff33b 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
@@ -304,6 +304,12 @@ class DBUpgrader {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
+ " ADD COLUMN " + PodDBAdapter.KEY_IMAGE_URL + " TEXT DEFAULT NULL");
}
+ if (oldVersion < 1090001) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS +
+ " ADD COLUMN " + PodDBAdapter.KEY_FEED_SKIP_INTRO + " INTEGER DEFAULT 0;");
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS +
+ " ADD COLUMN " + PodDBAdapter.KEY_FEED_SKIP_ENDING + " INTEGER DEFAULT 0;");
+ }
}
}
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 6ca3419cf..e6d47b32a 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
@@ -47,7 +47,7 @@ public class PodDBAdapter {
private static final String TAG = "PodDBAdapter";
public static final String DATABASE_NAME = "Antennapod.db";
- public static final int VERSION = 1090000;
+ public static final int VERSION = 1090001;
/**
* Maximum number of arguments for IN-operator.
@@ -109,6 +109,8 @@ public class PodDBAdapter {
public static final String KEY_INCLUDE_FILTER = "include_filter";
public static final String KEY_EXCLUDE_FILTER = "exclude_filter";
public static final String KEY_FEED_PLAYBACK_SPEED = "feed_playback_speed";
+ public static final String KEY_FEED_SKIP_INTRO = "feed_skip_intro";
+ public static final String KEY_FEED_SKIP_ENDING = "feed_skip_ending";
// Table names
static final String TABLE_NAME_FEEDS = "Feeds";
@@ -144,7 +146,9 @@ public class PodDBAdapter {
+ KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0,"
+ KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0,"
+ KEY_FEED_PLAYBACK_SPEED + " REAL DEFAULT " + SPEED_USE_GLOBAL + ","
- + KEY_FEED_VOLUME_ADAPTION + " INTEGER DEFAULT 0)";
+ + KEY_FEED_VOLUME_ADAPTION + " INTEGER DEFAULT 0,"
+ + KEY_FEED_SKIP_INTRO + " INTEGER DEFAULT 0,"
+ + KEY_FEED_SKIP_ENDING + " INTEGER DEFAULT 0)";
private static final String CREATE_TABLE_FEED_ITEMS = "CREATE TABLE "
+ TABLE_NAME_FEED_ITEMS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE
@@ -244,7 +248,9 @@ public class PodDBAdapter {
TABLE_NAME_FEEDS + "." + KEY_FEED_VOLUME_ADAPTION,
TABLE_NAME_FEEDS + "." + KEY_INCLUDE_FILTER,
TABLE_NAME_FEEDS + "." + KEY_EXCLUDE_FILTER,
- TABLE_NAME_FEEDS + "." + KEY_FEED_PLAYBACK_SPEED
+ TABLE_NAME_FEEDS + "." + KEY_FEED_PLAYBACK_SPEED,
+ TABLE_NAME_FEEDS + "." + KEY_FEED_SKIP_INTRO,
+ TABLE_NAME_FEEDS + "." + KEY_FEED_SKIP_ENDING
};
/**
@@ -421,6 +427,8 @@ public class PodDBAdapter {
values.put(KEY_INCLUDE_FILTER, prefs.getFilter().getIncludeFilter());
values.put(KEY_EXCLUDE_FILTER, prefs.getFilter().getExcludeFilter());
values.put(KEY_FEED_PLAYBACK_SPEED, prefs.getFeedPlaybackSpeed());
+ values.put(KEY_FEED_SKIP_INTRO, prefs.getFeedSkipIntro());
+ values.put(KEY_FEED_SKIP_ENDING, prefs.getFeedSkipEnding());
db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(prefs.getFeedID())});
}
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index efd7d698a..40ef88440 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -444,6 +444,12 @@
<string name="pref_playback_speed_title">Playback Speeds</string>
<string name="pref_playback_speed_sum">Customize the speeds available for variable speed audio playback</string>
<string name="pref_feed_playback_speed_sum">The speed to use when starting audio playback for episodes in this podcast</string>
+ <string name="pref_feed_skip">Auto Skip</string>
+ <string name="pref_feed_skip_sum">Skip introductions and ending credits.</string>
+ <string name="pref_feed_skip_ending">Skip last</string>
+ <string name="pref_feed_skip_intro">Skip first</string>
+ <string name="pref_feed_skip_ending_toast">Skipped last %d seconds</string>
+ <string name="pref_feed_skip_intro_toast">Skipped first %d seconds</string>
<string name="pref_playback_time_respects_speed_title">Adjust media info to playback speed</string>
<string name="pref_playback_time_respects_speed_sum">Displayed position and duration are adapted to playback speed</string>
<string name="pref_fast_forward">Fast Forward Skip Time</string>