2018-03-16 07:42:46 +01:00
|
|
|
package org.schabi.newpipe.player.helper;
|
|
|
|
|
|
|
|
import android.content.Context;
|
2018-04-03 07:11:53 +02:00
|
|
|
import android.content.Intent;
|
2019-10-04 20:47:01 +02:00
|
|
|
import android.graphics.Bitmap;
|
|
|
|
import android.support.v4.media.MediaMetadataCompat;
|
2019-10-07 07:54:31 +02:00
|
|
|
import android.support.v4.media.session.MediaSessionCompat;
|
2020-03-03 00:35:44 +01:00
|
|
|
import android.support.v4.media.session.PlaybackStateCompat;
|
|
|
|
import android.util.Log;
|
2019-10-07 07:54:31 +02:00
|
|
|
import android.view.KeyEvent;
|
2019-11-08 18:47:42 +01:00
|
|
|
|
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
import androidx.annotation.Nullable;
|
2020-03-31 19:20:15 +02:00
|
|
|
import androidx.media.session.MediaButtonReceiver;
|
2018-03-16 07:42:46 +01:00
|
|
|
|
|
|
|
import com.google.android.exoplayer2.Player;
|
|
|
|
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;
|
|
|
|
|
2020-05-15 15:05:20 +02:00
|
|
|
import org.schabi.newpipe.BuildConfig;
|
2018-03-16 07:42:46 +01:00
|
|
|
import org.schabi.newpipe.player.mediasession.MediaSessionCallback;
|
|
|
|
import org.schabi.newpipe.player.mediasession.PlayQueueNavigator;
|
|
|
|
import org.schabi.newpipe.player.mediasession.PlayQueuePlaybackController;
|
|
|
|
|
|
|
|
public class MediaSessionManager {
|
|
|
|
private static final String TAG = "MediaSessionManager";
|
2020-05-15 15:05:20 +02:00
|
|
|
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
|
2018-03-16 07:42:46 +01:00
|
|
|
|
2019-11-08 18:47:42 +01:00
|
|
|
@NonNull
|
|
|
|
private final MediaSessionCompat mediaSession;
|
|
|
|
@NonNull
|
|
|
|
private final MediaSessionConnector sessionConnector;
|
2020-03-03 00:35:44 +01:00
|
|
|
@NonNull
|
|
|
|
private final PlaybackStateCompat.Builder playbackStateCompatBuilder;
|
|
|
|
|
|
|
|
private int tmpThumbHash;
|
2018-03-16 07:42:46 +01:00
|
|
|
|
|
|
|
public MediaSessionManager(@NonNull final Context context,
|
|
|
|
@NonNull final Player player,
|
|
|
|
@NonNull final MediaSessionCallback callback) {
|
|
|
|
this.mediaSession = new MediaSessionCompat(context, TAG);
|
2020-03-03 00:35:44 +01:00
|
|
|
this.mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS
|
|
|
|
| MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
|
2018-05-29 05:02:02 +02:00
|
|
|
this.mediaSession.setActive(true);
|
|
|
|
|
2020-03-03 00:35:44 +01:00
|
|
|
this.playbackStateCompatBuilder = new PlaybackStateCompat.Builder();
|
|
|
|
this.playbackStateCompatBuilder.setState(PlaybackStateCompat.STATE_NONE, -1, 1);
|
|
|
|
this.playbackStateCompatBuilder.setActions(PlaybackStateCompat.ACTION_SEEK_TO
|
|
|
|
| PlaybackStateCompat.ACTION_PLAY
|
|
|
|
| PlaybackStateCompat.ACTION_PAUSE // was play and pause now play/pause
|
|
|
|
| PlaybackStateCompat.ACTION_SKIP_TO_NEXT
|
|
|
|
| PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
|
|
|
|
| PlaybackStateCompat.ACTION_SET_REPEAT_MODE | PlaybackStateCompat.ACTION_STOP);
|
|
|
|
this.mediaSession.setPlaybackState(playbackStateCompatBuilder.build());
|
|
|
|
|
2019-10-07 07:54:31 +02:00
|
|
|
this.sessionConnector = new MediaSessionConnector(mediaSession);
|
|
|
|
this.sessionConnector.setControlDispatcher(new PlayQueuePlaybackController(callback));
|
2018-03-16 07:42:46 +01:00
|
|
|
this.sessionConnector.setQueueNavigator(new PlayQueueNavigator(mediaSession, callback));
|
2019-10-07 07:54:31 +02:00
|
|
|
this.sessionConnector.setPlayer(player);
|
2018-03-16 07:42:46 +01:00
|
|
|
}
|
|
|
|
|
2018-04-03 07:11:53 +02:00
|
|
|
@Nullable
|
|
|
|
@SuppressWarnings("UnusedReturnValue")
|
|
|
|
public KeyEvent handleMediaButtonIntent(final Intent intent) {
|
|
|
|
return MediaButtonReceiver.handleIntent(mediaSession, intent);
|
2018-03-16 07:42:46 +01:00
|
|
|
}
|
2018-05-29 05:02:02 +02:00
|
|
|
|
2020-03-03 00:35:44 +01:00
|
|
|
public MediaSessionCompat.Token getSessionToken() {
|
|
|
|
return this.mediaSession.getSessionToken();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setMetadata(final String title, final String artist, final Bitmap albumArt,
|
|
|
|
final long duration) {
|
|
|
|
if (albumArt == null || !mediaSession.isActive()) {
|
2019-10-04 20:47:01 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-05-15 15:05:20 +02:00
|
|
|
if (DEBUG) {
|
|
|
|
if (getMetadataAlbumArt() == 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());
|
|
|
|
}
|
2020-03-03 00:35:44 +01:00
|
|
|
}
|
2019-10-04 20:47:01 +02:00
|
|
|
|
2020-03-03 00:35:44 +01:00
|
|
|
if (getMetadataAlbumArt() == null || getMetadataTitle() == null
|
|
|
|
|| getMetadataArtist() == null || getMetadataDuration() <= 1
|
|
|
|
|| albumArt.hashCode() != tmpThumbHash) {
|
2020-05-15 15:05:20 +02:00
|
|
|
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());
|
2020-03-03 00:35:44 +01:00
|
|
|
tmpThumbHash = albumArt.hashCode();
|
|
|
|
}
|
|
|
|
}
|
2019-10-04 20:47:01 +02:00
|
|
|
|
2020-03-03 00:35:44 +01:00
|
|
|
private Bitmap getMetadataAlbumArt() {
|
|
|
|
return mediaSession.getController().getMetadata()
|
|
|
|
.getBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART);
|
2019-10-04 20:47:01 +02:00
|
|
|
}
|
|
|
|
|
2020-03-03 00:35:44 +01:00
|
|
|
private String getMetadataTitle() {
|
|
|
|
return mediaSession.getController().getMetadata()
|
|
|
|
.getString(MediaMetadataCompat.METADATA_KEY_TITLE);
|
|
|
|
}
|
2019-11-28 19:46:37 +01:00
|
|
|
|
2020-03-03 00:35:44 +01:00
|
|
|
private String getMetadataArtist() {
|
|
|
|
return mediaSession.getController().getMetadata()
|
|
|
|
.getString(MediaMetadataCompat.METADATA_KEY_ARTIST);
|
|
|
|
}
|
2019-11-28 19:46:37 +01:00
|
|
|
|
2020-03-03 00:35:44 +01:00
|
|
|
private long getMetadataDuration() {
|
|
|
|
return mediaSession.getController().getMetadata()
|
|
|
|
.getLong(MediaMetadataCompat.METADATA_KEY_DURATION);
|
2019-11-28 19:46:37 +01:00
|
|
|
}
|
|
|
|
|
2018-05-11 02:48:05 +02:00
|
|
|
/**
|
2020-01-03 14:29:04 +01:00
|
|
|
* Should be called on player destruction to prevent leakage.
|
2019-10-04 20:47:01 +02:00
|
|
|
*/
|
2018-05-29 05:02:02 +02:00
|
|
|
public void dispose() {
|
2019-10-07 07:54:31 +02:00
|
|
|
this.sessionConnector.setPlayer(null);
|
2018-05-29 05:02:02 +02:00
|
|
|
this.sessionConnector.setQueueNavigator(null);
|
|
|
|
this.mediaSession.setActive(false);
|
|
|
|
this.mediaSession.release();
|
2019-10-04 20:47:01 +02:00
|
|
|
}
|
2018-03-16 07:42:46 +01:00
|
|
|
}
|