Search in sources :

Example 1 with Playable

use of de.danoeh.antennapod.model.playback.Playable in project AntennaPod by AntennaPod.

the class CastPsmp method endPlayback.

@Override
protected Future<?> endPlayback(boolean hasEnded, boolean wasSkipped, boolean shouldContinue, boolean toStoppedState) {
    Log.d(TAG, "endPlayback() called");
    boolean isPlaying = playerStatus == PlayerStatus.PLAYING;
    if (playerStatus != PlayerStatus.INDETERMINATE) {
        setPlayerStatus(PlayerStatus.INDETERMINATE, media);
    }
    if (media != null && wasSkipped) {
        // current position only really matters when we skip
        int position = getPosition();
        if (position >= 0) {
            media.setPosition(position);
        }
    }
    final Playable currentMedia = media;
    Playable nextMedia = null;
    if (shouldContinue) {
        nextMedia = callback.getNextInQueue(currentMedia);
        boolean playNextEpisode = isPlaying && nextMedia != null;
        if (playNextEpisode) {
            Log.d(TAG, "Playback of next episode will start immediately.");
        } else if (nextMedia == null) {
            Log.d(TAG, "No more episodes available to play");
        } else {
            Log.d(TAG, "Loading next episode, but not playing automatically.");
        }
        if (nextMedia != null) {
            callback.onPlaybackEnded(nextMedia.getMediaType(), !playNextEpisode);
            // setting media to null signals to playMediaObject() that we're taking care of post-playback processing
            media = null;
            playMediaObject(nextMedia, false, true, playNextEpisode, playNextEpisode);
        }
    }
    if (shouldContinue || toStoppedState) {
        if (nextMedia == null) {
            remoteMediaClient.stop();
            // Otherwise we rely on the chromecast callback to tell us the playback has stopped.
            callback.onPostPlayback(currentMedia, hasEnded, wasSkipped, false);
        } else {
            callback.onPostPlayback(currentMedia, hasEnded, wasSkipped, true);
        }
    } else if (isPlaying) {
        callback.onPlaybackPause(currentMedia, currentMedia != null ? currentMedia.getPosition() : INVALID_TIME);
    }
    FutureTask<?> future = new FutureTask<>(() -> {
    }, null);
    future.run();
    return future;
}
Also used : FutureTask(java.util.concurrent.FutureTask) Playable(de.danoeh.antennapod.model.playback.Playable)

Example 2 with Playable

use of de.danoeh.antennapod.model.playback.Playable 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 3 with Playable

use of de.danoeh.antennapod.model.playback.Playable in project AntennaPod by AntennaPod.

the class LocalPSMP method setVolumeSync.

/**
 * Sets the playback volume.
 * This method is executed on the caller's thread.
 */
private void setVolumeSync(float volumeLeft, float volumeRight) {
    playerLock.lock();
    Playable playable = getPlayable();
    if (playable instanceof FeedMedia) {
        FeedMedia feedMedia = (FeedMedia) playable;
        FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences();
        VolumeAdaptionSetting volumeAdaptionSetting = preferences.getVolumeAdaptionSetting();
        float adaptionFactor = volumeAdaptionSetting.getAdaptionFactor();
        volumeLeft *= adaptionFactor;
        volumeRight *= adaptionFactor;
    }
    mediaPlayer.setVolume(volumeLeft, volumeRight);
    Log.d(TAG, "Media player volume was set to " + volumeLeft + " " + volumeRight);
    playerLock.unlock();
}
Also used : FeedPreferences(de.danoeh.antennapod.model.feed.FeedPreferences) Playable(de.danoeh.antennapod.model.playback.Playable) FeedMedia(de.danoeh.antennapod.model.feed.FeedMedia) VolumeAdaptionSetting(de.danoeh.antennapod.model.feed.VolumeAdaptionSetting)

Example 4 with Playable

use of de.danoeh.antennapod.model.playback.Playable in project AntennaPod by AntennaPod.

the class LocalPSMP method endPlayback.

