Search in sources :

Example 1 with PlayerErrorEvent

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();
    }
}
Also used : PlayerErrorEvent(de.danoeh.antennapod.event.PlayerErrorEvent) Playable(de.danoeh.antennapod.model.playback.Playable)

Example 2 with PlayerErrorEvent

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);
    }
}
Also used : VideoPlayer(de.danoeh.antennapod.core.util.playback.VideoPlayer) PlayerErrorEvent(de.danoeh.antennapod.event.PlayerErrorEvent) AudioPlayer(de.danoeh.antennapod.core.util.playback.AudioPlayer)

Example 3 with PlayerErrorEvent

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()));
    }
}
Also used : FeedPreferences(de.danoeh.antennapod.model.feed.FeedPreferences) Playable(de.danoeh.antennapod.model.playback.Playable) FeedMedia(de.danoeh.antennapod.model.feed.FeedMedia) UiModeManager(android.app.UiModeManager) PlayerErrorEvent(de.danoeh.antennapod.event.PlayerErrorEvent) IOException(java.io.IOException) File(java.io.File)

Example 4 with PlayerErrorEvent

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);
        }
    }
}
Also used : Playable(de.danoeh.antennapod.model.playback.Playable) PlayerErrorEvent(de.danoeh.antennapod.event.PlayerErrorEvent) MediaStatus(com.google.android.gms.cast.MediaStatus)

Aggregations

PlayerErrorEvent (de.danoeh.antennapod.event.PlayerErrorEvent)4 Playable (de.danoeh.antennapod.model.playback.Playable)3 UiModeManager (android.app.UiModeManager)1 MediaStatus (com.google.android.gms.cast.MediaStatus)1 AudioPlayer (de.danoeh.antennapod.core.util.playback.AudioPlayer)1 VideoPlayer (de.danoeh.antennapod.core.util.playback.VideoPlayer)1 FeedMedia (de.danoeh.antennapod.model.feed.FeedMedia)1 FeedPreferences (de.danoeh.antennapod.model.feed.FeedPreferences)1 File (java.io.File)1 IOException (java.io.IOException)1