Merge pull request #7166 from litetex/various-fixes-for-mediasession-player
Various fixes related to MediasessionManager
This commit is contained in:
commit
f48ff610a3
|
@ -17,6 +17,7 @@ import org.schabi.newpipe.extractor.stream.StreamType.LIVE_STREAM
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType.VIDEO_STREAM
|
import org.schabi.newpipe.extractor.stream.StreamType.VIDEO_STREAM
|
||||||
import org.schabi.newpipe.util.Localization
|
import org.schabi.newpipe.util.Localization
|
||||||
import org.schabi.newpipe.util.PicassoHelper
|
import org.schabi.newpipe.util.PicassoHelper
|
||||||
|
import org.schabi.newpipe.util.StreamTypeUtil
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
data class StreamItem(
|
data class StreamItem(
|
||||||
|
@ -58,8 +59,6 @@ data class StreamItem(
|
||||||
viewBinding.itemVideoTitleView.text = stream.title
|
viewBinding.itemVideoTitleView.text = stream.title
|
||||||
viewBinding.itemUploaderView.text = stream.uploader
|
viewBinding.itemUploaderView.text = stream.uploader
|
||||||
|
|
||||||
val isLiveStream = stream.streamType == LIVE_STREAM || stream.streamType == AUDIO_LIVE_STREAM
|
|
||||||
|
|
||||||
if (stream.duration > 0) {
|
if (stream.duration > 0) {
|
||||||
viewBinding.itemDurationView.text = Localization.getDurationString(stream.duration)
|
viewBinding.itemDurationView.text = Localization.getDurationString(stream.duration)
|
||||||
viewBinding.itemDurationView.setBackgroundColor(
|
viewBinding.itemDurationView.setBackgroundColor(
|
||||||
|
@ -77,7 +76,7 @@ data class StreamItem(
|
||||||
} else {
|
} else {
|
||||||
viewBinding.itemProgressView.visibility = View.GONE
|
viewBinding.itemProgressView.visibility = View.GONE
|
||||||
}
|
}
|
||||||
} else if (isLiveStream) {
|
} else if (StreamTypeUtil.isLiveStream(stream.streamType)) {
|
||||||
viewBinding.itemDurationView.setText(R.string.duration_live)
|
viewBinding.itemDurationView.setText(R.string.duration_live)
|
||||||
viewBinding.itemDurationView.setBackgroundColor(
|
viewBinding.itemDurationView.setBackgroundColor(
|
||||||
ContextCompat.getColor(
|
ContextCompat.getColor(
|
||||||
|
|
|
@ -1,5 +1,53 @@
|
||||||
package org.schabi.newpipe.player;
|
package org.schabi.newpipe.player;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_AD_INSERTION;
|
||||||
|
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_INTERNAL;
|
||||||
|
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_PERIOD_TRANSITION;
|
||||||
|
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK;
|
||||||
|
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT;
|
||||||
|
import static com.google.android.exoplayer2.Player.DiscontinuityReason;
|
||||||
|
import static com.google.android.exoplayer2.Player.EventListener;
|
||||||
|
import static com.google.android.exoplayer2.Player.REPEAT_MODE_ALL;
|
||||||
|
import static com.google.android.exoplayer2.Player.REPEAT_MODE_OFF;
|
||||||
|
import static com.google.android.exoplayer2.Player.REPEAT_MODE_ONE;
|
||||||
|
import static com.google.android.exoplayer2.Player.RepeatMode;
|
||||||
|
import static org.schabi.newpipe.QueueItemMenuUtil.openPopupMenu;
|
||||||
|
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
|
||||||
|
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||||
|
import static org.schabi.newpipe.ktx.ViewUtils.animate;
|
||||||
|
import static org.schabi.newpipe.ktx.ViewUtils.animateRotation;
|
||||||
|
import static org.schabi.newpipe.player.MainPlayer.ACTION_CLOSE;
|
||||||
|
import static org.schabi.newpipe.player.MainPlayer.ACTION_FAST_FORWARD;
|
||||||
|
import static org.schabi.newpipe.player.MainPlayer.ACTION_FAST_REWIND;
|
||||||
|
import static org.schabi.newpipe.player.MainPlayer.ACTION_PLAY_NEXT;
|
||||||
|
import static org.schabi.newpipe.player.MainPlayer.ACTION_PLAY_PAUSE;
|
||||||
|
import static org.schabi.newpipe.player.MainPlayer.ACTION_PLAY_PREVIOUS;
|
||||||
|
import static org.schabi.newpipe.player.MainPlayer.ACTION_RECREATE_NOTIFICATION;
|
||||||
|
import static org.schabi.newpipe.player.MainPlayer.ACTION_REPEAT;
|
||||||
|
import static org.schabi.newpipe.player.MainPlayer.ACTION_SHUFFLE;
|
||||||
|
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_BACKGROUND;
|
||||||
|
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_NONE;
|
||||||
|
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_POPUP;
|
||||||
|
import static org.schabi.newpipe.player.helper.PlayerHelper.buildCloseOverlayLayoutParams;
|
||||||
|
import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed;
|
||||||
|
import static org.schabi.newpipe.player.helper.PlayerHelper.getMinimizeOnExitAction;
|
||||||
|
import static org.schabi.newpipe.player.helper.PlayerHelper.getMinimumVideoHeight;
|
||||||
|
import static org.schabi.newpipe.player.helper.PlayerHelper.getTimeString;
|
||||||
|
import static org.schabi.newpipe.player.helper.PlayerHelper.globalScreenOrientationLocked;
|
||||||
|
import static org.schabi.newpipe.player.helper.PlayerHelper.isPlaybackResumeEnabled;
|
||||||
|
import static org.schabi.newpipe.player.helper.PlayerHelper.nextRepeatMode;
|
||||||
|
import static org.schabi.newpipe.player.helper.PlayerHelper.nextResizeModeAndSaveToPrefs;
|
||||||
|
import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePlaybackParametersFromPrefs;
|
||||||
|
import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePlayerTypeFromIntent;
|
||||||
|
import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePopupLayoutParamsFromPrefs;
|
||||||
|
import static org.schabi.newpipe.player.helper.PlayerHelper.retrieveSeekDurationFromPreferences;
|
||||||
|
import static org.schabi.newpipe.player.helper.PlayerHelper.savePlaybackParametersToPrefs;
|
||||||
|
import static org.schabi.newpipe.util.ListHelper.getPopupResolutionIndex;
|
||||||
|
import static org.schabi.newpipe.util.ListHelper.getResolutionIndex;
|
||||||
|
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||||
|
import static org.schabi.newpipe.util.Localization.containsCaseInsensitive;
|
||||||
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
|
@ -94,7 +142,6 @@ import org.schabi.newpipe.databinding.PlayerPopupCloseOverlayBinding;
|
||||||
import org.schabi.newpipe.extractor.MediaFormat;
|
import org.schabi.newpipe.extractor.MediaFormat;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamSegment;
|
import org.schabi.newpipe.extractor.stream.StreamSegment;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
|
||||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||||
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
|
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
|
||||||
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
|
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
|
||||||
|
@ -127,12 +174,13 @@ import org.schabi.newpipe.player.resolver.MediaSourceTag;
|
||||||
import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
|
import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
|
||||||
import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHelper;
|
import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHelper;
|
||||||
import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHolder;
|
import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHolder;
|
||||||
|
import org.schabi.newpipe.util.StreamTypeUtil;
|
||||||
import org.schabi.newpipe.util.DeviceUtils;
|
import org.schabi.newpipe.util.DeviceUtils;
|
||||||
import org.schabi.newpipe.util.external_communication.KoreUtils;
|
|
||||||
import org.schabi.newpipe.util.ListHelper;
|
import org.schabi.newpipe.util.ListHelper;
|
||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
import org.schabi.newpipe.util.PicassoHelper;
|
import org.schabi.newpipe.util.PicassoHelper;
|
||||||
import org.schabi.newpipe.util.SerializedCache;
|
import org.schabi.newpipe.util.SerializedCache;
|
||||||
|
import org.schabi.newpipe.util.external_communication.KoreUtils;
|
||||||
import org.schabi.newpipe.util.external_communication.ShareUtils;
|
import org.schabi.newpipe.util.external_communication.ShareUtils;
|
||||||
import org.schabi.newpipe.views.ExpandableSurfaceView;
|
import org.schabi.newpipe.views.ExpandableSurfaceView;
|
||||||
|
|
||||||
|
@ -140,6 +188,7 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.rxjava3.core.Observable;
|
import io.reactivex.rxjava3.core.Observable;
|
||||||
|
@ -147,54 +196,6 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||||
import io.reactivex.rxjava3.disposables.Disposable;
|
import io.reactivex.rxjava3.disposables.Disposable;
|
||||||
import io.reactivex.rxjava3.disposables.SerialDisposable;
|
import io.reactivex.rxjava3.disposables.SerialDisposable;
|
||||||
|
|
||||||
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_AD_INSERTION;
|
|
||||||
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_INTERNAL;
|
|
||||||
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_PERIOD_TRANSITION;
|
|
||||||
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK;
|
|
||||||
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT;
|
|
||||||
import static com.google.android.exoplayer2.Player.DiscontinuityReason;
|
|
||||||
import static com.google.android.exoplayer2.Player.EventListener;
|
|
||||||
import static com.google.android.exoplayer2.Player.REPEAT_MODE_ALL;
|
|
||||||
import static com.google.android.exoplayer2.Player.REPEAT_MODE_OFF;
|
|
||||||
import static com.google.android.exoplayer2.Player.REPEAT_MODE_ONE;
|
|
||||||
import static com.google.android.exoplayer2.Player.RepeatMode;
|
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
|
||||||
import static org.schabi.newpipe.QueueItemMenuUtil.openPopupMenu;
|
|
||||||
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
|
|
||||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
|
||||||
import static org.schabi.newpipe.ktx.ViewUtils.animate;
|
|
||||||
import static org.schabi.newpipe.ktx.ViewUtils.animateRotation;
|
|
||||||
import static org.schabi.newpipe.player.MainPlayer.ACTION_CLOSE;
|
|
||||||
import static org.schabi.newpipe.player.MainPlayer.ACTION_FAST_FORWARD;
|
|
||||||
import static org.schabi.newpipe.player.MainPlayer.ACTION_FAST_REWIND;
|
|
||||||
import static org.schabi.newpipe.player.MainPlayer.ACTION_PLAY_NEXT;
|
|
||||||
import static org.schabi.newpipe.player.MainPlayer.ACTION_PLAY_PAUSE;
|
|
||||||
import static org.schabi.newpipe.player.MainPlayer.ACTION_PLAY_PREVIOUS;
|
|
||||||
import static org.schabi.newpipe.player.MainPlayer.ACTION_RECREATE_NOTIFICATION;
|
|
||||||
import static org.schabi.newpipe.player.MainPlayer.ACTION_REPEAT;
|
|
||||||
import static org.schabi.newpipe.player.MainPlayer.ACTION_SHUFFLE;
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_BACKGROUND;
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_NONE;
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_POPUP;
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.buildCloseOverlayLayoutParams;
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed;
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.getMinimizeOnExitAction;
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.getMinimumVideoHeight;
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.getTimeString;
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.globalScreenOrientationLocked;
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.isPlaybackResumeEnabled;
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.nextRepeatMode;
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.nextResizeModeAndSaveToPrefs;
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePlaybackParametersFromPrefs;
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePlayerTypeFromIntent;
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePopupLayoutParamsFromPrefs;
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.retrieveSeekDurationFromPreferences;
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.savePlaybackParametersToPrefs;
|
|
||||||
import static org.schabi.newpipe.util.ListHelper.getPopupResolutionIndex;
|
|
||||||
import static org.schabi.newpipe.util.ListHelper.getResolutionIndex;
|
|
||||||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
|
||||||
import static org.schabi.newpipe.util.Localization.containsCaseInsensitive;
|
|
||||||
|
|
||||||
public final class Player implements
|
public final class Player implements
|
||||||
EventListener,
|
EventListener,
|
||||||
PlaybackListener,
|
PlaybackListener,
|
||||||
|
@ -1622,12 +1623,6 @@ public final class Player implements
|
||||||
if (isQueueVisible) {
|
if (isQueueVisible) {
|
||||||
updateQueueTime(currentProgress);
|
updateQueueTime(currentProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean showThumbnail = prefs.getBoolean(
|
|
||||||
context.getString(R.string.show_thumbnail_key), true);
|
|
||||||
// setMetadata only updates the metadata when any of the metadata keys are null
|
|
||||||
mediaSessionManager.setMetadata(getVideoTitle(), getUploaderName(),
|
|
||||||
showThumbnail ? getThumbnail() : null, duration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startProgressLoop() {
|
private void startProgressLoop() {
|
||||||
|
@ -1652,8 +1647,8 @@ public final class Player implements
|
||||||
// TODO: revert #6307 when introducing proper HLS support
|
// TODO: revert #6307 when introducing proper HLS support
|
||||||
final int duration;
|
final int duration;
|
||||||
if (currentItem != null
|
if (currentItem != null
|
||||||
&& currentItem.getStreamType() != StreamType.AUDIO_LIVE_STREAM
|
&& !StreamTypeUtil.isLiveStream(currentItem.getStreamType())
|
||||||
&& currentItem.getStreamType() != StreamType.LIVE_STREAM) {
|
) {
|
||||||
// convert seconds to milliseconds
|
// convert seconds to milliseconds
|
||||||
duration = (int) (currentItem.getDuration() * 1000);
|
duration = (int) (currentItem.getDuration() * 1000);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2946,6 +2941,18 @@ public final class Player implements
|
||||||
tag.getMetadata().getPreviewFrames());
|
tag.getMetadata().getPreviewFrames());
|
||||||
|
|
||||||
NotificationUtil.getInstance().createNotificationIfNeededAndUpdate(this, false);
|
NotificationUtil.getInstance().createNotificationIfNeededAndUpdate(this, false);
|
||||||
|
|
||||||
|
final boolean showThumbnail = prefs.getBoolean(
|
||||||
|
context.getString(R.string.show_thumbnail_key), true);
|
||||||
|
mediaSessionManager.setMetadata(
|
||||||
|
getVideoTitle(),
|
||||||
|
getUploaderName(),
|
||||||
|
showThumbnail ? Optional.ofNullable(getThumbnail()) : Optional.empty(),
|
||||||
|
StreamTypeUtil.isLiveStream(tag.getMetadata().getStreamType())
|
||||||
|
? -1
|
||||||
|
: tag.getMetadata().getDuration()
|
||||||
|
);
|
||||||
|
|
||||||
notifyMetadataUpdateToListeners();
|
notifyMetadataUpdateToListeners();
|
||||||
|
|
||||||
if (areSegmentsVisible) {
|
if (areSegmentsVisible) {
|
||||||
|
@ -3023,9 +3030,11 @@ public final class Player implements
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Bitmap getThumbnail() {
|
public Bitmap getThumbnail() {
|
||||||
return currentThumbnail == null
|
if (currentThumbnail == null) {
|
||||||
? BitmapFactory.decodeResource(context.getResources(), R.drawable.dummy_thumbnail)
|
currentThumbnail = BitmapFactory.decodeResource(
|
||||||
: currentThumbnail;
|
context.getResources(), R.drawable.dummy_thumbnail);
|
||||||
|
}
|
||||||
|
return currentThumbnail;
|
||||||
}
|
}
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@ import org.schabi.newpipe.player.mediasession.MediaSessionCallback;
|
||||||
import org.schabi.newpipe.player.mediasession.PlayQueueNavigator;
|
import org.schabi.newpipe.player.mediasession.PlayQueueNavigator;
|
||||||
import org.schabi.newpipe.player.mediasession.PlayQueuePlaybackController;
|
import org.schabi.newpipe.player.mediasession.PlayQueuePlaybackController;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class MediaSessionManager {
|
public class MediaSessionManager {
|
||||||
private static final String TAG = MediaSessionManager.class.getSimpleName();
|
private static final String TAG = MediaSessionManager.class.getSimpleName();
|
||||||
public static final boolean DEBUG = MainActivity.DEBUG;
|
public static final boolean DEBUG = MainActivity.DEBUG;
|
||||||
|
@ -30,6 +32,9 @@ public class MediaSessionManager {
|
||||||
@NonNull
|
@NonNull
|
||||||
private final MediaSessionConnector sessionConnector;
|
private final MediaSessionConnector sessionConnector;
|
||||||
|
|
||||||
|
private int lastTitleHashCode;
|
||||||
|
private int lastArtistHashCode;
|
||||||
|
private long lastDuration;
|
||||||
private int lastAlbumArtHashCode;
|
private int lastAlbumArtHashCode;
|
||||||
|
|
||||||
public MediaSessionManager(@NonNull final Context context,
|
public MediaSessionManager(@NonNull final Context context,
|
||||||
|
@ -65,46 +70,126 @@ public class MediaSessionManager {
|
||||||
return mediaSession.getSessionToken();
|
return mediaSession.getSessionToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMetadata(final String title,
|
/**
|
||||||
final String artist,
|
* sets the Metadata - if required.
|
||||||
final Bitmap albumArt,
|
*
|
||||||
final long duration) {
|
* @param title {@link MediaMetadataCompat#METADATA_KEY_TITLE}
|
||||||
if (albumArt == null || !mediaSession.isActive()) {
|
* @param artist {@link MediaMetadataCompat#METADATA_KEY_ARTIST}
|
||||||
|
* @param optAlbumArt {@link MediaMetadataCompat#METADATA_KEY_ALBUM_ART}
|
||||||
|
* @param duration {@link MediaMetadataCompat#METADATA_KEY_DURATION}
|
||||||
|
* - should be a negative value for unknown durations, e.g. for livestreams
|
||||||
|
*/
|
||||||
|
public void setMetadata(@NonNull final String title,
|
||||||
|
@NonNull final String artist,
|
||||||
|
@NonNull final Optional<Bitmap> optAlbumArt,
|
||||||
|
final long duration
|
||||||
|
) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "setMetadata called:"
|
||||||
|
+ " t: " + title
|
||||||
|
+ " a: " + artist
|
||||||
|
+ " thumb: " + (
|
||||||
|
optAlbumArt.isPresent()
|
||||||
|
? optAlbumArt.get().hashCode()
|
||||||
|
: "<none>")
|
||||||
|
+ " d: " + duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mediaSession.isActive()) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "setMetadata: mediaSession not active - exiting");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!checkIfMetadataShouldBeSet(title, artist, optAlbumArt, duration)) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "setMetadata: No update required - exiting");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "setMetadata: N_Metadata update:"
|
||||||
|
+ " t: " + title
|
||||||
|
+ " a: " + artist
|
||||||
|
+ " thumb: " + (
|
||||||
|
optAlbumArt.isPresent()
|
||||||
|
? optAlbumArt.get().hashCode()
|
||||||
|
: "<none>")
|
||||||
|
+ " d: " + duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
final MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder()
|
||||||
|
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, title)
|
||||||
|
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, artist)
|
||||||
|
.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, duration);
|
||||||
|
|
||||||
|
if (optAlbumArt.isPresent()) {
|
||||||
|
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, optAlbumArt.get());
|
||||||
|
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, optAlbumArt.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaSession.setMetadata(builder.build());
|
||||||
|
|
||||||
|
lastTitleHashCode = title.hashCode();
|
||||||
|
lastArtistHashCode = artist.hashCode();
|
||||||
|
lastDuration = duration;
|
||||||
|
if (optAlbumArt.isPresent()) {
|
||||||
|
lastAlbumArtHashCode = optAlbumArt.get().hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkIfMetadataShouldBeSet(
|
||||||
|
@NonNull final String title,
|
||||||
|
@NonNull final String artist,
|
||||||
|
@NonNull final Optional<Bitmap> optAlbumArt,
|
||||||
|
final long duration
|
||||||
|
) {
|
||||||
|
// Check if the values have changed since the last time
|
||||||
|
if (title.hashCode() != lastTitleHashCode
|
||||||
|
|| artist.hashCode() != lastArtistHashCode
|
||||||
|
|| duration != lastDuration
|
||||||
|
|| (optAlbumArt.isPresent() && optAlbumArt.get().hashCode() != lastAlbumArtHashCode)
|
||||||
|
) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG,
|
||||||
|
"checkIfMetadataShouldBeSet: true - reason: changed values since last");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the currently set metadata is valid
|
||||||
|
if (getMetadataTitle() == null
|
||||||
|
|| getMetadataArtist() == null
|
||||||
|
// Note that the duration can be <= 0 for live streams
|
||||||
|
) {
|
||||||
|
if (DEBUG) {
|
||||||
|
if (getMetadataTitle() == null) {
|
||||||
|
Log.d(TAG,
|
||||||
|
"N_getMetadataTitle: title == null");
|
||||||
|
} else if (getMetadataArtist() == null) {
|
||||||
|
Log.d(TAG,
|
||||||
|
"N_getMetadataArtist: artist == null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we got an album art check if the current set AlbumArt is null
|
||||||
|
if (optAlbumArt.isPresent() && getMetadataAlbumArt() == null) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
if (getMetadataAlbumArt() == null) {
|
if (getMetadataAlbumArt() == null) {
|
||||||
Log.d(TAG, "N_getMetadataAlbumArt: thumb == null");
|
Log.d(TAG, "N_getMetadataAlbumArt: thumb == null");
|
||||||
}
|
}
|
||||||
if (getMetadataTitle() == null) {
|
|
||||||
Log.d(TAG, "N_getMetadataTitle: title == null");
|
|
||||||
}
|
|
||||||
if (getMetadataArtist() == null) {
|
|
||||||
Log.d(TAG, "N_getMetadataArtist: artist == null");
|
|
||||||
}
|
|
||||||
if (getMetadataDuration() <= 1) {
|
|
||||||
Log.d(TAG, "N_getMetadataDuration: duration <= 1; " + getMetadataDuration());
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getMetadataAlbumArt() == null || getMetadataTitle() == null
|
// Default - no update required
|
||||||
|| getMetadataArtist() == null || getMetadataDuration() <= 1
|
return false;
|
||||||
|| albumArt.hashCode() != lastAlbumArtHashCode) {
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.d(TAG, "setMetadata: N_Metadata update: t: " + title + " a: " + artist
|
|
||||||
+ " thumb: " + albumArt.hashCode() + " d: " + duration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaSession.setMetadata(new MediaMetadataCompat.Builder()
|
|
||||||
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, title)
|
|
||||||
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, artist)
|
|
||||||
.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt)
|
|
||||||
.putBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, albumArt)
|
|
||||||
.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, duration).build());
|
|
||||||
lastAlbumArtHashCode = albumArt.hashCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Bitmap getMetadataAlbumArt() {
|
private Bitmap getMetadataAlbumArt() {
|
||||||
return mediaSession.getController().getMetadata()
|
return mediaSession.getController().getMetadata()
|
||||||
|
@ -121,11 +206,6 @@ public class MediaSessionManager {
|
||||||
.getString(MediaMetadataCompat.METADATA_KEY_ARTIST);
|
.getString(MediaMetadataCompat.METADATA_KEY_ARTIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getMetadataDuration() {
|
|
||||||
return mediaSession.getController().getMetadata()
|
|
||||||
.getLong(MediaMetadataCompat.METADATA_KEY_DURATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should be called on player destruction to prevent leakage.
|
* Should be called on player destruction to prevent leakage.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -14,6 +14,7 @@ import com.google.android.exoplayer2.util.Util;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
import org.schabi.newpipe.player.helper.PlayerDataSource;
|
import org.schabi.newpipe.player.helper.PlayerDataSource;
|
||||||
|
import org.schabi.newpipe.util.StreamTypeUtil;
|
||||||
|
|
||||||
public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
||||||
default MediaSource maybeBuildLiveMediaSource(@NonNull final PlayerDataSource dataSource,
|
default MediaSource maybeBuildLiveMediaSource(@NonNull final PlayerDataSource dataSource,
|
||||||
@NonNull final StreamInfo info) {
|
@NonNull final StreamInfo info) {
|
||||||
final StreamType streamType = info.getStreamType();
|
final StreamType streamType = info.getStreamType();
|
||||||
if (!(streamType == StreamType.AUDIO_LIVE_STREAM || streamType == StreamType.LIVE_STREAM)) {
|
if (!StreamTypeUtil.isLiveStream(streamType)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package org.schabi.newpipe.util;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for {@link org.schabi.newpipe.extractor.stream.StreamType}.
|
||||||
|
*/
|
||||||
|
public final class StreamTypeUtil {
|
||||||
|
private StreamTypeUtil() {
|
||||||
|
// No impl pls
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the streamType is a livestream.
|
||||||
|
*
|
||||||
|
* @param streamType
|
||||||
|
* @return <code>true</code> when the streamType is a
|
||||||
|
* {@link StreamType#LIVE_STREAM} or {@link StreamType#AUDIO_LIVE_STREAM}
|
||||||
|
*/
|
||||||
|
public static boolean isLiveStream(final StreamType streamType) {
|
||||||
|
return streamType == StreamType.LIVE_STREAM
|
||||||
|
|| streamType == StreamType.AUDIO_LIVE_STREAM;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue