fix picture in picture

Signed-off-by: Toni Förster <toni.foerster@gmail.com>
This commit is contained in:
Toni Förster 2024-09-02 22:40:48 +02:00
parent 2d7a101ce0
commit d56ef74a99
No known key found for this signature in database
GPG Key ID: 292F3E5086C83FC7
3 changed files with 38 additions and 41 deletions

View File

@ -679,38 +679,24 @@ final class PlayerModel: ObservableObject {
avPlayerBackend.startPictureInPictureOnPlay = false avPlayerBackend.startPictureInPictureOnPlay = false
avPlayerBackend.startPictureInPictureOnSwitch = false avPlayerBackend.startPictureInPictureOnSwitch = false
if activeBackend == .appleAVPlayer { guard activeBackend != .appleAVPlayer else {
avPlayerBackend.tryStartingPictureInPicture() avPlayerBackend.tryStartingPictureInPicture()
return return
} }
// First, we need to create an array with supported formats. avPlayerBackend.startPictureInPictureOnSwitch = true
let formatOrderPiP: [QualityProfile.Format] = [.stream, .hls]
guard let video = currentVideo else { return } saveTime {
guard let stream = avPlayerBackend.bestPlayable(availableStreams, maxResolution: .hd720p30, formatOrder: formatOrderPiP) else { return } self.changeActiveBackend(from: .mpv, to: .appleAVPlayer)
_ = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] timer in
if avPlayerBackend.video == video { if let pipController = self?.pipController, pipController.isPictureInPictureActive, self?.avPlayerBackend.isPlaying == true {
if activeBackend != .appleAVPlayer { self?.exitFullScreen()
avPlayerBackend.startPictureInPictureOnSwitch = true self?.controls.objectWillChange.send()
} timer.invalidate()
changeActiveBackend(from: activeBackend, to: .appleAVPlayer) } else if self?.activeBackend == .appleAVPlayer, self?.avPlayerBackend.startPictureInPictureOnSwitch == false {
} else { self?.avPlayerBackend.startPictureInPictureOnSwitch = true
avPlayerBackend.startPictureInPictureOnPlay = true self?.avPlayerBackend.tryStartingPictureInPicture()
playStream(stream, of: video, preservingTime: true, upgrading: true, withBackend: avPlayerBackend) }
}
var retryCount = 0
_ = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] timer in
if let pipController = self?.pipController, pipController.isPictureInPictureActive, self?.avPlayerBackend.isPlaying == true {
self?.exitFullScreen()
self?.controls.objectWillChange.send()
timer.invalidate()
} else if retryCount < 3, self?.activeBackend == .appleAVPlayer, self?.avPlayerBackend.startPictureInPictureOnSwitch == false {
// If PiP didn't start, try starting it again up to 3 times,
self?.avPlayerBackend.startPictureInPictureOnSwitch = true
self?.avPlayerBackend.tryStartingPictureInPicture()
retryCount += 1
} }
} }
} }
@ -740,19 +726,27 @@ final class PlayerModel: ObservableObject {
show() show()
#endif #endif
if previousActiveBackend == .mpv { avPlayerBackend.closePiP()
saveTime { _ = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] timer in
self.changeActiveBackend(from: self.activeBackend, to: .mpv, isInClosePip: true) if self?.activeBackend == .appleAVPlayer, self?.avPlayerBackend.isPlaying == true, self?.playingInPictureInPicture == false {
_ = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] timer in timer.invalidate()
if self?.activeBackend == .mpv, self?.mpvBackend.isPlaying == true { }
self?.backend.closePiP() }
self?.controls.resetTimer()
timer.invalidate() guard previousActiveBackend == .mpv else { return }
}
saveTime {
self.changeActiveBackend(from: .appleAVPlayer, to: .mpv, isInClosePip: true)
_ = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] timer in
if self?.activeBackend == .mpv, self?.mpvBackend.isPlaying == true {
timer.invalidate()
} }
} }
} else { }
backend.closePiP()
// We need to remove the itme from the player, if not it will be displayed when next video goe to PiP.
Delay.by(1.0) {
self.avPlayerBackend.closeItem()
} }
} }
@ -999,7 +993,10 @@ final class PlayerModel: ObservableObject {
} }
show() show()
closePiP() // Needs to be delayed a bit, otherwise the PiP windows stays open
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
self?.closePiP()
}
} }
func handleEnterBackground() { func handleEnterBackground() {

View File

@ -383,7 +383,7 @@ struct PlayerControls: View {
} }
private var pipButton: some View { private var pipButton: some View {
button("PiP", systemImage: player.pipImage, action: player.togglePiPAction) button("PiP", systemImage: player.pipImage, active: player.playingInPictureInPicture, action: player.togglePiPAction)
.disabled(!player.pipPossible) .disabled(!player.pipPossible)
} }

View File

@ -155,7 +155,7 @@ struct VideoActions: View {
case .fullScreen: case .fullScreen:
actionButton("Fullscreen", systemImage: player.fullscreenImage, action: player.toggleFullScreenAction) actionButton("Fullscreen", systemImage: player.fullscreenImage, action: player.toggleFullScreenAction)
case .pip: case .pip:
actionButton("PiP", systemImage: player.pipImage, action: player.togglePiPAction) actionButton("PiP", systemImage: player.pipImage, active: player.playingInPictureInPicture, action: player.togglePiPAction)
#if os(iOS) #if os(iOS)
case .lockOrientation: case .lockOrientation:
actionButton("Lock", systemImage: player.lockOrientationImage, active: player.lockedOrientation != nil, action: player.lockOrientationAction) actionButton("Lock", systemImage: player.lockOrientationImage, active: player.lockedOrientation != nil, action: player.lockOrientationAction)