MiniPlayer/Sources/PiPController.swift

95 lines
3.4 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Foundation
import AVKit
import Combine
#if os(iOS)
/// Picture-in-Picture
/// AVPictureInPictureController PiP
@MainActor
final class PiPController: NSObject, ObservableObject {
@Published var isPiPActive = false
@Published var isPiPSupported = false
private var pipController: AVPictureInPictureController?
private weak var playerLayer: AVPlayerLayer?
/// AVPlayerLayer PiP
func setup(with playerLayer: AVPlayerLayer) {
self.playerLayer = playerLayer
guard AVPictureInPictureController.isPictureInPictureSupported() else {
NSLog("[MiniPlayer] PiP not supported on this device")
isPiPSupported = false
return
}
isPiPSupported = true
let pip = AVPictureInPictureController(playerLayer: playerLayer)
pip?.delegate = self
self.pipController = pip
NSLog("[MiniPlayer] PiP controller initialized")
}
///
func togglePiP() {
guard let pip = pipController else {
NSLog("[MiniPlayer] PiP controller not initialized")
return
}
if pip.isPictureInPictureActive {
pip.stopPictureInPicture()
} else if pip.isPictureInPicturePossible {
pip.startPictureInPicture()
} else {
NSLog("[MiniPlayer] PiP not possible right now (player may not be ready)")
}
}
/// PiP
var canStartPiP: Bool {
pipController?.isPictureInPicturePossible ?? false
}
deinit {
pipController?.delegate = nil
}
}
// MARK: - AVPictureInPictureControllerDelegate
extension PiPController: AVPictureInPictureControllerDelegate {
nonisolated func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
NSLog("[MiniPlayer] PiP will start")
Task { @MainActor in self.isPiPActive = true }
}
nonisolated func pictureInPictureControllerDidStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
NSLog("[MiniPlayer] PiP did start")
}
nonisolated func pictureInPictureControllerWillStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
NSLog("[MiniPlayer] PiP will stop")
}
nonisolated func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
NSLog("[MiniPlayer] PiP did stop")
Task { @MainActor in self.isPiPActive = false }
}
nonisolated func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, failedToStartPictureInPictureWithError error: Error) {
NSLog("[MiniPlayer] PiP failed to start: \(error.localizedDescription)")
}
nonisolated func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {
// PiP
// true app
NSLog("[MiniPlayer] PiP restore requested")
completionHandler(true)
}
}
#endif