Add Open in PiP option (fix #137)

This commit is contained in:
Arkadiusz Fal 2022-05-29 16:38:37 +02:00
parent 3b1f6b21f3
commit 9abba2d19c
5 changed files with 61 additions and 22 deletions

View File

@ -37,6 +37,9 @@ final class PiPDelegate: NSObject, AVPictureInPictureControllerDelegate {
_: AVPictureInPictureController, _: AVPictureInPictureController,
restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void
) { ) {
completionHandler(true) player?.show()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
completionHandler(true)
}
} }
} }

View File

@ -109,6 +109,29 @@ final class PlayerControlsModel: ObservableObject {
} }
} }
func startPiP(startImmediately: Bool = true) {
if player.activeBackend == .mpv {
player.avPlayerBackend.switchToMPVOnPipClose = true
}
#if !os(macOS)
player.exitFullScreen()
#endif
if player.activeBackend != PlayerBackendType.appleAVPlayer {
player.saveTime { [weak player] in
player?.changeActiveBackend(from: .mpv, to: .appleAVPlayer)
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { [weak player] in
player?.avPlayerBackend.startPictureInPictureOnPlay = true
if startImmediately {
player?.pipController?.startPictureInPicture()
}
}
}
func removeTimer() { func removeTimer() {
timer?.invalidate() timer?.invalidate()
timer = nil timer = nil

View File

@ -205,7 +205,7 @@ final class PlayerModel: ObservableObject {
backend.pause() backend.pause()
} }
func play(_ video: Video, at time: CMTime? = nil) { func play(_ video: Video, at time: CMTime? = nil, showingPlayer: Bool = true) {
var delay = 0.0 var delay = 0.0
#if !os(macOS) #if !os(macOS)
delay = 0.3 delay = 0.3
@ -223,7 +223,9 @@ final class PlayerModel: ObservableObject {
return return
} }
show() if showingPlayer {
show()
}
} }
func playStream( func playStream(
@ -268,6 +270,7 @@ final class PlayerModel: ObservableObject {
func saveTime(completionHandler: @escaping () -> Void = {}) { func saveTime(completionHandler: @escaping () -> Void = {}) {
guard let currentTime = backend.currentTime, currentTime.seconds > 0 else { guard let currentTime = backend.currentTime, currentTime.seconds > 0 else {
completionHandler()
return return
} }
@ -341,6 +344,10 @@ final class PlayerModel: ObservableObject {
} }
func changeActiveBackend(from: PlayerBackendType, to: PlayerBackendType) { func changeActiveBackend(from: PlayerBackendType, to: PlayerBackendType) {
guard activeBackend != to else {
return
}
Defaults[.activeBackend] = to Defaults[.activeBackend] = to
self.activeBackend = to self.activeBackend = to

View File

@ -265,25 +265,7 @@ struct PlayerControls: View {
private var pipButton: some View { private var pipButton: some View {
button("PiP", systemImage: "pip") { button("PiP", systemImage: "pip") {
if player.activeBackend == .mpv { model.startPiP()
player.avPlayerBackend.switchToMPVOnPipClose = true
}
#if !os(macOS)
player.exitFullScreen()
#endif
if player.activeBackend != PlayerBackendType.appleAVPlayer {
player.saveTime {
player.changeActiveBackend(from: .mpv, to: .appleAVPlayer)
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
print(player.pipController?.isPictureInPicturePossible ?? false ? "possible" : "NOT possible")
player.avPlayerBackend.startPictureInPictureOnPlay = true
player.pipController?.startPictureInPicture()
}
} }
} }

View File

@ -1,4 +1,5 @@
import CoreData import CoreData
import CoreMedia
import Defaults import Defaults
import SwiftUI import SwiftUI
@ -53,6 +54,9 @@ struct VideoContextMenuView: View {
Section { Section {
playNowButton playNowButton
#if os(iOS)
playNowInPictureInPictureButton
#endif
} }
Section { Section {
@ -133,6 +137,26 @@ struct VideoContextMenuView: View {
} }
} }
private var playNowInPictureInPictureButton: some View {
Button {
player.controls.startPiP(startImmediately: false)
var time: CMTime?
if saveHistory,
let stoppedAt = watch?.stoppedAt,
!watch!.finished
{
time = .secondsInDefaultTimescale(stoppedAt)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
player.play(video, at: time, showingPlayer: false)
}
} label: {
Label("Play in PiP", systemImage: "pip")
}
}
private var playNextButton: some View { private var playNextButton: some View {
Button { Button {
player.playNext(video) player.playNext(video)