summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorDomingos Lopes <domingos86lopes+github@gmail.com>2016-04-26 01:10:08 -0400
committerDomingos Lopes <domingos86lopes+github@gmail.com>2016-04-26 01:18:55 -0400
commitb1f62b56cdf0e1f1011bf8b4eec6fe1bdd053220 (patch)
treee90ad3b7e47803a3be64fc915fc93812e4127c33 /core/src
parent86cc2233d3f6c7a7d5957049468865221762f2e8 (diff)
downloadAntennaPod-b1f62b56cdf0e1f1011bf8b4eec6fe1bdd053220.zip
add a general callback method for reporting media updates
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java23
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java106
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java73
4 files changed, 126 insertions, 78 deletions
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 28424306f..32bafd580 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
@@ -158,7 +158,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
setPlayerStatus(PlayerStatus.INITIALIZING, media);
try {
media.loadMetadata();
- executor.submit(() -> callback.updateMediaSessionMetadata(media));
+ callback.reloadUI();
if (stream) {
mediaPlayer.setDataSource(media.getStreamUrl());
} else {
@@ -599,7 +599,6 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
public void shutdown() {
executor.shutdown();
if (mediaPlayer != null) {
- removeMediaPlayerListeners(mediaPlayer);
mediaPlayer.release();
}
releaseWifiLockIfNecessary();
@@ -822,26 +821,6 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
return mp;
}
- private void removeMediaPlayerListeners(IPlayer mp) {
- if (mp == null) {
- return;
- }
- if (mp instanceof AudioPlayer) {
- ((AudioPlayer) mp).setOnCompletionListener(null);
- ((AudioPlayer) mp).setOnSeekCompleteListener(null);
- ((AudioPlayer) mp).setOnErrorListener(null);
- ((AudioPlayer) mp).setOnBufferingUpdateListener(null);
- ((AudioPlayer) mp).setOnInfoListener(null);
- ((AudioPlayer) mp).setOnSpeedAdjustmentAvailableChangedListener(null);
- } else {
- ((VideoPlayer) mp).setOnCompletionListener(null);
- ((VideoPlayer) mp).setOnSeekCompleteListener(null);
- ((VideoPlayer) mp).setOnErrorListener(null);
- ((VideoPlayer) mp).setOnBufferingUpdateListener(null);
- ((VideoPlayer) mp).setOnInfoListener(null);
- }
- }
-
private final MediaPlayer.OnCompletionListener audioCompletionListener =
mp -> genericOnCompletion();
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 e477b9273..215acad17 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
@@ -22,10 +22,10 @@ import android.os.Build;
import android.os.IBinder;
import android.os.Vibrator;
import android.preference.PreferenceManager;
+import android.support.annotation.NonNull;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
-import android.support.annotation.NonNull;
import android.support.v7.app.NotificationCompat;
import android.support.v7.media.MediaRouter;
import android.text.TextUtils;
@@ -39,6 +39,7 @@ import android.view.WindowManager;
import android.widget.Toast;
import com.bumptech.glide.Glide;
+import com.bumptech.glide.request.target.Target;
import com.google.android.gms.cast.ApplicationMetadata;
import com.google.android.libraries.cast.companionlibrary.cast.BaseCastManager;
@@ -633,8 +634,9 @@ public class PlaybackService extends Service {
}
@Override
- public void updateMediaSessionMetadata(Playable p) {
- PlaybackService.this.updateMediaSessionMetadata(p);
+ public void reloadUI() {
+ sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, 0);
+ PlaybackService.this.updateMediaSessionMetadata(getPlayable());
}
@Override
@@ -672,7 +674,7 @@ public class PlaybackService extends Service {
};
private void endPlayback(final Playable playable, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
- Log.d(TAG, "Playback ended");
+ Log.d(TAG, "Playback ended" + (switchingPlayers ? " from switching players": ""));
if (playable == null) {
Log.e(TAG, "Cannot end playback: media was null");
@@ -707,12 +709,12 @@ public class PlaybackService extends Service {
if (isInQueue) {
DBWriter.removeQueueItem(PlaybackService.this, item, true);
}
- }
- // Delete episode if enabled
- if (item.getFeed().getPreferences().getCurrentAutoDelete() && !shouldKeep) {
- DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId());
- Log.d(TAG, "Episode Deleted");
+ // Delete episode if enabled
+ if (item.getFeed().getPreferences().getCurrentAutoDelete()) {
+ DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId());
+ Log.d(TAG, "Episode Deleted");
+ }
}
}
@@ -904,11 +906,6 @@ public class PlaybackService extends Service {
}
/**
- * Used by setupNotification to load notification data in another thread.
- */
- private Thread notificationSetupThread;
-
- /**
* Updates the Media Session for the corresponding status.
* @param playerStatus the current {@link PlayerStatus}
*/
@@ -957,38 +954,69 @@ public class PlaybackService extends Service {
mediaSession.setPlaybackState(sessionState.build());
}
- private void updateMediaSessionMetadata(Playable p) {
+ /**
+ * Used by updateMediaSessionMetadata to load notification data in another thread.
+ */
+ private Thread mediaSessionSetupThread;
+
+ private void updateMediaSessionMetadata(final Playable p) {
if (p == null || mediaSession == null) {
return;
}
- MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
- builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, p.getFeedTitle());
- builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, p.getEpisodeTitle());
- builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, p.getDuration());
- builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, p.getEpisodeTitle());
- builder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, p.getFeedTitle());
-
- if (p.getImageUri() != null && UserPreferences.setLockscreenBackground()) {
- builder.putString(MediaMetadataCompat.METADATA_KEY_ART_URI, p.getImageUri().toString());
- try {
- WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
- Display display = wm.getDefaultDisplay();
- Bitmap art = Glide.with(this)
- .load(p.getImageUri())
- .asBitmap()
- .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
- .centerCrop()
- .into(display.getWidth(), display.getHeight())
- .get();
- builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, art);
- } catch (Throwable tr) {
- Log.e(TAG, Log.getStackTraceString(tr));
- }
+ if (mediaSessionSetupThread != null) {
+ mediaSessionSetupThread.interrupt();
}
- mediaSession.setMetadata(builder.build());
+
+ Runnable mediaSessionSetupTask = () -> {
+ MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
+ builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, p.getFeedTitle());
+ builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, p.getEpisodeTitle());
+ builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, p.getDuration());
+ builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, p.getEpisodeTitle());
+ builder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, p.getFeedTitle());
+
+ if (p.getImageUri() != null && UserPreferences.setLockscreenBackground()) {
+ builder.putString(MediaMetadataCompat.METADATA_KEY_ART_URI, p.getImageUri().toString());
+ try {
+ if (isCasting) {
+ Bitmap art = Glide.with(this)
+ .load(p.getImageUri())
+ .asBitmap()
+ .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
+ .into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
+ .get();
+ builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, art);
+ } else {
+ WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
+ Display display = wm.getDefaultDisplay();
+ Bitmap art = Glide.with(this)
+ .load(p.getImageUri())
+ .asBitmap()
+ .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
+ .centerCrop()
+ .into(display.getWidth(), display.getHeight())
+ .get();
+ builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, art);
+ }
+ } catch (Throwable tr) {
+ Log.e(TAG, Log.getStackTraceString(tr));
+ }
+ }
+ if (!Thread.currentThread().isInterrupted() && started) {
+ mediaSession.setMetadata(builder.build());
+ }
+ };
+
+ mediaSessionSetupThread = new Thread(mediaSessionSetupTask);
+ mediaSessionSetupThread.start();
}
/**
+ * Used by setupNotification to load notification data in another thread.
+ */
+ private Thread notificationSetupThread;
+
+ /**
* Prepares notification and starts the service in the foreground.
*/
private void setupNotification(final PlaybackServiceMediaPlayer.PSMPInfo info) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java
index 43ec260c4..bd870a85d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java
@@ -321,7 +321,7 @@ public abstract class PlaybackServiceMediaPlayer {
void onBufferingUpdate(int percent);
- void updateMediaSessionMetadata(Playable p);
+ void reloadUI();
boolean onMediaPlayerInfo(int code);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java
index e3474f55a..203633b3c 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java
@@ -7,6 +7,7 @@ import android.util.Log;
import android.util.Pair;
import android.view.SurfaceHolder;
+import com.google.android.gms.cast.Cast;
import com.google.android.gms.cast.CastStatusCodes;
import com.google.android.gms.cast.MediaInfo;
import com.google.android.gms.cast.MediaStatus;
@@ -14,9 +15,6 @@ import com.google.android.libraries.cast.companionlibrary.cast.exceptions.CastEx
import com.google.android.libraries.cast.companionlibrary.cast.exceptions.NoConnectionException;
import com.google.android.libraries.cast.companionlibrary.cast.exceptions.TransientNetworkDisconnectionException;
-import java.util.concurrent.LinkedBlockingDeque;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import de.danoeh.antennapod.core.cast.CastConsumer;
@@ -46,8 +44,6 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer {
private final AtomicBoolean startWhenPrepared;
- private final ThreadPoolExecutor executor;
-
public RemotePSMP(@NonNull Context context, @NonNull PSMPCallback callback) {
super(context, callback);
@@ -57,9 +53,6 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer {
startWhenPrepared = new AtomicBoolean(false);
isBuffering = new AtomicBoolean(false);
- executor = new ThreadPoolExecutor(1, 1, 5, TimeUnit.MINUTES, new LinkedBlockingDeque<>(),
- (r, executor) -> Log.d(TAG, "Rejected execution of runnable"));
-
try {
if (castMgr.isConnected() && castMgr.isRemoteMediaLoaded()) {
// updates the state, but does not start playing new media if it was going to
@@ -107,6 +100,26 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer {
Log.d(TAG, "onMediaLoadResult called, but Player Status wasn't in preparing state, so we ignore the result");
}
}
+
+ @Override
+ public void onApplicationStatusChanged(String appStatus) {
+ if (playerStatus != PlayerStatus.PLAYING) {
+ Log.d(TAG, "onApplicationStatusChanged, but no media was playing");
+ return;
+ }
+ boolean playbackEnded = false;
+ try {
+ int standbyState = castMgr.getApplicationStandbyState();
+ Log.d(TAG, "standbyState: " + standbyState);
+ playbackEnded = standbyState == Cast.STANDBY_STATE_YES;
+ } catch (IllegalStateException e) {
+ Log.d(TAG, "unable to get standbyState on onApplicationStatusChanged()");
+ }
+ if (playbackEnded) {
+ setPlayerStatus(PlayerStatus.INDETERMINATE, media);
+ callback.endPlayback(media, true, false, false);
+ }
+ }
};
private void setBuffering(boolean buffering) {
@@ -147,13 +160,14 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer {
MediaStatus status = castMgr.getMediaStatus();
if (status == null) {
Log.d(TAG, "Received null MediaStatus");
- setBuffering(false);
- setPlayerStatus(PlayerStatus.INDETERMINATE, null);
+ //setBuffering(false);
+ //setPlayerStatus(PlayerStatus.INDETERMINATE, null);
return;
} else {
Log.d(TAG, "Received remote status/media update. New state=" + status.getPlayerState());
}
Playable currentMedia = localVersion(status.getMediaInfo());
+ boolean updateUI = currentMedia != media;
if (currentMedia != null) {
long position = status.getStreamPosition();
if (position > 0 && currentMedia.getPosition() == 0) {
@@ -176,10 +190,20 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer {
int reason = status.getIdleReason();
switch (reason) {
case MediaStatus.IDLE_REASON_CANCELED:
- setPlayerStatus(PlayerStatus.STOPPED, currentMedia);
+ // check if we're already loading something else
+ if (!updateUI || media == null) {
+ setPlayerStatus(PlayerStatus.STOPPED, currentMedia);
+ } else {
+ updateUI = false;
+ }
break;
case MediaStatus.IDLE_REASON_INTERRUPTED:
- setPlayerStatus(PlayerStatus.PREPARING, currentMedia);
+ // check if we're already loading something else
+ if (!updateUI || media == null) {
+ setPlayerStatus(PlayerStatus.PREPARING, currentMedia);
+ } else {
+ updateUI = false;
+ }
break;
case MediaStatus.IDLE_REASON_NONE:
setPlayerStatus(PlayerStatus.INITIALIZED, currentMedia);
@@ -188,11 +212,15 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer {
boolean playing = playerStatus == PlayerStatus.PLAYING;
setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia);
endPlaybackCall.endPlayback(currentMedia,playing, false, false);
+ // endPlayback already updates the UI, so no need to trigger it ourselves
+ updateUI = false;
break;
case MediaStatus.IDLE_REASON_ERROR:
Log.w(TAG, "Got an error status from the Chromecast. Skipping, if possible, to the next episode...");
setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia);
endPlaybackCall.endPlayback(currentMedia, startWhenPrepared.get(), true, false);
+ // endPlayback already updates the UI, so no need to trigger it ourselves
+ updateUI = false;
}
break;
case MediaStatus.PLAYER_STATE_UNKNOWN:
@@ -203,6 +231,9 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer {
Log.e(TAG, "Remote media state undetermined!");
setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia);
}
+ if (updateUI) {
+ callback.reloadUI();
+ }
}
@Override
@@ -257,7 +288,7 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer {
setPlayerStatus(PlayerStatus.INITIALIZING, media);
try {
media.loadMetadata();
- executor.execute(() -> callback.updateMediaSessionMetadata(media));
+ callback.reloadUI();
setPlayerStatus(PlayerStatus.INITIALIZED, media);
if (prepareImmediately) {
prepare();
@@ -471,13 +502,11 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer {
@Override
public void shutdown() {
castMgr.removeCastConsumer(castConsumer);
- executor.shutdown();
}
@Override
public void shutdownQuietly() {
- executor.execute(this::shutdown);
- executor.shutdown();
+ shutdown();
}
@Override
@@ -512,6 +541,18 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer {
public void endPlayback(boolean wasSkipped, boolean switchingPlayers) {
Log.d(TAG, "endPlayback() called");
boolean isPlaying = playerStatus == PlayerStatus.PLAYING;
+ try {
+ isPlaying = castMgr.isRemoteMediaPlaying();
+ } catch (TransientNetworkDisconnectionException | NoConnectionException e) {
+ Log.e(TAG, "Could not determine if media is playing", e);
+ }
+ if (wasSkipped) {
+ try {
+ castMgr.stop();
+ } catch (CastException | TransientNetworkDisconnectionException | NoConnectionException e) {
+ Log.e(TAG, "Could not stop remote playback when skipping", e);
+ }
+ }
if (playerStatus != PlayerStatus.INDETERMINATE) {
setPlayerStatus(PlayerStatus.INDETERMINATE, media);
}