2024-05-30 19:49:41 +05:30
|
|
|
//
|
|
|
|
|
// PlayerVC.swift
|
|
|
|
|
// WOKA
|
|
|
|
|
//
|
|
|
|
|
// Created by MacBook Pro on 30/05/24.
|
2024-06-07 21:04:29 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
|
|
|
|
|
import UIKit
|
|
|
|
|
import JWPlayerKit
|
|
|
|
|
import AVKit
|
|
|
|
|
|
2024-08-23 20:34:08 +05:30
|
|
|
class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate {
|
2024-05-30 19:49:41 +05:30
|
|
|
|
2024-07-19 21:21:19 +05:30
|
|
|
@IBOutlet weak var backButton: UIButton!
|
2024-05-30 19:49:41 +05:30
|
|
|
var previousScale: CGFloat = 1.0
|
2024-07-17 20:05:39 +05:30
|
|
|
|
2024-06-26 20:01:14 +05:30
|
|
|
var contentType : VideoContentType?
|
|
|
|
|
|
2024-06-07 21:04:29 +05:30
|
|
|
var config: JWPlayerConfiguration!
|
|
|
|
|
var dismissTapped: (() -> Void)?
|
2024-06-25 11:29:00 +05:30
|
|
|
var videoIndex : Int?
|
2024-08-17 01:34:28 +05:30
|
|
|
|
2024-08-21 01:56:53 +05:30
|
|
|
var errorCount = 0
|
2024-08-17 01:34:28 +05:30
|
|
|
|
2024-08-01 00:08:56 +05:30
|
|
|
var isFullScreenBtn = false
|
2024-06-03 20:02:39 +05:30
|
|
|
|
2024-08-17 01:34:28 +05:30
|
|
|
var vm = PlayerVM()
|
|
|
|
|
|
|
|
|
|
deinit {
|
|
|
|
|
NotificationCenter.default.removeObserver(self,name: UIApplication.didEnterBackgroundNotification, object: nil)
|
|
|
|
|
NotificationCenter.default.removeObserver(self,name: UIApplication.willEnterForegroundNotification, object: nil)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-01 00:08:56 +05:30
|
|
|
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
|
|
|
|
return .allButUpsideDown
|
|
|
|
|
}
|
2024-08-26 19:43:41 +05:30
|
|
|
|
2024-08-01 00:08:56 +05:30
|
|
|
override var shouldAutorotate: Bool {
|
|
|
|
|
return true
|
2024-07-25 20:06:58 +05:30
|
|
|
}
|
2024-08-22 00:29:23 +05:30
|
|
|
|
|
|
|
|
override var prefersStatusBarHidden: Bool {
|
|
|
|
|
if #available(iOS 16.0, *) {
|
|
|
|
|
// Code for iOS 16.0 and above
|
|
|
|
|
return false
|
|
|
|
|
} else {
|
|
|
|
|
// Fallback code for earlier iOS versions
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-07-26 23:21:09 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
override func viewDidLoad() {
|
|
|
|
|
super.viewDidLoad()
|
2024-08-21 19:47:30 +05:30
|
|
|
self.delegate = self
|
2024-08-23 20:34:08 +05:30
|
|
|
player.configurePlayer(with: config)
|
2024-08-17 01:34:28 +05:30
|
|
|
vm.vc = self
|
|
|
|
|
vm.initView()
|
2024-08-01 00:08:56 +05:30
|
|
|
//bring back button to the front
|
2024-07-19 21:21:19 +05:30
|
|
|
self.view.bringSubviewToFront(backButton)
|
2024-08-17 01:34:28 +05:30
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(appDidEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
|
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(appWillEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
|
2024-09-17 22:52:09 +05:30
|
|
|
|
2024-09-18 19:25:25 +05:30
|
|
|
|
|
|
|
|
let skinStylingBuilder = JWPlayerSkinBuilder()
|
|
|
|
|
.adCueColor(.yellow)
|
|
|
|
|
// .buttonsColor(.blue)
|
|
|
|
|
// .backgroundColor(.cyan)
|
2024-09-17 22:52:09 +05:30
|
|
|
|
2024-09-18 19:25:25 +05:30
|
|
|
let skinStyling = try? skinStylingBuilder.build()
|
|
|
|
|
self.styling = skinStyling
|
|
|
|
|
self.setVisibility(.hidden, for: [.fullscreenButton, .pictureInPictureButton,.languagesButton])
|
2024-09-17 22:52:09 +05:30
|
|
|
|
2024-09-18 19:25:25 +05:30
|
|
|
print("Quality:- ", player.visualQualityLevels)
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|
2024-09-13 22:21:22 +05:30
|
|
|
|
|
|
|
|
override func viewDidAppear(_ animated: Bool) {
|
|
|
|
|
super.viewDidAppear(animated)
|
|
|
|
|
setNeedsStatusBarAppearanceUpdate()
|
|
|
|
|
}
|
2024-08-22 00:29:23 +05:30
|
|
|
|
|
|
|
|
// for ios 15 and below
|
|
|
|
|
func rotateView(to angle: CGFloat) {
|
|
|
|
|
// Apply rotation to the view's transform
|
|
|
|
|
view.transform = CGAffineTransform(rotationAngle: angle)
|
|
|
|
|
}
|
2024-08-01 00:08:56 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
override func viewWillAppear(_ animated: Bool) {
|
2024-06-07 21:04:29 +05:30
|
|
|
super.viewWillAppear(animated)
|
2024-08-10 00:48:45 +05:30
|
|
|
|
2024-08-22 00:29:23 +05:30
|
|
|
if #available(iOS 16.0, *) {
|
|
|
|
|
// Code for iOS 15.0 and above
|
|
|
|
|
print("Running on iOS 15.0 or later")
|
2024-09-04 20:17:33 +05:30
|
|
|
DispatchQueue.main.async {
|
|
|
|
|
appDelegate.deviceOrientation = .landscapeRight
|
|
|
|
|
let value = UIInterfaceOrientation.landscapeRight.rawValue
|
|
|
|
|
UIDevice.current.setValue(value, forKey: "orientation")
|
|
|
|
|
}
|
2024-08-22 00:29:23 +05:30
|
|
|
} else {
|
|
|
|
|
// Fallback code for earlier iOS versions
|
2024-09-13 22:21:22 +05:30
|
|
|
rotateView(to: .pi / 2) // Example: 90 degrees rotation
|
2024-08-22 00:29:23 +05:30
|
|
|
print("Running on a version earlier than iOS 15.0")
|
|
|
|
|
}
|
2024-08-21 19:47:30 +05:30
|
|
|
|
2024-08-21 01:56:53 +05:30
|
|
|
//Disable Picture in Picture
|
|
|
|
|
playerView.allowsPictureInPicturePlayback = false
|
|
|
|
|
playerView.captionStyle = .none
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override func viewWillDisappear(_ animated: Bool) {
|
2024-06-07 21:04:29 +05:30
|
|
|
super.viewWillDisappear(animated)
|
2024-05-30 19:49:41 +05:30
|
|
|
player.stop()
|
|
|
|
|
}
|
2024-08-10 00:48:45 +05:30
|
|
|
|
2024-07-19 21:21:19 +05:30
|
|
|
@IBAction func backBtnTapped(_ sender: UIButton) {
|
2024-08-17 01:34:28 +05:30
|
|
|
switch contentType {
|
|
|
|
|
case .liveStream:
|
|
|
|
|
if let postID = vm.videoIDs.first {
|
|
|
|
|
let duration = DateFormatterLib.dateDifferenceINT(date1: vm.startTimeStamp, date2: Date())
|
|
|
|
|
let totalDuration = duration + vm.totalVideoViewTime
|
|
|
|
|
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.liveTV.rawValue, duration: totalDuration, catID: 0) { _ in}
|
|
|
|
|
vm.handleBackAction()
|
|
|
|
|
}
|
|
|
|
|
case .webSeries:
|
|
|
|
|
if let catID = vm.catID, vm.currentPlayingIndex >= 0 && vm.currentPlayingIndex < (vm.videoIDs.count - 1) {
|
|
|
|
|
let postID = vm.videoIDs[vm.currentPlayingIndex]
|
|
|
|
|
let duration = DateFormatterLib.dateDifferenceINT(date1: vm.startTimeStamp, date2: Date())
|
|
|
|
|
let totalDuration = duration + vm.totalVideoViewTime
|
|
|
|
|
Utilities.startProgressHUD(msg: K.ConstantString.sync)
|
|
|
|
|
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.episode.rawValue, duration: totalDuration, catID: catID) { [weak self] isDone in
|
|
|
|
|
guard let self else{return}
|
|
|
|
|
if isDone{
|
|
|
|
|
Utilities.dismissProgressHUD()
|
|
|
|
|
vm.handleBackAction()
|
|
|
|
|
K.GVar.reloadContinueWebSeries = true
|
|
|
|
|
}else{
|
|
|
|
|
Utilities.dismissProgressHUD()
|
|
|
|
|
vm.handleBackAction()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
vm.handleBackAction()
|
|
|
|
|
}
|
|
|
|
|
case .trailer:
|
|
|
|
|
let duration = DateFormatterLib.dateDifferenceINT(date1: vm.startTimeStamp, date2: Date())
|
|
|
|
|
let totalDuration = duration + vm.totalVideoViewTime
|
|
|
|
|
AuthFunc.shareInstance.userVideoView(postID: 0, postType: PostType.episode.rawValue, duration: totalDuration, catID: 0) { _ in}
|
|
|
|
|
vm.handleBackAction()
|
|
|
|
|
case .continueWatching:
|
|
|
|
|
if let catID = vm.catID,let postID = vm.videoIDs.first{
|
|
|
|
|
let duration = DateFormatterLib.dateDifferenceINT(date1: vm.startTimeStamp, date2: Date())
|
|
|
|
|
let totalDuration = duration + vm.totalVideoViewTime
|
|
|
|
|
Utilities.startProgressHUD(msg: K.ConstantString.sync)
|
|
|
|
|
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.episode.rawValue, duration: totalDuration, catID: catID) { [weak self] isDone in
|
|
|
|
|
guard let self else{return}
|
|
|
|
|
if isDone{
|
|
|
|
|
Utilities.dismissProgressHUD()
|
|
|
|
|
vm.handleBackAction()
|
|
|
|
|
K.GVar.reloadContinueWebSeries = true
|
|
|
|
|
}else{
|
|
|
|
|
Utilities.dismissProgressHUD()
|
|
|
|
|
vm.handleBackAction()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
vm.handleBackAction()
|
|
|
|
|
}
|
|
|
|
|
case .audioBooks:
|
|
|
|
|
if let postID = vm.videoIDs.first {
|
|
|
|
|
let duration = DateFormatterLib.dateDifferenceINT(date1: vm.startTimeStamp, date2: Date())
|
|
|
|
|
let totalDuration = duration + vm.totalVideoViewTime
|
|
|
|
|
Utilities.startProgressHUD(msg: K.ConstantString.sync)
|
|
|
|
|
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.audio.rawValue, duration: totalDuration, catID: 0) { [weak self] isDone in
|
|
|
|
|
guard let self else{
|
|
|
|
|
Utilities.dismissProgressHUD()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if isDone{
|
|
|
|
|
Utilities.dismissProgressHUD()
|
2024-08-23 20:34:08 +05:30
|
|
|
K.GVar.reloadContinueAudioBooks = true
|
2024-08-17 01:34:28 +05:30
|
|
|
vm.handleBackAction()
|
|
|
|
|
}else{
|
|
|
|
|
Utilities.dismissProgressHUD()
|
|
|
|
|
vm.handleBackAction()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
case .games:
|
|
|
|
|
break
|
|
|
|
|
case .songs:
|
|
|
|
|
break
|
|
|
|
|
default:
|
|
|
|
|
vm.handleBackAction()
|
2024-07-26 23:21:09 +05:30
|
|
|
}
|
2024-08-01 00:08:56 +05:30
|
|
|
|
2024-07-19 21:21:19 +05:30
|
|
|
}
|
|
|
|
|
|
2024-08-17 01:34:28 +05:30
|
|
|
// MARK: - App LifeCycle Handling
|
|
|
|
|
|
|
|
|
|
@objc func appDidEnterBackground() {
|
|
|
|
|
print("App entered background PlayerVC")
|
|
|
|
|
player.pause()
|
|
|
|
|
|
|
|
|
|
//Update uservideo view
|
2024-08-07 20:21:47 +05:30
|
|
|
switch contentType {
|
|
|
|
|
case .liveStream:
|
2024-08-17 01:34:28 +05:30
|
|
|
vm.updateUserView()
|
|
|
|
|
case .webSeries:
|
|
|
|
|
vm.updateUserView()
|
2024-08-07 20:21:47 +05:30
|
|
|
case .trailer:
|
2024-08-17 01:34:28 +05:30
|
|
|
vm.updateUserView()
|
|
|
|
|
case .continueWatching:
|
|
|
|
|
vm.updateUserView()
|
|
|
|
|
case .audioBooks:
|
|
|
|
|
vm.updateUserView()
|
|
|
|
|
case .games:
|
|
|
|
|
break
|
|
|
|
|
case .songs:
|
2024-08-07 20:21:47 +05:30
|
|
|
break
|
|
|
|
|
default:
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-17 01:34:28 +05:30
|
|
|
@objc func appWillEnterForeground() {
|
|
|
|
|
print("App will enter foreground PlayerVC")
|
|
|
|
|
|
|
|
|
|
//Reset StartTimestamp
|
|
|
|
|
vm.startTimeStamp = Date()
|
|
|
|
|
|
|
|
|
|
player.play()
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-01 00:08:56 +05:30
|
|
|
// MARK: - Handle Screen Transition
|
|
|
|
|
|
|
|
|
|
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
|
|
|
|
|
super.viewWillTransition(to: size, with: coordinator)
|
|
|
|
|
|
2024-08-17 01:34:28 +05:30
|
|
|
coordinator.animate(alongsideTransition: nil) { [weak self] _ in
|
|
|
|
|
guard let self else{return}
|
|
|
|
|
vm.checkOrientation()
|
2024-08-01 00:08:56 +05:30
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-07 21:04:29 +05:30
|
|
|
// MARK: - JWPlayerViewControllerDelegate
|
2024-08-07 20:21:47 +05:30
|
|
|
|
2024-08-20 23:47:15 +05:30
|
|
|
override func jwplayerPlaylistHasCompleted(_ player: any JWPlayer) {
|
|
|
|
|
super.jwplayerPlaylistHasCompleted(player)
|
|
|
|
|
// if playlist is finised make sure to add it to user video view
|
|
|
|
|
vm.updateUserView()
|
|
|
|
|
print("PlayList Over", vm.currentPlayingIndex)
|
|
|
|
|
}
|
2024-08-23 20:34:08 +05:30
|
|
|
|
2024-08-21 01:56:53 +05:30
|
|
|
override func jwplayer(_ player: any JWPlayer, didLoadPlaylist playlist: [JWPlayerItem]) {
|
|
|
|
|
super.jwplayer(player, didLoadPlaylist: playlist)
|
|
|
|
|
print("Playlist loaded")
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-17 01:34:28 +05:30
|
|
|
// this will give index
|
|
|
|
|
override func jwplayer(_ player: any JWPlayer, didLoadPlaylistItem item: JWPlayerItem, at index: UInt) {
|
|
|
|
|
super.jwplayer(player, didLoadPlaylistItem: item, at: index)
|
|
|
|
|
print("didLoadPlaylistItem ", index)
|
2024-08-21 01:56:53 +05:30
|
|
|
|
- TC 18, TC 20, TC 21, TC 23, TC 25, TC 26, TC 27, TC 28, TC 30, TC 33, TC 34, TC 37, TC 38
- Fixed contact support name error , if user goes back it used to display on top
2024-08-22 19:55:17 +05:30
|
|
|
// if currentplaylist index is not set, and the video index that we got from back screen check with the load index
|
|
|
|
|
if contentType == .webSeries{
|
|
|
|
|
if let videoIndex,vm.currentPlayingIndex == -1 && (index != videoIndex){
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-08-23 20:34:08 +05:30
|
|
|
|
|
|
|
|
if vm.currentPlayingIndex != -1 && vm.currentPlayingIndex != index{
|
|
|
|
|
// so update the loaded index and increase the current playing index
|
|
|
|
|
vm.updateUserView()
|
|
|
|
|
vm.currentPlayingIndex = Int(index)
|
|
|
|
|
}else{
|
|
|
|
|
vm.currentPlayingIndex = Int(index)
|
|
|
|
|
}
|
2024-08-20 23:47:15 +05:30
|
|
|
}
|
2024-08-17 01:34:28 +05:30
|
|
|
}
|
|
|
|
|
|
2024-06-07 21:04:29 +05:30
|
|
|
override func jwplayer(_ player: any JWPlayer, didFinishLoadingWithTime loadTime: TimeInterval) {
|
|
|
|
|
super.jwplayer(player, didFinishLoadingWithTime: loadTime)
|
|
|
|
|
print("LoadTime", loadTime)
|
2024-08-10 00:48:45 +05:30
|
|
|
// if let videoIndex , contentType == .webSeries, videoIndex != 0{
|
|
|
|
|
// player.nextUpPlaylistIndex = videoIndex
|
|
|
|
|
// player.next()
|
|
|
|
|
// self.videoIndex = nil
|
|
|
|
|
// }
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|
2024-06-25 19:41:04 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
override func jwplayerIsReady(_ player: JWPlayer) {
|
|
|
|
|
super.jwplayerIsReady(player)
|
2024-06-26 20:01:14 +05:30
|
|
|
switch contentType {
|
|
|
|
|
case .liveStream:
|
|
|
|
|
player.play()
|
|
|
|
|
case .webSeries:
|
2024-08-10 00:48:45 +05:30
|
|
|
break
|
|
|
|
|
// player.loadPlayerItemAt(index: videoIndex ?? 0)
|
|
|
|
|
// self.player.play(relatedContent: videoIndex ?? 0)
|
|
|
|
|
// self.player.loadPlayerItemAt(index: videoIndex ?? 0)
|
|
|
|
|
// player.play()
|
|
|
|
|
// if videoIndex == 0{
|
|
|
|
|
// player.seek(to: 0)
|
|
|
|
|
// }else{
|
2024-07-19 21:21:19 +05:30
|
|
|
// player.nextUpPlaylistIndex = videoIndex ?? 0
|
|
|
|
|
// player.next()
|
2024-08-10 00:48:45 +05:30
|
|
|
// }
|
2024-09-25 20:10:31 +05:30
|
|
|
case .trailer,.songs, .masilaSongs:
|
2024-07-24 19:59:08 +05:30
|
|
|
break
|
2024-07-04 19:48:15 +05:30
|
|
|
case .continueWatching,.audioBooks, .games:
|
|
|
|
|
player.seek(to: 0)
|
2024-07-15 20:10:33 +05:30
|
|
|
player.play()
|
2024-06-26 20:01:14 +05:30
|
|
|
case nil:
|
|
|
|
|
break
|
|
|
|
|
}
|
2024-05-30 19:49:41 +05:30
|
|
|
print("IsReady")
|
|
|
|
|
}
|
2024-08-23 20:34:08 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
override func jwplayer(_ player: JWPlayer, failedWithSetupError code: UInt, message: String) {
|
|
|
|
|
super.jwplayer(player, failedWithSetupError: code, message: message)
|
2024-06-07 21:04:29 +05:30
|
|
|
print("Setup Error: \(code) - \(message)")
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|
2024-06-07 21:04:29 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
override func jwplayer(_ player: JWPlayer, failedWithError code: UInt, message: String) {
|
|
|
|
|
super.jwplayer(player, failedWithError: code, message: message)
|
2024-06-07 21:04:29 +05:30
|
|
|
print("Error: \(code) - \(message)")
|
2024-08-21 01:56:53 +05:30
|
|
|
|
|
|
|
|
// try reconnect 3 times else show retry
|
|
|
|
|
if errorCount < 4{
|
|
|
|
|
errorCount += 1
|
|
|
|
|
self.player.configurePlayer(with: config)
|
|
|
|
|
self.player.play()
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-08-09 21:04:55 +05:30
|
|
|
DispatchQueue.main.async {
|
|
|
|
|
Utilities.alertWithBtnCancelCompletion(title: "Error", msgBody: message, okBtnStr: "Connect", vc: self) { [weak self] isDone in
|
|
|
|
|
guard let self else{
|
2024-08-17 01:34:28 +05:30
|
|
|
self?.vm.handleBackAction()
|
2024-08-09 21:04:55 +05:30
|
|
|
return
|
|
|
|
|
}
|
2024-08-21 01:56:53 +05:30
|
|
|
errorCount = 0
|
|
|
|
|
|
2024-08-09 21:04:55 +05:30
|
|
|
if isDone{
|
|
|
|
|
self.player.configurePlayer(with: config)
|
|
|
|
|
self.player.play()
|
|
|
|
|
}else{
|
2024-08-17 01:34:28 +05:30
|
|
|
self.vm.handleBackAction()
|
2024-08-09 21:04:55 +05:30
|
|
|
}
|
2024-08-01 00:08:56 +05:30
|
|
|
}
|
|
|
|
|
}
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|
2024-08-17 01:34:28 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
override func jwplayer(_ player: JWPlayer, encounteredWarning code: UInt, message: String) {
|
|
|
|
|
super.jwplayer(player, encounteredWarning: code, message: message)
|
2024-07-17 20:05:39 +05:30
|
|
|
//Handle the reconnecting of video here
|
|
|
|
|
|
2024-06-07 21:04:29 +05:30
|
|
|
print("Warning: \(code) - \(message)")
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|
2024-06-07 21:04:29 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
override func jwplayer(_ player: JWPlayer, encounteredAdError code: UInt, message: String) {
|
|
|
|
|
super.jwplayer(player, encounteredAdError: code, message: message)
|
2024-06-07 21:04:29 +05:30
|
|
|
print("Ad Error: \(code) - \(message)")
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|
2024-06-07 21:04:29 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
override func jwplayer(_ player: JWPlayer, encounteredAdWarning code: UInt, message: String) {
|
2024-06-07 21:04:29 +05:30
|
|
|
super.jwplayer(player, encounteredAdWarning: code, message: message)
|
|
|
|
|
print("Ad Warning: \(code) - \(message)")
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|
2024-06-07 21:04:29 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
override func jwplayer(_ player: JWPlayer, isBufferingWithReason reason: JWBufferReason) {
|
2024-06-07 21:04:29 +05:30
|
|
|
super.jwplayer(player, isBufferingWithReason: reason)
|
|
|
|
|
print("Buffering Reason:", reason)
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|
|
|
|
|
|
2024-08-07 20:21:47 +05:30
|
|
|
//When Player is Paused
|
2024-06-07 21:04:29 +05:30
|
|
|
override func jwplayer(_ player: JWPlayer, didPauseWithReason reason: JWPauseReason) {
|
|
|
|
|
super.jwplayer(player, didPauseWithReason: reason)
|
2024-08-07 20:21:47 +05:30
|
|
|
if reason == .interaction{
|
2024-08-17 01:34:28 +05:30
|
|
|
vm.updateClicks()
|
2024-08-07 20:21:47 +05:30
|
|
|
}
|
2024-06-07 21:04:29 +05:30
|
|
|
// Implement custom behavior
|
|
|
|
|
}
|
2024-08-07 20:21:47 +05:30
|
|
|
|
|
|
|
|
//When Player is Play
|
|
|
|
|
override func jwplayer(_ player: JWPlayer, isPlayingWithReason reason: JWPlayReason) {
|
|
|
|
|
super.jwplayer(player, isPlayingWithReason: reason)
|
|
|
|
|
if reason == .interaction{
|
2024-08-17 01:34:28 +05:30
|
|
|
vm.updateClicks()
|
2024-08-07 20:21:47 +05:30
|
|
|
}
|
|
|
|
|
}
|
2024-08-17 01:34:28 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|
|
|
|
|
|
2024-06-07 21:04:29 +05:30
|
|
|
// MARK: - Full Screen Handling
|
2024-05-30 19:49:41 +05:30
|
|
|
|
2024-06-07 21:04:29 +05:30
|
|
|
extension PlayerVC {
|
|
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
func playerViewControllerWillGoFullScreen(_ controller: JWPlayerViewController) -> JWFullScreenViewController? {
|
2024-06-03 20:02:39 +05:30
|
|
|
print("playerViewControllerWillGoFullScreen")
|
2024-07-26 23:21:09 +05:30
|
|
|
self.interfaceBehavior = .hidden
|
|
|
|
|
self.player.stop()
|
2024-07-19 21:21:19 +05:30
|
|
|
controller.player.stop()
|
2024-07-26 23:21:09 +05:30
|
|
|
if contentType == .liveStream{
|
|
|
|
|
self.dismissTapped?()
|
|
|
|
|
}
|
2024-05-30 19:49:41 +05:30
|
|
|
return nil
|
|
|
|
|
}
|
2024-08-01 00:08:56 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
func playerViewControllerDidGoFullScreen(_ controller: JWPlayerViewController) {
|
2024-06-03 20:02:39 +05:30
|
|
|
print("playerViewControllerDidGoFullScreen")
|
2024-08-01 00:08:56 +05:30
|
|
|
self.player.pause()
|
|
|
|
|
self.dismissFullScreen(animated: false)
|
|
|
|
|
self.dismiss(animated: true)
|
2024-05-30 19:49:41 +05:30
|
|
|
return
|
|
|
|
|
}
|
2024-07-25 20:06:58 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
func playerViewControllerWillDismissFullScreen(_ controller: JWPlayerViewController) {
|
2024-08-17 01:34:28 +05:30
|
|
|
switch contentType {
|
|
|
|
|
case .audioBooks,.liveStream,.webSeries, .continueWatching, .trailer:
|
|
|
|
|
vm.updateUserView()
|
|
|
|
|
default:
|
|
|
|
|
break
|
|
|
|
|
}
|
2024-06-03 20:02:39 +05:30
|
|
|
print("playerViewControllerWillDismissFullScreen")
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|
2024-08-17 01:34:28 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
func playerViewControllerDidDismissFullScreen(_ controller: JWPlayerViewController) {
|
2024-06-03 20:02:39 +05:30
|
|
|
print("playerViewControllerDidDismissFullScreen")
|
2024-08-17 01:34:28 +05:30
|
|
|
vm.updateClicks()
|
2024-08-22 00:29:23 +05:30
|
|
|
|
|
|
|
|
if #available(iOS 16.0, *) {
|
|
|
|
|
// Code for iOS 16.0 and above
|
2024-09-04 20:17:33 +05:30
|
|
|
DispatchQueue.main.async {
|
|
|
|
|
appDelegate.deviceOrientation = .portrait
|
|
|
|
|
let value = UIInterfaceOrientation.portrait.rawValue
|
|
|
|
|
UIDevice.current.setValue(value, forKey: "orientation")
|
|
|
|
|
UIViewController.attemptRotationToDeviceOrientation()
|
|
|
|
|
}
|
2024-08-22 00:29:23 +05:30
|
|
|
} else {
|
|
|
|
|
// Fallback code for earlier iOS versions
|
2024-09-04 20:17:33 +05:30
|
|
|
DispatchQueue.main.async {
|
|
|
|
|
self.dismiss(animated: true)
|
|
|
|
|
}
|
2024-08-22 00:29:23 +05:30
|
|
|
}
|
|
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-13 12:17:17 +05:30
|
|
|
// MARK: - Handle ADs
|
|
|
|
|
|
|
|
|
|
extension PlayerVC{
|
|
|
|
|
// Reports when an event is emitted by the player.
|
|
|
|
|
// override func jwplayer(_ player: JWPlayer, adEvent event: JWAdEvent) {
|
|
|
|
|
// super.jwplayer(player, adEvent: event)
|
|
|
|
|
//
|
|
|
|
|
// switch event.type {
|
|
|
|
|
// case .adBreakStart:
|
|
|
|
|
// print("The ad break has begun")
|
|
|
|
|
// case .schedule:
|
|
|
|
|
// print("The ad(s) has been scheduled")
|
|
|
|
|
// case .request:
|
|
|
|
|
// print("The ad has been requested")
|
|
|
|
|
// case .started:
|
|
|
|
|
// print("The ad playback has started")
|
|
|
|
|
// case .impression:
|
|
|
|
|
// print("The ad impression has been fulfilled")
|
|
|
|
|
// case .meta:
|
|
|
|
|
// print("The ad metadata is ready")
|
|
|
|
|
// case .clicked:
|
|
|
|
|
// print("The ad has been tapped")
|
|
|
|
|
// case .pause:
|
|
|
|
|
// print("The ad playback has been paused")
|
|
|
|
|
// case .play:
|
|
|
|
|
// print("The ad playback has been resumed")
|
|
|
|
|
// case .skipped:
|
|
|
|
|
// print("The ad has been skipped")
|
|
|
|
|
// case .complete:
|
|
|
|
|
// print("The ad playback has finished")
|
|
|
|
|
// case .adBreakEnd:
|
|
|
|
|
// print("The ad break has finished")
|
|
|
|
|
// default:
|
|
|
|
|
// break
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// // This method is triggered when a time event fires for a currently playing ad.
|
|
|
|
|
// override func onAdTimeEvent(_ time: JWTimeData) {
|
|
|
|
|
// super.onAdTimeEvent(time)
|
|
|
|
|
//
|
|
|
|
|
// // If you are not interested in the ad time data, avoid overriding this method due to performance reasons.
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// // When the player encounters an ad warning within the SDK, this method is called on the delegate.
|
|
|
|
|
// // Ad warnings do not prevent the ad from continuing to play.
|
|
|
|
|
// override func jwplayer(_ player: JWPlayer, encounteredAdWarning code: UInt, message: String) {
|
|
|
|
|
// super.jwplayer(player, encounteredAdWarning: code, message: message)
|
|
|
|
|
//
|
|
|
|
|
// print("An ad warning has been encountered: (\(code))-\(message)")
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// // When the player encounters an ad error within the SDK, this method is called on the delegate.
|
|
|
|
|
// // Ad errors prevent ads from playing, but do not prevent media playback from continuing.
|
|
|
|
|
// override func jwplayer(_ player: JWPlayer, encounteredAdError code: UInt, message: String) {
|
|
|
|
|
// super.jwplayer(player, encounteredAdError: code, message: message)
|
|
|
|
|
//
|
|
|
|
|
// print("An ad error has been encountered: (\(code))-\(message)")
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2024-06-07 21:04:29 +05:30
|
|
|
// MARK: - JWPlayerViewController Delegate Functions
|
2024-05-30 19:49:41 +05:30
|
|
|
|
2024-06-07 21:04:29 +05:30
|
|
|
extension PlayerVC {
|
|
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, controlBarVisibilityChanged isVisible: Bool, frame: CGRect) {
|
2024-07-19 21:21:19 +05:30
|
|
|
self.backButton.isHidden = !isVisible
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|
2024-06-07 21:04:29 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, sizeChangedFrom oldSize: CGSize, to newSize: CGSize) {
|
2024-06-07 21:04:29 +05:30
|
|
|
// Handle size change if necessary
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|
2024-06-07 21:04:29 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, screenTappedAt position: CGPoint) {
|
2024-06-07 21:04:29 +05:30
|
|
|
// Handle screen tap if necessary
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|
2024-06-07 21:04:29 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, relatedMenuOpenedWithItems items: [JWPlayerKit.JWPlayerItem], withMethod method: JWPlayerKit.JWRelatedInteraction) {
|
2024-06-07 21:04:29 +05:30
|
|
|
print("Related items:", items)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, relatedMenuClosedWithMethod method: JWRelatedInteraction) {
|
|
|
|
|
print("Related menu closed")
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|
|
|
|
|
|
2024-06-07 21:04:29 +05:30
|
|
|
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, relatedItemBeganPlaying item: JWPlayerKit.JWPlayerItem, atIndex index: Int, withMethod method: JWPlayerKit.JWRelatedMethod) {
|
2024-08-17 01:34:28 +05:30
|
|
|
print("Item ", item, index)
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|
2024-08-07 20:21:47 +05:30
|
|
|
|
2024-05-30 19:49:41 +05:30
|
|
|
}
|