@Override
protected Future<?> endPlayback(final boolean hasEnded, final boolean wasSkipped, final boolean shouldContinue, final boolean toStoppedState) {
    useCallerThread = UserPreferences.useExoplayer();
    return executor.submit(() -> {
        playerLock.lock();
        releaseWifiLockIfNecessary();
        boolean isPlaying = playerStatus == PlayerStatus.PLAYING;
        // we're relying on the position stored in the Playable object for post-playback processing
        if (media != null) {
            int position = getPosition();
            if (position >= 0) {
                media.setPosition(position);
            }
        }
        if (mediaPlayer != null) {
            mediaPlayer.reset();
        }
        abandonAudioFocus();
        final Playable currentMedia = media;
        Playable nextMedia = null;
        if (shouldContinue) {
            // Load next episode if previous episode was in the queue and if there
            // is an episode in the queue left.
            // Start playback immediately if continuous playback is enabled
            nextMedia = callback.getNextInQueue(currentMedia);
            boolean playNextEpisode = isPlaying && nextMedia != null;
            if (playNextEpisode) {
                Log.d(TAG, "Playback of next episode will start immediately.");
            } else if (nextMedia == null) {
                Log.d(TAG, "No more episodes available to play");
            } else {
                Log.d(TAG, "Loading next episode, but not playing automatically.");
            }
            if (nextMedia != null) {
                callback.onPlaybackEnded(nextMedia.getMediaType(), !playNextEpisode);
                // setting media to null signals to playMediaObject() that we're taking care of post-playback processing
                media = null;
                playMediaObject(nextMedia, false, !nextMedia.localFileAvailable(), playNextEpisode, playNextEpisode);
            }
        }
        if (shouldContinue || toStoppedState) {
            if (nextMedia == null) {
                callback.onPlaybackEnded(null, true);
                stop();
            }
            final boolean hasNext = nextMedia != null;
            executor.submit(() -> callback.onPostPlayback(currentMedia, hasEnded, wasSkipped, hasNext));
        } else if (isPlaying) {
            callback.onPlaybackPause(currentMedia, currentMedia.getPosition());
        }
        playerLock.unlock();
    });
}
Also used : Playable(de.danoeh.antennapod.model.playback.Playable)

Example 5 with Playable

use of de.danoeh.antennapod.model.playback.Playable in project AntennaPod by AntennaPod.

the class PlaybackService method recreateMediaPlayer.

void recreateMediaPlayer() {
    Playable media = null;
    boolean wasPlaying = false;
    if (mediaPlayer != null) {
        media = mediaPlayer.getPlayable();
        wasPlaying = mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING;
        mediaPlayer.pause(true, false);
        mediaPlayer.shutdown();
    }
    mediaPlayer = CastPsmp.getInstanceIfConnected(this, mediaPlayerCallback);
    if (mediaPlayer == null) {
        // Cast not supported or not connected
        mediaPlayer = new LocalPSMP(this, mediaPlayerCallback);
    }
    if (media != null) {
        mediaPlayer.playMediaObject(media, !media.localFileAvailable(), wasPlaying, true);
    }
    isCasting = mediaPlayer.isCasting();
}
Also used : Playable(de.danoeh.antennapod.model.playback.Playable)

Aggregations

Playable (de.danoeh.antennapod.model.playback.Playable)35 Context (android.content.Context)14 CountDownLatch (java.util.concurrent.CountDownLatch)13 LocalPSMP (de.danoeh.antennapod.core.service.playback.LocalPSMP)11 PlaybackServiceMediaPlayer (de.danoeh.antennapod.playback.base.PlaybackServiceMediaPlayer)11 Test (org.junit.Test)11 UiThreadTest (androidx.test.annotation.UiThreadTest)10 AssertionFailedError (junit.framework.AssertionFailedError)9 MediumTest (androidx.test.filters.MediumTest)8 FeedMedia (de.danoeh.antennapod.model.feed.FeedMedia)8 LayoutInflater (android.view.LayoutInflater)3 Nullable (androidx.annotation.Nullable)3 PlayerErrorEvent (de.danoeh.antennapod.event.PlayerErrorEvent)3 FeedItem (de.danoeh.antennapod.model.feed.FeedItem)3 FeedPreferences (de.danoeh.antennapod.model.feed.FeedPreferences)3 Intent (android.content.Intent)2 Bundle (android.os.Bundle)2 Log (android.util.Log)2 View (android.view.View)2 ViewGroup (android.view.ViewGroup)2