arielgk
10/16/2017 - 4:19 AM

YouTubePlayerViaTVJS.swift

//
//  Created by Nick Vance on 12/4/15.
//  Modified by Ryan Reece on 11/14/16.
//

import AVKit
import XCDYouTubeKit
import TVMLKit

class YTPlayerViewController: AVPlayerViewController, AVPlayerViewControllerDelegate {
    
    struct YouTubeVideoQuality {
        static let hd720 = NSNumber(value: XCDYouTubeVideoQuality.HD720.rawValue)
        static let medium360 = NSNumber(value: XCDYouTubeVideoQuality.medium360.rawValue)
        static let small240 = NSNumber(value: XCDYouTubeVideoQuality.small240.rawValue)
    }
    
    //call this method once after setting up your appController.
    func createPlayYT( appController:TVApplicationController ){
        
        //allows us to access the javascript context
        appController.evaluate(inJavaScriptContext: {(evaluation: JSContext) -> Void in
            
            //this is the block that will be called when javascript calls playYTblock(videoIdentifier)
            let playYTblock : @convention(block) (String) -> Void = {
                (videoIdentifier : String) -> Void in
                
                print("Playing YouTube Video with ID:", videoIdentifier)
                
                let playerViewController = AVPlayerViewController()
                
                if var topController = UIApplication.shared.keyWindow?.rootViewController {
                    while let presentedViewController = topController.presentedViewController {
                        topController = presentedViewController
                    }
                    // topController should now be your topmost view controller
                    topController.present(playerViewController, animated: true, completion: nil)
                    
                    XCDYouTubeClient.default().getVideoWithIdentifier(videoIdentifier) { [weak playerViewController] (video: XCDYouTubeVideo?, error: Error?) in
                        
                        if let streamURLs = video?.streamURLs, let streamURL = (streamURLs[XCDYouTubeVideoQualityHTTPLiveStreaming] ?? streamURLs[YouTubeVideoQuality.hd720] ?? streamURLs[YouTubeVideoQuality.medium360] ?? streamURLs[YouTubeVideoQuality.small240]) {
                            playerViewController?.player = AVPlayer(url: streamURL)
                            playerViewController?.player?.play()
                            playerViewController?.player?.actionAtItemEnd = AVPlayerActionAtItemEnd.none
                            
                            NotificationCenter.default.addObserver(self, selector: #selector(self.playerItemDidReachEnd(notification:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: playerViewController?.player?.currentItem)
                            
                        } else {
                            self.dismiss(animated: true, completion: nil)
                        }
                    }
                }
            }
            
            //this creates a function in the javascript context called "playYTblock".
            //calling playYTblock(videoIdentifier) in javascript will call the block we created above.
            evaluation.setObject(unsafeBitCast(playYTblock, to: AnyObject.self), forKeyedSubscript: "playYTblock" as (NSCopying & NSObjectProtocol)!)
            }, completion: {(Bool) -> Void in
                //evaluation block finished running
        })
    }
    
    func playerItemDidReachEnd(notification: NSNotification) {
        print("Video reached end! Dismiss player")
        
        if var topController = UIApplication.shared.keyWindow?.rootViewController {
            while let presentedViewController = topController.presentedViewController {
                topController = presentedViewController
            }
            // topController should now be your topmost view controller
            topController.dismiss(animated: true, completion: nil)
        }
    }
}