From 6b1a7a9162cb27f0b2aa3e550069945b6e0d95f3 Mon Sep 17 00:00:00 2001 From: Jonas Kalderstam Date: Thu, 12 Sep 2019 10:57:16 +0200 Subject: [PATCH] Fixed playback speed issues when switching to next media Fixes some issues related to the playback speed when playback was completed or playback was paused and the app went away for awhile. Now a media item which is "in progress" will remember its playback speed so that it can be restored properly. The per-feed-media speed is cleared once playback finishes, either by reaching the end or by the user starting to play something different. --- .../activity/AudioplayerActivity.java | 22 ++++++++------ .../activity/MediaplayerActivity.java | 2 +- .../dialog/PlaybackControlsDialog.java | 2 +- .../antennapod/core/feed/FeedMedia.java | 30 ++++++++++++++++--- .../antennapod/core/feed/FeedPreferences.java | 1 - .../core/service/playback/LocalPSMP.java | 2 +- .../antennapod/core/storage/DBUpgrader.java | 2 ++ .../antennapod/core/storage/DBWriter.java | 14 +++++++++ .../antennapod/core/storage/PodDBAdapter.java | 19 +++++++++++- 9 files changed, 76 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java index 222923448..5e81295b1 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java @@ -11,9 +11,11 @@ import java.text.DecimalFormatSymbols; import java.util.Locale; import java.util.concurrent.atomic.AtomicBoolean; +import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; +import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.dialog.VariableSpeedDialog; /** @@ -24,9 +26,6 @@ public class AudioplayerActivity extends MediaplayerInfoActivity { private final AtomicBoolean isSetup = new AtomicBoolean(false); - // Used to work around race condition in updating the controller speed and receiving the callback that it has changed - private float playbackSpeed = -1; - @Override protected void onResume() { super.onResume(); @@ -81,10 +80,7 @@ public class AudioplayerActivity extends MediaplayerInfoActivity { } float speed = 1.0f; if(controller.canSetPlaybackSpeed()) { - speed = playbackSpeed; - if (speed == -1) { - speed = getPlaybackSpeedForMedia(); - } + speed = getPlaybackSpeedForMedia(); } String speedStr = new DecimalFormat("0.00x").format(speed); butPlaybackSpeed.setText(speedStr); @@ -136,9 +132,10 @@ public class AudioplayerActivity extends MediaplayerInfoActivity { break; } } - playbackSpeed = Float.parseFloat(newSpeed); + + storeNewMediaPlaybackSpeed(newSpeed); UserPreferences.setPlaybackSpeed(newSpeed); - controller.setPlaybackSpeed(playbackSpeed); + controller.setPlaybackSpeed(Float.parseFloat(newSpeed)); onPositionObserverUpdate(); } else { VariableSpeedDialog.showGetPluginDialog(this); @@ -151,4 +148,11 @@ public class AudioplayerActivity extends MediaplayerInfoActivity { butPlaybackSpeed.setVisibility(View.VISIBLE); } } + + private void storeNewMediaPlaybackSpeed(String speed) { + Playable media = controller.getMedia(); + if (media instanceof FeedMedia) { + ((FeedMedia) media).updateLastPlaybackSpeed(speed); + } + } } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java index 9f364fec1..b6697ef52 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java @@ -879,7 +879,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements boolean isFeedMedia = media instanceof FeedMedia; if (isFeedMedia) { - return ((FeedMedia) media).getFeedPlaybackSpeed(); + return ((FeedMedia) media).getMediaPlaybackSpeed(); } } diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java index 4c52e7c75..86720f40a 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java @@ -219,7 +219,7 @@ public class PlaybackControlsDialog extends DialogFragment { boolean isFeedMedia = media instanceof FeedMedia; if (isFeedMedia) { - return ((FeedMedia) media).getFeedPlaybackSpeed(); + return ((FeedMedia) media).getMediaPlaybackSpeed(); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index 192fa0c2d..46795bc11 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -55,6 +55,7 @@ public class FeedMedia extends FeedFile implements Playable { private Date playbackCompletionDate; private int startPosition = -1; private int playedDurationWhenStarted; + private String lastPlaybackSpeed = null; // if null: unknown, will be checked private Boolean hasEmbeddedPicture; @@ -91,10 +92,11 @@ public class FeedMedia extends FeedFile implements Playable { private FeedMedia(long id, FeedItem item, int duration, int position, long size, String mime_type, String file_url, String download_url, boolean downloaded, Date playbackCompletionDate, int played_duration, - Boolean hasEmbeddedPicture, long lastPlayedTime) { + Boolean hasEmbeddedPicture, long lastPlayedTime, String lastPlaybackSpeed) { this(id, item, duration, position, size, mime_type, file_url, download_url, downloaded, playbackCompletionDate, played_duration, lastPlayedTime); this.hasEmbeddedPicture = hasEmbeddedPicture; + this.lastPlaybackSpeed = lastPlaybackSpeed; } public static FeedMedia fromCursor(Cursor cursor) { @@ -109,6 +111,7 @@ public class FeedMedia extends FeedFile implements Playable { int indexDownloaded = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOADED); int indexPlayedDuration = cursor.getColumnIndex(PodDBAdapter.KEY_PLAYED_DURATION); int indexLastPlayedTime = cursor.getColumnIndex(PodDBAdapter.KEY_LAST_PLAYED_TIME); + int indexLastPlaybackSpeed = cursor.getColumnIndex(PodDBAdapter.KEY_LAST_PLAYBACK_SPEED); long mediaId = cursor.getLong(indexId); Date playbackCompletionDate = null; @@ -143,7 +146,8 @@ public class FeedMedia extends FeedFile implements Playable { playbackCompletionDate, cursor.getInt(indexPlayedDuration), hasEmbeddedPicture, - cursor.getLong(indexLastPlayedTime) + cursor.getLong(indexLastPlayedTime), + cursor.getString(indexLastPlaybackSpeed) ); } @@ -624,15 +628,33 @@ public class FeedMedia extends FeedFile implements Playable { return super.equals(o); } + public String getLastPlaybackSpeed() { + return lastPlaybackSpeed; + } + + public void updateLastPlaybackSpeed(String newSpeed) { + lastPlaybackSpeed = newSpeed; + DBWriter.setFeedMediaPlaybackInformation(this); + } + /** * - * @return playback speed for this feed, or the global setting if no feed-specific setting + * @return the current playback speed for the media, or the feed's configured speed */ - public float getFeedPlaybackSpeed() { + public float getMediaPlaybackSpeed() { + if (lastPlaybackSpeed != null) { + try { + return Float.parseFloat(lastPlaybackSpeed); + } catch (NumberFormatException e) { + lastPlaybackSpeed = null; + } + } + FeedItem item = getItem(); if (item != null) { return item.getFeedPlaybackSpeed(); } + return UserPreferences.getPlaybackSpeed(); } } 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 7864f51bd..d7d173e19 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 @@ -187,7 +187,6 @@ public class FeedPreferences { try { speed = Float.parseFloat(getFeedPlaybackSpeed()); } catch (NumberFormatException e) { - Log.e(TAG, Log.getStackTraceString(e)); setFeedPlaybackSpeed("global"); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index c2c503abe..abb5d83bd 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -308,7 +308,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { if (media.getMediaType() == MediaType.VIDEO) { setPlaybackParams(UserPreferences.getVideoPlaybackSpeed(), UserPreferences.isSkipSilence()); } else if (media instanceof FeedMedia) { - setPlaybackParams(((FeedMedia) media).getFeedPlaybackSpeed(), UserPreferences.isSkipSilence()); + setPlaybackParams(((FeedMedia) media).getMediaPlaybackSpeed(), UserPreferences.isSkipSilence()); } else { setPlaybackParams(UserPreferences.getPlaybackSpeed(), UserPreferences.isSkipSilence()); } 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 ddc8e770a..6126508c6 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 @@ -291,6 +291,8 @@ class DBUpgrader { if (oldVersion < 1070306) { db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " + PodDBAdapter.KEY_FEED_PLAYBACK_SPEED + " TEXT"); + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " ADD COLUMN " + PodDBAdapter.KEY_LAST_PLAYBACK_SPEED + " TEXT"); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index 4f0ee70ef..afd99bc1b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -760,6 +760,20 @@ public class DBWriter { }); } + /** + * Saves the 'lastPlaybackSpeed' attribute of a FeedMedia object + * + * @param media The FeedMedia object. + */ + public static Future setFeedMediaLastPlaybackSpeed(final FeedMedia media) { + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setFeedMediaLastPlaybackSpeed(media); + adapter.close(); + }); + } + /** * Saves a FeedItem object in the database. This method will save all attributes of the FeedItem object including * the content of FeedComponent-attributes. 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 63c036b6e..0f4bca09a 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 @@ -115,6 +115,7 @@ 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_LAST_PLAYBACK_SPEED = "last_playback_speed"; // Table names static final String TABLE_NAME_FEEDS = "Feeds"; @@ -169,7 +170,8 @@ public class PodDBAdapter { + KEY_FEEDITEM + " INTEGER," + KEY_PLAYED_DURATION + " INTEGER," + KEY_HAS_EMBEDDED_PICTURE + " INTEGER," - + KEY_LAST_PLAYED_TIME + " INTEGER)"; + + KEY_LAST_PLAYED_TIME + " INTEGER," + + KEY_LAST_PLAYBACK_SPEED + " TEXT)"; private static final String CREATE_TABLE_DOWNLOAD_LOG = "CREATE TABLE " + TABLE_NAME_DOWNLOAD_LOG + " (" + TABLE_PRIMARY_KEY + KEY_FEEDFILE @@ -440,6 +442,7 @@ public class PodDBAdapter { values.put(KEY_FILE_URL, media.getFile_url()); values.put(KEY_HAS_EMBEDDED_PICTURE, media.hasEmbeddedPicture()); values.put(KEY_LAST_PLAYED_TIME, media.getLastPlayedTime()); + values.put(KEY_LAST_PLAYBACK_SPEED, media.getLastPlaybackSpeed()); if (media.getPlaybackCompletionDate() != null) { values.put(KEY_PLAYBACK_COMPLETION_DATE, media.getPlaybackCompletionDate().getTime()); @@ -465,6 +468,7 @@ public class PodDBAdapter { values.put(KEY_DURATION, media.getDuration()); values.put(KEY_PLAYED_DURATION, media.getPlayedDuration()); values.put(KEY_LAST_PLAYED_TIME, media.getLastPlayedTime()); + values.put(KEY_LAST_PLAYBACK_SPEED, media.getLastPlaybackSpeed()); db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?", new String[]{String.valueOf(media.getId())}); } else { @@ -472,11 +476,24 @@ public class PodDBAdapter { } } + public void setFeedMediaLastPlaybackSpeed(FeedMedia media) { + if (media.getId() != 0) { + ContentValues values = new ContentValues(); + values.put(KEY_LAST_PLAYBACK_SPEED, media.getLastPlaybackSpeed()); + db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?", + new String[]{String.valueOf(media.getId())}); + } else { + Log.e(TAG, "setFeedMediaLastPlaybackSpeed: ID of media was 0"); + } + } + public void setFeedMediaPlaybackCompletionDate(FeedMedia media) { if (media.getId() != 0) { ContentValues values = new ContentValues(); values.put(KEY_PLAYBACK_COMPLETION_DATE, media.getPlaybackCompletionDate().getTime()); values.put(KEY_PLAYED_DURATION, media.getPlayedDuration()); + // Also reset stored playback speed for media + values.putNull(KEY_LAST_PLAYBACK_SPEED); db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?", new String[]{String.valueOf(media.getId())}); } else {