@@ -12,7 +12,7 @@ import MediaPlayer
1212import AVFoundation
1313import MarqueeLabel
1414
15- class CustomMediaPlayerViewController : UIViewController , UIGestureRecognizerDelegate {
15+ class CustomMediaPlayerViewController : UIViewController , UIGestureRecognizerDelegate , AVPlayerViewControllerDelegate {
1616 private var airplayButton : AVRoutePickerView !
1717 let module : ScrapingModule
1818 let streamURL : String
@@ -68,21 +68,13 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
6868 return UserDefaults . standard. bool ( forKey: " doubleTapSeekEnabled " )
6969 }
7070
71- private var isPipButtonVisible : Bool {
72- if UserDefaults . standard. object ( forKey: " pipButtonVisible " ) == nil {
73- return true
74- }
75- return UserDefaults . standard. bool ( forKey: " pipButtonVisible " )
76- }
77-
7871 private var isAutoplayEnabled : Bool {
7972 if UserDefaults . standard. object ( forKey: " autoplayNext " ) == nil {
8073 return true
8174 }
8275 return UserDefaults . standard. bool ( forKey: " autoplayNext " )
8376 }
8477 private var pipController : AVPictureInPictureController ?
85- private var pipButton : UIButton !
8678
8779 var portraitButtonVisibleConstraints : [ NSLayoutConstraint ] = [ ]
8880 var portraitButtonHiddenConstraints : [ NSLayoutConstraint ] = [ ]
@@ -187,7 +179,6 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
187179 skip85Button,
188180 controlButtonsContainer,
189181 volumeSliderHostingView,
190- pipButton,
191182 airplayButton,
192183 timeBatteryContainer,
193184 endTimeIcon,
@@ -207,7 +198,7 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
207198
208199 views. append ( contentsOf: view. subviews. filter {
209200 $0 is UIVisualEffectView ||
210- ( $0. layer. cornerRadius > 0 && $0 != dismissButton && $0 != lockButton && $0 != dimButton && $0 != pipButton && $0 != holdSpeedIndicator && $0 != volumeSliderHostingView)
201+ ( $0. layer. cornerRadius > 0 && $0 != dismissButton && $0 != lockButton && $0 != dimButton && $0 != holdSpeedIndicator && $0 != volumeSliderHostingView)
211202 } )
212203
213204 return views
@@ -496,7 +487,7 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
496487 view. addSubview ( capsuleContainer)
497488 capsuleContainer. alpha = isControlsVisible ? 1.0 : 0.0
498489
499- let buttons : [ UIView ] = [ airplayButton, pipButton , lockButton, dimButton]
490+ let buttons : [ UIView ] = [ airplayButton, lockButton, dimButton]
500491 for btn in buttons {
501492 btn. removeFromSuperview ( )
502493 capsuleContainer. addSubview ( btn)
@@ -728,7 +719,6 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
728719 skipIntroButton? . removeFromSuperview ( )
729720 skipOutroButton? . removeFromSuperview ( )
730721 skip85Button? . removeFromSuperview ( )
731- pipButton? . removeFromSuperview ( )
732722 airplayButton? . removeFromSuperview ( )
733723 menuButton? . removeFromSuperview ( )
734724 speedButton? . removeFromSuperview ( )
@@ -807,6 +797,8 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
807797 playerViewController = AVPlayerViewController ( )
808798 playerViewController. player = player
809799 playerViewController. showsPlaybackControls = false
800+ playerViewController. delegate = self
801+
810802 addChild ( playerViewController)
811803 if playerViewController. view. superview == nil {
812804 view. addSubview ( playerViewController. view)
@@ -2205,18 +2197,23 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
22052197 }
22062198 }
22072199
2208- @objc private func pipButtonTapped( _ sender: UIButton ) {
2209- guard let pip = pipController else { return }
2210- if pip. isPictureInPictureActive {
2211- pip. stopPictureInPicture ( )
2212- } else {
2213- pip. startPictureInPicture ( )
2214- }
2215- }
2216-
22172200 @objc private func startPipIfNeeded( ) {
2218- Logger . shared. log ( " PIP " , type: " Genral " )
2219- pipController!. startPictureInPicture ( )
2201+ guard let pipController = pipController else {
2202+ Logger . shared. log ( " PiP controller not available " , type: " Error " )
2203+ return
2204+ }
2205+
2206+ guard AVPictureInPictureController . isPictureInPictureSupported ( ) else {
2207+ Logger . shared. log ( " PiP not supported on this device " , type: " Error " )
2208+ return
2209+ }
2210+
2211+ guard !pipController. isPictureInPictureActive else {
2212+ Logger . shared. log ( " PiP already active " , type: " Debug " )
2213+ return
2214+ }
2215+
2216+ pipController. startPictureInPicture ( )
22202217 }
22212218
22222219 @objc private func lockTapped( ) {
@@ -3568,47 +3565,20 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
35683565
35693566 playerViewController. allowsPictureInPicturePlayback = true
35703567
3571- let playerLayerContainer = UIView ( )
3572- playerLayerContainer. translatesAutoresizingMaskIntoConstraints = false
3573- view. insertSubview ( playerLayerContainer, at: 0 )
3574-
3575- NSLayoutConstraint . activate ( [
3576- playerLayerContainer. topAnchor. constraint ( equalTo: view. topAnchor) ,
3577- playerLayerContainer. bottomAnchor. constraint ( equalTo: view. bottomAnchor) ,
3578- playerLayerContainer. leadingAnchor. constraint ( equalTo: view. leadingAnchor) ,
3579- playerLayerContainer. trailingAnchor. constraint ( equalTo: view. trailingAnchor)
3580- ] )
3581-
3582- let pipPlayerLayer = AVPlayerLayer ( player: playerViewController. player)
3583- pipPlayerLayer. frame = playerViewController. view. layer. bounds
3584- pipPlayerLayer. videoGravity = . resizeAspect
3585-
3586- playerViewController. view. layer. insertSublayer ( pipPlayerLayer, at: 0 )
3587- pipController = AVPictureInPictureController ( playerLayer: pipPlayerLayer)
3568+ if let playerLayer = playerViewController. view. layer. sublayers? . first ( where: { $0 is AVPlayerLayer } ) as? AVPlayerLayer {
3569+ pipController = AVPictureInPictureController ( playerLayer: playerLayer)
3570+ } else {
3571+ pipController = AVPictureInPictureController ( playerLayer: AVPlayerLayer ( player: player) )
3572+ }
35883573 pipController? . delegate = self
35893574
3590- let Image = UIImage ( systemName: " pip " , withConfiguration: cfg)
3591- pipButton = UIButton ( type: . system)
3592- pipButton. setImage ( Image, for: . normal)
3593- pipButton. tintColor = . white
3594- pipButton. addTarget ( self , action: #selector( pipButtonTapped ( _: ) ) , for: . touchUpInside)
3595-
3596- controlsContainerView. addSubview ( pipButton)
3597- pipButton. translatesAutoresizingMaskIntoConstraints = false
3598-
35993575 NSLayoutConstraint . activate ( [
3600- pipButton. centerYAnchor. constraint ( equalTo: dimButton. centerYAnchor) ,
3601- pipButton. trailingAnchor. constraint ( equalTo: dimButton. leadingAnchor, constant: - 8 ) ,
3602- pipButton. widthAnchor. constraint ( equalToConstant: 30 ) ,
3603- pipButton. heightAnchor. constraint ( equalToConstant: 24 ) ,
3604- airplayButton. centerYAnchor. constraint ( equalTo: pipButton. centerYAnchor) ,
3605- airplayButton. trailingAnchor. constraint ( equalTo: pipButton. leadingAnchor, constant: - 4 ) ,
3576+ airplayButton. centerYAnchor. constraint ( equalTo: dimButton. centerYAnchor) ,
3577+ airplayButton. trailingAnchor. constraint ( equalTo: dimButton. leadingAnchor, constant: - 8 ) ,
36063578 airplayButton. widthAnchor. constraint ( equalToConstant: 24 ) ,
36073579 airplayButton. heightAnchor. constraint ( equalToConstant: 24 )
36083580 ] )
36093581
3610- pipButton. isHidden = !isPipButtonVisible
3611-
36123582 NotificationCenter . default. addObserver ( self , selector: #selector( startPipIfNeeded) , name: UIApplication . didEnterBackgroundNotification, object: nil )
36133583 }
36143584
@@ -3701,18 +3671,42 @@ class GradientOverlayButton: UIButton {
37013671
37023672extension CustomMediaPlayerViewController : AVPictureInPictureControllerDelegate {
37033673 func pictureInPictureControllerWillStartPictureInPicture( _ pipController: AVPictureInPictureController ) {
3704- pipButton . alpha = 0.5
3674+ // PiP will start
37053675 }
37063676
37073677 func pictureInPictureControllerDidStopPictureInPicture( _ pipController: AVPictureInPictureController ) {
3708- pipButton . alpha = 1.0
3678+ // PiP did stop
37093679 }
37103680
37113681 func pictureInPictureController( _ pipController: AVPictureInPictureController , failedToStartPictureInPictureWithError error: Error ) {
37123682 Logger . shared. log ( " PiP failed to start: \( error. localizedDescription) " , type: " Error " )
37133683 }
37143684}
37153685
3686+ // MARK: - AVPlayerViewControllerDelegate
3687+ extension CustomMediaPlayerViewController {
3688+ func playerViewController( _ playerViewController: AVPlayerViewController , restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping ( Bool ) -> Void ) {
3689+ let windowScene = UIApplication . shared. connectedScenes
3690+ . filter { $0. activationState == . foregroundActive }
3691+ . compactMap { $0 as? UIWindowScene }
3692+ . first
3693+
3694+ let window = windowScene? . windows. first ( where: { $0. isKeyWindow } )
3695+
3696+ if let topVC = window? . rootViewController? . topmostViewController ( ) {
3697+ if topVC != self {
3698+ topVC. present ( self , animated: true ) {
3699+ completionHandler ( true )
3700+ }
3701+ } else {
3702+ completionHandler ( true )
3703+ }
3704+ } else {
3705+ completionHandler ( false )
3706+ }
3707+ }
3708+ }
3709+
37163710extension CustomMediaPlayerViewController {
37173711 func gestureRecognizer( _ gestureRecognizer: UIGestureRecognizer , shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer ) -> Bool {
37183712 return true
@@ -3897,3 +3891,21 @@ extension CustomMediaPlayerViewController {
38973891 }
38983892 }
38993893}
3894+
3895+ extension UIViewController {
3896+ func topmostViewController( ) -> UIViewController {
3897+ if let presented = self . presentedViewController {
3898+ return presented. topmostViewController ( )
3899+ }
3900+
3901+ if let navigation = self as? UINavigationController {
3902+ return navigation. visibleViewController? . topmostViewController ( ) ?? navigation
3903+ }
3904+
3905+ if let tabBar = self as? UITabBarController {
3906+ return tabBar. selectedViewController? . topmostViewController ( ) ?? tabBar
3907+ }
3908+
3909+ return self
3910+ }
3911+ }
0 commit comments