Search in sources :

Example 26 with Playable

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

the class PlaybackServiceMediaPlayerTest method pauseTestSkeleton.

private void pauseTestSkeleton(final PlayerStatus initialState, final boolean stream, final boolean abandonAudioFocus, final boolean reinit, long timeoutSeconds) throws InterruptedException {
    final Context c = getInstrumentation().getTargetContext();
    final int latchCount = (stream && reinit) ? 2 : 1;
    final CountDownLatch countDownLatch = new CountDownLatch(latchCount);
    CancelablePSMPCallback callback = new CancelablePSMPCallback(new DefaultPSMPCallback() {

        @Override
        public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
            checkPSMPInfo(newInfo);
            if (newInfo.playerStatus == PlayerStatus.ERROR) {
                if (assertionError == null)
                    assertionError = new UnexpectedStateChange(newInfo.playerStatus);
            } else if (initialState != PlayerStatus.PLAYING) {
                if (assertionError == null)
                    assertionError = new UnexpectedStateChange(newInfo.playerStatus);
            } else {
                switch(newInfo.playerStatus) {
                    case PAUSED:
                        if (latchCount == countDownLatch.getCount())
                            countDownLatch.countDown();
                        else {
                            if (assertionError == null)
                                assertionError = new UnexpectedStateChange(newInfo.playerStatus);
                        }
                        break;
                    case INITIALIZED:
                        if (stream && reinit && countDownLatch.getCount() < latchCount) {
                            countDownLatch.countDown();
                        } else if (countDownLatch.getCount() < latchCount) {
                            if (assertionError == null)
                                assertionError = new UnexpectedStateChange(newInfo.playerStatus);
                        }
                        break;
                }
            }
        }

        @Override
        public void shouldStop() {
            if (assertionError == null)
                assertionError = new AssertionFailedError("Unexpected call to shouldStop");
        }
    });
    PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
    Playable p = writeTestPlayable(playableFileUrl, PLAYABLE_LOCAL_URL);
    if (initialState == PlayerStatus.PLAYING) {
        psmp.playMediaObject(p, stream, true, true);
    }
    psmp.pause(abandonAudioFocus, reinit);
    boolean res = countDownLatch.await(timeoutSeconds, TimeUnit.SECONDS);
    if (assertionError != null)
        throw assertionError;
    assertTrue(res || initialState != PlayerStatus.PLAYING);
    callback.cancel();
    psmp.shutdown();
}
Also used : Context(android.content.Context) LocalPSMP(de.danoeh.antennapod.core.service.playback.LocalPSMP) PlaybackServiceMediaPlayer(de.danoeh.antennapod.playback.base.PlaybackServiceMediaPlayer) CountDownLatch(java.util.concurrent.CountDownLatch) Playable(de.danoeh.antennapod.model.playback.Playable) AssertionFailedError(junit.framework.AssertionFailedError)

Example 27 with Playable

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

the class PlaybackServiceTaskManagerTest method testStartPositionSaver.

@Test
public void testStartPositionSaver() throws InterruptedException {
    final Context c = InstrumentationRegistry.getInstrumentation().getTargetContext();
    final int NUM_COUNTDOWNS = 2;
    final int TIMEOUT = 3 * PlaybackServiceTaskManager.POSITION_SAVER_WAITING_INTERVAL;
    final CountDownLatch countDownLatch = new CountDownLatch(NUM_COUNTDOWNS);
    PlaybackServiceTaskManager pstm = new PlaybackServiceTaskManager(c, new PlaybackServiceTaskManager.PSTMCallback() {

        @Override
        public void positionSaverTick() {
            countDownLatch.countDown();
        }

        @Override
        public WidgetUpdater.WidgetState requestWidgetState() {
            return null;
        }

        @Override
        public void onChapterLoaded(Playable media) {
        }
    });
    pstm.startPositionSaver();
    countDownLatch.await(TIMEOUT, TimeUnit.MILLISECONDS);
    pstm.shutdown();
}
Also used : Context(android.content.Context) Playable(de.danoeh.antennapod.model.playback.Playable) PlaybackServiceTaskManager(de.danoeh.antennapod.core.service.playback.PlaybackServiceTaskManager) CountDownLatch(java.util.concurrent.CountDownLatch) LargeTest(androidx.test.filters.LargeTest) Test(org.junit.Test) UiThreadTest(androidx.test.annotation.UiThreadTest)

Example 28 with Playable

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

