// // PlayerVC.swift // WOKA // // Created by MacBook Pro on 30/05/24. import UIKit import JWPlayerKit import AVKit class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate { @IBOutlet weak var backButton: UIButton! var previousScale: CGFloat = 1.0 var contentType : VideoContentType? var config: JWPlayerConfiguration! var dismissTapped: (() -> Void)? var videoIndex : Int? func rotateToLandsScapeDevice(){ let appDelegate = UIApplication.shared.delegate as! AppDelegate appDelegate.myOrientation = .landscapeRight if #available(iOS 16.0, *) { let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: UIInterfaceOrientationMask.landscapeRight)) } else { UIDevice.current.setValue(UIInterfaceOrientationMask.landscapeRight.rawValue, forKey: "orientation") } UIView.setAnimationsEnabled(true) } func rotateToPortraitScapeDevice(){ let appDelegate = UIApplication.shared.delegate as! AppDelegate appDelegate.myOrientation = .portrait if #available(iOS 16.0, *) { let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: UIInterfaceOrientationMask.portrait)) } else { UIDevice.current.setValue(UIInterfaceOrientationMask.portrait.rawValue, forKey: "orientation") } // UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation") UIView.setAnimationsEnabled(true) } // func rotateToPortraitScapeDevice() { // let appDelegate = UIApplication.shared.delegate as! AppDelegate // appDelegate.myOrientation = .portrait // // UIView.animate(withDuration: 0.3) { // if #available(iOS 16.0, *) { // let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene // windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: .portrait)) { error in // print("Error updating geometry: \(error.localizedDescription)") // } // } else { // UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation") // } // } // } override func viewDidLoad() { super.viewDidLoad() self.rotateToLandsScapeDevice() self.view.bringSubviewToFront(backButton) } @objc func applicationDidBecomeActive() { self.setDeviceOrientation(orientation: .landscapeRight) } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { if size.width > self.view.frame.size.width { print("Landscape") }else{ DispatchQueue.main.async { self.dismiss(animated: true) } } } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) player.configurePlayer(with: config) self.delegate = self // self.uiDelegate = self // self.relatedDelegate = self //Disable Picture in Picture playerView.allowsPictureInPicturePlayback = false playerView.captionStyle = .none } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) player.stop() } @IBAction func backBtnTapped(_ sender: UIButton) { self.transitionToFullScreen(animated: true) } // MARK: - JWPlayerViewControllerDelegate override func jwplayer(_ player: any JWPlayer, didFinishLoadingWithTime loadTime: TimeInterval) { super.jwplayer(player, didFinishLoadingWithTime: loadTime) print("LoadTime", loadTime) if let videoIndex , contentType == .webSeries{ player.nextUpPlaylistIndex = videoIndex player.next() self.videoIndex = nil } } override func jwplayerIsReady(_ player: JWPlayer) { super.jwplayerIsReady(player) switch contentType { case .liveStream: player.play() case .webSeries: if videoIndex == 0{ player.seek(to: 0) }else{ // player.nextUpPlaylistIndex = videoIndex ?? 0 // player.next() } case .trailer: break // player.play() case .continueWatching,.audioBooks, .games: player.seek(to: 0) player.play() case nil: break } print("IsReady") } override func jwplayer(_ player: JWPlayer, failedWithSetupError code: UInt, message: String) { super.jwplayer(player, failedWithSetupError: code, message: message) print("Setup Error: \(code) - \(message)") } override func jwplayer(_ player: JWPlayer, failedWithError code: UInt, message: String) { super.jwplayer(player, failedWithError: code, message: message) print("Error: \(code) - \(message)") self.player.configurePlayer(with: config) self.player.play() } override func jwplayer(_ player: JWPlayer, encounteredWarning code: UInt, message: String) { super.jwplayer(player, encounteredWarning: code, message: message) //Handle the reconnecting of video here print("Warning: \(code) - \(message)") } override func jwplayer(_ player: JWPlayer, encounteredAdError code: UInt, message: String) { super.jwplayer(player, encounteredAdError: code, message: message) print("Ad Error: \(code) - \(message)") } override func jwplayer(_ player: JWPlayer, encounteredAdWarning code: UInt, message: String) { super.jwplayer(player, encounteredAdWarning: code, message: message) print("Ad Warning: \(code) - \(message)") } override func jwplayer(_ player: JWPlayer, isBufferingWithReason reason: JWBufferReason) { super.jwplayer(player, isBufferingWithReason: reason) // player.play() print("Buffering Reason:", reason) } override func jwplayer(_ player: JWPlayer, didPauseWithReason reason: JWPauseReason) { super.jwplayer(player, didPauseWithReason: reason) // Implement custom behavior } } // MARK: - Full Screen Handling extension PlayerVC { func playerViewControllerWillGoFullScreen(_ controller: JWPlayerViewController) -> JWFullScreenViewController? { // controller.shouldEnterFullScreen = false // self.setDeviceOrientation(orientation: .po0rtrait) print("playerViewControllerWillGoFullScreen") controller.player.stop() self.rotateToPortraitScapeDevice() return nil } func playerViewControllerDidGoFullScreen(_ controller: JWPlayerViewController) { print("playerViewControllerDidGoFullScreen") controller.dismissFullScreen(animated: true) controller.player.stop() // self.player.stop() Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { _ in DispatchQueue.main.async { [weak self] in guard let self else{return} if contentType == .liveStream{ self.dismissTapped?() } self.dismiss(animated: true) } } // self.player.stop() // Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { _ in // DispatchQueue.main.async { // self.dismissTapped?() // self.dismiss(animated: true) // } // } return } func playerViewControllerWillDismissFullScreen(_ controller: JWPlayerViewController) { print("playerViewControllerWillDismissFullScreen") // self.setDeviceOrientation(orientation: .portrait) // Timer.scheduledTimer(withTimeInterval: 0.4, repeats: false) { _ in // controller.dismissFullScreen(animated: false) { // self.dismissTapped?() // } // } // self.rotateToPotraitScapeDevice() // self.dismiss // self.setDeviceOrientation(orientation: .portrait) // Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in // controller.dismiss(animated: false) { // } // self.setDeviceOrientation(orientation: .portrait) // } } func playerViewControllerDidDismissFullScreen(_ controller: JWPlayerViewController) { print("playerViewControllerDidDismissFullScreen") // self.dismissTapped?() // Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { _ in // self.player.stop() // controller.dismiss(animated: true) // } // self.navigationController?.popViewController(animated: true) } } // MARK: - JWPlayerViewController Delegate Functions extension PlayerVC { func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, controlBarVisibilityChanged isVisible: Bool, frame: CGRect) { self.backButton.isHidden = !isVisible } func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, sizeChangedFrom oldSize: CGSize, to newSize: CGSize) { // Handle size change if necessary } func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, screenTappedAt position: CGPoint) { // Handle screen tap if necessary } func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, relatedMenuOpenedWithItems items: [JWPlayerKit.JWPlayerItem], withMethod method: JWPlayerKit.JWRelatedInteraction) { print("Related items:", items) } func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, relatedMenuClosedWithMethod method: JWRelatedInteraction) { print("Related menu closed") } func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, relatedItemBeganPlaying item: JWPlayerKit.JWPlayerItem, atIndex index: Int, withMethod method: JWPlayerKit.JWRelatedMethod) { print("Item ", item) } } // MARK: - Orientation Handling extension UIViewController { func setDeviceOrientation(orientation: UIInterfaceOrientationMask) { if #available(iOS 16.0, *) { let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: orientation)) } else { UIDevice.current.setValue(orientation.toUIInterfaceOrientation.rawValue, forKey: "orientation") } } } extension UIInterfaceOrientationMask { var toUIInterfaceOrientation: UIInterfaceOrientation { switch self { case .portrait: return .portrait case .portraitUpsideDown: return .portraitUpsideDown case .landscapeRight: return .landscapeRight case .landscapeLeft: return .landscapeLeft default: return .unknown } } }