fix pip screen bug
This commit is contained in:
@@ -30,12 +30,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
func sceneWillResignActive(_ scene: UIScene) {
|
||||
// 键盘还在时,系统会把键盘场景挂到画中画上;连接一旦被拆掉就会报 scene 不存在。
|
||||
window?.endEditing(true)
|
||||
let defaults = UserDefaults(suiteName: "group.com.zhushenwudi.lovelivemusicplayer")
|
||||
let playing = defaults?.bool(forKey: "pipIsPlaying") ?? false
|
||||
let enabled = defaults?.bool(forKey: "desktopLyricEnabled") ?? false
|
||||
if playing && enabled {
|
||||
pipManager.manualChangePicInPic(needStart: true)
|
||||
}
|
||||
}
|
||||
|
||||
func sceneDidBecomeActive(_ scene: UIScene) {
|
||||
@@ -44,9 +38,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
let defaults = UserDefaults(suiteName: "group.com.zhushenwudi.lovelivemusicplayer")
|
||||
let playing = defaults?.bool(forKey: "pipIsPlaying") ?? false
|
||||
let enabled = defaults?.bool(forKey: "desktopLyricEnabled") ?? false
|
||||
if playing && enabled {
|
||||
pipManager.picInPicAutoOpen(nil)
|
||||
}
|
||||
pipManager.picInPicAutoOpen(enabled)
|
||||
pipManager.setPlaying(playing)
|
||||
}
|
||||
|
||||
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
|
||||
@@ -72,7 +65,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
pipManager.addScreenView(on: window)
|
||||
let enabled = UserDefaults(suiteName: "group.com.zhushenwudi.lovelivemusicplayer")?
|
||||
.bool(forKey: "desktopLyricEnabled") ?? false
|
||||
let playing = UserDefaults(suiteName: "group.com.zhushenwudi.lovelivemusicplayer")?
|
||||
.bool(forKey: "pipIsPlaying") ?? false
|
||||
pipManager.picInPicAutoOpen(enabled)
|
||||
pipManager.setPlaying(playing)
|
||||
didSetupPip = true
|
||||
}
|
||||
|
||||
@@ -91,13 +87,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
self.pipManager.picInPicAutoOpen(enabled)
|
||||
case "playing":
|
||||
let playing = (notification.userInfo?["playing"] as? String) == "true"
|
||||
if playing {
|
||||
self.pipManager.picInPicAutoOpen(nil)
|
||||
} else {
|
||||
self.pipManager.manualChangePicInPic(needStart: false)
|
||||
}
|
||||
self.pipManager.setPlaying(playing)
|
||||
case "show":
|
||||
self.pipManager.manualChangePicInPic(needStart: true)
|
||||
// PiP 需要在前台时就准备好,由系统在真正转入后台时自动启动。
|
||||
self.pipManager.picInPicAutoOpen(nil)
|
||||
case "hide":
|
||||
self.pipManager.stopPictureInPictureOnly()
|
||||
case "foreground":
|
||||
|
||||
@@ -13,8 +13,8 @@ class PipScreenManager: NSObject, @preconcurrency AVPictureInPictureControllerDe
|
||||
private let sampleHost = SampleBufferHostView()
|
||||
private var didPrepare = false
|
||||
private var wantsPip = false
|
||||
private var isOpenPicInPic = false
|
||||
private var isStartingPip = false
|
||||
private var isAutoOpenEnabled = false
|
||||
private var isPlaying = false
|
||||
private var timebase: CMTimebase?
|
||||
private var line1 = ""
|
||||
private var line2 = ""
|
||||
@@ -54,8 +54,14 @@ class PipScreenManager: NSObject, @preconcurrency AVPictureInPictureControllerDe
|
||||
}
|
||||
|
||||
func picInPicAutoOpen(_ isOpen: Bool?) {
|
||||
if let isOpen { isOpenPicInPic = isOpen }
|
||||
if isOpenPicInPic { enqueueCurrentFrame() }
|
||||
if let isOpen { isAutoOpenEnabled = isOpen }
|
||||
refreshAutomaticStartEligibility()
|
||||
if isAutoOpenEnabled { enqueueCurrentFrame() }
|
||||
}
|
||||
|
||||
func setPlaying(_ playing: Bool) {
|
||||
isPlaying = playing
|
||||
refreshAutomaticStartEligibility()
|
||||
}
|
||||
|
||||
@objc func updatePipScreenView(lyricLine1: String?, lyricLine2: String?, currentLine: Int) {
|
||||
@@ -65,19 +71,7 @@ class PipScreenManager: NSObject, @preconcurrency AVPictureInPictureControllerDe
|
||||
enqueueCurrentFrame()
|
||||
}
|
||||
|
||||
func manualChangePicInPic(needStart: Bool) {
|
||||
if needStart {
|
||||
wantsPip = true
|
||||
isOpenPicInPic = true
|
||||
pipController?.invalidatePlaybackState()
|
||||
startPipIfPossible(retries: 8)
|
||||
} else {
|
||||
stopPictureInPictureOnly()
|
||||
}
|
||||
}
|
||||
|
||||
func stopPictureInPictureOnly() {
|
||||
wantsPip = false
|
||||
if pipController?.isPictureInPictureActive == true {
|
||||
pipController?.stopPictureInPicture()
|
||||
}
|
||||
@@ -86,7 +80,6 @@ class PipScreenManager: NSObject, @preconcurrency AVPictureInPictureControllerDe
|
||||
func pictureInPictureControllerDidStartPictureInPicture(
|
||||
_ pictureInPictureController: AVPictureInPictureController
|
||||
) {
|
||||
isStartingPip = false
|
||||
if !wantsPip {
|
||||
pictureInPictureController.stopPictureInPicture()
|
||||
return
|
||||
@@ -98,7 +91,6 @@ class PipScreenManager: NSObject, @preconcurrency AVPictureInPictureControllerDe
|
||||
_ pictureInPictureController: AVPictureInPictureController,
|
||||
failedToStartPictureInPictureWithError error: Error
|
||||
) {
|
||||
isStartingPip = false
|
||||
print("PiP failed to start: \(error)")
|
||||
}
|
||||
|
||||
@@ -118,7 +110,7 @@ class PipScreenManager: NSObject, @preconcurrency AVPictureInPictureControllerDe
|
||||
func pictureInPictureControllerIsPlaybackPaused(
|
||||
_ pictureInPictureController: AVPictureInPictureController
|
||||
) -> Bool {
|
||||
!isOpenPicInPic
|
||||
!wantsPip
|
||||
}
|
||||
|
||||
func pictureInPictureController(
|
||||
@@ -153,33 +145,23 @@ class PipScreenManager: NSObject, @preconcurrency AVPictureInPictureControllerDe
|
||||
controller.requiresLinearPlayback = true
|
||||
controller.setValue(1, forKey: "controlsStyle")
|
||||
controller.delegate = self
|
||||
// 自动开启会和 sceneWillResignActive 里的手动开启抢同一次系统连接,快速上滑时连接会被拆掉。
|
||||
controller.canStartPictureInPictureAutomaticallyFromInline = false
|
||||
// 系统只会在 App 真正转入后台时自动开启;临时 inactive
|
||||
// (下拉系统界面、未完成的任务切换手势)不会误弹出桌面歌词。
|
||||
controller.canStartPictureInPictureAutomaticallyFromInline = true
|
||||
pipController = controller
|
||||
didPrepare = true
|
||||
refreshAutomaticStartEligibility()
|
||||
}
|
||||
|
||||
/// 必须在还没进后台时同步调用。启动过程中再调一次会拆掉系统连接。
|
||||
private func startPipIfPossible(retries: Int) {
|
||||
guard wantsPip, let pip = pipController else { return }
|
||||
if pip.isPictureInPictureActive || isStartingPip { return }
|
||||
guard UIApplication.shared.applicationState != .background else { return }
|
||||
guard pip.isPictureInPicturePossible else {
|
||||
if retries > 0 {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.startPipIfPossible(retries: retries - 1)
|
||||
}
|
||||
} else {
|
||||
print("PiP not possible after retries")
|
||||
}
|
||||
return
|
||||
private func refreshAutomaticStartEligibility() {
|
||||
wantsPip = isAutoOpenEnabled && isPlaying
|
||||
pipController?.invalidatePlaybackState()
|
||||
if !wantsPip {
|
||||
stopPictureInPictureOnly()
|
||||
}
|
||||
isStartingPip = true
|
||||
pip.startPictureInPicture()
|
||||
}
|
||||
|
||||
private func enqueueCurrentFrame() {
|
||||
if isStartingPip { return }
|
||||
guard didPrepare || sampleHost.superview != nil else { return }
|
||||
guard let pixelBuffer = makePixelBuffer(size: Self.renderSize) else { return }
|
||||
CVPixelBufferLockBaseAddress(pixelBuffer, [])
|
||||
|
||||
Reference in New Issue
Block a user