import UIKit
import AVFoundation
import AVKit
import AssetsLibrary
import Photos
class PlayerViewController: UIViewController {
//MARK: - Outlet
@IBOutlet weak var lblTitle: UILabel!
@IBOutlet weak var ViewTitle: UIView!
@IBOutlet weak var ViewPlayer: UIView!
@IBOutlet weak var ViewBottom: UIView!
@IBOutlet weak var btnbackword: UIButton!
@IBOutlet weak var btnForword: UIButton!
@IBOutlet weak var btnPlay: UIButton!
@IBOutlet weak var lblTimeRemaining: UILabel!
@IBOutlet weak var SliderSeek: UISlider!
@IBOutlet weak var progressView: UIProgressView!
//MARK: - Properteis
var avPlayer = AVPlayer()
var avPlayerLayer: AVPlayerLayer!
var PlayTemp = false
var index = Int()
var tableDataSource1 = [Video]()
let invisibleButton = UIButton()
var timeObserver: AnyObject!
var CurrentTime : CMTime!
var playerRateBeforeSeek: Float = 0
var VedioPlayerItem : AVPlayerItem!
var urlString : String!
// MARK: - ViewController Method
override func viewDidLoad() {
super.viewDidLoad()
// Rotate
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.shouldRotate = true
// Vedio Title
let title: Video = tableDataSource1[index]
let TitleName = title.title
lblTitle.text = TitleName
// Notification Center
NotificationCenter.default.addObserver(self, selector: #selector(playerItemDidReachEnd), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
print(tableDataSource1)
print(index)
let video: Video = tableDataSource1[index]
let url = URL(string: video.url)
urlString = video.url
// check file exist or not in file manager
let theFileName = (video.url as NSString).lastPathComponent
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
let filePath="\(documentsPath)/\(theFileName)"
print(filePath)
let fileManager = FileManager.default
if fileManager.fileExists(atPath: filePath) {
print(filePath)
VedioPlayerItem = AVPlayerItem(url:NSURL(fileURLWithPath: filePath) as URL)
}
else
{
VedioPlayerItem = AVPlayerItem(url: url!)
}
// setup AvPlayer
//let playerItem = AVPlayerItem(url: url!)
avPlayer = AVPlayer(playerItem: VedioPlayerItem)
avPlayerLayer = AVPlayerLayer(player: avPlayer)
self.ViewPlayer.layer.addSublayer(avPlayerLayer)
avPlayer.isMuted = false
avPlayer.play()
// Setup invisible Button
ViewPlayer.addSubview(invisibleButton)
invisibleButton.addTarget(self, action: #selector(invisibleButtonTapped),
for: .touchUpInside)
// time Interval
let timeInterval: CMTime = CMTimeMakeWithSeconds(1.0, 10)
timeObserver = avPlayer.addPeriodicTimeObserver(forInterval: timeInterval,queue: DispatchQueue.main) {
(elapsedTime: CMTime) -> Void in
self.observeTime(elapsedTime)
} as AnyObject!
// Setup Slider
SliderSeek.addTarget(self, action: #selector(sliderBeganTracking1),
for: .touchDown)
SliderSeek.addTarget(self, action: #selector(sliderEndedTracking),
for: .touchUpInside)
SliderSeek.addTarget(self, action: #selector(sliderEndedTracking),
for: .touchUpOutside)
SliderSeek.addTarget(self, action: #selector(sliderValueChanged),
for: .valueChanged)
SliderSeek.setThumbImage(UIImage(named:"ic_playhead_default"), for: UIControlState())
// Setup navigation
self.title = "Player"
self.navigationController?.navigationBar.barTintColor = UIColor(red: 126/255, green: 174/255, blue: 0/255, alpha: 1)
self.navigationController?.navigationBar.tintColor = UIColor.black
// Setup Progress View
customizeProgressView()
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
// remove Time Observer
avPlayer.removeTimeObserver(timeObserver!)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Back", style: .plain, target: self, action: #selector(BackbuttonTapped))
avPlayer.play()
}
override func viewWillLayoutSubviews() {
// Layout subviews manually
avPlayerLayer.frame = ViewPlayer.bounds
invisibleButton.frame = ViewPlayer.bounds
}
//MARK: - Action
@IBAction func backwordAction(_ sender: UIButton) {
previousTrack()
}
@IBAction func forwordAction(_ sender: UIButton) {
nextTrack()
}
@IBAction func playAction(_ sender: UIButton)
{
let playerIsPlaying = avPlayer.rate > 0
if playerIsPlaying {
avPlayer.pause()
avPlayer.isMuted = true
btnPlay.setImage( imageLiteral(resourceName: "play-button"), for:UIControlState.normal)
} else {
avPlayer.play()
avPlayer.isMuted = false
btnPlay.setImage( imageLiteral(resourceName: "pause"), for:UIControlState.normal)
}
}
// MARK: - Custom Method
func customizeProgressView() {
progressView.layer.cornerRadius = 2
progressView.layer.masksToBounds = true
}
// Back Button
@objc func BackbuttonTapped(){
UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "Orientation")
self.navigationController?.popViewController(animated: true)
avPlayer.pause()
avPlayer.isMuted = true
}
// invisible Button
@objc func invisibleButtonTapped(sender: UIButton) {
let playerIsPlaying = avPlayer.rate > 0
if playerIsPlaying {
avPlayer.pause()
avPlayer.isMuted = true
btnPlay.setImage( imageLiteral(resourceName: "play-button"), for:UIControlState.normal)
} else {
avPlayer.play()
avPlayer.isMuted = false
btnPlay.setImage( imageLiteral(resourceName: "pause"), for:UIControlState.normal)
}
}
// previous
func previousTrack() {
lblTimeRemaining.text = "00:00"
SliderSeek.setValue(00.00, animated: true)
if index - 1 < 0 {
index = (tableDataSource1.count - 1) < 0 ? 0 : (tableDataSource1.count - 1)
print(index)
} else {
index -= 1
print(index)
}
playTrack()
}
// play
func playTrack() {
let video: Video = tableDataSource1[index]
let url = URL(string: video.url)
let theFileName = (video.url as NSString).lastPathComponent
// check file exist or not in file manager
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
let filePath="\(documentsPath)/\(theFileName)"
print(filePath)
let fileManager = FileManager.default
if fileManager.fileExists(atPath: filePath) {
print(filePath)
VedioPlayerItem = AVPlayerItem(url:NSURL(fileURLWithPath: filePath) as URL)
}
else
{
VedioPlayerItem = AVPlayerItem(url: url!)
}
let TitleName = video.title
lblTitle.text = TitleName
if tableDataSource1.count > 0 {
avPlayer.replaceCurrentItem(with: VedioPlayerItem)
avPlayer.play()
}
}
// next
func nextTrack() {
lblTimeRemaining.text = "00:00"
SliderSeek.setValue(00.00, animated: true)
if index + 1 == tableDataSource1.count{
index = 0
}
else if index + 1 > tableDataSource1.count {
index = 0
print(index)
} else {
index += 1;
print(index)
}
playTrack()
}
// deinit
deinit {
avPlayer.removeTimeObserver(timeObserver)
NotificationCenter.default.removeObserver(self)
}
// update Time Label
func updatePlayerTimer(_ elapsedTime: Float64, duration: Float64) {
lblTimeRemaining.text = String(format: "%02d:%02d", ((lround(elapsedTime) / 60) % 60), lround(elapsedTime) % 60)
}
// observe Time
fileprivate func observeTime(_ elapsedTime: CMTime) {
let duration = CMTimeGetSeconds(avPlayer.currentItem!.duration)
if (duration.isFinite) {
let elapsedTime = CMTimeGetSeconds(elapsedTime)
updatePlayerTimer(elapsedTime,duration: duration)
updatePlayerSlider(elapsedTime,duration: duration)
}
}
// slider Began Tracking
@objc func sliderBeganTracking1(slider: UISlider) {
playerRateBeforeSeek = avPlayer.rate
avPlayer.pause()
}
// slider Ended Tracking
@objc func sliderEndedTracking(slider: UISlider) {
if let duration = self.avPlayer.currentItem?.duration {
let videoDuration = CMTimeGetSeconds(duration)
let elapsedTime: Float64 = videoDuration * Float64(slider.value)
updatePlayerTimer(elapsedTime,duration: videoDuration)
avPlayer.seek(to: CMTimeMakeWithSeconds(elapsedTime, 10), completionHandler: { (completed: Bool) -> Void in
if (self.playerRateBeforeSeek > 0) {
if (self.avPlayer != nil) {
self.avPlayer.play()
}
}})
}
SliderSeek.setThumbImage(UIImage(named:"ic_playhead_default"), for: UIControlState())
}
// slider Value Changed
@objc func sliderValueChanged(slider: UISlider) {
if let duration = self.avPlayer.currentItem?.duration {
let videoDuration = CMTimeGetSeconds(duration)
let elapsedTime: Float64 = videoDuration * Float64(slider.value)
updatePlayerTimer(elapsedTime,duration: videoDuration)
}
SliderSeek.setThumbImage(UIImage(named:"ic_playhead_pressed"), for: UIControlState())
}
// player Item Duration
private func playerItemDuration() -> CMTime {
let thePlayerItem = avPlayer.currentItem
if thePlayerItem?.status == .readyToPlay {
return thePlayerItem!.duration
}
return kCMTimeInvalid
}
// player Item Did Reach End
@objc func playerItemDidReachEnd(notification: NSNotification) {
if notification.object as? AVPlayerItem == avPlayer.currentItem {
avPlayer.seek(to: kCMTimeZero)
let urrl = ((avPlayer.currentItem?.asset) as! AVURLAsset).url
let urlString : String = String(describing: urrl)
// get last path of URL
let theFileName = (urlString as NSString).lastPathComponent
DispatchQueue.global(qos: .background).async {
if let url : URL = urrl,
let urlData = NSData(contentsOf: url)
{
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
let filePath="\(documentsPath)/\(theFileName)"
print(filePath)
let fileManager = FileManager.default
if fileManager.fileExists(atPath: filePath) {
print(filePath)
}
else
{
DispatchQueue.main.async {
urlData.write(toFile: filePath, atomically: true)
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: URL(fileURLWithPath: filePath))
}) { completed, error in
if completed {
print(filePath)
print("Video is saved!")
}
if (error != nil) {
print("Video is not saved!")
print(error?.localizedDescription)
}
}
}
}
}
}
}
nextTrack()
}
// update Player Slider
func updatePlayerSlider(_ elapsedTime: Float64, duration: Float64) {
let progress = elapsedTime / duration
SliderSeek.setValue(Float(progress), animated: false)
}
// URLAsset function
lazy var asset: AVURLAsset = {
let video: Video = tableDataSource1[index]
let currVedioURL = URL(string: video.url)
var asset : AVURLAsset = AVURLAsset(url: currVedioURL!)
asset.resourceLoader.setDelegate(self, queue: DispatchQueue.main)
print(currVedioURL!)
return asset
}()
//MARK: - Orientation
override var shouldAutorotate: Bool {
return false
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask{
return .landscapeLeft
}
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation{
return .landscapeLeft
}
}
//MARK: AVAssetResourceLoaderDelegate
extension PlayerViewController : AVAssetResourceLoaderDelegate {
}
Comments
Post a Comment