// // 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? var isFullScreenBtn = false override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return .allButUpsideDown } override var shouldAutorotate: Bool { return true } override func viewDidLoad() { super.viewDidLoad() // self.rotateToLandsScapeDevice() // rotateView(to: .pi / 2) // Example: 90 degrees rotation //bring back button to the front self.view.bringSubviewToFront(backButton) } // func rotateView(to angle: CGFloat) { // // Apply rotation to the view's transform // view.transform = CGAffineTransform(rotationAngle: angle) // } @objc func applicationDidBecomeActive() { // self.setDeviceOrientation(orientation: .landscapeRight) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) appDelegate.deviceOrientation = .landscapeRight let value = UIInterfaceOrientation.landscapeRight.rawValue UIDevice.current.setValue(value, forKey: "orientation") player.configurePlayer(with: config) self.delegate = 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) { handleBackAction() } func handleBackAction(){ self.interfaceBehavior = .hidden self.player.stop() if contentType == .liveStream{ self.dismissTapped?() } appDelegate.deviceOrientation = .portrait updateClicks() let value = UIInterfaceOrientation.portrait.rawValue UIDevice.current.setValue(value, forKey: "orientation") UIViewController.attemptRotationToDeviceOrientation() } func updateClicks(){ switch contentType { case .liveStream: PersistentStorage.shared.addLiveTVCount() // case .webSeries: //// PersistentStorage.shared.addOthersCount() case .trailer: PersistentStorage.shared.addTrailerCount() // case .continueWatching: // <#code#> // case .audioBooks: // <#code#> // case .games: // <#code#> // case .songs: // <#code#> case nil: break default: break } } // MARK: - Handle Screen Transition override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) coordinator.animate(alongsideTransition: nil) { _ in self.checkOrientation() } } private func checkOrientation() { let isPortrait = UIScreen.main.bounds.size.width < UIScreen.main.bounds.size.height if isPortrait { print("Device is in portrait mode") self.dismiss(animated: true) } else { print("Device is in landscape mode") if isFullScreenBtn{ appDelegate.deviceOrientation = .portrait let value = UIInterfaceOrientation.portrait.rawValue UIDevice.current.setValue(value, forKey: "orientation") UIViewController.attemptRotationToDeviceOrientation() } } } // MARK: - JWPlayerViewControllerDelegate override func jwplayer(_ player: any JWPlayer, didFinishLoadingWithTime loadTime: TimeInterval) { super.jwplayer(player, didFinishLoadingWithTime: loadTime) print("LoadTime", loadTime) if let videoIndex , contentType == .webSeries, videoIndex != 0{ 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,.songs: break 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)") Utilities.alertWithBtnCancelCompletion(title: "Error", msgBody: message, okBtnStr: "Connect", vc: self) { [weak self] isDone in guard let self else{ self?.handleBackAction() return } if isDone{ self.player.configurePlayer(with: config) self.player.play() }else{ self.handleBackAction() } } } 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) print("Buffering Reason:", reason) } //When Player is Paused override func jwplayer(_ player: JWPlayer, didPauseWithReason reason: JWPauseReason) { super.jwplayer(player, didPauseWithReason: reason) if reason == .interaction{ updateClicks() } // Implement custom behavior } //When Player is Play override func jwplayer(_ player: JWPlayer, isPlayingWithReason reason: JWPlayReason) { super.jwplayer(player, isPlayingWithReason: reason) if reason == .interaction{ updateClicks() } } } // MARK: - Full Screen Handling extension PlayerVC { func playerViewControllerWillGoFullScreen(_ controller: JWPlayerViewController) -> JWFullScreenViewController? { print("playerViewControllerWillGoFullScreen") self.interfaceBehavior = .hidden self.player.stop() controller.player.stop() if contentType == .liveStream{ self.dismissTapped?() } return nil } func playerViewControllerDidGoFullScreen(_ controller: JWPlayerViewController) { print("playerViewControllerDidGoFullScreen") self.player.pause() self.dismissFullScreen(animated: false) self.dismiss(animated: true) return } func playerViewControllerWillDismissFullScreen(_ controller: JWPlayerViewController) { print("playerViewControllerWillDismissFullScreen") } func playerViewControllerDidDismissFullScreen(_ controller: JWPlayerViewController) { print("playerViewControllerDidDismissFullScreen") appDelegate.deviceOrientation = .portrait updateClicks() let value = UIInterfaceOrientation.portrait.rawValue UIDevice.current.setValue(value, forKey: "orientation") UIViewController.attemptRotationToDeviceOrientation() } } // 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) } }