diff options
author | Tony Tam <engineer.tonytam@pm.me> | 2020-04-21 14:20:22 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-21 23:20:22 +0200 |
commit | 92eb1d669ba14318b90ad4da4cd925279007fa3a (patch) | |
tree | 07924bd7b28104f581e8b715749587dd3cab94a9 /core | |
parent | 3a86745e8144baa6d0a2cdc88aa0e29d1fd6e66c (diff) | |
download | AntennaPod-92eb1d669ba14318b90ad4da4cd925279007fa3a.zip |
Skip intro and ending per feed (#3975)
Diffstat (limited to 'core')
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> |