Addressed review comments

This commit is contained in:
Siddhesh Naik 2024-12-07 02:08:06 +05:30
parent c8ccc60047
commit 9d750edf5f
3 changed files with 36 additions and 42 deletions

View File

@ -45,7 +45,6 @@ import static org.schabi.newpipe.player.notification.NotificationConstants.ACTIO
import static org.schabi.newpipe.util.ListHelper.getPopupResolutionIndex; import static org.schabi.newpipe.util.ListHelper.getPopupResolutionIndex;
import static org.schabi.newpipe.util.ListHelper.getResolutionIndex; import static org.schabi.newpipe.util.ListHelper.getResolutionIndex;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
@ -87,8 +86,8 @@ import org.schabi.newpipe.databinding.PlayerBinding;
import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.ErrorInfo;
import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.ErrorUtil;
import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.Image; import org.schabi.newpipe.extractor.Image;
import org.schabi.newpipe.extractor.stream.AudioStream;
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.extractor.stream.VideoStream; import org.schabi.newpipe.extractor.stream.VideoStream;
@ -119,9 +118,9 @@ import org.schabi.newpipe.player.ui.VideoPlayerUi;
import org.schabi.newpipe.util.DependentPreferenceHelper; import org.schabi.newpipe.util.DependentPreferenceHelper;
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.image.PicassoHelper;
import org.schabi.newpipe.util.SerializedCache; import org.schabi.newpipe.util.SerializedCache;
import org.schabi.newpipe.util.StreamTypeUtil; import org.schabi.newpipe.util.StreamTypeUtil;
import org.schabi.newpipe.util.image.PicassoHelper;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -416,9 +415,12 @@ public final class Player implements PlaybackListener, Listener {
== com.google.android.exoplayer2.Player.STATE_IDLE) { == com.google.android.exoplayer2.Player.STATE_IDLE) {
simpleExoPlayer.prepare(); simpleExoPlayer.prepare();
} }
// Seeks to a specific index and position in the player if the queue index has changed.
if (playQueue.getIndex() != newQueue.getIndex()) { if (playQueue.getIndex() != newQueue.getIndex()) {
simpleExoPlayer.seekTo(newQueue.getIndex(), final PlayQueueItem queueItem = newQueue.getItem();
requireNonNull(newQueue.getItem()).getRecoveryPosition()); if (queueItem != null) {
simpleExoPlayer.seekTo(newQueue.getIndex(), queueItem.getRecoveryPosition());
}
} }
simpleExoPlayer.setPlayWhenReady(playWhenReady); simpleExoPlayer.setPlayWhenReady(playWhenReady);

View File

