mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-08-22 01:58:16 +00:00
PlayerHolder: use object class to implement singleton pattern
This commit is contained in:
parent
cc3ecd4169
commit
38ed1da79e
@ -849,7 +849,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PlayerHolder.Companion.getInstance().isPlayerOpen()) {
|
||||
if (PlayerHolder.INSTANCE.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.Companion.getInstance().isPlayerOpen()) {
|
||||
&& PlayerHolder.INSTANCE.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.Companion.getInstance().tryBindIfNeeded(this);
|
||||
PlayerHolder.INSTANCE.tryBindIfNeeded(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -701,7 +701,7 @@ public class RouterActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
// ...the player is not running or in normal Video-mode/type
|
||||
final PlayerType playerType = PlayerHolder.Companion.getInstance().getType();
|
||||
final PlayerType playerType = PlayerHolder.INSTANCE.getType();
|
||||
return playerType == null || playerType == PlayerType.MAIN;
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ import org.schabi.newpipe.player.PlayerType
|
||||
import org.schabi.newpipe.player.event.OnKeyDownListener
|
||||
import org.schabi.newpipe.player.event.PlayerServiceExtendedEventListener
|
||||
import org.schabi.newpipe.player.helper.PlayerHelper
|
||||
import org.schabi.newpipe.player.helper.PlayerHolder.Companion.getInstance
|
||||
import org.schabi.newpipe.player.helper.PlayerHolder
|
||||
import org.schabi.newpipe.player.playqueue.PlayQueue
|
||||
import org.schabi.newpipe.player.playqueue.SinglePlayQueue
|
||||
import org.schabi.newpipe.player.playqueue.events.PlayQueueEvent
|
||||
@ -212,7 +212,6 @@ class VideoDetailFragment :
|
||||
private var settingsContentObserver: ContentObserver? = null
|
||||
private var playerService: PlayerService? = null
|
||||
private var player: Player? = null
|
||||
private val playerHolder = getInstance()
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Service management
|
||||
@ -367,9 +366,9 @@ class VideoDetailFragment :
|
||||
// Stop the service when user leaves the app with double back press
|
||||
// if video player is selected. Otherwise unbind
|
||||
if (activity.isFinishing() && this.isPlayerAvailable && player!!.videoPlayerSelected()) {
|
||||
playerHolder.stopService()
|
||||
PlayerHolder.stopService()
|
||||
} else {
|
||||
playerHolder.setListener(null)
|
||||
PlayerHolder.setListener(null)
|
||||
}
|
||||
|
||||
PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
@ -768,10 +767,10 @@ class VideoDetailFragment :
|
||||
)
|
||||
|
||||
setupBottomPlayer()
|
||||
if (!playerHolder.isBound) {
|
||||
if (!PlayerHolder.isBound) {
|
||||
setHeightThumbnail()
|
||||
} else {
|
||||
playerHolder.startService(false, this)
|
||||
PlayerHolder.startService(false, this)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1175,7 +1174,7 @@ class VideoDetailFragment :
|
||||
|
||||
// See UI changes while remote playQueue changes
|
||||
if (!this.isPlayerAvailable) {
|
||||
playerHolder.startService(false, this)
|
||||
PlayerHolder.startService(false, this)
|
||||
} else {
|
||||
// FIXME Workaround #7427
|
||||
player!!.setRecovery()
|
||||
@ -1245,7 +1244,7 @@ class VideoDetailFragment :
|
||||
private fun openNormalBackgroundPlayer(append: Boolean) {
|
||||
// See UI changes while remote playQueue changes
|
||||
if (!this.isPlayerAvailable) {
|
||||
playerHolder.startService(false, this)
|
||||
PlayerHolder.startService(false, this)
|
||||
}
|
||||
|
||||
val queue = setupPlayQueueForIntent(append)
|
||||
@ -1263,7 +1262,7 @@ class VideoDetailFragment :
|
||||
|
||||
private fun openMainPlayer() {
|
||||
if (noPlayerServiceAvailable()) {
|
||||
playerHolder.startService(autoPlayEnabled, this)
|
||||
PlayerHolder.startService(autoPlayEnabled, this)
|
||||
return
|
||||
}
|
||||
if (currentInfo == null) {
|
||||
@ -1298,7 +1297,7 @@ class VideoDetailFragment :
|
||||
playerService!!.stopForImmediateReusing()
|
||||
root.ifPresent(Consumer { view: View -> view.setVisibility(View.GONE) })
|
||||
} else {
|
||||
playerHolder.stopService()
|
||||
PlayerHolder.stopService()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1551,8 +1550,8 @@ class VideoDetailFragment :
|
||||
bottomSheetBehavior!!.setState(BottomSheetBehavior.STATE_COLLAPSED)
|
||||
}
|
||||
// Rebound to the service if it was closed via notification or mini player
|
||||
if (!playerHolder.isBound) {
|
||||
playerHolder.startService(
|
||||
if (!PlayerHolder.isBound) {
|
||||
PlayerHolder.startService(
|
||||
false, this@VideoDetailFragment
|
||||
)
|
||||
}
|
||||
@ -2472,7 +2471,7 @@ class VideoDetailFragment :
|
||||
if (currentWorker != null) {
|
||||
currentWorker!!.dispose()
|
||||
}
|
||||
playerHolder.stopService()
|
||||
PlayerHolder.stopService()
|
||||
setInitialData(0, null, "", null)
|
||||
currentInfo = null
|
||||
updateOverlayData(null, null, mutableListOf<Image>())
|
||||
|
@ -252,7 +252,7 @@ public final class InfoItemDialog {
|
||||
* @return the current {@link Builder} instance
|
||||
*/
|
||||
public Builder addEnqueueEntriesIfNeeded() {
|
||||
final PlayerHolder holder = PlayerHolder.Companion.getInstance();
|
||||
final PlayerHolder holder = PlayerHolder.INSTANCE;
|
||||
if (holder.isPlayQueueReady()) {
|
||||
addEntry(StreamDialogDefaultEntry.ENQUEUE);
|
||||
|
||||
|
@ -22,12 +22,19 @@ import org.schabi.newpipe.player.playqueue.PlayQueue
|
||||
import org.schabi.newpipe.util.NavigationHelper
|
||||
import java.util.function.Consumer
|
||||
|
||||
class PlayerHolder private constructor() {
|
||||
private val DEBUG = MainActivity.DEBUG
|
||||
private val TAG: String = PlayerHolder::class.java.getSimpleName()
|
||||
|
||||
/**
|
||||
* Singleton that manages a `PlayerService`
|
||||
* and can be used to control the player instance through the service.
|
||||
*/
|
||||
object PlayerHolder {
|
||||
private var listener: PlayerServiceExtendedEventListener? = null
|
||||
|
||||
private val serviceConnection = PlayerServiceConnection()
|
||||
var isBound: Boolean = false
|
||||
private set
|
||||
|
||||
private var playerService: PlayerService? = null
|
||||
|
||||
private val player: Player?
|
||||
@ -110,7 +117,7 @@ class PlayerHolder private constructor() {
|
||||
val intent = Intent(context, PlayerService::class.java)
|
||||
intent.putExtra(PlayerService.SHOULD_START_FOREGROUND_EXTRA, true)
|
||||
ContextCompat.startForegroundService(context, intent)
|
||||
serviceConnection.doPlayAfterConnect(playAfterConnect)
|
||||
PlayerServiceConnection.doPlayAfterConnect(playAfterConnect)
|
||||
bind(context)
|
||||
}
|
||||
|
||||
@ -126,7 +133,7 @@ class PlayerHolder private constructor() {
|
||||
context.stopService(Intent(context, PlayerService::class.java))
|
||||
}
|
||||
|
||||
internal inner class PlayerServiceConnection : ServiceConnection {
|
||||
internal object PlayerServiceConnection : ServiceConnection {
|
||||
internal var playAfterConnect = false
|
||||
|
||||
/**
|
||||
@ -185,7 +192,7 @@ class PlayerHolder private constructor() {
|
||||
// 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)
|
||||
context.unbindService(PlayerServiceConnection)
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,7 +208,7 @@ class PlayerHolder private constructor() {
|
||||
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)
|
||||
return context.bindService(serviceIntent, PlayerServiceConnection, flags)
|
||||
}
|
||||
|
||||
private fun unbind(context: Context) {
|
||||
@ -210,7 +217,7 @@ class PlayerHolder private constructor() {
|
||||
}
|
||||
|
||||
if (this.isBound) {
|
||||
context.unbindService(serviceConnection)
|
||||
context.unbindService(PlayerServiceConnection)
|
||||
this.isBound = false
|
||||
stopPlayerListener()
|
||||
playerService = null
|
||||
@ -223,18 +230,18 @@ class PlayerHolder private constructor() {
|
||||
// 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?.setFragmentListener(internalListener)
|
||||
this.player?.setFragmentListener(HolderPlayerServiceEventListener)
|
||||
}
|
||||
|
||||
private fun stopPlayerListener() {
|
||||
playerService?.setPlayerListener(null)
|
||||
this.player?.removeFragmentListener(internalListener)
|
||||
this.player?.removeFragmentListener(HolderPlayerServiceEventListener)
|
||||
}
|
||||
|
||||
/**
|
||||
* This listener will be held by the players created by [PlayerService].
|
||||
*/
|
||||
private val internalListener: PlayerServiceEventListener = object : PlayerServiceEventListener {
|
||||
private object HolderPlayerServiceEventListener : PlayerServiceEventListener {
|
||||
override fun onViewCreated() {
|
||||
listener?.onViewCreated()
|
||||
}
|
||||
@ -307,26 +314,11 @@ class PlayerHolder private constructor() {
|
||||
// before setting its player to null
|
||||
l.onPlayerDisconnected()
|
||||
} else {
|
||||
l.onPlayerConnected(player, serviceConnection.playAfterConnect)
|
||||
l.onPlayerConnected(player, PlayerServiceConnection.playAfterConnect)
|
||||
// reset the value of playAfterConnect: if it was true before, it is now "consumed"
|
||||
serviceConnection.playAfterConnect = false;
|
||||
player.setFragmentListener(internalListener)
|
||||
PlayerServiceConnection.playAfterConnect = false
|
||||
player.setFragmentListener(HolderPlayerServiceEventListener)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
@ -28,10 +28,9 @@ fun StreamMenu(
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val streamViewModel = viewModel<StreamViewModel>()
|
||||
val playerHolder = PlayerHolder.Companion.getInstance()
|
||||
|
||||
DropdownMenu(expanded = expanded, onDismissRequest = onDismissRequest) {
|
||||
if (playerHolder.isPlayQueueReady) {
|
||||
if (PlayerHolder.isPlayQueueReady) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(text = stringResource(R.string.enqueue_stream)) },
|
||||
onClick = {
|
||||
@ -42,7 +41,7 @@ fun StreamMenu(
|
||||
}
|
||||
)
|
||||
|
||||
if (playerHolder.queuePosition < playerHolder.queueSize - 1) {
|
||||
if (PlayerHolder.queuePosition < PlayerHolder.queueSize - 1) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(text = stringResource(R.string.enqueue_next_stream)) },
|
||||
onClick = {
|
||||
|
@ -200,7 +200,7 @@ public final class NavigationHelper {
|
||||
}
|
||||
|
||||
public static void enqueueOnPlayer(final Context context, final PlayQueue queue) {
|
||||
PlayerType playerType = PlayerHolder.Companion.getInstance().getType();
|
||||
PlayerType playerType = PlayerHolder.INSTANCE.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.Companion.getInstance().getType();
|
||||
PlayerType playerType = PlayerHolder.INSTANCE.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.Companion.getInstance().getType();
|
||||
@Nullable final PlayerType playerType = PlayerHolder.INSTANCE.getType();
|
||||
if (playerType == null) {
|
||||
// no player open
|
||||
autoPlay = PlayerHelper.isAutoplayAllowedByUser(context);
|
||||
} else if (switchingPlayers) {
|
||||
// switching player to main player
|
||||
autoPlay = PlayerHolder.Companion.getInstance().isPlaying(); // keep play/pause state
|
||||
autoPlay = PlayerHolder.INSTANCE.isPlaying(); // keep play/pause state
|
||||
} else if (playerType == PlayerType.MAIN) {
|
||||
// opening new stream while already playing in main player
|
||||
autoPlay = PlayerHelper.isAutoplayAllowedByUser(context);
|
||||
|
Loading…
x
Reference in New Issue
Block a user