diff options
8 files changed, 113 insertions, 205 deletions
diff --git a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java index 7803144e1..5dd419412 100644 --- a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java +++ b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java @@ -5,10 +5,12 @@ import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.annotation.UiThreadTest; import androidx.test.filters.LargeTest; +import de.danoeh.antennapod.core.event.playback.SleepTimerUpdatedEvent; import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; import de.danoeh.antennapod.core.widget.WidgetUpdater; import org.awaitility.Awaitility; import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -173,21 +175,6 @@ public class PlaybackServiceTaskManagerTest { } @Override - public void onSleepTimerAlmostExpired(long timeLeft) { - - } - - @Override - public void onSleepTimerExpired() { - - } - - @Override - public void onSleepTimerReset() { - - } - - @Override public WidgetUpdater.WidgetState requestWidgetState() { return null; } @@ -234,21 +221,6 @@ public class PlaybackServiceTaskManagerTest { } @Override - public void onSleepTimerAlmostExpired(long timeLeft) { - - } - - @Override - public void onSleepTimerExpired() { - - } - - @Override - public void onSleepTimerReset() { - - } - - @Override public WidgetUpdater.WidgetState requestWidgetState() { countDownLatch.countDown(); return null; @@ -325,42 +297,20 @@ public class PlaybackServiceTaskManagerTest { final long TIME = 2000; final long TIMEOUT = 2 * TIME; final CountDownLatch countDownLatch = new CountDownLatch(1); - PlaybackServiceTaskManager pstm = new PlaybackServiceTaskManager(c, new PlaybackServiceTaskManager.PSTMCallback() { - @Override - public void positionSaverTick() { - - } - - @Override - public void onSleepTimerAlmostExpired(long timeLeft) { - - } - - @Override - public void onSleepTimerExpired() { + Object timerReceiver = new Object() { + @Subscribe + public void sleepTimerUpdate(SleepTimerUpdatedEvent event) { if (countDownLatch.getCount() == 0) { fail(); } countDownLatch.countDown(); } - - @Override - public void onSleepTimerReset() { - - } - - @Override - public WidgetUpdater.WidgetState requestWidgetState() { - return null; - } - - @Override - public void onChapterLoaded(Playable media) { - - } - }); + }; + EventBus.getDefault().register(timerReceiver); + PlaybackServiceTaskManager pstm = new PlaybackServiceTaskManager(c, defaultPSTM); pstm.setSleepTimer(TIME); countDownLatch.await(TIMEOUT, TimeUnit.MILLISECONDS); + EventBus.getDefault().unregister(timerReceiver); pstm.shutdown(); } @@ -368,44 +318,26 @@ public class PlaybackServiceTaskManagerTest { @UiThreadTest public void testDisableSleepTimer() throws InterruptedException { final Context c = InstrumentationRegistry.getInstrumentation().getTargetContext(); - final long TIME = 1000; + final long TIME = 5000; final long TIMEOUT = 2 * TIME; final CountDownLatch countDownLatch = new CountDownLatch(1); - PlaybackServiceTaskManager pstm = new PlaybackServiceTaskManager(c, new PlaybackServiceTaskManager.PSTMCallback() { - @Override - public void positionSaverTick() { - - } - - @Override - public void onSleepTimerAlmostExpired(long timeLeft) { - - } - - @Override - public void onSleepTimerExpired() { - fail("Sleeptimer expired"); - } - - @Override - public void onSleepTimerReset() { - - } - - @Override - public WidgetUpdater.WidgetState requestWidgetState() { - return null; - } - - @Override - public void onChapterLoaded(Playable media) { - + Object timerReceiver = new Object() { + @Subscribe + public void sleepTimerUpdate(SleepTimerUpdatedEvent event) { + if (event.isOver()) { + countDownLatch.countDown(); + } else if (event.getTimeLeft() == 1) { + fail("Arrived at 1 but should have been cancelled"); + } } - }); + }; + PlaybackServiceTaskManager pstm = new PlaybackServiceTaskManager(c, defaultPSTM); + EventBus.getDefault().register(timerReceiver); pstm.setSleepTimer(TIME); pstm.disableSleepTimer(); assertFalse(countDownLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)); pstm.shutdown(); + EventBus.getDefault().unregister(timerReceiver); } @Test @@ -436,21 +368,6 @@ public class PlaybackServiceTaskManagerTest { } @Override - public void onSleepTimerAlmostExpired(long timeLeft) { - - } - - @Override - public void onSleepTimerExpired() { - - } - - @Override - public void onSleepTimerReset() { - - } - - @Override public WidgetUpdater.WidgetState requestWidgetState() { return null; } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java index dba884fb7..5d7ab8959 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java @@ -40,6 +40,7 @@ import de.danoeh.antennapod.core.event.playback.BufferUpdateEvent; import de.danoeh.antennapod.core.event.playback.PlaybackPositionEvent; import de.danoeh.antennapod.core.event.PlayerErrorEvent; import de.danoeh.antennapod.core.event.playback.PlaybackServiceEvent; +import de.danoeh.antennapod.core.event.playback.SleepTimerUpdatedEvent; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.service.playback.PlayerStatus; @@ -199,11 +200,6 @@ public class VideoplayerActivity extends CastEnabledActivity implements SeekBar. } @Override - public void onSleepTimerUpdate() { - supportInvalidateOptionsMenu(); - } - - @Override protected void updatePlayButtonShowsPlay(boolean showPlay) { viewBinding.playButton.setIsShowPlay(showPlay); } @@ -250,6 +246,14 @@ public class VideoplayerActivity extends CastEnabledActivity implements SeekBar. } } + @Subscribe(threadMode = ThreadMode.MAIN) + @SuppressWarnings("unused") + public void sleepTimerUpdate(SleepTimerUpdatedEvent event) { + if (event.isCancelled() || event.wasJustEnabled()) { + supportInvalidateOptionsMenu(); + } + } + protected void loadMediaInfo() { Log.d(TAG, "loadMediaInfo()"); if (controller == null || controller.getMedia() == null) { diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java index 691bd65e8..26e222539 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java @@ -18,20 +18,17 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; import com.google.android.material.snackbar.Snackbar; import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.event.playback.SleepTimerUpdatedEvent; import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.playback.PlaybackController; -import io.reactivex.Observable; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.Disposable; - -import java.util.concurrent.TimeUnit; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; public class SleepTimerDialog extends DialogFragment { private PlaybackController controller; - private Disposable timeUpdater; - private EditText etxtTime; private Spinner spTimeUnit; private LinearLayout timeSetup; @@ -47,19 +44,11 @@ public class SleepTimerDialog extends DialogFragment { super.onStart(); controller = new PlaybackController(getActivity()) { @Override - public void onSleepTimerUpdate() { - updateTime(); - } - - @Override public void loadMediaInfo() { - updateTime(); } }; controller.init(); - timeUpdater = Observable.interval(1, TimeUnit.SECONDS) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(tick -> updateTime()); + EventBus.getDefault().register(this); } @Override @@ -68,9 +57,7 @@ public class SleepTimerDialog extends DialogFragment { if (controller != null) { controller.release(); } - if (timeUpdater != null) { - timeUpdater.dispose(); - } + EventBus.getDefault().unregister(this); } @NonNull @@ -170,13 +157,12 @@ public class SleepTimerDialog extends DialogFragment { return builder.create(); } - private void updateTime() { - if (controller == null) { - return; - } - timeSetup.setVisibility(controller.sleepTimerActive() ? View.GONE : View.VISIBLE); - timeDisplay.setVisibility(controller.sleepTimerActive() ? View.VISIBLE : View.GONE); - time.setText(Converter.getDurationStringLong((int) controller.getSleepTimerTimeLeft())); + @Subscribe(threadMode = ThreadMode.MAIN) + @SuppressWarnings("unused") + public void timerUpdated(SleepTimerUpdatedEvent event) { + timeDisplay.setVisibility(event.isOver() || event.isCancelled() ? View.GONE : View.VISIBLE); + timeSetup.setVisibility(event.isOver() || event.isCancelled() ? View.VISIBLE : View.GONE); + time.setText(Converter.getDurationStringLong((int) event.getTimeLeft())); } private void closeKeyboard(View content) { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java index 94326efe8..77c99c3a8 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java @@ -28,6 +28,7 @@ import com.google.android.material.snackbar.Snackbar; import de.danoeh.antennapod.core.event.playback.BufferUpdateEvent; import de.danoeh.antennapod.core.event.playback.PlaybackServiceEvent; import de.danoeh.antennapod.core.event.PlayerErrorEvent; +import de.danoeh.antennapod.core.event.playback.SleepTimerUpdatedEvent; import de.danoeh.antennapod.core.event.playback.SpeedChangedEvent; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; @@ -281,11 +282,6 @@ public class AudioPlayerFragment extends Fragment implements private PlaybackController newPlaybackController() { return new PlaybackController(getActivity()) { @Override - public void onSleepTimerUpdate() { - AudioPlayerFragment.this.loadMediaInfo(false); - } - - @Override protected void updatePlayButtonShowsPlay(boolean showPlay) { butPlay.setIsShowPlay(showPlay); } @@ -313,6 +309,14 @@ public class AudioPlayerFragment extends Fragment implements setupOptionsMenu(media); } + @Subscribe(threadMode = ThreadMode.MAIN) + @SuppressWarnings("unused") + public void sleepTimerUpdate(SleepTimerUpdatedEvent event) { + if (event.isCancelled() || event.wasJustEnabled()) { + AudioPlayerFragment.this.loadMediaInfo(false); + } + } + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/playback/SleepTimerUpdatedEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/playback/SleepTimerUpdatedEvent.java new file mode 100644 index 000000000..37a073799 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/event/playback/SleepTimerUpdatedEvent.java @@ -0,0 +1,38 @@ +package de.danoeh.antennapod.core.event.playback; + +public class SleepTimerUpdatedEvent { + private static final long CANCELLED = Long.MAX_VALUE; + private final long timeLeft; + + private SleepTimerUpdatedEvent(long timeLeft) { + this.timeLeft = timeLeft; + } + + public static SleepTimerUpdatedEvent justEnabled(long timeLeft) { + return new SleepTimerUpdatedEvent(-timeLeft); + } + + public static SleepTimerUpdatedEvent updated(long timeLeft) { + return new SleepTimerUpdatedEvent(Math.max(0, timeLeft)); + } + + public static SleepTimerUpdatedEvent cancelled() { + return new SleepTimerUpdatedEvent(CANCELLED); + } + + public long getTimeLeft() { + return Math.abs(timeLeft); + } + + public boolean isOver() { + return timeLeft == 0; + } + + public boolean wasJustEnabled() { + return timeLeft < 0; + } + + public boolean isCancelled() { + return timeLeft == CANCELLED; + } +} 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 10c78bee6..3465d952d 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 @@ -45,7 +45,7 @@ import androidx.preference.PreferenceManager; import de.danoeh.antennapod.core.event.playback.BufferUpdateEvent; import de.danoeh.antennapod.core.event.playback.PlaybackServiceEvent; import de.danoeh.antennapod.core.event.PlayerErrorEvent; -import de.danoeh.antennapod.core.event.playback.SpeedChangedEvent; +import de.danoeh.antennapod.core.event.playback.SleepTimerUpdatedEvent; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; @@ -167,10 +167,6 @@ public class PlaybackService extends MediaBrowserServiceCompat { * Receivers of this intent should update their information about the curently playing media */ public static final int NOTIFICATION_TYPE_RELOAD = 3; - /** - * The state of the sleeptimer changed. - */ - public static final int NOTIFICATION_TYPE_SLEEPTIMER_UPDATE = 4; /** * Set a max number of episodes to load for Android Auto, otherwise there could be performance issues @@ -786,25 +782,7 @@ public class PlaybackService extends MediaBrowserServiceCompat { saveCurrentPosition(true, null, PlaybackServiceMediaPlayer.INVALID_TIME); } - @Override - public void onSleepTimerAlmostExpired(long timeLeft) { - final float[] multiplicators = {0.1f, 0.2f, 0.3f, 0.3f, 0.3f, 0.4f, 0.4f, 0.4f, 0.6f, 0.8f}; - float multiplicator = multiplicators[Math.max(0, (int) timeLeft / 1000)]; - Log.d(TAG, "onSleepTimerAlmostExpired: " + multiplicator); - mediaPlayer.setVolume(multiplicator, multiplicator); - } - @Override - public void onSleepTimerExpired() { - mediaPlayer.pause(true, true); - mediaPlayer.setVolume(1.0f, 1.0f); - sendNotificationBroadcast(NOTIFICATION_TYPE_SLEEPTIMER_UPDATE, 0); - } - - @Override - public void onSleepTimerReset() { - mediaPlayer.setVolume(1.0f, 1.0f); - } @Override public WidgetUpdater.WidgetState requestWidgetState() { @@ -971,6 +949,22 @@ public class PlaybackService extends MediaBrowserServiceCompat { } } + @Subscribe(threadMode = ThreadMode.MAIN) + @SuppressWarnings("unused") + public void sleepTimerUpdate(SleepTimerUpdatedEvent event) { + if (event.isOver()) { + mediaPlayer.pause(true, true); + mediaPlayer.setVolume(1.0f, 1.0f); + } else if (event.getTimeLeft() < PlaybackServiceTaskManager.SleepTimer.NOTIFICATION_THRESHOLD) { + final float[] multiplicators = {0.1f, 0.2f, 0.3f, 0.3f, 0.3f, 0.4f, 0.4f, 0.4f, 0.6f, 0.8f}; + float multiplicator = multiplicators[Math.max(0, (int) event.getTimeLeft() / 1000)]; + Log.d(TAG, "onSleepTimerAlmostExpired: " + multiplicator); + mediaPlayer.setVolume(multiplicator, multiplicator); + } else if (event.isCancelled()) { + mediaPlayer.setVolume(1.0f, 1.0f); + } + } + private Playable getNextInQueue(final Playable currentMedia) { if (!(currentMedia instanceof FeedMedia)) { Log.d(TAG, "getNextInQueue(), but playable not an instance of FeedMedia, so not proceeding"); @@ -1136,12 +1130,10 @@ public class PlaybackService extends MediaBrowserServiceCompat { public void setSleepTimer(long waitingTime) { Log.d(TAG, "Setting sleep timer to " + waitingTime + " milliseconds"); taskManager.setSleepTimer(waitingTime); - sendNotificationBroadcast(NOTIFICATION_TYPE_SLEEPTIMER_UPDATE, 0); } public void disableSleepTimer() { taskManager.disableSleepTimer(); - sendNotificationBroadcast(NOTIFICATION_TYPE_SLEEPTIMER_UPDATE, 0); } private void sendNotificationBroadcast(int type, int code) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java index a14605e5b..a99a178da 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java @@ -7,6 +7,7 @@ import android.os.Vibrator; import androidx.annotation.NonNull; import android.util.Log; +import de.danoeh.antennapod.core.event.playback.SleepTimerUpdatedEvent; import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; import de.danoeh.antennapod.core.util.ChapterUtils; import de.danoeh.antennapod.core.widget.WidgetUpdater; @@ -25,7 +26,6 @@ import java.util.concurrent.TimeUnit; import de.danoeh.antennapod.core.event.FeedItemEvent; import de.danoeh.antennapod.core.event.QueueEvent; import de.danoeh.antennapod.model.feed.FeedItem; -import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.model.playback.Playable; import io.reactivex.Completable; @@ -244,6 +244,7 @@ public class PlaybackServiceTaskManager { } sleepTimer = new SleepTimer(waitingTime); sleepTimerFuture = schedExecutor.schedule(sleepTimer, 0, TimeUnit.MILLISECONDS); + EventBus.getDefault().post(SleepTimerUpdatedEvent.justEnabled(waitingTime)); } /** @@ -377,27 +378,11 @@ public class PlaybackServiceTaskManager { private final long waitingTime; private long timeLeft; private ShakeListener shakeListener; - private final Handler handler; public SleepTimer(long waitingTime) { super(); this.waitingTime = waitingTime; this.timeLeft = waitingTime; - - if (UserPreferences.useExoplayer() && Looper.myLooper() == Looper.getMainLooper()) { - // Run callbacks in main thread so they can call ExoPlayer methods themselves - this.handler = new Handler(Looper.getMainLooper()); - } else { - this.handler = null; - } - } - - private void postCallback(Runnable r) { - if (handler == null) { - r.run(); - } else { - handler.post(r); - } } @Override @@ -417,6 +402,7 @@ public class PlaybackServiceTaskManager { timeLeft -= now - lastTick; lastTick = now; + EventBus.getDefault().post(SleepTimerUpdatedEvent.updated(timeLeft)); if (timeLeft < NOTIFICATION_THRESHOLD) { Log.d(TAG, "Sleep timer is about to expire"); if (SleepTimerPreferences.vibrate() && !hasVibrated) { @@ -429,7 +415,6 @@ public class PlaybackServiceTaskManager { if (shakeListener == null && SleepTimerPreferences.shakeToReset()) { shakeListener = new ShakeListener(context, this); } - postCallback(() -> callback.onSleepTimerAlmostExpired(timeLeft)); } if (timeLeft <= 0) { Log.d(TAG, "Sleep timer expired"); @@ -438,11 +423,6 @@ public class PlaybackServiceTaskManager { shakeListener = null; } hasVibrated = false; - if (!Thread.currentThread().isInterrupted()) { - postCallback(callback::onSleepTimerExpired); - } else { - Log.d(TAG, "Sleep timer interrupted"); - } } } } @@ -452,10 +432,8 @@ public class PlaybackServiceTaskManager { } public void restart() { - postCallback(() -> { - setSleepTimer(waitingTime); - callback.onSleepTimerReset(); - }); + EventBus.getDefault().post(SleepTimerUpdatedEvent.cancelled()); + setSleepTimer(waitingTime); if (shakeListener != null) { shakeListener.pause(); shakeListener = null; @@ -467,19 +445,13 @@ public class PlaybackServiceTaskManager { if (shakeListener != null) { shakeListener.pause(); } - postCallback(callback::onSleepTimerReset); + EventBus.getDefault().post(SleepTimerUpdatedEvent.cancelled()); } } public interface PSTMCallback { void positionSaverTick(); - void onSleepTimerAlmostExpired(long timeLeft); - - void onSleepTimerExpired(); - - void onSleepTimerReset(); - WidgetUpdater.WidgetState requestWidgetState(); void onChapterLoaded(Playable media); 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 a52cb99fe..649e97c42 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 @@ -217,9 +217,6 @@ public abstract class PlaybackController { onReloadNotification(intent.getIntExtra( PlaybackService.EXTRA_NOTIFICATION_CODE, -1)); break; - case PlaybackService.NOTIFICATION_TYPE_SLEEPTIMER_UPDATE: - onSleepTimerUpdate(); - break; case PlaybackService.NOTIFICATION_TYPE_PLAYBACK_END: onPlaybackEnd(); break; @@ -235,8 +232,6 @@ public abstract class PlaybackController { */ public void onReloadNotification(int code) {} - public void onSleepTimerUpdate() {} - public void onPlaybackEnd() {} /** |