@ -39,28 +39,18 @@ import java.lang.ref.WeakReference
* One service for all players. * One service for all players.
*/ */
class PlayerService : MediaBrowserServiceCompat() { class PlayerService : MediaBrowserServiceCompat() {
private val player: Player by lazy { private var player: Player? = null
Player(this).apply {
/*
Create the player notification and start immediately the service in foreground,
otherwise if nothing is played or initializing the player and its components (especially
loading stream metadata) takes a lot of time, the app would crash on Android 8+ as the
service would never be put in the foreground while we said to the system we would do so
*/
UIs()[NotificationPlayerUi::class.java].ifPresent {
it.createNotificationAndStartForeground()
}
}
}
private val mBinder: IBinder = LocalBinder(this) private val mBinder: IBinder = LocalBinder(this)
private val compositeDisposableLoadChildren = CompositeDisposable() private val disposables = CompositeDisposable()
private var mediaBrowserConnector: MediaBrowserConnector? = null private var _mediaBrowserConnector: MediaBrowserConnector? = null
private val mediaBrowserConnector: MediaBrowserConnector
get() { get() {
if (field == null) { return _mediaBrowserConnector ?: run {
field = MediaBrowserConnector(this) val newMediaBrowserConnector = MediaBrowserConnector(this)
_mediaBrowserConnector = newMediaBrowserConnector
newMediaBrowserConnector
} }
return field
} }
val sessionConnector: MediaSessionConnector? val sessionConnector: MediaSessionConnector?
@ -78,13 +68,14 @@ class PlayerService : MediaBrowserServiceCompat() {
Localization.assureCorrectAppLanguage(this) Localization.assureCorrectAppLanguage(this)
ThemeHelper.setTheme(this) ThemeHelper.setTheme(this)
player = Player(this)
/* /*
Create the player notification and start immediately the service in foreground, Create the player notification and start immediately the service in foreground,
otherwise if nothing is played or initializing the player and its components (especially otherwise if nothing is played or initializing the player and its components (especially
loading stream metadata) takes a lot of time, the app would crash on Android 8+ as the loading stream metadata) takes a lot of time, the app would crash on Android 8+ as the
service would never be put in the foreground while we said to the system we would do so service would never be put in the foreground while we said to the system we would do so
*/ */
player.UIs()[NotificationPlayerUi::class.java].ifPresent { player!!.UIs()[NotificationPlayerUi::class.java].ifPresent {
it.createNotificationAndStartForeground() it.createNotificationAndStartForeground()
} }
} }
@ -112,11 +103,11 @@ class PlayerService : MediaBrowserServiceCompat() {
If the service is already started in foreground, requesting it to be started shouldn't If the service is already started in foreground, requesting it to be started shouldn't
do anything do anything
*/ */
player.UIs()[NotificationPlayerUi::class.java].ifPresent { player?.UIs()?.get(NotificationPlayerUi::class.java)?.ifPresent {
it.createNotificationAndStartForeground() it.createNotificationAndStartForeground()
} }
if (Intent.ACTION_MEDIA_BUTTON == intent.action && (player.playQueue == null)) { if (Intent.ACTION_MEDIA_BUTTON == intent.action && (player?.playQueue == null)) {
/* /*
No need to process media button's actions if the player is not working, otherwise No need to process media button's actions if the player is not working, otherwise
the player service would strangely start with nothing to play the player service would strangely start with nothing to play
@ -127,8 +118,8 @@ class PlayerService : MediaBrowserServiceCompat() {
return START_NOT_STICKY return START_NOT_STICKY
} }
player.handleIntent(intent) player?.handleIntent(intent)
player.UIs()[MediaSessionPlayerUi::class.java].ifPresent { player?.UIs()?.get(MediaSessionPlayerUi::class.java)?.ifPresent {
it.handleMediaButtonIntent(intent) it.handleMediaButtonIntent(intent)
} }
@ -140,17 +131,17 @@ class PlayerService : MediaBrowserServiceCompat() {
Log.d(TAG, "stopForImmediateReusing() called") Log.d(TAG, "stopForImmediateReusing() called")
} }
if (!player.exoPlayerIsNull()) { if (player != null && !player!!.exoPlayerIsNull()) {
// Releases wifi & cpu, disables keepScreenOn, etc. // Releases wifi & cpu, disables keepScreenOn, etc.
// We can't just pause the player here because it will make transition // We can't just pause the player here because it will make transition
// from one stream to a new stream not smooth // from one stream to a new stream not smooth
player.smoothStopForImmediateReusing() player?.smoothStopForImmediateReusing()
} }
} }
override fun onTaskRemoved(rootIntent: Intent) { override fun onTaskRemoved(rootIntent: Intent) {
super.onTaskRemoved(rootIntent) super.onTaskRemoved(rootIntent)
if (!player.videoPlayerSelected()) { if (player != null && !player!!.videoPlayerSelected()) {
return return
} }
onDestroy() onDestroy()
@ -166,14 +157,15 @@ class PlayerService : MediaBrowserServiceCompat() {
cleanup() cleanup()
mediaBrowserConnector?.release() mediaBrowserConnector.release()
mediaBrowserConnector = null _mediaBrowserConnector = null
compositeDisposableLoadChildren.clear() disposables.clear()
} }
private fun cleanup() { private fun cleanup() {
player.destroy() player?.destroy()
player = null
} }
fun stopService() { fun stopService() {
@ -187,7 +179,7 @@ class PlayerService : MediaBrowserServiceCompat() {
override fun onBind(intent: Intent): IBinder = mBinder override fun onBind(intent: Intent): IBinder = mBinder
// MediaBrowserServiceCompat methods // MediaBrowserServiceCompat methods (they defer function calls to mediaBrowserConnector)
override fun onGetRoot( override fun onGetRoot(
clientPackageName: String, clientPackageName: String,
clientUid: Int, clientUid: Int,
@ -204,7 +196,7 @@ class PlayerService : MediaBrowserServiceCompat() {
it.onLoadChildren(parentId).subscribe { mediaItems -> it.onLoadChildren(parentId).subscribe { mediaItems ->
result.sendResult(mediaItems) result.sendResult(mediaItems)
} }
compositeDisposableLoadChildren.add(disposable) disposables.add(disposable)
} }
} }

View File

@ -125,20 +125,20 @@ class MediaBrowserConnector(
private fun createPlaylistMediaItem(playlist: PlaylistLocalItem): MediaBrowserCompat.MediaItem { private fun createPlaylistMediaItem(playlist: PlaylistLocalItem): MediaBrowserCompat.MediaItem {
val builder = MediaDescriptionCompat.Builder() val builder = MediaDescriptionCompat.Builder()
val isRemote = playlist is PlaylistRemoteEntity builder
builder.setMediaId(createMediaIdForInfoItem(isRemote, playlist.uid)) .setMediaId(createMediaIdForInfoItem(playlist is PlaylistRemoteEntity, playlist.uid))
.setTitle(playlist.orderingName) .setTitle(playlist.orderingName)
.setIconUri(Uri.parse(playlist.thumbnailUrl)) .setIconUri(playlist.thumbnailUrl?.let { Uri.parse(it) })
val extras = Bundle() val extras = Bundle()
extras.putString( extras.putString(
MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE,
playerService.resources.getString(R.string.tab_bookmarks) playerService.resources.getString(R.string.tab_bookmarks),
) )
builder.setExtras(extras) builder.setExtras(extras)
return MediaBrowserCompat.MediaItem( return MediaBrowserCompat.MediaItem(
builder.build(), builder.build(),
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE MediaBrowserCompat.MediaItem.FLAG_BROWSABLE,
) )
} }