2
0
mirror of https://github.com/TeamNewPipe/NewPipe synced 2025-08-22 10:09:39 +00:00

PlayerHolder: convert to kotlin (mechanical)

This commit is contained in:
Profpatsch 2025-01-01 15:18:37 +01:00 committed by Stypox
parent 86063fda6a
commit 9b22773070
No known key found for this signature in database
GPG Key ID: 4BDF1B40A49FDD23
8 changed files with 395 additions and 396 deletions

View File

@ -849,7 +849,7 @@ public class MainActivity extends AppCompatActivity {
return;
}
if (PlayerHolder.getInstance().isPlayerOpen()) {
if (PlayerHolder.Companion.getInstance().isPlayerOpen()) {
// if the player is already open, no need for a broadcast receiver
openMiniPlayerIfMissing();
} else {
@ -859,7 +859,7 @@ public class MainActivity extends AppCompatActivity {
public void onReceive(final Context context, final Intent intent) {
if (Objects.equals(intent.getAction(),
VideoDetailFragment.ACTION_PLAYER_STARTED)
&& PlayerHolder.getInstance().isPlayerOpen()) {
&& PlayerHolder.Companion.getInstance().isPlayerOpen()) {
openMiniPlayerIfMissing();
// At this point the player is added 100%, we can unregister. Other actions
// are useless since the fragment will not be removed after that.
@ -874,7 +874,7 @@ public class MainActivity extends AppCompatActivity {
// If the PlayerHolder is not bound yet, but the service is running, try to bind to it.
// Once the connection is established, the ACTION_PLAYER_STARTED will be sent.
PlayerHolder.getInstance().tryBindIfNeeded(this);
PlayerHolder.Companion.getInstance().tryBindIfNeeded(this);
}
}

View File

@ -701,7 +701,7 @@ public class RouterActivity extends AppCompatActivity {
}
// ...the player is not running or in normal Video-mode/type
final PlayerType playerType = PlayerHolder.getInstance().getType();
final PlayerType playerType = PlayerHolder.Companion.getInstance().getType();
return playerType == null || playerType == PlayerType.MAIN;
}

View File

@ -228,7 +228,7 @@ public final class VideoDetailFragment
@Nullable
private PlayerService playerService;
private Player player;
private final PlayerHolder playerHolder = PlayerHolder.getInstance();
private final PlayerHolder playerHolder = PlayerHolder.Companion.getInstance();
/*//////////////////////////////////////////////////////////////////////////
// Service management

View File

@ -252,7 +252,7 @@ public final class InfoItemDialog {
* @return the current {@link Builder} instance
*/
public Builder addEnqueueEntriesIfNeeded() {
final PlayerHolder holder = PlayerHolder.getInstance();
final PlayerHolder holder = PlayerHolder.Companion.getInstance();
if (holder.isPlayQueueReady()) {
addEntry(StreamDialogDefaultEntry.ENQUEUE);

View File

@ -1,385 +0,0 @@
package org.schabi.newpipe.player.helper;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.PlaybackParameters;
import org.schabi.newpipe.App;
import org.schabi.newpipe.MainActivity;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.player.PlayerService;
import org.schabi.newpipe.player.Player;
import org.schabi.newpipe.player.PlayerType;
import org.schabi.newpipe.player.event.PlayerServiceEventListener;
import org.schabi.newpipe.player.event.PlayerServiceExtendedEventListener;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.util.NavigationHelper;
import java.util.Optional;
import java.util.function.Consumer;
public final class PlayerHolder {
private PlayerHolder() {
}
private static PlayerHolder instance;
public static synchronized PlayerHolder getInstance() {
if (PlayerHolder.instance == null) {
PlayerHolder.instance = new PlayerHolder();
}
return PlayerHolder.instance;
}
private static final boolean DEBUG = MainActivity.DEBUG;
private static final String TAG = PlayerHolder.class.getSimpleName();
@Nullable private PlayerServiceExtendedEventListener listener;
private final PlayerServiceConnection serviceConnection = new PlayerServiceConnection();
private boolean bound;
@Nullable private PlayerService playerService;
private Optional<Player> getPlayer() {
return Optional.ofNullable(playerService)
.flatMap(s -> Optional.ofNullable(s.getPlayer()));
}
private Optional<PlayQueue> getPlayQueue() {
// player play queue might be null e.g. while player is starting
return getPlayer().flatMap(p -> Optional.ofNullable(p.getPlayQueue()));
}
/**
* Returns the current {@link PlayerType} of the {@link PlayerService} service,
* otherwise `null` if no service is running.
*
* @return Current PlayerType
*/
@Nullable
public PlayerType getType() {
return getPlayer().map(Player::getPlayerType).orElse(null);
}
public boolean isPlaying() {
return getPlayer().map(Player::isPlaying).orElse(false);
}
public boolean isPlayerOpen() {
return getPlayer().isPresent();
}
/**
* Use this method to only allow the user to manipulate the play queue (e.g. by enqueueing via
* the stream long press menu) when there actually is a play queue to manipulate.
* @return true only if the player is open and its play queue is ready (i.e. it is not null)
*/
public boolean isPlayQueueReady() {
return getPlayQueue().isPresent();
}
public boolean isBound() {
return bound;
}
public int getQueueSize() {
return getPlayQueue().map(PlayQueue::size).orElse(0);
}
public int getQueuePosition() {
return getPlayQueue().map(PlayQueue::getIndex).orElse(0);
}
public void setListener(@Nullable final PlayerServiceExtendedEventListener newListener) {
listener = newListener;
if (listener == null) {
return;
}
// Force reload data from service
if (playerService != null) {
listener.onServiceConnected(playerService);
startPlayerListener();
// ^ will call listener.onPlayerConnected() down the line if there is an active player
}
}
// helper to handle context in common place as using the same
// context to bind/unbind a service is crucial
private Context getCommonContext() {
return App.getInstance();
}
/**
* Connect to (and if needed start) the {@link PlayerService}
* and bind {@link PlayerServiceConnection} to it.
* If the service is already started, only set the listener.
* @param playAfterConnect If this holders service was already started,
* start playing immediately
* @param newListener set this listener
* */
public void startService(final boolean playAfterConnect,
final PlayerServiceExtendedEventListener newListener) {
if (DEBUG) {
Log.d(TAG, "startService() called with playAfterConnect=" + playAfterConnect);
}
final Context context = getCommonContext();
setListener(newListener);
if (bound) {
return;
}
// startService() can be called concurrently and it will give a random crashes
// and NullPointerExceptions inside the service because the service will be
// bound twice. Prevent it with unbinding first
unbind(context);
final Intent intent = new Intent(context, PlayerService.class);
intent.putExtra(PlayerService.SHOULD_START_FOREGROUND_EXTRA, true);
ContextCompat.startForegroundService(context, intent);
serviceConnection.doPlayAfterConnect(playAfterConnect);
bind(context);
}
public void stopService() {
if (DEBUG) {
Log.d(TAG, "stopService() called");
}
if (playerService != null) {
playerService.destroyPlayerAndStopService();
}
final Context context = getCommonContext();
unbind(context);
// destroyPlayerAndStopService() already runs the next line of code, but run it again just
// to make sure to stop the service even if playerService is null by any chance.
context.stopService(new Intent(context, PlayerService.class));
}
class PlayerServiceConnection implements ServiceConnection {
private boolean playAfterConnect = false;
/**
* @param playAfterConnection Sets the value of `playAfterConnect` to pass to the {@link
* PlayerServiceExtendedEventListener#onPlayerConnected(Player, boolean)} the next time it
* is called. The value of `playAfterConnect` will be reset to false after that.
*/
public void doPlayAfterConnect(final boolean playAfterConnection) {
this.playAfterConnect = playAfterConnection;
}
@Override
public void onServiceDisconnected(final ComponentName compName) {
if (DEBUG) {
Log.d(TAG, "Player service is disconnected");
}
final Context context = getCommonContext();
unbind(context);
}
@Override
public void onServiceConnected(final ComponentName compName, final IBinder service) {
if (DEBUG) {
Log.d(TAG, "Player service is connected");
}
final PlayerService.LocalBinder localBinder = (PlayerService.LocalBinder) service;
@Nullable final PlayerService s = localBinder.getService();
if (s == null) {
throw new IllegalArgumentException(
"PlayerService.LocalBinder.getService() must never be"
+ "null after the service connects");
}
playerService = s;
if (listener != null) {
listener.onServiceConnected(s);
getPlayer().ifPresent(p -> listener.onPlayerConnected(p, playAfterConnect));
}
startPlayerListener();
// ^ will call listener.onPlayerConnected() down the line if there is an active player
// notify the main activity that binding the service has completed, so that it can
// open the bottom mini-player
NavigationHelper.sendPlayerStartedEvent(s);
}
}
private void bind(final Context context) {
if (DEBUG) {
Log.d(TAG, "bind() called");
}
// BIND_AUTO_CREATE starts the service if it's not already running
bound = bind(context, Context.BIND_AUTO_CREATE);
if (!bound) {
context.unbindService(serviceConnection);
}
}
public void tryBindIfNeeded(final Context context) {
if (!bound) {
// flags=0 means the service will not be started if it does not already exist. In this
// case the return value is not useful, as a value of "true" does not really indicate
// that the service is going to be bound.
bind(context, 0);
}
}
private boolean bind(final Context context, final int flags) {
final Intent serviceIntent = new Intent(context, PlayerService.class);
serviceIntent.setAction(PlayerService.BIND_PLAYER_HOLDER_ACTION);
return context.bindService(serviceIntent, serviceConnection, flags);
}
private void unbind(final Context context) {
if (DEBUG) {
Log.d(TAG, "unbind() called");
}
if (bound) {
context.unbindService(serviceConnection);
bound = false;
stopPlayerListener();
playerService = null;
if (listener != null) {
listener.onPlayerDisconnected();
listener.onServiceDisconnected();
}
}
}
private void startPlayerListener() {
if (playerService != null) {
// setting the player listener will take care of calling relevant callbacks if the
// player in the service is (not) already active, also see playerStateListener below
playerService.setPlayerListener(playerStateListener);
}
getPlayer().ifPresent(p -> p.setFragmentListener(internalListener));
}
private void stopPlayerListener() {
if (playerService != null) {
playerService.setPlayerListener(null);
}
getPlayer().ifPresent(p -> p.removeFragmentListener(internalListener));
}
/**
* This listener will be held by the players created by {@link PlayerService}.
*/
private final PlayerServiceEventListener internalListener =
new PlayerServiceEventListener() {
@Override
public void onViewCreated() {
if (listener != null) {
listener.onViewCreated();
}
}
@Override
public void onFullscreenStateChanged(final boolean fullscreen) {
if (listener != null) {
listener.onFullscreenStateChanged(fullscreen);
}
}
@Override
public void onScreenRotationButtonClicked() {
if (listener != null) {
listener.onScreenRotationButtonClicked();
}
}
@Override
public void onMoreOptionsLongClicked() {
if (listener != null) {
listener.onMoreOptionsLongClicked();
}
}
@Override
public void onPlayerError(final PlaybackException error,
final boolean isCatchableException) {
if (listener != null) {
listener.onPlayerError(error, isCatchableException);
}
}
@Override
public void hideSystemUiIfNeeded() {
if (listener != null) {
listener.hideSystemUiIfNeeded();
}
}
@Override
public void onQueueUpdate(final PlayQueue queue) {
if (listener != null) {
listener.onQueueUpdate(queue);
}
}
@Override
public void onPlaybackUpdate(final int state,
final int repeatMode,
final boolean shuffled,
final PlaybackParameters parameters) {
if (listener != null) {
listener.onPlaybackUpdate(state, repeatMode, shuffled, parameters);
}
}
@Override
public void onProgressUpdate(final int currentProgress,
final int duration,
final int bufferPercent) {
if (listener != null) {
listener.onProgressUpdate(currentProgress, duration, bufferPercent);
}
}
@Override
public void onMetadataUpdate(final StreamInfo info, final PlayQueue queue) {
if (listener != null) {
listener.onMetadataUpdate(info, queue);
}
}
@Override
public void onServiceStopped() {
if (listener != null) {
listener.onServiceStopped();
}
unbind(getCommonContext());
}
};
/**
* This listener will be held by bound {@link PlayerService}s to notify of the player starting
* or stopping. This is necessary since the service outlives the player e.g. to answer Android
* Auto media browser queries.
*/
private final Consumer<Player> playerStateListener = (@Nullable final Player player) -> {
if (listener != null) {
if (player == null) {
// player.fragmentListener=null is already done by player.stopActivityBinding(),
// which is called by player.destroy(), which is in turn called by PlayerService
// before setting its player to null
listener.onPlayerDisconnected();
} else {
listener.onPlayerConnected(player, serviceConnection.playAfterConnect);
// reset the value of playAfterConnect: if it was true before, it is now "consumed"
serviceConnection.playAfterConnect = false;
player.setFragmentListener(internalListener);
}
}
};
}

View File

@ -0,0 +1,384 @@
package org.schabi.newpipe.player.helper
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import android.util.Log
import androidx.core.content.ContextCompat
import com.google.android.exoplayer2.PlaybackException
import com.google.android.exoplayer2.PlaybackParameters
import org.schabi.newpipe.App
import org.schabi.newpipe.MainActivity
import org.schabi.newpipe.extractor.stream.StreamInfo
import org.schabi.newpipe.player.Player
import org.schabi.newpipe.player.PlayerService
import org.schabi.newpipe.player.PlayerService.LocalBinder
import org.schabi.newpipe.player.PlayerType
import org.schabi.newpipe.player.event.PlayerServiceEventListener
import org.schabi.newpipe.player.event.PlayerServiceExtendedEventListener
import org.schabi.newpipe.player.playqueue.PlayQueue
import org.schabi.newpipe.util.NavigationHelper
import java.util.Optional
import java.util.function.Consumer
import java.util.function.Function
class PlayerHolder private constructor() {
private var listener: PlayerServiceExtendedEventListener? = null
private val serviceConnection = PlayerServiceConnection()
var isBound: Boolean = false
private set
private var playerService: PlayerService? = null
private val player: Optional<Player?>
get() = Optional.ofNullable<PlayerService?>(playerService)
.flatMap<Player?>(
Function { s: PlayerService? ->
Optional.ofNullable<Player?>(
s!!.player
)
}
)
private val playQueue: Optional<PlayQueue?>
get() = // player play queue might be null e.g. while player is starting
this.player.flatMap<PlayQueue?>(
Function { p: Player? ->
Optional.ofNullable<PlayQueue?>(
p!!.getPlayQueue()
)
}
)
val type: PlayerType?
/**
* Returns the current [PlayerType] of the [PlayerService] service,
* otherwise `null` if no service is running.
*
* @return Current PlayerType
*/
get() = this.player.map<PlayerType?>(Function { obj: Player? -> obj!!.getPlayerType() })
.orElse(null)
val isPlaying: Boolean
get() = this.player.map<Boolean?>(Function { obj: Player? -> obj!!.isPlaying() })
.orElse(false)
val isPlayerOpen: Boolean
get() = this.player.isPresent()
val isPlayQueueReady: Boolean
/**
* Use this method to only allow the user to manipulate the play queue (e.g. by enqueueing via
* the stream long press menu) when there actually is a play queue to manipulate.
* @return true only if the player is open and its play queue is ready (i.e. it is not null)
*/
get() = this.playQueue.isPresent()
val queueSize: Int
get() = this.playQueue.map<Int?>(Function { obj: PlayQueue? -> obj!!.size() }).orElse(0)
val queuePosition: Int
get() = this.playQueue.map<Int?>(Function { obj: PlayQueue? -> obj!!.getIndex() }).orElse(0)
fun setListener(newListener: PlayerServiceExtendedEventListener?) {
listener = newListener
if (listener == null) {
return
}
// Force reload data from service
if (playerService != null) {
listener!!.onServiceConnected(playerService!!)
startPlayerListener()
// ^ will call listener.onPlayerConnected() down the line if there is an active player
}
}
private val commonContext: Context
// helper to handle context in common place as using the same
get() = App.instance
/**
* Connect to (and if needed start) the [PlayerService]
* and bind [PlayerServiceConnection] to it.
* If the service is already started, only set the listener.
* @param playAfterConnect If this holders service was already started,
* start playing immediately
* @param newListener set this listener
*/
fun startService(
playAfterConnect: Boolean,
newListener: PlayerServiceExtendedEventListener?
) {
if (DEBUG) {
Log.d(TAG, "startService() called with playAfterConnect=" + playAfterConnect)
}
val context = this.commonContext
setListener(newListener)
if (this.isBound) {
return
}
// startService() can be called concurrently and it will give a random crashes
// and NullPointerExceptions inside the service because the service will be
// bound twice. Prevent it with unbinding first
unbind(context)
val intent = Intent(context, PlayerService::class.java)
intent.putExtra(PlayerService.SHOULD_START_FOREGROUND_EXTRA, true)
ContextCompat.startForegroundService(context, intent)
serviceConnection.doPlayAfterConnect(playAfterConnect)
bind(context)
}
fun stopService() {
if (DEBUG) {
Log.d(TAG, "stopService() called")
}
if (playerService != null) {
playerService!!.destroyPlayerAndStopService()
}
val context = this.commonContext
unbind(context)
// destroyPlayerAndStopService() already runs the next line of code, but run it again just
// to make sure to stop the service even if playerService is null by any chance.
context.stopService(Intent(context, PlayerService::class.java))
}
internal inner class PlayerServiceConnection : ServiceConnection {
internal var playAfterConnect = false
/**
* @param playAfterConnection Sets the value of [playAfterConnect] to pass to the
* [PlayerServiceExtendedEventListener.onPlayerConnected] the next time it
* is called. The value of [playAfterConnect] will be reset to false after that.
*/
fun doPlayAfterConnect(playAfterConnection: Boolean) {
this.playAfterConnect = playAfterConnection
}
override fun onServiceDisconnected(compName: ComponentName?) {
if (DEBUG) {
Log.d(TAG, "Player service is disconnected")
}
val context: Context = this@PlayerHolder.commonContext
unbind(context)
}
override fun onServiceConnected(compName: ComponentName?, service: IBinder?) {
if (DEBUG) {
Log.d(TAG, "Player service is connected")
}
val localBinder = service as LocalBinder
val s = localBinder.service
requireNotNull(s) {
(
"PlayerService.LocalBinder.getService() must never be" +
"null after the service connects"
)
}
playerService = s
if (listener != null) {
listener!!.onServiceConnected(s)
this@PlayerHolder.player.ifPresent(
Consumer { p: Player? ->
listener!!.onPlayerConnected(
p!!,
playAfterConnect
)
}
)
}
startPlayerListener()
// ^ will call listener.onPlayerConnected() down the line if there is an active player
// notify the main activity that binding the service has completed, so that it can
// open the bottom mini-player
NavigationHelper.sendPlayerStartedEvent(s)
}
}
private fun bind(context: Context) {
if (DEBUG) {
Log.d(TAG, "bind() called")
}
// BIND_AUTO_CREATE starts the service if it's not already running
this.isBound = bind(context, Context.BIND_AUTO_CREATE)
if (!this.isBound) {
context.unbindService(serviceConnection)
}
}
fun tryBindIfNeeded(context: Context) {
if (!this.isBound) {
// flags=0 means the service will not be started if it does not already exist. In this
// case the return value is not useful, as a value of "true" does not really indicate
// that the service is going to be bound.
bind(context, 0)
}
}
private fun bind(context: Context, flags: Int): Boolean {
val serviceIntent = Intent(context, PlayerService::class.java)
serviceIntent.setAction(PlayerService.BIND_PLAYER_HOLDER_ACTION)
return context.bindService(serviceIntent, serviceConnection, flags)
}
private fun unbind(context: Context) {
if (DEBUG) {
Log.d(TAG, "unbind() called")
}
if (this.isBound) {
context.unbindService(serviceConnection)
this.isBound = false
stopPlayerListener()
playerService = null
if (listener != null) {
listener!!.onPlayerDisconnected()
listener!!.onServiceDisconnected()
}
}
}
private fun startPlayerListener() {
if (playerService != null) {
// setting the player listener will take care of calling relevant callbacks if the
// player in the service is (not) already active, also see playerStateListener below
playerService!!.setPlayerListener(playerStateListener)
}
this.player.ifPresent(Consumer { p: Player? -> p!!.setFragmentListener(internalListener) })
}
private fun stopPlayerListener() {
if (playerService != null) {
playerService!!.setPlayerListener(null)
}
this.player.ifPresent(Consumer { p: Player? -> p!!.removeFragmentListener(internalListener) })
}
/**
* This listener will be held by the players created by [PlayerService].
*/
private val internalListener: PlayerServiceEventListener = object : PlayerServiceEventListener {
override fun onViewCreated() {
if (listener != null) {
listener!!.onViewCreated()
}
}
override fun onFullscreenStateChanged(fullscreen: Boolean) {
if (listener != null) {
listener!!.onFullscreenStateChanged(fullscreen)
}
}
override fun onScreenRotationButtonClicked() {
if (listener != null) {
listener!!.onScreenRotationButtonClicked()
}
}
override fun onMoreOptionsLongClicked() {
if (listener != null) {
listener!!.onMoreOptionsLongClicked()
}
}
override fun onPlayerError(
error: PlaybackException?,
isCatchableException: Boolean
) {
if (listener != null) {
listener!!.onPlayerError(error, isCatchableException)
}
}
override fun hideSystemUiIfNeeded() {
if (listener != null) {
listener!!.hideSystemUiIfNeeded()
}
}
override fun onQueueUpdate(queue: PlayQueue?) {
if (listener != null) {
listener!!.onQueueUpdate(queue)
}
}
override fun onPlaybackUpdate(
state: Int,
repeatMode: Int,
shuffled: Boolean,
parameters: PlaybackParameters?
) {
if (listener != null) {
listener!!.onPlaybackUpdate(state, repeatMode, shuffled, parameters)
}
}
override fun onProgressUpdate(
currentProgress: Int,
duration: Int,
bufferPercent: Int
) {
if (listener != null) {
listener!!.onProgressUpdate(currentProgress, duration, bufferPercent)
}
}
override fun onMetadataUpdate(info: StreamInfo?, queue: PlayQueue?) {
if (listener != null) {
listener!!.onMetadataUpdate(info, queue)
}
}
override fun onServiceStopped() {
if (listener != null) {
listener!!.onServiceStopped()
}
unbind(this@PlayerHolder.commonContext)
}
}
/**
* This listener will be held by bound [PlayerService]s to notify of the player starting
* or stopping. This is necessary since the service outlives the player e.g. to answer Android
* Auto media browser queries.
*/
private val playerStateListener = Consumer { player: Player? ->
if (listener != null) {
if (player == null) {
// player.fragmentListener=null is already done by player.stopActivityBinding(),
// which is called by player.destroy(), which is in turn called by PlayerService
// before setting its player to null
listener!!.onPlayerDisconnected()
} else {
listener!!.onPlayerConnected(player, serviceConnection.playAfterConnect)
// reset the value of playAfterConnect: if it was true before, it is now "consumed"
serviceConnection.playAfterConnect = false;
player.setFragmentListener(internalListener)
}
}
}
companion object {
private var instance: PlayerHolder? = null
@Synchronized
fun getInstance(): PlayerHolder {
if (instance == null) {
instance = PlayerHolder()
}
return instance!!
}
private val DEBUG = MainActivity.DEBUG
private val TAG: String = PlayerHolder::class.java.getSimpleName()
}
}

View File

@ -28,7 +28,7 @@ fun StreamMenu(
) {
val context = LocalContext.current
val streamViewModel = viewModel<StreamViewModel>()
val playerHolder = PlayerHolder.getInstance()
val playerHolder = PlayerHolder.Companion.getInstance()
DropdownMenu(expanded = expanded, onDismissRequest = onDismissRequest) {
if (playerHolder.isPlayQueueReady) {

View File

@ -200,7 +200,7 @@ public final class NavigationHelper {
}
public static void enqueueOnPlayer(final Context context, final PlayQueue queue) {
PlayerType playerType = PlayerHolder.getInstance().getType();
PlayerType playerType = PlayerHolder.Companion.getInstance().getType();
if (playerType == null) {
Log.e(TAG, "Enqueueing but no player is open; defaulting to background player");
playerType = PlayerType.AUDIO;
@ -211,7 +211,7 @@ public final class NavigationHelper {
/* ENQUEUE NEXT */
public static void enqueueNextOnPlayer(final Context context, final PlayQueue queue) {
PlayerType playerType = PlayerHolder.getInstance().getType();
PlayerType playerType = PlayerHolder.Companion.getInstance().getType();
if (playerType == null) {
Log.e(TAG, "Enqueueing next but no player is open; defaulting to background player");
playerType = PlayerType.AUDIO;
@ -421,13 +421,13 @@ public final class NavigationHelper {
final boolean switchingPlayers) {
final boolean autoPlay;
@Nullable final PlayerType playerType = PlayerHolder.getInstance().getType();
@Nullable final PlayerType playerType = PlayerHolder.Companion.getInstance().getType();
if (playerType == null) {
// no player open
autoPlay = PlayerHelper.isAutoplayAllowedByUser(context);
} else if (switchingPlayers) {
// switching player to main player
autoPlay = PlayerHolder.getInstance().isPlaying(); // keep play/pause state
autoPlay = PlayerHolder.Companion.getInstance().isPlaying(); // keep play/pause state
} else if (playerType == PlayerType.MAIN) {
// opening new stream while already playing in main player
autoPlay = PlayerHelper.isAutoplayAllowedByUser(context);