the class PlaybackServiceTaskManagerTest method testStartWidgetUpdater.

@Test
public void testStartWidgetUpdater() throws InterruptedException {
    final Context c = InstrumentationRegistry.getInstrumentation().getTargetContext();
    final int NUM_COUNTDOWNS = 2;
    final int TIMEOUT = 3 * PlaybackServiceTaskManager.WIDGET_UPDATER_NOTIFICATION_INTERVAL;
    final CountDownLatch countDownLatch = new CountDownLatch(NUM_COUNTDOWNS);
    PlaybackServiceTaskManager pstm = new PlaybackServiceTaskManager(c, new PlaybackServiceTaskManager.PSTMCallback() {

        @Override
        public void positionSaverTick() {
        }

        @Override
        public WidgetUpdater.WidgetState requestWidgetState() {
            countDownLatch.countDown();
            return null;
        }

        @Override
        public void onChapterLoaded(Playable media) {
        }
    });
    pstm.startWidgetUpdater();
    countDownLatch.await(TIMEOUT, TimeUnit.MILLISECONDS);
    pstm.shutdown();
}
Also used : Context(android.content.Context) Playable(de.danoeh.antennapod.model.playback.Playable) PlaybackServiceTaskManager(de.danoeh.antennapod.core.service.playback.PlaybackServiceTaskManager) CountDownLatch(java.util.concurrent.CountDownLatch) LargeTest(androidx.test.filters.LargeTest) Test(org.junit.Test) UiThreadTest(androidx.test.annotation.UiThreadTest)

Example 29 with Playable

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

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

the class FeedItemlistDescriptionAdapter method getView.

@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
    Holder holder;
    FeedItem item = getItem(position);
    // Inflate layout
    if (convertView == null) {
        holder = new Holder();
        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.itemdescription_listitem, parent, false);
        holder.title = convertView.findViewById(R.id.txtvTitle);
        holder.pubDate = convertView.findViewById(R.id.txtvPubDate);
        holder.description = convertView.findViewById(R.id.txtvDescription);
        holder.preview = convertView.findViewById(R.id.butPreview);
        convertView.setTag(holder);
    } else {
        holder = (Holder) convertView.getTag();
    }
    holder.title.setText(item.getTitle());
    holder.pubDate.setText(DateFormatter.formatAbbrev(getContext(), item.getPubDate()));
    if (item.getDescription() != null) {
        String description = HtmlToPlainText.getPlainText(item.getDescription()).replaceAll("\n", " ").replaceAll("\\s+", " ").trim();
        holder.description.setText(description);
        holder.description.setMaxLines(MAX_LINES_COLLAPSED);
    }
    // not expanded
    holder.description.setTag(Boolean.FALSE);
    holder.preview.setVisibility(View.GONE);
    holder.preview.setOnClickListener(v -> {
        if (item.getMedia() == null) {
            return;
        }
        Playable playable = new RemoteMedia(item);
        if (!NetworkUtils.isStreamingAllowed()) {
            new StreamingConfirmationDialog(getContext(), playable).show();
            return;
        }
        new PlaybackServiceStarter(getContext(), playable).shouldStream(true).startWhenPrepared(true).callEvenIfRunning(true).start();
        if (playable.getMediaType() == MediaType.VIDEO) {
            getContext().startActivity(PlaybackService.getPlayerActivityIntent(getContext(), playable));
        }
    });
    convertView.setOnClickListener(v -> {
        if (holder.description.getTag() == Boolean.TRUE) {
            holder.description.setMaxLines(MAX_LINES_COLLAPSED);
            holder.preview.setVisibility(View.GONE);
            holder.description.setTag(Boolean.FALSE);
        } else {
            holder.description.setMaxLines(30);
            holder.description.setTag(Boolean.TRUE);
            holder.preview.setVisibility(item.getMedia() != null ? View.VISIBLE : View.GONE);
            holder.preview.setText(R.string.preview_episode);
        }
    });
    return convertView;
}
Also used : FeedItem(de.danoeh.antennapod.model.feed.FeedItem) PlaybackServiceStarter(de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter) Playable(de.danoeh.antennapod.model.playback.Playable) LayoutInflater(android.view.LayoutInflater) RemoteMedia(de.danoeh.antennapod.model.playback.RemoteMedia) StreamingConfirmationDialog(de.danoeh.antennapod.dialog.StreamingConfirmationDialog) NonNull(androidx.annotation.NonNull)

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