mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 13:33:42 +00:00
Add basic PiP support
This commit is contained in:
parent
2dff68200d
commit
8d5a191779
@ -23,6 +23,8 @@ final class PlayerState: ObservableObject {
|
||||
let maxResolution: Stream.Resolution?
|
||||
var timeObserver: Any?
|
||||
|
||||
var playingOutsideViewController = false
|
||||
|
||||
init(_ video: Video? = nil, maxResolution: Stream.Resolution? = nil) {
|
||||
self.video = video
|
||||
self.maxResolution = maxResolution
|
||||
@ -222,6 +224,11 @@ final class PlayerState: ObservableObject {
|
||||
fileprivate func destroyPlayer() {
|
||||
logger.critical("destroying player")
|
||||
|
||||
guard !playingOutsideViewController else {
|
||||
logger.critical("cannot destroy, playing outside view controller")
|
||||
return
|
||||
}
|
||||
|
||||
player?.currentItem?.tracks.forEach { $0.assetTrack?.asset?.cancelLoading() }
|
||||
|
||||
player?.replaceCurrentItem(with: nil)
|
||||
|
@ -232,6 +232,7 @@
|
||||
37977582268922F600DD52A8 /* InvidiousAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvidiousAPI.swift; sourceTree = "<group>"; };
|
||||
3797758A2689345500DD52A8 /* Store.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Store.swift; sourceTree = "<group>"; };
|
||||
379775922689365600DD52A8 /* Array+Next.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Next.swift"; sourceTree = "<group>"; };
|
||||
37992DC726CC50BC003D4C27 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
37AAF27D26737323007FC770 /* PopularView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopularView.swift; sourceTree = "<group>"; };
|
||||
37AAF27F26737550007FC770 /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = "<group>"; };
|
||||
37AAF2892673AB89007FC770 /* ChannelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelView.swift; sourceTree = "<group>"; };
|
||||
@ -356,6 +357,14 @@
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
37992DC826CC50CD003D4C27 /* iOS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
37992DC726CC50BC003D4C27 /* Info.plist */,
|
||||
);
|
||||
path = iOS;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
37BE0BD826A214500092E2DB /* macOS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -378,6 +387,7 @@
|
||||
37D4B0BC2671614700C925CA = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
37992DC826CC50CD003D4C27 /* iOS */,
|
||||
37BE0BD826A214500092E2DB /* macOS */,
|
||||
37D4B159267164AE00C925CA /* tvOS */,
|
||||
37D4B0C12671614700C925CA /* Shared */,
|
||||
@ -1082,6 +1092,7 @@
|
||||
DEVELOPMENT_TEAM = 78Z5H3M6RJ;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = iOS/Info.plist;
|
||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||
@ -1112,6 +1123,7 @@
|
||||
DEVELOPMENT_TEAM = 78Z5H3M6RJ;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = iOS/Info.plist;
|
||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||
|
@ -6,8 +6,6 @@ final class PlayerViewController: UIViewController {
|
||||
var video: Video!
|
||||
|
||||
var playerLoaded = false
|
||||
var playingFullScreen = false
|
||||
|
||||
var player = AVPlayer()
|
||||
var playerState: PlayerState! = PlayerState()
|
||||
var playerViewController = AVPlayerViewController()
|
||||
@ -15,19 +13,19 @@ final class PlayerViewController: UIViewController {
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
if !playerLoaded {
|
||||
loadPlayer()
|
||||
}
|
||||
loadPlayer()
|
||||
|
||||
try? AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
|
||||
try? AVAudioSession.sharedInstance().setCategory(.playback, mode: .moviePlayback)
|
||||
try? AVAudioSession.sharedInstance().setActive(true)
|
||||
}
|
||||
|
||||
override func viewDidDisappear(_ animated: Bool) {
|
||||
#if os(iOS)
|
||||
if !playingFullScreen {
|
||||
if !playerState.playingOutsideViewController {
|
||||
playerViewController.player?.replaceCurrentItem(with: nil)
|
||||
playerViewController.player = nil
|
||||
|
||||
try? AVAudioSession.sharedInstance().setActive(false)
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -35,6 +33,10 @@ final class PlayerViewController: UIViewController {
|
||||
}
|
||||
|
||||
func loadPlayer() {
|
||||
guard !playerLoaded else {
|
||||
return
|
||||
}
|
||||
|
||||
playerState.player = player
|
||||
playerViewController.player = playerState.player
|
||||
playerState.loadVideo(video)
|
||||
@ -42,6 +44,16 @@ final class PlayerViewController: UIViewController {
|
||||
#if os(tvOS)
|
||||
present(playerViewController, animated: false)
|
||||
#else
|
||||
embedViewController()
|
||||
#endif
|
||||
|
||||
playerViewController.allowsPictureInPicturePlayback = true
|
||||
playerViewController.delegate = self
|
||||
playerLoaded = true
|
||||
}
|
||||
|
||||
#if !os(tvOS)
|
||||
func embedViewController() {
|
||||
playerViewController.exitsFullScreenWhenPlaybackEnds = true
|
||||
playerViewController.view.frame = view.bounds
|
||||
|
||||
@ -49,11 +61,8 @@ final class PlayerViewController: UIViewController {
|
||||
view.addSubview(playerViewController.view)
|
||||
|
||||
playerViewController.didMove(toParent: self)
|
||||
#endif
|
||||
|
||||
playerViewController.delegate = self
|
||||
playerLoaded = true
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
extension PlayerViewController: AVPlayerViewControllerDelegate {
|
||||
@ -61,8 +70,12 @@ extension PlayerViewController: AVPlayerViewControllerDelegate {
|
||||
true
|
||||
}
|
||||
|
||||
func playerViewControllerShouldAutomaticallyDismissAtPictureInPictureStart(_: AVPlayerViewController) -> Bool {
|
||||
false
|
||||
}
|
||||
|
||||
func playerViewControllerDidEndDismissalTransition(_: AVPlayerViewController) {
|
||||
playingFullScreen = false
|
||||
playerState.playingOutsideViewController = false
|
||||
dismiss(animated: false)
|
||||
}
|
||||
|
||||
@ -70,7 +83,7 @@ extension PlayerViewController: AVPlayerViewControllerDelegate {
|
||||
_: AVPlayerViewController,
|
||||
willBeginFullScreenPresentationWithAnimationCoordinator _: UIViewControllerTransitionCoordinator
|
||||
) {
|
||||
playingFullScreen = true
|
||||
playerState.playingOutsideViewController = true
|
||||
}
|
||||
|
||||
func playerViewController(
|
||||
@ -79,8 +92,16 @@ extension PlayerViewController: AVPlayerViewControllerDelegate {
|
||||
) {
|
||||
coordinator.animate(alongsideTransition: nil) { context in
|
||||
if !context.isCancelled {
|
||||
self.playingFullScreen = false
|
||||
self.playerState.playingOutsideViewController = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func playerViewControllerWillStartPictureInPicture(_: AVPlayerViewController) {
|
||||
playerState.playingOutsideViewController = true
|
||||
}
|
||||
|
||||
func playerViewControllerWillStopPictureInPicture(_: AVPlayerViewController) {
|
||||
playerState.playingOutsideViewController = false
|
||||
}
|
||||
}
|
||||
|
10
iOS/Info.plist
Normal file
10
iOS/Info.plist
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
@ -26,7 +26,7 @@ final class PlayerViewController: NSViewController {
|
||||
playerState.player = player
|
||||
playerView.player = playerState.player
|
||||
|
||||
playerView.controlsStyle = .floating
|
||||
playerView.allowsPictureInPicturePlayback = true
|
||||
playerView.showsFullScreenToggleButton = true
|
||||
|
||||
view = playerView
|
||||
|
@ -2,7 +2,9 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
Loading…
Reference in New Issue
Block a user