use of de.danoeh.antennapod.event.PlayerErrorEvent in project AntennaPod by AntennaPod.
the class CastPsmp method playMediaObject.
/**
* Internal implementation of playMediaObject. This method has an additional parameter that
* allows the caller to force a media player reset even if
* the given playable parameter is the same object as the currently playing media.
*
* @see #playMediaObject(Playable, boolean, boolean, boolean)
*/
private void playMediaObject(@NonNull final Playable playable, final boolean forceReset, final boolean stream, final boolean startWhenPrepared, final boolean prepareImmediately) {
if (!CastUtils.isCastable(playable, castContext.getSessionManager().getCurrentCastSession())) {
Log.d(TAG, "media provided is not compatible with cast device");
EventBus.getDefault().post(new PlayerErrorEvent("Media not compatible with cast device"));
Playable nextPlayable = playable;
do {
nextPlayable = callback.getNextInQueue(nextPlayable);
} while (nextPlayable != null && !CastUtils.isCastable(nextPlayable, castContext.getSessionManager().getCurrentCastSession()));
if (nextPlayable != null) {
playMediaObject(nextPlayable, forceReset, stream, startWhenPrepared, prepareImmediately);
}
return;
}
if (media != null) {
if (!forceReset && media.getIdentifier().equals(playable.getIdentifier()) && playerStatus == PlayerStatus.PLAYING) {
// episode is already playing -> ignore method call
Log.d(TAG, "Method call to playMediaObject was ignored: media file already playing.");
return;
} else {
// set temporarily to pause in order to update list with current position
boolean isPlaying = remoteMediaClient.isPlaying();
int position = (int) remoteMediaClient.getApproximateStreamPosition();
if (isPlaying) {
callback.onPlaybackPause(media, position);
}
if (!media.getIdentifier().equals(playable.getIdentifier())) {
final Playable oldMedia = media;
callback.onPostPlayback(oldMedia, false, false, true);
}
setPlayerStatus(PlayerStatus.INDETERMINATE, null);
}
}
this.media = playable;
remoteMedia = remoteVersion(playable);
this.mediaType = media.getMediaType();
this.startWhenPrepared.set(startWhenPrepared);
setPlayerStatus(PlayerStatus.INITIALIZING, media);
callback.ensureMediaInfoLoaded(media);
callback.onMediaChanged(true);
setPlayerStatus(PlayerStatus.INITIALIZED, media);
if (prepareImmediately) {
prepare();
}
}
use of de.danoeh.antennapod.event.PlayerErrorEvent in project AntennaPod by AntennaPod.
the class LocalPSMP method setMediaPlayerListeners.
private void setMediaPlayerListeners(IPlayer mp) {
if (mp == null || media == null) {
return;
}
if (mp instanceof VideoPlayer) {
if (media.getMediaType() != MediaType.VIDEO) {
Log.w(TAG, "video player, but media type is " + media.getMediaType());
}
VideoPlayer vp = (VideoPlayer) mp;
vp.setOnCompletionListener(videoCompletionListener);
vp.setOnSeekCompleteListener(videoSeekCompleteListener);
vp.setOnErrorListener(videoErrorListener);
vp.setOnBufferingUpdateListener(videoBufferingUpdateListener);
vp.setOnInfoListener(videoInfoListener);
} else if (mp instanceof AudioPlayer) {
if (media.getMediaType() != MediaType.AUDIO) {
Log.w(TAG, "audio player, but media type is " + media.getMediaType());
}
AudioPlayer ap = (AudioPlayer) mp;
ap.setOnCompletionListener(audioCompletionListener);
ap.setOnSeekCompleteListener(audioSeekCompleteListener);
ap.setOnErrorListener(audioErrorListener);
ap.setOnBufferingUpdateListener(audioBufferingUpdateListener);
ap.setOnInfoListener(audioInfoListener);
} else if (mp instanceof ExoPlayerWrapper) {
ExoPlayerWrapper ap = (ExoPlayerWrapper) mp;
ap.setOnCompletionListener(audioCompletionListener);
ap.setOnSeekCompleteListener(audioSeekCompleteListener);
ap.setOnBufferingUpdateListener(audioBufferingUpdateListener);
ap.setOnErrorListener(message -> EventBus.getDefault().postSticky(new PlayerErrorEvent(message)));
ap.setOnInfoListener(audioInfoListener);
} else {
Log.w(TAG, "Unknown media player: " + mp);
}
}
use of de.danoeh.antennapod.event.PlayerErrorEvent in project AntennaPod by AntennaPod.
the class LocalPSMP method playMediaObject.
/**
* Internal implementation of playMediaObject. This method has an additional parameter that allows the caller to force a media player reset even if
* the given playable parameter is the same object as the currently playing media.
* <p/>
* This method requires the playerLock and is executed on the caller's thread.
*
* @see #playMediaObject(Playable, boolean, boolean, boolean)
*/
private void playMediaObject(@NonNull final Playable playable, final boolean forceReset, final boolean stream, final boolean startWhenPrepared, final boolean prepareImmediately) {
if (!playerLock.isHeldByCurrentThread()) {
throw new IllegalStateException("method requires playerLock");
}
if (media != null) {
if (!forceReset && media.getIdentifier().equals(playable.getIdentifier()) && playerStatus == PlayerStatus.PLAYING) {
// episode is already playing -> ignore method call
Log.d(TAG, "Method call to playMediaObject was ignored: media file already playing.");
return;
} else {
// stop playback of this episode
if (playerStatus == PlayerStatus.PAUSED || playerStatus == PlayerStatus.PLAYING || playerStatus == PlayerStatus.PREPARED) {
mediaPlayer.stop();
}
// set temporarily to pause in order to update list with current position
if (playerStatus == PlayerStatus.PLAYING) {
callback.onPlaybackPause(media, getPosition());
}
if (!media.getIdentifier().equals(playable.getIdentifier())) {
final Playable oldMedia = media;
executor.submit(() -> callback.onPostPlayback(oldMedia, false, false, true));
}
setPlayerStatus(PlayerStatus.INDETERMINATE, null);
}
}
this.media = playable;
this.stream = stream;
this.mediaType = media.getMediaType();
this.videoSize = null;
createMediaPlayer();
LocalPSMP.this.startWhenPrepared.set(startWhenPrepared);
setPlayerStatus(PlayerStatus.INITIALIZING, media);
try {
callback.ensureMediaInfoLoaded(media);
callback.onMediaChanged(false);
setPlaybackParams(PlaybackSpeedUtils.getCurrentPlaybackSpeed(media), UserPreferences.isSkipSilence());
if (stream) {
if (playable instanceof FeedMedia) {
FeedMedia feedMedia = (FeedMedia) playable;
FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences();
mediaPlayer.setDataSource(media.getStreamUrl(), preferences.getUsername(), preferences.getPassword());
} else {
mediaPlayer.setDataSource(media.getStreamUrl());
}
} else if (media.getLocalMediaUrl() != null && new File(media.getLocalMediaUrl()).canRead()) {
mediaPlayer.setDataSource(media.getLocalMediaUrl());
} else {
throw new IOException("Unable to read local file " + media.getLocalMediaUrl());
}
UiModeManager uiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE);
if (uiModeManager.getCurrentModeType() != Configuration.UI_MODE_TYPE_CAR) {
setPlayerStatus(PlayerStatus.INITIALIZED, media);
}
if (prepareImmediately) {
setPlayerStatus(PlayerStatus.PREPARING, media);
mediaPlayer.prepare();
onPrepared(startWhenPrepared);
}
} catch (IOException | IllegalStateException e) {
e.printStackTrace();
setPlayerStatus(PlayerStatus.ERROR, null);
EventBus.getDefault().postSticky(new PlayerErrorEvent(e.getLocalizedMessage()));
}
}
use of de.danoeh.antennapod.event.PlayerErrorEvent in project AntennaPod by AntennaPod.
the class CastPsmp method onRemoteMediaPlayerStatusUpdated.
private void onRemoteMediaPlayerStatusUpdated() {
MediaStatus status = remoteMediaClient.getMediaStatus();
if (status == null) {
Log.d(TAG, "Received null MediaStatus");
return;
} else {
Log.d(TAG, "Received remote status/media update. New state=" + status.getPlayerState());
}
int state = status.getPlayerState();
int oldState = remoteState;
remoteMedia = status.getMediaInfo();
boolean mediaChanged = !CastUtils.matches(remoteMedia, media);
boolean stateChanged = state != oldState;
if (!mediaChanged && !stateChanged) {
Log.d(TAG, "Both media and state haven't changed, so nothing to do");
return;
}
Playable currentMedia = mediaChanged ? localVersion(remoteMedia) : media;
Playable oldMedia = media;
int position = (int) status.getStreamPosition();
// check for incompatible states
if ((state == MediaStatus.PLAYER_STATE_PLAYING || state == MediaStatus.PLAYER_STATE_PAUSED) && currentMedia == null) {
Log.w(TAG, "RemoteMediaPlayer returned playing or pausing state, but with no media");
state = MediaStatus.PLAYER_STATE_UNKNOWN;
stateChanged = oldState != MediaStatus.PLAYER_STATE_UNKNOWN;
}
if (stateChanged) {
remoteState = state;
}
if (mediaChanged && stateChanged && oldState == MediaStatus.PLAYER_STATE_PLAYING && state != MediaStatus.PLAYER_STATE_IDLE) {
callback.onPlaybackPause(null, INVALID_TIME);
// We don't want setPlayerStatus to handle the onPlaybackPause callback
setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia);
}
setBuffering(state == MediaStatus.PLAYER_STATE_BUFFERING);
switch(state) {
case MediaStatus.PLAYER_STATE_PLAYING:
if (!stateChanged) {
// These steps are necessary because they won't be performed by setPlayerStatus()
if (position >= 0) {
currentMedia.setPosition(position);
}
currentMedia.onPlaybackStart();
}
setPlayerStatus(PlayerStatus.PLAYING, currentMedia, position);
break;
case MediaStatus.PLAYER_STATE_PAUSED:
setPlayerStatus(PlayerStatus.PAUSED, currentMedia, position);
break;
case MediaStatus.PLAYER_STATE_BUFFERING:
setPlayerStatus((mediaChanged || playerStatus == PlayerStatus.PREPARING) ? PlayerStatus.PREPARING : PlayerStatus.SEEKING, currentMedia, currentMedia != null ? currentMedia.getPosition() : INVALID_TIME);
break;
case MediaStatus.PLAYER_STATE_IDLE:
int reason = status.getIdleReason();
switch(reason) {
case MediaStatus.IDLE_REASON_CANCELED:
// Essentially means stopped at the request of a user
callback.onPlaybackEnded(null, true);
setPlayerStatus(PlayerStatus.STOPPED, currentMedia);
if (oldMedia != null) {
if (position >= 0) {
oldMedia.setPosition(position);
}
callback.onPostPlayback(oldMedia, false, false, false);
}
// onPlaybackEnded pretty much takes care of updating the UI
return;
case MediaStatus.IDLE_REASON_INTERRUPTED:
// Not sure if currentMedia already reflects the to be loaded one
if (mediaChanged && oldState == MediaStatus.PLAYER_STATE_PLAYING) {
callback.onPlaybackPause(null, INVALID_TIME);
setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia);
}
setPlayerStatus(PlayerStatus.PREPARING, currentMedia);
break;
case MediaStatus.IDLE_REASON_NONE:
// This probably only happens when we connected but no command has been sent yet.
setPlayerStatus(PlayerStatus.INITIALIZED, currentMedia);
break;
case MediaStatus.IDLE_REASON_FINISHED:
// This is our onCompletionListener...
if (mediaChanged && currentMedia != null) {
media = currentMedia;
}
endPlayback(true, false, true, true);
return;
case MediaStatus.IDLE_REASON_ERROR:
Log.w(TAG, "Got an error status from the Chromecast. " + "Skipping, if possible, to the next episode...");
EventBus.getDefault().post(new PlayerErrorEvent("Chromecast error code 1"));
endPlayback(false, false, true, true);
return;
default:
return;
}
break;
case MediaStatus.PLAYER_STATE_UNKNOWN:
if (playerStatus != PlayerStatus.INDETERMINATE || media != currentMedia) {
setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia);
}
break;
default:
Log.w(TAG, "Remote media state undetermined!");
}
if (mediaChanged) {
callback.onMediaChanged(true);
if (oldMedia != null) {
callback.onPostPlayback(oldMedia, false, false, currentMedia != null);
}
}
}
Aggregations