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();
}
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();
}
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();
}
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()));
}
}
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;
}
Aggregations