react-native-video/ios/Video/Features/RCTPictureInPicture.swift

90 lines
3.5 KiB
Swift

import AVFoundation
import AVKit
import Foundation
import MediaAccessibility
import React
#if os(iOS)
class RCTPictureInPicture: NSObject, AVPictureInPictureControllerDelegate {
public private(set) var _pipController: AVPictureInPictureController?
private var _onPictureInPictureEnter: (() -> Void)?
private var _onPictureInPictureExit: (() -> Void)?
private var _onRestoreUserInterfaceForPictureInPictureStop: (() -> Void)?
private var _restoreUserInterfaceForPIPStopCompletionHandler: ((Bool) -> Void)?
private var _isActive = false
init(
_ onPictureInPictureEnter: (() -> Void)? = nil,
_ onPictureInPictureExit: (() -> Void)? = nil,
_ onRestoreUserInterfaceForPictureInPictureStop: (() -> Void)? = nil
) {
_onPictureInPictureEnter = onPictureInPictureEnter
_onPictureInPictureExit = onPictureInPictureExit
_onRestoreUserInterfaceForPictureInPictureStop = onRestoreUserInterfaceForPictureInPictureStop
}
func pictureInPictureControllerDidStartPictureInPicture(_: AVPictureInPictureController) {
guard let _onPictureInPictureEnter else { return }
_onPictureInPictureEnter()
}
func pictureInPictureControllerDidStopPictureInPicture(_: AVPictureInPictureController) {
guard let _onPictureInPictureExit else { return }
_onPictureInPictureExit()
}
func pictureInPictureController(
_: AVPictureInPictureController,
restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void
) {
guard let _onRestoreUserInterfaceForPictureInPictureStop else { return }
_onRestoreUserInterfaceForPictureInPictureStop()
_restoreUserInterfaceForPIPStopCompletionHandler = completionHandler
}
func setRestoreUserInterfaceForPIPStopCompletionHandler(_ restore: Bool) {
guard let _restoreUserInterfaceForPIPStopCompletionHandler else { return }
_restoreUserInterfaceForPIPStopCompletionHandler(restore)
self._restoreUserInterfaceForPIPStopCompletionHandler = nil
}
func setupPipController(_ playerLayer: AVPlayerLayer?) {
guard let playerLayer else { return }
if !AVPictureInPictureController.isPictureInPictureSupported() { return }
// Create new controller passing reference to the AVPlayerLayer
_pipController = AVPictureInPictureController(playerLayer: playerLayer)
if #available(iOS 14.2, *) {
_pipController?.canStartPictureInPictureAutomaticallyFromInline = true
}
_pipController?.delegate = self
}
func deinitPipController() {
_pipController = nil
}
func setPictureInPicture(_ isActive: Bool) {
if _isActive == isActive {
return
}
_isActive = isActive
guard let _pipController else { return }
if _isActive && !_pipController.isPictureInPictureActive {
DispatchQueue.main.async {
_pipController.startPictureInPicture()
}
} else if !_isActive && _pipController.isPictureInPictureActive {
DispatchQueue.main.async {
_pipController.stopPictureInPicture()
}
}
}
}
#endif