Skip to content

Commit

Permalink
Swift style fixes
Browse files Browse the repository at this point in the history
Change-Id: I603054028fd3a77acb9ef062f4b899b585122dd8
ulukaya committed Mar 9, 2017
1 parent 02a1198 commit a6c593e
Showing 13 changed files with 330 additions and 304 deletions.
13 changes: 8 additions & 5 deletions CastVideos-swift/ActionSheet.swift
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Foundation
import UIKit

@@ -59,13 +60,15 @@ class ActionSheet: NSObject, UIAlertViewDelegate {
// iOS 8+ approach.
let controller = UIAlertController(title: title, message: message, preferredStyle: .actionSheet)
for action: ActionSheetAction in actions {
let alertAction = UIAlertAction(title: action.title, style: .default, handler: {(_ unused: UIAlertAction) -> Void in
let alertAction = UIAlertAction(title: action.title,
style: .default, handler: {(_ unused: UIAlertAction) -> Void in
action.trigger()
})
controller.addAction(alertAction)
}
if let cancelButtonText = cancelButtonText {
let cancelAction = UIAlertAction(title: cancelButtonText, style: .cancel, handler: {(_ action: UIAlertAction) -> Void in
let cancelAction = UIAlertAction(title: cancelButtonText, style: .cancel,
handler: {(_ action: UIAlertAction) -> Void in
controller.dismiss(animated: true)
})
controller.addAction(cancelAction)
@@ -78,10 +81,10 @@ class ActionSheet: NSObject, UIAlertViewDelegate {
presentationController.sourceRect = sourceView.bounds
presentationController.permittedArrowDirections = UIPopoverArrowDirection(rawValue: 0)
parent.present(controller, animated: true)
}
else {
} else {
// iOS 7 and below.
let alertView = UIAlertView(title: title!, message: message!, delegate: self, cancelButtonTitle: cancelButtonText, otherButtonTitles: "")
let alertView = UIAlertView(title: title!, message: message!,
delegate: self, cancelButtonTitle: cancelButtonText, otherButtonTitles: "")
indexedActions = [AnyHashable: Any](minimumCapacity: actions.count) as? [Int : ActionSheetAction]
for action: ActionSheetAction in actions {
let position = alertView.addButton(withTitle: action.title)
63 changes: 35 additions & 28 deletions CastVideos-swift/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -11,20 +11,20 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import UIKit
import AVFoundation
import GoogleCast


let kPrefPreloadTime: String = "preload_time_sec"
let kPrefEnableAnalyticsLogging: String = "enable_analytics_logging"
let kPrefEnableSDKLogging: String = "enable_sdk_logging"
let kPrefAppVersion: String = "app_version"
let kPrefSDKVersion: String = "sdk_version"
let kPrefReceiverAppID: String = "receiver_app_id"
let kPrefCustomReceiverSelectedValue: String = "use_custom_receiver_app_id"
let kPrefCustomReceiverAppID: String = "custom_receiver_app_id"
let kPrefEnableMediaNotifications: String = "enable_media_notifications"
let kPrefPreloadTime = "preload_time_sec"
let kPrefEnableAnalyticsLogging = "enable_analytics_logging"
let kPrefEnableSDKLogging = "enable_sdk_logging"
let kPrefAppVersion = "app_version"
let kPrefSDKVersion = "sdk_version"
let kPrefReceiverAppID = "receiver_app_id"
let kPrefCustomReceiverSelectedValue = "use_custom_receiver_app_id"
let kPrefCustomReceiverAppID = "custom_receiver_app_id"
let kPrefEnableMediaNotifications = "enable_media_notifications"

let kApplicationID: String? = nil
let appDelegate = (UIApplication.shared.delegate as? AppDelegate)
@@ -61,8 +61,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}
}


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
populateRegistrationDomain()
let applicationID: String = applicationIDFromUserDefaults()!
if applicationID == "" {
@@ -90,8 +90,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

if useCastContainerViewController {
let appStoryboard = UIStoryboard(name: "Main", bundle: nil)
let navigationController = appStoryboard.instantiateViewController(withIdentifier: "MainNavigation") as! UINavigationController
let castContainerVC = GCKCastContext.sharedInstance().createCastContainerController(for: navigationController) as GCKUICastContainerViewController
guard let navigationController = appStoryboard.instantiateViewController(withIdentifier: "MainNavigation")
as? UINavigationController else { return false }
let castContainerVC = GCKCastContext.sharedInstance().createCastContainerController(for: navigationController)
as GCKUICastContainerViewController
castContainerVC.miniMediaControlsItemEnabled = true
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = castContainerVC
@@ -101,8 +103,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
rootContainerVC?.miniMediaControlsViewEnabled = true
}

NotificationCenter.default.addObserver(self, selector: #selector(syncWithUserDefaults), name: UserDefaults.didChangeNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(presentExpandedMediaControls), name: NSNotification.Name.gckExpandedMediaControlsTriggered, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(syncWithUserDefaults),
name: UserDefaults.didChangeNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(presentExpandedMediaControls),
name: NSNotification.Name.gckExpandedMediaControlsTriggered, object: nil)
firstUserDefaultsSync = true
syncWithUserDefaults()
UIApplication.shared.statusBarStyle = .lightContent
@@ -112,12 +116,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}

func applicationWillTerminate(_ application: UIApplication) {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.gckExpandedMediaControlsTriggered, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.gckExpandedMediaControlsTriggered,
object: nil)
}

func setupCastLogging() {
let logFilter = GCKLoggerFilter()
let classesToLog = ["GCKDeviceScanner", "GCKDeviceProvider", "GCKDiscoveryManager", "GCKCastChannel", "GCKMediaControlChannel", "GCKUICastButton", "GCKUIMediaController", "NSMutableDictionary"]
let classesToLog = ["GCKDeviceScanner", "GCKDeviceProvider", "GCKDiscoveryManager", "GCKCastChannel",
"GCKMediaControlChannel", "GCKUICastButton", "GCKUIMediaController", "NSMutableDictionary"]
logFilter.setLoggingLevel(.verbose, forClasses: classesToLog)
GCKLogger.sharedInstance().filter = logFilter
GCKLogger.sharedInstance().delegate = self
@@ -135,7 +141,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
navigationController = rootContainerVC?.navigationController
}
// NOTE: Why aren't we just setting this to nil?
navigationController?.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
navigationController?.navigationItem.backBarButtonItem =
UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
if let appDelegate = appDelegate, appDelegate.isCastControlBarsEnabled == true {
appDelegate.isCastControlBarsEnabled = false
}
@@ -158,16 +165,16 @@ extension AppDelegate {
userDefaults.synchronize()
}


func loadDefaults(_ appDefaults: inout [String: Any], fromSettingsPage plistName: String, inSettingsBundleAt settingsBundleURL: URL) {
func loadDefaults(_ appDefaults: inout [String: Any], fromSettingsPage plistName: String,
inSettingsBundleAt settingsBundleURL: URL) {
let plistFileName = plistName.appending(".plist")
let settingsDict = NSDictionary(contentsOf: settingsBundleURL.appendingPathComponent(plistFileName))
if let prefSpecifierArray = settingsDict?["PreferenceSpecifiers"] as? [[AnyHashable:Any]] {
for prefItem in prefSpecifierArray {
let prefItemType = prefItem["Type"] as? String
let prefItemKey = prefItem["Key"] as? String
let prefItemDefaultValue = prefItem["DefaultValue"] as? String
if (prefItemType == "PSChildPaneSpecifier") {
if prefItemType == "PSChildPaneSpecifier" {
let prefItemFile = prefItem["File"] as? String
loadDefaults(&appDefaults, fromSettingsPage: prefItemFile!, inSettingsBundleAt: settingsBundleURL)
} else if (prefItemKey != nil) && (prefItemDefaultValue != nil) {
@@ -180,7 +187,7 @@ extension AppDelegate {
func applicationIDFromUserDefaults() -> String? {
let userDefaults = UserDefaults.standard
var prefApplicationID = userDefaults.string(forKey: kPrefReceiverAppID)
if (prefApplicationID == kPrefCustomReceiverSelectedValue) {
if prefApplicationID == kPrefCustomReceiverSelectedValue {
prefApplicationID = userDefaults.string(forKey: kPrefCustomReceiverAppID)
}
if prefApplicationID == nil {
@@ -209,14 +216,14 @@ extension AppDelegate {
// Forcing no logging from the SDK
enableSDKLogging = false
let mediaNotificationsEnabled = userDefaults.bool(forKey: kPrefEnableMediaNotifications)
GCKLogger.sharedInstance().delegate?.logMessage?("Notifications on? \(mediaNotificationsEnabled)", fromFunction: #function)
GCKLogger.sharedInstance().delegate?.logMessage?("Notifications on? \(mediaNotificationsEnabled)",
fromFunction: #function)
if firstUserDefaultsSync || (self.mediaNotificationsEnabled != mediaNotificationsEnabled) {
self.mediaNotificationsEnabled = mediaNotificationsEnabled
if useCastContainerViewController {
let castContainerVC = (window?.rootViewController as? GCKUICastContainerViewController)
castContainerVC?.miniMediaControlsItemEnabled = mediaNotificationsEnabled
}
else {
} else {
let rootContainerVC = (window?.rootViewController as? RootContainerViewController)
rootContainerVC?.miniMediaControlsViewEnabled = mediaNotificationsEnabled
}
@@ -255,7 +262,8 @@ extension AppDelegate: GCKSessionManagerListener {

func showAlert(withTitle title: String, message: String) {
// TODO: Pull this out into a class that either shows an AlertVeiw or a AlertController
let alert = UIAlertView(title: title, message: message, delegate: nil, cancelButtonTitle: "OK", otherButtonTitles: "")
let alert = UIAlertView(title: title, message: message,
delegate: nil, cancelButtonTitle: "OK", otherButtonTitles: "")
alert.show()
}

@@ -273,4 +281,3 @@ extension AppDelegate: GCKUIImagePicker {
}
}
}

94 changes: 46 additions & 48 deletions CastVideos-swift/LocalPlayerView.swift
Original file line number Diff line number Diff line change
@@ -36,13 +36,13 @@ protocol LocalPlayerViewDelegate: NSObjectProtocol {
}

/* Navigation Bar styles/ */
enum LPVNavBarStyle : Int {
enum LPVNavBarStyle: Int {
case lpvNavBarTransparent
case lpvNavBarDefault
}

/* The player state. */
enum LocalPlayerState : Int {
enum LocalPlayerState: Int {
case stopped
case starting
case playing
@@ -63,7 +63,6 @@ class LocalPlayerView: UIView {
// If a seek is currently in progress.
var seeking: Bool = false


/* The aspect ratio constraint for the view. */
@IBOutlet weak var viewAspectRatio: NSLayoutConstraint?
/* The splash image to display before playback or while casting. */
@@ -104,7 +103,8 @@ class LocalPlayerView: UIView {
}
/* YES if the video is fullscreen. */
var isFullscreen: Bool {
let full: Bool = (playerState != .stopped) && UIInterfaceOrientationIsLandscape(UIApplication.shared.statusBarOrientation)
let full: Bool = (playerState != .stopped) &&
UIInterfaceOrientationIsLandscape(UIApplication.shared.statusBarOrientation)
print("fullscreen=\(full)")
return full
}
@@ -169,12 +169,10 @@ class LocalPlayerView: UIView {
func play() {
if seeking {
pendingPlay = true
}
else if playerState == .paused {
} else if playerState == .paused {
mediaPlayer?.play()
playerState = .playing
}
else if playerState == .starting {
} else if playerState == .starting {
playerState = .playing
}

@@ -220,7 +218,6 @@ class LocalPlayerView: UIView {
handleMediaPlaybackEnded()
}


deinit {
purgeMediaPlayer()
NotificationCenter.default.removeObserver(self)
@@ -242,7 +239,8 @@ class LocalPlayerView: UIView {
/* Update the frame for the toolbar. */

func layoutToolbar(_ frame: CGRect) {
toolbarView.frame = CGRect(x: CGFloat(0), y: CGFloat(frame.size.height - CGFloat(kToolbarHeight)), width: CGFloat(frame.size.width), height: CGFloat(kToolbarHeight))
toolbarView.frame = CGRect(x: CGFloat(0), y: CGFloat(frame.size.height - CGFloat(kToolbarHeight)),
width: CGFloat(frame.size.width), height: CGFloat(kToolbarHeight))
}
/* Return the full frame with no offsets. */

@@ -276,7 +274,8 @@ class LocalPlayerView: UIView {
func loadMediaImage() {
if let images = media.metadata?.images(), !images.isEmpty {
let image = images[0] as? GCKImage
GCKCastContext.sharedInstance().imageCache?.fetchImage(for: (image?.url)!, completion: {(_ image: UIImage?) -> Void in
GCKCastContext.sharedInstance().imageCache?.fetchImage(for: (image?.url)!,
completion: {(_ image: UIImage?) -> Void in
self.splashImage.image = image
})
}
@@ -324,16 +323,14 @@ class LocalPlayerView: UIView {
performSeek(toTime: pendingPlayPosition)
pendingPlayPosition = kGCKInvalidTimeInterval
return
}
else {
} else {
activityIndicator.stopAnimating()
}
if pendingPlay {
pendingPlay = false
mediaPlayer?.play()
playerState = .playing
}
else {
} else {
playerState = .paused
}
}
@@ -357,8 +354,7 @@ class LocalPlayerView: UIView {
pendingPlay = false
mediaPlayer?.play()
playerState = .playing
}
else {
} else {
playerState = .paused
}
seeking = false
@@ -383,7 +379,8 @@ class LocalPlayerView: UIView {
streamPosition = CMTimeGetSeconds(time)
guard let streamDuration = streamDuration, let streamPosition = streamPosition else { return }
slider.value = Float(streamPosition)
var remainingTime: TimeInterval = (Float(streamDuration) > Float(streamPosition)) ? (streamDuration - streamPosition) : 0
var remainingTime: TimeInterval = (Float(streamDuration) > Float(streamPosition)) ?
(streamDuration - streamPosition) : 0
if remainingTime > 0 {
remainingTime = -remainingTime
}
@@ -398,8 +395,7 @@ class LocalPlayerView: UIView {
if controlView.isHidden {
didTouchControl(nil)
return nil
}
else if point.y > frame.size.height - CGFloat(kToolbarHeight) {
} else if point.y > frame.size.height - CGFloat(kToolbarHeight) {
return controlView.hitTest(point, with: event)!
}
}
@@ -427,16 +423,13 @@ class LocalPlayerView: UIView {
activityIndicator.startAnimating()
if (mediaPlayer?.currentItem != nil) && !CMTIME_IS_INDEFINITE((mediaPlayer?.currentItem?.duration)!) {
handleMediaPlayerReady()
}
else {
} else {
playerState = .starting
}
}
else if playerState == .playing {
} else if playerState == .playing {
mediaPlayer?.pause()
playerState = .paused
}
else if playerState == .paused {
} else if playerState == .paused {
mediaPlayer?.play()
playerState = .playing
}
@@ -457,12 +450,11 @@ class LocalPlayerView: UIView {
/* On slider value change the movie play time. */

@IBAction func onSliderValueChanged(_ sender: Any) {
if (streamDuration != nil) {
if streamDuration != nil {
let newTime: CMTime = CMTimeMakeWithSeconds(Float64(slider.value), 1)
activityIndicator.startAnimating()
mediaPlayer?.seek(to: newTime)
}
else {
} else {
slider.value = 0
}
}
@@ -476,8 +468,7 @@ class LocalPlayerView: UIView {
splashImage.layer.isHidden = false
mediaPlayerLayer?.isHidden = true
controlView.isHidden = true
}
else if playerState == .playing || playerState == .paused || playerState == .starting {
} else if playerState == .playing || playerState == .paused || playerState == .starting {
// Play or Pause button based on state.
let image: UIImage? = playerState == .paused ? playImage : pauseImage
playButton.setImage(image, for: .normal)
@@ -516,7 +507,9 @@ class LocalPlayerView: UIView {
// Background gradient
let gradient = CAGradientLayer()
gradient.frame = toolbarView.bounds
gradient.colors = [(UIColor.clear.cgColor), (UIColor(red: CGFloat((50 / 255.0)), green: CGFloat((50 / 255.0)), blue: CGFloat((50 / 255.0)), alpha: CGFloat((200 / 255.0))).cgColor)]
gradient.colors = [(UIColor.clear.cgColor), (UIColor(red: CGFloat((50 / 255.0)), green: CGFloat((50 / 255.0)),
blue: CGFloat((50 / 255.0)),
alpha: CGFloat((200 / 255.0))).cgColor)]
gradient.startPoint = CGPoint.zero
gradient.endPoint = CGPoint(x: CGFloat(0), y: CGFloat(1))
// Play/Pause button.
@@ -547,7 +540,8 @@ class LocalPlayerView: UIView {
slider.addTarget(self, action: #selector(onSliderTouchEnded), for: .touchUpOutside)
slider.autoresizingMask = .flexibleWidth
slider.minimumValue = 0
slider.minimumTrackTintColor = UIColor(red: CGFloat(15.0 / 255), green: CGFloat(153.0 / 255), blue: CGFloat(242.0 / 255), alpha: CGFloat(1.0))
slider.minimumTrackTintColor = UIColor(red: CGFloat(15.0 / 255), green: CGFloat(153.0 / 255),
blue: CGFloat(242.0 / 255), alpha: CGFloat(1.0))
slider.translatesAutoresizingMaskIntoConstraints = false
toolbarView.addSubview(playButton)
toolbarView.addSubview(totalTime)
@@ -562,8 +556,10 @@ class LocalPlayerView: UIView {
"-[totalTime(>=40)]-|"
let vlayout: String = "V:|[playButton(==40)]"
viewsDictionary = ["slider": slider, "totalTime": totalTime, "playButton": playButton]
toolbarView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: hlayout, options: .alignAllCenterY, metrics: nil, views: viewsDictionary!))
toolbarView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: vlayout, options: [], metrics: nil, views: viewsDictionary!))
toolbarView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: hlayout, options: .alignAllCenterY,
metrics: nil, views: viewsDictionary!))
toolbarView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: vlayout, options: [],
metrics: nil, views: viewsDictionary!))
}
/* Hide the tool bar, and the navigation controller if in the appropriate state.
* If there has been a recent interaction, retry in kToolbarDelay seconds. */
@@ -576,8 +572,7 @@ class LocalPlayerView: UIView {
if isRecentInteraction {
isRecentInteraction = false
perform(#selector(hideToolBar), with: self, afterDelay: TimeInterval(kToolbarDelay))
}
else {
} else {
UIView.animate(withDuration: 0.5, animations: {() -> Void in
self.toolbarView.alpha = 0
}, completion: {(_ finished: Bool) -> Void in
@@ -608,10 +603,13 @@ class LocalPlayerView: UIView {
print("addMediaPlayerObservers")
// We take a weak reference to self to avoid retain cycles in the block.

mediaTimeObserver = mediaPlayer?.addPeriodicTimeObserver(forInterval: CMTimeMake(1, 1), queue: nil, using: {[weak self] (_ time: CMTime) -> Void in
mediaTimeObserver = mediaPlayer?.addPeriodicTimeObserver(forInterval: CMTimeMake(1, 1),
queue: nil, using: {[weak self] (_ time: CMTime) -> Void in
self?.notifyStreamPositionChanged(time)
})
NotificationCenter.default.addObserver(self, selector: #selector(handleMediaPlaybackEnded), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: mediaPlayer?.currentItem)
NotificationCenter.default.addObserver(self, selector: #selector(handleMediaPlaybackEnded),
name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
object: mediaPlayer?.currentItem)
mediaPlayer?.currentItem?.addObserver(self, forKeyPath: "playbackBufferEmpty", options: .new, context: nil)
mediaPlayer?.currentItem?.addObserver(self, forKeyPath: "playbackLikelyToKeepUp", options: .new, context: nil)
mediaPlayer?.currentItem?.addObserver(self, forKeyPath: "status", options: .new, context: nil)
@@ -621,12 +619,13 @@ class LocalPlayerView: UIView {
func removeMediaPlayerObservers() {
print("removeMediaPlayerObservers")
if observingMediaPlayer {
if (mediaTimeObserver != nil) {
if mediaTimeObserver != nil {
mediaPlayer?.removeTimeObserver(mediaTimeObserver!)
mediaTimeObserver = nil
}
if (mediaPlayer?.currentItem != nil) {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: mediaPlayer?.currentItem)
if mediaPlayer?.currentItem != nil {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
object: mediaPlayer?.currentItem)
}
mediaPlayer?.currentItem?.removeObserver(self, forKeyPath: "playbackBufferEmpty")
mediaPlayer?.currentItem?.removeObserver(self, forKeyPath: "playbackLikelyToKeepUp")
@@ -635,18 +634,17 @@ class LocalPlayerView: UIView {
}
}

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
override func observeValue(forKeyPath keyPath: String?, of object: Any?,
change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
print("observeValueForKeyPath \(keyPath)")
guard let currentItem = mediaPlayer?.currentItem, let object = object as? AVPlayerItem, object == currentItem else {
return
}
if (keyPath == "playbackLikelyToKeepUp") {
if keyPath == "playbackLikelyToKeepUp" {
activityIndicator.stopAnimating()
}
else if (keyPath == "playbackBufferEmpty") {
} else if keyPath == "playbackBufferEmpty" {
activityIndicator.startAnimating()
}
else if (keyPath == "status") {
} else if keyPath == "status" {
if mediaPlayer?.status == .readyToPlay {
handleMediaPlayerReady()
}
2 changes: 1 addition & 1 deletion CastVideos-swift/MediaItem.swift
Original file line number Diff line number Diff line change
@@ -11,10 +11,10 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Foundation
import GoogleCast


/**
* An object representing a media item (or a container group of media items).
*/
114 changes: 57 additions & 57 deletions CastVideos-swift/MediaListModel.swift
Original file line number Diff line number Diff line change
@@ -11,85 +11,86 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Foundation
import GoogleCast

/** A key for the URL of the media item's poster (large image). */
let kMediaKeyPosterURL: String = "posterUrl"
let kMediaKeyPosterURL = "posterUrl"
/** A key for the media item's extended description. */
let kMediaKeyDescription: String = "description"
let kMediaKeyDescription = "description"

let kKeyCategories: String = "categories"
let kKeyCategories = "categories"

let kKeyMP4BaseURL: String = "mp4"
let kKeyMP4BaseURL = "mp4"

let kKeyImagesBaseURL: String = "images"
let kKeyImagesBaseURL = "images"

let kKeyTracksBaseURL: String = "tracks"
let kKeyTracksBaseURL = "tracks"

let kKeySources: String = "sources"
let kKeySources = "sources"

let kKeyVideos: String = "videos"
let kKeyVideos = "videos"

let kKeyArtist: String = "artist"
let kKeyArtist = "artist"

let kKeyBaseURL: String = "baseUrl"
let kKeyBaseURL = "baseUrl"

let kKeyContentID: String = "contentId"
let kKeyContentID = "contentId"

let kKeyDescription: String = "description"
let kKeyDescription = "description"

let kKeyID: String = "id"
let kKeyID = "id"

let kKeyImageURL: String = "image-480x270"
let kKeyImageURL = "image-480x270"

let kKeyItems: String = "items"
let kKeyItems = "items"

let kKeyLanguage: String = "language"
let kKeyLanguage = "language"

let kKeyMimeType: String = "mime"
let kKeyMimeType = "mime"

let kKeyName: String = "name"
let kKeyName = "name"

let kKeyPosterURL: String = "image-780x1200"
let kKeyPosterURL = "image-780x1200"

let kKeyStreamType: String = "streamType"
let kKeyStreamType = "streamType"

let kKeyStudio: String = "studio"
let kKeyStudio = "studio"

let kKeySubtitle: String = "subtitle"
let kKeySubtitle = "subtitle"

let kKeySubtype: String = "subtype"
let kKeySubtype = "subtype"

let kKeyTitle: String = "title"
let kKeyTitle = "title"

let kKeyTracks: String = "tracks"
let kKeyTracks = "tracks"

let kKeyType: String = "type"
let kKeyType = "type"

let kKeyURL: String = "url"
let kKeyURL = "url"

let kKeyDuration: String = "duration"
let kKeyDuration = "duration"

let kDefaultVideoMimeType: String = "video/mp4"
let kDefaultVideoMimeType = "video/mp4"

let kDefaultTrackMimeType: String = "text/vtt"
let kDefaultTrackMimeType = "text/vtt"

let kTypeAudio: String = "audio"
let kTypeAudio = "audio"

let kTypePhoto: String = "photos"
let kTypePhoto = "photos"

let kTypeVideo: String = "videos"
let kTypeVideo = "videos"

let kTypeLive: String = "live"
let kTypeLive = "live"

let kThumbnailWidth: Int = 480
let kThumbnailWidth = 480

let kThumbnailHeight: Int = 720
let kThumbnailHeight = 720

let kPosterWidth: Int = 780
let kPosterWidth = 780

let kPosterHeight: Int = 1200
let kPosterHeight = 1200

/**
* The delegate protocol for receiving notifications from the model.
@@ -150,8 +151,6 @@ class MediaListModel: NSObject, NSURLConnectionDelegate, NSURLConnectionDataDele
GCKLogger.sharedInstance().delegate?.logMessage!("loading media list from URL \(url)", fromFunction: #function)
}



override init() {
super.init()

@@ -192,14 +191,14 @@ class MediaListModel: NSObject, NSURLConnectionDelegate, NSURLConnectionDataDele
}

func connectionDidFinishLoading(_ connection: NSURLConnection) {
GCKLogger.sharedInstance().delegate?.logMessage!("httpRequest completed with \(self.responseStatus)", fromFunction: #function)
GCKLogger.sharedInstance().delegate?.logMessage!("httpRequest completed with \(self.responseStatus)",
fromFunction: #function)
if self.responseStatus == 200 {
let jsonData = (try? JSONSerialization.jsonObject(with: self.responseData, options: .mutableContainers))
self.rootItem = self.decodeMediaTree(fromJSON: jsonData! as! NSDictionary)
self.isLoaded = true
self.delegate?.mediaListModelDidLoad(self)
}
else {
} else {
let error = NSError.init(domain: "HTTP", code: self.responseStatus, userInfo: nil)
self.delegate?.mediaListModel(self, didFailToLoadWithError: error)
}
@@ -215,7 +214,7 @@ class MediaListModel: NSObject, NSURLConnectionDelegate, NSURLConnectionDataDele
}
let category = (categoryElement as? NSDictionary)
let mediaList = category?.gck_array(forKey: kKeyVideos)
if (mediaList != nil) {
if mediaList != nil {
self.title = (category?.gck_string(forKey: kKeyName))!
// Pick the MP4 files only
let videosBaseURLString: String? = category?.gck_string(forKey: kKeyMP4BaseURL)
@@ -224,7 +223,8 @@ class MediaListModel: NSObject, NSURLConnectionDelegate, NSURLConnectionDataDele
let imagesBaseURL = URL(string: imagesBaseURLString!)
let tracksBaseURLString: String? = category?.gck_string(forKey: kKeyTracksBaseURL)
let tracksBaseURL = URL(string: tracksBaseURLString!)
self.decodeItemList(fromArray: mediaList!, into: rootItem, videoFormat: kKeyMP4BaseURL, videosBaseURL: videosBaseURL!, imagesBaseURL: imagesBaseURL!, tracksBaseURL: tracksBaseURL!)
self.decodeItemList(fromArray: mediaList!, into: rootItem, videoFormat: kKeyMP4BaseURL,
videosBaseURL: videosBaseURL!, imagesBaseURL: imagesBaseURL!, tracksBaseURL: tracksBaseURL!)
break
}
}
@@ -235,13 +235,13 @@ class MediaListModel: NSObject, NSURLConnectionDelegate, NSURLConnectionDataDele
guard let string = string else { return nil}
if string.hasPrefix("http://") || string.hasPrefix("https://") {
return URL(string: string)!
}
else {
} else {
return URL(string: string, relativeTo: baseURL)!
}
}

func decodeItemList(fromArray array: [Any], into item: MediaItem, videoFormat: String, videosBaseURL: URL, imagesBaseURL: URL, tracksBaseURL: URL) {
func decodeItemList(fromArray array: [Any], into item: MediaItem, videoFormat: String,
videosBaseURL: URL, imagesBaseURL: URL, tracksBaseURL: URL) {
for element in array {
if let dict = element as? NSDictionary {
let metadata = GCKMediaMetadata(metadataType: .movie)
@@ -254,7 +254,7 @@ class MediaListModel: NSObject, NSURLConnectionDelegate, NSURLConnectionDataDele
for sourceElement in sources {
if let sourceDict = sourceElement as? NSDictionary {
let type: String? = sourceDict.gck_string(forKey: kKeyType)
if (type == videoFormat) {
if type == videoFormat {
mimeType = sourceDict.gck_string(forKey: kKeyMimeType)
let urlText: String? = sourceDict.gck_string(forKey: kKeyURL)
url = self.buildURL(with: urlText, baseURL: videosBaseURL)
@@ -307,32 +307,32 @@ class MediaListModel: NSObject, NSURLConnectionDelegate, NSURLConnectionDataDele
}

func trackType(from string: String) -> GCKMediaTrackType {
if (string == "audio") {
if string == "audio" {
return .audio
}
if (string == "text") {
if string == "text" {
return .text
}
if (string == "video") {
if string == "video" {
return .video
}
return .unknown
}

func textTrackSubtype(from string: String) -> GCKMediaTextTrackSubtype {
if (string == "captions") {
if string == "captions" {
return .captions
}
if (string == "chapters") {
if string == "chapters" {
return .chapters
}
if (string == "descriptions") {
if string == "descriptions" {
return .descriptions
}
if (string == "metadata") {
if string == "metadata" {
return .metadata
}
if (string == "subtitles") {
if string == "subtitles" {
return .subtitles
}
return .unknown
29 changes: 15 additions & 14 deletions CastVideos-swift/MediaQueueViewController.swift
Original file line number Diff line number Diff line change
@@ -14,8 +14,8 @@
import UIKit
import GoogleCast
@objc(MediaQueueViewController)
class MediaQueueViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, GCKSessionManagerListener, GCKRemoteMediaClientListener, GCKRequestDelegate {

class MediaQueueViewController: UIViewController, UITableViewDataSource, UITableViewDelegate,
GCKSessionManagerListener, GCKRemoteMediaClientListener, GCKRequestDelegate {

var timer: Timer!
// Queue
@@ -27,7 +27,6 @@ class MediaQueueViewController: UIViewController, UITableViewDataSource, UITable
var mediaController: GCKUIMediaController!
var queueRequest: GCKRequest!


override func viewDidLoad() {
print("_tableView is \(self.tableView)")
self.tableView.dataSource = self
@@ -57,8 +56,7 @@ class MediaQueueViewController: UIViewController, UITableViewDataSource, UITable
self.tableView.isUserInteractionEnabled = true
if self.mediaClient.mediaStatus?.queueItemCount() == 0 {
self.editButton.isEnabled = false
}
else {
} else {
self.editButton.isEnabled = true
}
self.tableView.reloadData()
@@ -77,16 +75,16 @@ class MediaQueueViewController: UIViewController, UITableViewDataSource, UITable
if self.mediaClient.mediaStatus?.queueItemCount() == 0 {
self.editButton.isEnabled = false
}
}
else {
} else {
self.editButton.title = "Done"
self.tableView.setEditing(true, animated: true)
self.isEditing = true
}
}

func showErrorMessage(_ message: String) {
let alert = UIAlertView(title: NSLocalizedString("Error", comment: ""), message: message, delegate: nil, cancelButtonTitle: NSLocalizedString("OK", comment: ""), otherButtonTitles: "")
let alert = UIAlertView(title: NSLocalizedString("Error", comment: ""), message: message, delegate: nil,
cancelButtonTitle: NSLocalizedString("OK", comment: ""), otherButtonTitles: "")
alert.show()
}

@@ -126,15 +124,16 @@ class MediaQueueViewController: UIViewController, UITableViewDataSource, UITable
let mediaOwner: UILabel? = (cell?.viewWithTag(2) as? UILabel)
mediaOwner?.text = detail
if self.mediaClient.mediaStatus?.currentItemID == item?.itemID {
cell?.backgroundColor = UIColor(red: CGFloat(15.0 / 255), green: CGFloat(153.0 / 255), blue: CGFloat(242.0 / 255), alpha: CGFloat(0.1))
}
else {
cell?.backgroundColor = UIColor(red: CGFloat(15.0 / 255), green: CGFloat(153.0 / 255),
blue: CGFloat(242.0 / 255), alpha: CGFloat(0.1))
} else {
cell?.backgroundColor = nil
}
let imageView = (cell?.contentView.viewWithTag(3) as? UIImageView)
if let images = item?.mediaInformation.metadata?.images(), images.count > 0 {
let image = images[0] as? GCKImage
GCKCastContext.sharedInstance().imageCache?.fetchImage(for: (image?.url)!, completion: {(_ image: UIImage?) -> Void in
GCKCastContext.sharedInstance().imageCache?.fetchImage(for: (image?.url)!,
completion: {(_ image: UIImage?) -> Void in
imageView?.image = image
cell?.setNeedsLayout()
})
@@ -164,7 +163,8 @@ class MediaQueueViewController: UIViewController, UITableViewDataSource, UITable
return .delete
}

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle,
forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete row.
let item: GCKMediaQueueItem? = self.mediaClient.mediaStatus?.queueItem(at: UInt(indexPath.row))
@@ -196,7 +196,8 @@ class MediaQueueViewController: UIViewController, UITableViewDataSource, UITable
self.attach(to: session)
}

func sessionManager(_ sessionManager: GCKSessionManager, didSuspend session: GCKCastSession, with reason: GCKConnectionSuspendReason) {
func sessionManager(_ sessionManager: GCKSessionManager, didSuspend session: GCKCastSession,
with reason: GCKConnectionSuspendReason) {
self.detachFromCastSession()
}

95 changes: 56 additions & 39 deletions CastVideos-swift/MediaTableViewController.swift
Original file line number Diff line number Diff line change
@@ -16,7 +16,8 @@ import GoogleCast
let kPrefMediaListURL: String = "media_list_url"

@objc(MediaTableViewController)
class MediaTableViewController: UITableViewController, GCKSessionManagerListener, MediaListModelDelegate, GCKRequestDelegate {
class MediaTableViewController: UITableViewController, GCKSessionManagerListener,
MediaListModelDelegate, GCKRequestDelegate {
var sessionManager: GCKSessionManager!
var castSession: GCKCastSession!
var rootTitleView: UIImageView!
@@ -28,7 +29,6 @@ class MediaTableViewController: UITableViewController, GCKSessionManagerListener
var queueAdded: Bool = false
var castButton: GCKUICastButton!


/** The media to be displayed. */
var mediaList: MediaListModel?
var rootItem: MediaItem? {
@@ -38,26 +38,31 @@ class MediaTableViewController: UITableViewController, GCKSessionManagerListener
}
}


override func viewDidLoad() {
print("MediaTableViewController - viewDidLoad")
super.viewDidLoad()
self.sessionManager = GCKCastContext.sharedInstance().sessionManager
self.sessionManager.add(self)
self.titleView = self.navigationItem.titleView
self.rootTitleView = UIImageView(image: UIImage(named: "logo_castvideos.png"))
NotificationCenter.default.addObserver(self, selector: #selector(self.loadMediaList), name: UserDefaults.didChangeNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.loadMediaList),
name: UserDefaults.didChangeNotification, object: nil)
if self.rootItem == nil {
self.loadMediaList()
}
self.castButton = GCKUICastButton(frame: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(24), height: CGFloat(24)))
self.castButton = GCKUICastButton(frame: CGRect(x: CGFloat(0), y: CGFloat(0),
width: CGFloat(24), height: CGFloat(24)))
self.castButton.tintColor = UIColor.white
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: self.castButton)
self.queueButton = UIBarButtonItem(image: UIImage(named: "playlist_white.png"), style: .plain, target: self, action: #selector(self.didTapQueueButton))
self.queueButton = UIBarButtonItem(image: UIImage(named: "playlist_white.png"),
style: .plain, target: self, action: #selector(self.didTapQueueButton))
self.tableView.separatorColor = UIColor.clear
NotificationCenter.default.addObserver(self, selector: #selector(self.deviceOrientationDidChange), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.deviceOrientationDidChange),
name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
NotificationCenter.default.addObserver(self, selector: #selector(self.castDeviceDidChange), name: NSNotification.Name.gckCastStateDidChange, object: GCKCastContext.sharedInstance())
NotificationCenter.default.addObserver(self, selector: #selector(self.castDeviceDidChange),
name: NSNotification.Name.gckCastStateDidChange,
object: GCKCastContext.sharedInstance())
}

func castDeviceDidChange(_ notification: Notification) {
@@ -78,8 +83,7 @@ class MediaTableViewController: UITableViewController, GCKSessionManagerListener
barItems?.append(self.queueButton)
self.navigationItem.rightBarButtonItems = barItems
self.queueAdded = true
}
else if !visible && self.queueAdded {
} else if !visible && self.queueAdded {
var barItems = (arrayLiteral: self.navigationItem.rightBarButtonItems)
barItems?.remove(at: barItems?.index(of: self.queueButton) ?? -1)
self.navigationItem.rightBarButtonItems = barItems
@@ -104,8 +108,7 @@ class MediaTableViewController: UITableViewController, GCKSessionManagerListener
// If this is the root group, show stylized application title in the title
// view.
self.navigationItem.titleView = self.rootTitleView
}
else {
} else {
// Otherwise show the title of the group in the title view.
self.navigationItem.titleView = self.titleView
self.title = self.rootItem?.title
@@ -123,7 +126,7 @@ class MediaTableViewController: UITableViewController, GCKSessionManagerListener
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (self.rootItem != nil) {
if self.rootItem != nil {
return self.rootItem!.children.count
} else {
return 0
@@ -151,19 +154,22 @@ class MediaTableViewController: UITableViewController, GCKSessionManagerListener
let titleTextRange = NSRange(location: 0, length: (titleText?.characters.count ?? 0))
attributedText.setAttributes([NSForegroundColorAttributeName: blackColor], range: titleTextRange)
let lightGrayColor = UIColor.lightGray
let ownerTextRange = NSRange(location: (titleText?.characters.count ?? 0) + 1, length: (ownerText?.characters.count ?? 0))
attributedText.setAttributes([NSForegroundColorAttributeName: lightGrayColor, NSFontAttributeName: UIFont.systemFont(ofSize: CGFloat(12))], range: ownerTextRange)
let ownerTextRange = NSRange(location: (titleText?.characters.count ?? 0) + 1,
length: (ownerText?.characters.count ?? 0))
attributedText.setAttributes([NSForegroundColorAttributeName: lightGrayColor,
NSFontAttributeName: UIFont.systemFont(ofSize: CGFloat(12))],
range: ownerTextRange)
mediaTitle?.attributedText = attributedText
mediaOwner?.isHidden = true

if item?.mediaInfo != nil {
cell?.accessoryType = .none
}
else {
} else {
cell?.accessoryType = .disclosureIndicator
}
let imageView: UIImageView? = (cell?.contentView.viewWithTag(3) as? UIImageView)
GCKCastContext.sharedInstance().imageCache?.fetchImage(for: (item?.imageURL)!, completion: {(_ image: UIImage?) -> Void in
GCKCastContext.sharedInstance().imageCache?.fetchImage(for: (item?.imageURL)!,
completion: {(_ image: UIImage?) -> Void in
imageView?.image = image
cell?.setNeedsLayout()
})
@@ -172,8 +178,7 @@ class MediaTableViewController: UITableViewController, GCKSessionManagerListener
if hasConnectedCastSession {
addButton?.isHidden = false
addButton?.addTarget(self, action: #selector(self.playButtonClicked), for: .touchDown)
}
else {
} else {
addButton?.isHidden = true
}
return cell!
@@ -187,28 +192,32 @@ class MediaTableViewController: UITableViewController, GCKSessionManagerListener
if (selectedItem.mediaInfo != nil) && hasConnectedCastSession {
// Display an popover to allow the user to add to queue or play
// immediately.
if (self.actionSheet == nil) {
if self.actionSheet == nil {
self.actionSheet = ActionSheet(title: "Play Item", message: "Select an action", cancelButtonText: "Cancel")
self.actionSheet.addAction(withTitle: "Play Now", target: self, selector: #selector(self.playSelectedItemRemotely))
self.actionSheet.addAction(withTitle: "Add to Queue", target: self, selector: #selector(self.enqueueSelectedItemRemotely))
self.actionSheet.addAction(withTitle: "Play Now", target: self,
selector: #selector(self.playSelectedItemRemotely))
self.actionSheet.addAction(withTitle: "Add to Queue", target: self,
selector: #selector(self.enqueueSelectedItemRemotely))
}
self.actionSheet.present(in: self, sourceView: tableViewCell!)
}
}
// TODO

@IBAction func playButtonClickedOld(_ sender: Any) {
let tableViewCell = (sender as AnyObject).superview??.superview as! UITableViewCell
guard let tableViewCell = (sender as AnyObject).superview??.superview as? UITableViewCell else { return }
var indexPathForCell: IndexPath? = self.tableView.indexPath(for: tableViewCell)
selectedItem = (self.rootItem?.children[(indexPathForCell?.row)!] as? MediaItem)
let isHasConnectedCastSession: Bool = GCKCastContext.sharedInstance().sessionManager.hasConnectedCastSession()
if (selectedItem.mediaInfo != nil) && isHasConnectedCastSession {
// Display an alert box to allow the user to add to queue or play
// immediately.
if (self.actionSheet == nil) {
if self.actionSheet == nil {
self.actionSheet = ActionSheet(title: "Play Item", message: "Select an action", cancelButtonText: "Cancel")
self.actionSheet.addAction(withTitle: "Play Now", target: self, selector: #selector(self.playSelectedItemRemotely))
self.actionSheet.addAction(withTitle: "Add to Queue", target: self, selector: #selector(self.enqueueSelectedItemRemotely))
self.actionSheet.addAction(withTitle: "Play Now", target: self,
selector: #selector(self.playSelectedItemRemotely))
self.actionSheet.addAction(withTitle: "Add to Queue", target: self,
selector: #selector(self.enqueueSelectedItemRemotely))
}
self.actionSheet.present(in: self, sourceView: tableViewCell)
}
@@ -222,7 +231,7 @@ class MediaTableViewController: UITableViewController, GCKSessionManagerListener

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
print("prepareForSegue")
if (segue.identifier == "mediaDetails") {
if segue.identifier == "mediaDetails" {
let viewController: MediaViewController? = (segue.destination as? MediaViewController)
if let mediaInfo = self.getSelectedItem().mediaInfo {
viewController?.mediaInfo = mediaInfo
@@ -252,19 +261,21 @@ class MediaTableViewController: UITableViewController, GCKSessionManagerListener
func loadSelectedItem(byAppending appending: Bool) {
print("enqueue item \(selectedItem.mediaInfo)")
if let castSession = GCKCastContext.sharedInstance().sessionManager.currentSession as? GCKCastSession {
if ((castSession.remoteMediaClient) != nil) {
if (castSession.remoteMediaClient) != nil {
let builder = GCKMediaQueueItemBuilder()
builder.mediaInformation = selectedItem.mediaInfo
builder.autoplay = true
builder.preloadTime = TimeInterval(UserDefaults.standard.integer(forKey: kPrefPreloadTime))
let item = builder.build()
if ((castSession.remoteMediaClient?.mediaStatus) != nil) && appending {
let request: GCKRequest? = castSession.remoteMediaClient?.queueInsert(item, beforeItemWithID: kGCKMediaQueueInvalidItemID)
let request: GCKRequest? =
castSession.remoteMediaClient?.queueInsert(item, beforeItemWithID: kGCKMediaQueueInvalidItemID)
request?.delegate = self
}
else {
let repeatMode = (castSession.remoteMediaClient?.mediaStatus != nil) ? castSession.remoteMediaClient?.mediaStatus?.queueRepeatMode : .off
let request = castSession.remoteMediaClient?.queueLoad([item], start: 0, playPosition: 0, repeatMode: repeatMode!, customData: nil)
} else {
let repeatMode = (castSession.remoteMediaClient?.mediaStatus != nil) ?
castSession.remoteMediaClient?.mediaStatus?.queueRepeatMode : .off
let request = castSession.remoteMediaClient?.queueLoad([item], start: 0, playPosition: 0,
repeatMode: repeatMode!, customData: nil)
request?.delegate = self
}
}
@@ -289,7 +300,10 @@ class MediaTableViewController: UITableViewController, GCKSessionManagerListener

func mediaListModel(_ list: MediaListModel, didFailToLoadWithError error: Error?) {
let errorMessage: String = "Unable to load the media list from\n\(self.mediaListURL.absoluteString)."
let alert = UIAlertView(title: NSLocalizedString("Cast Error", comment: ""), message: NSLocalizedString(errorMessage, comment: ""), delegate: nil, cancelButtonTitle: NSLocalizedString("OK", comment: ""), otherButtonTitles: "")
let alert = UIAlertView(title: NSLocalizedString("Cast Error", comment: ""),
message: NSLocalizedString(errorMessage, comment: ""),
delegate: nil, cancelButtonTitle: NSLocalizedString("OK", comment: ""),
otherButtonTitles: "")
alert.show()
}

@@ -299,7 +313,7 @@ class MediaTableViewController: UITableViewController, GCKSessionManagerListener
let urlKey: String? = userDefaults.string(forKey: kPrefMediaListURL)
let urlText: String? = userDefaults.string(forKey: urlKey!)
let mediaListURL = URL(string: urlText!)
if (mediaListURL == self.mediaListURL) {
if mediaListURL == self.mediaListURL {
// The URL hasn't changed; do nothing.
return
}
@@ -341,14 +355,17 @@ class MediaTableViewController: UITableViewController, GCKSessionManagerListener
self.tableView.reloadData()
}

func sessionManager(_ sessionManager: GCKSessionManager, didFailToResumeSession session: GCKSession, withError error: Error?) {
Toast.displayMessage("The Casting session could not be resumed.", for: 3, in: (UIApplication.shared.delegate?.window)!)
func sessionManager(_ sessionManager: GCKSessionManager,
didFailToResumeSession session: GCKSession, withError error: Error?) {
Toast.displayMessage("The Casting session could not be resumed.",
for: 3, in: (UIApplication.shared.delegate?.window)!)
self.setQueueButtonVisible(false)
self.tableView.reloadData()
}

func showAlert(withTitle title: String, message: String) {
let alert = UIAlertView(title: title, message: message, delegate: nil, cancelButtonTitle: "OK", otherButtonTitles: "")
let alert = UIAlertView(title: title, message: message,
delegate: nil, cancelButtonTitle: "OK", otherButtonTitles: "")
alert.show()
}
// MARK: - GCKRequestDelegate
101 changes: 49 additions & 52 deletions CastVideos-swift/MediaViewController.swift
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@
import UIKit
import GoogleCast
/* The player state. */
enum PlaybackMode : Int {
enum PlaybackMode: Int {
case none = 0
case local
case remote
@@ -25,11 +25,10 @@ let kPrefShowStreamTimeRemaining: String = "show_stream_time_remaining"
@objc(MediaViewController)
class MediaViewController: UIViewController, GCKSessionManagerListener, GCKRemoteMediaClientListener, LocalPlayerViewDelegate, GCKRequestDelegate {


@IBOutlet var _titleLabel: UILabel!
@IBOutlet var _subtitleLabel: UILabel!
@IBOutlet var _descriptionTextView: UITextView!
@IBOutlet var _localPlayerView: LocalPlayerView!
@IBOutlet var titleLabel: UILabel!
@IBOutlet var subtitleLabel: UILabel!
@IBOutlet var descriptionTextView: UITextView!
@IBOutlet var localPlayerView: LocalPlayerView!
var sessionManager: GCKSessionManager!
var castSession: GCKCastSession?
var castMediaController: GCKUIMediaController!
@@ -64,7 +63,7 @@ class MediaViewController: UIViewController, GCKSessionManagerListener, GCKRemot
override func viewDidLoad() {
super.viewDidLoad()
print("in MediaViewController viewDidLoad")
self._localPlayerView.delegate = self
self.localPlayerView.delegate = self
self.castButton = GCKUICastButton(frame: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(24), height: CGFloat(24)))
self.castButton.tintColor = UIColor.white
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: self.castButton)
@@ -85,7 +84,7 @@ class MediaViewController: UIViewController, GCKSessionManagerListener, GCKRemot
print("viewWillAppear; mediaInfo is \(self.mediaInfo), mode is \(self.playbackMode)")
appDelegate?.isCastControlBarsEnabled = true
if (self.playbackMode == .local) && self.localPlaybackImplicitlyPaused {
self._localPlayerView.play()
self.localPlayerView.play()
self.localPlaybackImplicitlyPaused = false
}
// Do we need to switch modes? If we're in remote playback mode but no longer
@@ -95,25 +94,25 @@ class MediaViewController: UIViewController, GCKSessionManagerListener, GCKRemot
if hasConnectedSession && (self.playbackMode != .remote) {
self.populateMediaInfo(false, playPosition: 0)
self.switchToRemotePlayback()
}
else if (self.sessionManager.currentSession == nil) && (self.playbackMode != .local) {
} else if (self.sessionManager.currentSession == nil) && (self.playbackMode != .local) {
self.switchToLocalPlayback()
}

self.sessionManager.add(self)
self.gradient = CAGradientLayer()
self.gradient.colors = [(UIColor.clear.cgColor), (UIColor(red: CGFloat((50 / 255.0)), green: CGFloat((50 / 255.0)), blue: CGFloat((50 / 255.0)), alpha: CGFloat((200 / 255.0))).cgColor)]
self.gradient.colors = [(UIColor.clear.cgColor), (UIColor(red: CGFloat((50 / 255.0)), green: CGFloat((50 / 255.0)),
blue: CGFloat((50 / 255.0)), alpha: CGFloat((200 / 255.0))).cgColor)]
self.gradient.startPoint = CGPoint(x: CGFloat(0), y: CGFloat(1))
self.gradient.endPoint = CGPoint.zero
let orientation: UIInterfaceOrientation = UIApplication.shared.statusBarOrientation
if UIInterfaceOrientationIsLandscape(orientation) {
self.setNavigationBarStyle(.lpvNavBarTransparent)
}
else if self.isResetEdgesOnDisappear {
} else if self.isResetEdgesOnDisappear {
self.setNavigationBarStyle(.lpvNavBarDefault)
}

NotificationCenter.default.addObserver(self, selector: #selector(self.deviceOrientationDidChange), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.deviceOrientationDidChange),
name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
super.viewWillAppear(animated)
}
@@ -124,8 +123,7 @@ class MediaViewController: UIViewController, GCKSessionManagerListener, GCKRemot
barItems?.append(self.queueButton)
self.navigationItem.rightBarButtonItems = barItems
self.queueAdded = true
}
else if !visible && self.queueAdded {
} else if !visible && self.queueAdded {
var barItems = (arrayLiteral: self.navigationItem.rightBarButtonItems)
barItems?.remove(at: barItems?.index(of: self.queueButton) ?? -1)
self.navigationItem.rightBarButtonItems = barItems
@@ -139,9 +137,9 @@ class MediaViewController: UIViewController, GCKSessionManagerListener, GCKRemot
self.setNavigationBarStyle(.lpvNavBarDefault)
switch playbackMode! {
case .local:
if self._localPlayerView.playerState == .playing || self._localPlayerView.playerState == .starting {
if self.localPlayerView.playerState == .playing || self.localPlayerView.playerState == .starting {
self.localPlaybackImplicitlyPaused = true
self._localPlayerView.pause()
self.localPlayerView.pause()
}
default:
// Do nothing.
@@ -159,12 +157,11 @@ class MediaViewController: UIViewController, GCKSessionManagerListener, GCKRemot
let orientation: UIInterfaceOrientation = UIApplication.shared.statusBarOrientation
if UIInterfaceOrientationIsLandscape(orientation) {
self.setNavigationBarStyle(.lpvNavBarTransparent)
}
else if !UIInterfaceOrientationIsLandscape(orientation) || !self._localPlayerView.isPlayingLocally {
} else if !UIInterfaceOrientationIsLandscape(orientation) || !self.localPlayerView.isPlayingLocally {
self.setNavigationBarStyle(.lpvNavBarDefault)
}

self._localPlayerView.orientationChanged()
self.localPlayerView.orientationChanged()
}

func didTapQueueButton(_ sender: Any) {
@@ -196,48 +193,48 @@ class MediaViewController: UIViewController, GCKSessionManagerListener, GCKRemot

func populateMediaInfo(_ autoPlay: Bool, playPosition: TimeInterval) {
print("populateMediaInfo")
self._titleLabel.text = self.mediaInfo?.metadata?.string(forKey: kGCKMetadataKeyTitle)
self.titleLabel.text = self.mediaInfo?.metadata?.string(forKey: kGCKMetadataKeyTitle)
var subtitle = self.mediaInfo?.metadata?.string(forKey: kGCKMetadataKeyArtist)
if subtitle == nil {
subtitle = self.mediaInfo?.metadata?.string(forKey: kGCKMetadataKeyStudio)
}
self._subtitleLabel.text = subtitle
self.subtitleLabel.text = subtitle
let description = self.mediaInfo?.metadata?.string(forKey: kMediaKeyDescription)
self._descriptionTextView.text = description?.replacingOccurrences(of: "\\n", with: "\n")
self._localPlayerView.loadMedia(self.mediaInfo, autoPlay: autoPlay, playPosition: playPosition)
self.descriptionTextView.text = description?.replacingOccurrences(of: "\\n", with: "\n")
self.localPlayerView.loadMedia(self.mediaInfo, autoPlay: autoPlay, playPosition: playPosition)
}

func switchToRemotePlayback() {
print("switchToRemotePlayback; mediaInfo is \(self.mediaInfo)")
if self.playbackMode == .remote {
return
}
if (self.sessionManager.currentSession is GCKCastSession) {
if self.sessionManager.currentSession is GCKCastSession {
self.castSession = (self.sessionManager.currentSession as? GCKCastSession)
}
// If we were playing locally, load the local media on the remote player
if (self.playbackMode == .local) && (self._localPlayerView.playerState != .stopped) && (self.mediaInfo != nil) {
if (self.playbackMode == .local) && (self.localPlayerView.playerState != .stopped) && (self.mediaInfo != nil) {
print("loading media: \(self.mediaInfo)")
let playPosition = self._localPlayerView.streamPosition
let paused: Bool = (self._localPlayerView.playerState == .paused)
let playPosition = self.localPlayerView.streamPosition
let paused: Bool = (self.localPlayerView.playerState == .paused)
let builder = GCKMediaQueueItemBuilder()
builder.mediaInformation = self.mediaInfo
builder.autoplay = !paused
builder.preloadTime = TimeInterval(UserDefaults.standard.integer(forKey: kPrefPreloadTime))
let item: GCKMediaQueueItem? = builder.build()
self.castSession?.remoteMediaClient?.queueLoad([item!], start: 0, playPosition: playPosition!, repeatMode: .off, customData: nil)
}
self._localPlayerView.stop()
self._localPlayerView.showSplashScreen()
self.localPlayerView.stop()
self.localPlayerView.showSplashScreen()
self.setQueueButtonVisible(true)
self.castSession?.remoteMediaClient?.add(self)
self.playbackMode = .remote
}

func clearMetadata() {
self._titleLabel.text = ""
self._subtitleLabel.text = ""
self._descriptionTextView.text = ""
self.titleLabel.text = ""
self.subtitleLabel.text = ""
self.descriptionTextView.text = ""
}

func showAlert(withTitle title: String, message: String) {
@@ -255,7 +252,7 @@ class MediaViewController: UIViewController, GCKSessionManagerListener, GCKRemot
}

func togglePlayPause(_ sender: Any) {
self._localPlayerView.togglePause()
self.localPlayerView.togglePause()
}
// MARK: - GCKSessionManagerListener

@@ -302,11 +299,9 @@ class MediaViewController: UIViewController, GCKSessionManagerListener, GCKRemot
func setNavigationBarStyle(_ style: LPVNavBarStyle) {
if style == .lpvNavBarDefault {
print("setNavigationBarStyle: Default")
}
else if style == .lpvNavBarTransparent {
} else if style == .lpvNavBarTransparent {
print("setNavigationBarStyle: Transparent")
}
else {
} else {
print("setNavigationBarStyle: Unknown - \(style)")
}

@@ -319,8 +314,7 @@ class MediaViewController: UIViewController, GCKSessionManagerListener, GCKRemot
UIApplication.shared.setStatusBarHidden(false, with: .fade)
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
self.isResetEdgesOnDisappear = false
}
else if style == .lpvNavBarTransparent {
} else if style == .lpvNavBarTransparent {
self.edgesForExtendedLayout = .top
self.navigationController?.navigationBar.isTranslucent = true
// Gradient background
@@ -343,8 +337,7 @@ class MediaViewController: UIViewController, GCKSessionManagerListener, GCKRemot
func hideNavigationBar(_ hide: Bool) {
if hide {
print("HIDE NavBar.")
}
else {
} else {
print("SHOW NavBar.")
}
self.navigationController?.navigationBar.isHidden = hide
@@ -358,10 +351,12 @@ class MediaViewController: UIViewController, GCKSessionManagerListener, GCKRemot
// immediately.
if self.actionSheet == nil {
self.actionSheet = ActionSheet(title: "Play Item", message: "Select an action", cancelButtonText: "Cancel")
self.actionSheet.addAction(withTitle: "Play Now", target: self, selector: #selector(self.playSelectedItemRemotely))
self.actionSheet.addAction(withTitle: "Add to Queue", target: self, selector: #selector(self.enqueueSelectedItemRemotely))
self.actionSheet.addAction(withTitle: "Play Now", target: self,
selector: #selector(self.playSelectedItemRemotely))
self.actionSheet.addAction(withTitle: "Add to Queue", target: self,
selector: #selector(self.enqueueSelectedItemRemotely))
}
self.actionSheet.present(in: self, sourceView: self._localPlayerView)
self.actionSheet.present(in: self, sourceView: self.localPlayerView)
return false
}
return true
@@ -388,19 +383,21 @@ class MediaViewController: UIViewController, GCKSessionManagerListener, GCKRemot
func loadSelectedItem(byAppending appending: Bool) {
print("enqueue item \(self.mediaInfo)")
if let castSession = GCKCastContext.sharedInstance().sessionManager.currentSession as? GCKCastSession {
if ((castSession.remoteMediaClient) != nil) {
if (castSession.remoteMediaClient) != nil {
let builder = GCKMediaQueueItemBuilder()
builder.mediaInformation = self.mediaInfo
builder.autoplay = true
builder.preloadTime = TimeInterval(UserDefaults.standard.integer(forKey: kPrefPreloadTime))
let item: GCKMediaQueueItem? = builder.build()
if ((castSession.remoteMediaClient?.mediaStatus) != nil) && appending {
let request: GCKRequest? = castSession.remoteMediaClient?.queueInsert(item!, beforeItemWithID: kGCKMediaQueueInvalidItemID)
let request: GCKRequest? =
castSession.remoteMediaClient?.queueInsert(item!, beforeItemWithID: kGCKMediaQueueInvalidItemID)
request?.delegate = self
}
else {
let repeatMode = (castSession.remoteMediaClient?.mediaStatus != nil) ? castSession.remoteMediaClient?.mediaStatus?.queueRepeatMode : .off
let request: GCKRequest? = castSession.remoteMediaClient?.queueLoad([item!], start: 0, playPosition: 0, repeatMode: repeatMode!, customData: nil)
} else {
let repeatMode = (castSession.remoteMediaClient?.mediaStatus != nil) ?
castSession.remoteMediaClient?.mediaStatus?.queueRepeatMode : .off
let request: GCKRequest? = castSession.remoteMediaClient?.queueLoad([item!], start: 0, playPosition: 0,
repeatMode: repeatMode!, customData: nil)
request?.delegate = self
}
}
21 changes: 10 additions & 11 deletions CastVideos-swift/RootContainerViewController.swift
Original file line number Diff line number Diff line change
@@ -20,8 +20,8 @@ let kCastControlBarsAnimationDuration: TimeInterval = 0.20
class RootContainerViewController: UIViewController, GCKUIMiniMediaControlsViewControllerDelegate {


@IBOutlet weak var _miniMediaControlsContainerView: UIView!
@IBOutlet weak var _miniMediaControlsHeightConstraint: NSLayoutConstraint!
@IBOutlet weak var miniMediaControlsContainerView: UIView!
@IBOutlet weak var miniMediaControlsHeightConstraint: NSLayoutConstraint!
var miniMediaControlsViewController: GCKUIMiniMediaControlsViewController!
var miniMediaControlsViewEnabled: Bool = false {
didSet {
@@ -45,24 +45,22 @@ class RootContainerViewController: UIViewController, GCKUIMiniMediaControlsViewC
}
var isMiniMediaControlsItemEnabled: Bool = false


override func viewDidLoad() {
super.viewDidLoad()
let castContext = GCKCastContext.sharedInstance()
self.miniMediaControlsViewController = castContext.createMiniMediaControlsViewController()
self.miniMediaControlsViewController.delegate = self
self.updateControlBarsVisibility()
self.installViewController(self.miniMediaControlsViewController, inContainerView: self._miniMediaControlsContainerView)
self.installViewController(self.miniMediaControlsViewController, inContainerView: self.miniMediaControlsContainerView)
}
// MARK: - Internal methods

func updateControlBarsVisibility() {
if self.miniMediaControlsViewEnabled && self.miniMediaControlsViewController.active {
self._miniMediaControlsHeightConstraint.constant = self.miniMediaControlsViewController.minHeight
self.view.bringSubview(toFront: self._miniMediaControlsContainerView)
}
else {
self._miniMediaControlsHeightConstraint.constant = 0
self.miniMediaControlsHeightConstraint.constant = self.miniMediaControlsViewController.minHeight
self.view.bringSubview(toFront: self.miniMediaControlsContainerView)
} else {
self.miniMediaControlsHeightConstraint.constant = 0
}
UIView.animate(withDuration: kCastControlBarsAnimationDuration, animations: {() -> Void in
self.view.layoutIfNeeded()
@@ -86,13 +84,14 @@ class RootContainerViewController: UIViewController, GCKUIMiniMediaControlsViewC
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "NavigationVCEmbedSegue") {
if segue.identifier == "NavigationVCEmbedSegue" {
self.navigationController = (segue.destination as? UINavigationController)
}
}
// MARK: - GCKUIMiniMediaControlsViewControllerDelegate

func miniMediaControlsViewController(_ miniMediaControlsViewController: GCKUIMiniMediaControlsViewController, shouldAppear: Bool) {
func miniMediaControlsViewController(_ miniMediaControlsViewController: GCKUIMiniMediaControlsViewController,
shouldAppear: Bool) {
self.updateControlBarsVisibility()
}
}
11 changes: 7 additions & 4 deletions CastVideos-swift/Toast.swift
Original file line number Diff line number Diff line change
@@ -34,7 +34,8 @@ class Toast: UIView {
let toastRect = CGRect(x: horizontalOffset, y: verticalOffset, width: toastWidth, height: toastHeight)
// Init and stylize the toast and message.
let toast = Toast(frame: toastRect)
toast.backgroundColor = UIColor(red: CGFloat((50 / 255.0)), green: CGFloat((50 / 255.0)), blue: CGFloat((50 / 255.0)), alpha: CGFloat(1))
toast.backgroundColor = UIColor(red: CGFloat((50 / 255.0)), green: CGFloat((50 / 255.0)),
blue: CGFloat((50 / 255.0)), alpha: CGFloat(1))
toast.messageLabel = UILabel(frame: CGRect(x: CGFloat(0), y: CGFloat(0), width: toastWidth, height: toastHeight))
toast.messageLabel.text = message
toast.messageLabel.textColor = UIColor.white
@@ -46,9 +47,11 @@ class Toast: UIView {
view.insertSubview(toast, aboveSubview: view.subviews.last!)
activeToast = toast
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
NotificationCenter.default.addObserver(self, selector: #selector(self.orientationChanged), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.orientationChanged),
name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
// Set the toast's timeout
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(timeInterval * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: {() -> Void in
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(timeInterval * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC),
execute: {() -> Void in
toast.removeFromSuperview()
NotificationCenter.default.removeObserver(self)
isToastActive = false
@@ -60,7 +63,7 @@ class Toast: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
50 changes: 25 additions & 25 deletions Classes/MediaViewController.m
Original file line number Diff line number Diff line change
@@ -37,10 +37,10 @@ typedef NS_ENUM(NSInteger, PlaybackMode) {
@interface MediaViewController ()<GCKSessionManagerListener,
GCKRemoteMediaClientListener,
LocalPlayerViewDelegate, GCKRequestDelegate> {
IBOutlet UILabel *_titleLabel;
IBOutlet UILabel *_subtitleLabel;
IBOutlet UITextView *_descriptionTextView;
IBOutlet LocalPlayerView *_localPlayerView;
IBOutlet UILabel *titleLabel;
IBOutlet UILabel *subtitleLabel;
IBOutlet UITextView *descriptionTextView;
IBOutlet LocalPlayerView *localPlayerView;
GCKSessionManager *_sessionManager;
GCKCastSession *_castSession;
GCKUIMediaController *_castMediaController;
@@ -77,7 +77,7 @@ - (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"in MediaViewController viewDidLoad");

_localPlayerView.delegate = self;
localPlayerView.delegate = self;

_castButton =
[[GCKUICastButton alloc] initWithFrame:CGRectMake(0, 0, 24, 24)];
@@ -115,7 +115,7 @@ - (void)viewWillAppear:(BOOL)animated {
appDelegate.castControlBarsEnabled = YES;

if ((_playbackMode == PlaybackModeLocal) && _localPlaybackImplicitlyPaused) {
[_localPlayerView play];
[localPlayerView play];
_localPlaybackImplicitlyPaused = NO;
}

@@ -184,10 +184,10 @@ - (void)viewWillDisappear:(BOOL)animated {
[self setNavigationBarStyle:LPVNavBarDefault];
switch (_playbackMode) {
case PlaybackModeLocal:
if (_localPlayerView.playerState == LocalPlayerStatePlaying ||
_localPlayerView.playerState == LocalPlayerStateStarting) {
if (localPlayerView.playerState == LocalPlayerStatePlaying ||
localPlayerView.playerState == LocalPlayerStateStarting) {
_localPlaybackImplicitlyPaused = YES;
[_localPlayerView pause];
[localPlayerView pause];
}
break;
case PlaybackModeRemote:
@@ -215,11 +215,11 @@ - (void)deviceOrientationDidChange:(NSNotification *)notification {
if (UIInterfaceOrientationIsLandscape(orientation)) {
[self setNavigationBarStyle:LPVNavBarTransparent];
} else if (!UIInterfaceOrientationIsLandscape(orientation) ||
!_localPlayerView.playingLocally) {
!localPlayerView.playingLocally) {
[self setNavigationBarStyle:LPVNavBarDefault];
}

[_localPlayerView orientationChanged];
[localPlayerView orientationChanged];
}

- (void)setMediaInfo:(GCKMediaInformation *)mediaInfo {
@@ -269,22 +269,22 @@ - (void)switchToLocalPlayback {
- (void)populateMediaInfo:(BOOL)autoPlay
playPosition:(NSTimeInterval)playPosition {
NSLog(@"populateMediaInfo");
_titleLabel.text =
titleLabel.text =
[self.mediaInfo.metadata stringForKey:kGCKMetadataKeyTitle];

NSString *subtitle =
[self.mediaInfo.metadata stringForKey:kGCKMetadataKeyArtist];
if (!subtitle) {
subtitle = [self.mediaInfo.metadata stringForKey:kGCKMetadataKeyStudio];
}
_subtitleLabel.text = subtitle;
subtitleLabel.text = subtitle;

NSString *description =
[self.mediaInfo.metadata stringForKey:kMediaKeyDescription];
_descriptionTextView.text =
descriptionTextView.text =
[description stringByReplacingOccurrencesOfString:@"\\n"
withString:@"\n"];
[_localPlayerView loadMedia:self.mediaInfo
[localPlayerView loadMedia:self.mediaInfo
autoPlay:autoPlay
playPosition:playPosition];
}
@@ -302,11 +302,11 @@ - (void)switchToRemotePlayback {

// If we were playing locally, load the local media on the remote player
if ((_playbackMode == PlaybackModeLocal) &&
(_localPlayerView.playerState != LocalPlayerStateStopped) &&
(localPlayerView.playerState != LocalPlayerStateStopped) &&
self.mediaInfo) {
NSLog(@"loading media: %@", self.mediaInfo);
NSTimeInterval playPosition = _localPlayerView.streamPosition;
BOOL paused = (_localPlayerView.playerState == LocalPlayerStatePaused);
NSTimeInterval playPosition = localPlayerView.streamPosition;
BOOL paused = (localPlayerView.playerState == LocalPlayerStatePaused);
GCKMediaQueueItemBuilder *builder = [[GCKMediaQueueItemBuilder alloc] init];
builder.mediaInformation = self.mediaInfo;
builder.autoplay = !paused;
@@ -320,17 +320,17 @@ - (void)switchToRemotePlayback {
repeatMode:GCKMediaRepeatModeOff
customData:nil];
}
[_localPlayerView stop];
[_localPlayerView showSplashScreen];
[localPlayerView stop];
[localPlayerView showSplashScreen];
[self setQueueButtonVisible:YES];
[_castSession.remoteMediaClient addListener:self];
_playbackMode = PlaybackModeRemote;
}

- (void)clearMetadata {
_titleLabel.text = @"";
_subtitleLabel.text = @"";
_descriptionTextView.text = @"";
titleLabel.text = @"";
subtitleLabel.text = @"";
descriptionTextView.text = @"";
}

- (void)showAlertWithTitle:(NSString *)title message:(NSString *)message {
@@ -353,7 +353,7 @@ - (void)finishAdjustingStreamPosition:(id)sender {
}

- (void)togglePlayPause:(id)sender {
[_localPlayerView togglePause];
[localPlayerView togglePause];
}

#pragma mark - GCKSessionManagerListener
@@ -487,7 +487,7 @@ - (BOOL)continueAfterPlayButtonClicked {
target:self
selector:@selector(enqueueSelectedItemRemotely)];
}
[_actionSheet presentInController:self sourceView:_localPlayerView];
[_actionSheet presentInController:self sourceView:localPlayerView];
return NO;
}

24 changes: 12 additions & 12 deletions Classes/RootContainerViewController.m
Original file line number Diff line number Diff line change
@@ -21,9 +21,9 @@

@interface RootContainerViewController ()<
GCKUIMiniMediaControlsViewControllerDelegate> {
__weak IBOutlet UIView *_miniMediaControlsContainerView;
__weak IBOutlet NSLayoutConstraint *_miniMediaControlsHeightConstraint;
GCKUIMiniMediaControlsViewController *_miniMediaControlsViewController;
__weak IBOutlet UIView *miniMediaControlsContainerView;
__weak IBOutlet NSLayoutConstraint *miniMediaControlsHeightConstraint;
GCKUIMiniMediaControlsViewController *miniMediaControlsViewController;
}

@property(nonatomic, weak, readwrite)
@@ -36,13 +36,13 @@ @implementation RootContainerViewController
- (void)viewDidLoad {
[super viewDidLoad];
GCKCastContext *castContext = [GCKCastContext sharedInstance];
_miniMediaControlsViewController =
miniMediaControlsViewController =
[castContext createMiniMediaControlsViewController];
_miniMediaControlsViewController.delegate = self;
miniMediaControlsViewController.delegate = self;

[self updateControlBarsVisibility];
[self installViewController:_miniMediaControlsViewController
inContainerView:_miniMediaControlsContainerView];
[self installViewController:miniMediaControlsViewController
inContainerView:miniMediaControlsContainerView];
}

- (void)setMiniMediaControlsViewEnabled:(BOOL)miniMediaControlsViewEnabled {
@@ -56,12 +56,12 @@ - (void)setMiniMediaControlsViewEnabled:(BOOL)miniMediaControlsViewEnabled {

- (void)updateControlBarsVisibility {
if (self.miniMediaControlsViewEnabled &&
_miniMediaControlsViewController.active) {
_miniMediaControlsHeightConstraint.constant =
_miniMediaControlsViewController.minHeight;
[self.view bringSubviewToFront:_miniMediaControlsContainerView];
miniMediaControlsViewController.active) {
miniMediaControlsHeightConstraint.constant =
miniMediaControlsViewController.minHeight;
[self.view bringSubviewToFront:miniMediaControlsContainerView];
} else {
_miniMediaControlsHeightConstraint.constant = 0;
miniMediaControlsHeightConstraint.constant = 0;
}
[UIView animateWithDuration:kCastControlBarsAnimationDuration
animations:^{
17 changes: 9 additions & 8 deletions Resources/Main.storyboard
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@
<rect key="frame" x="0.0" y="22" width="414" height="80"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="wSy-zd-FfY" id="REg-OY-kXt">
<rect key="frame" x="0.0" y="0.0" width="414" height="79.5"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="79"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView userInteractionEnabled="NO" tag="3" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Sqf-Ut-xUR" customClass="GCKUIImageView">
@@ -193,10 +193,10 @@
</view>
<extendedEdge key="edgesForExtendedLayout" bottom="YES"/>
<connections>
<outlet property="_descriptionTextView" destination="Dal-Sb-jv1" id="oRR-X7-mwe"/>
<outlet property="_localPlayerView" destination="rRF-aW-11A" id="teU-td-kBI"/>
<outlet property="_subtitleLabel" destination="0Bp-Yh-mdK" id="KS3-j1-7Ab"/>
<outlet property="_titleLabel" destination="RjS-V6-5ll" id="iu0-lK-JaT"/>
<outlet property="descriptionTextView" destination="Dal-Sb-jv1" id="QHq-3H-kUV"/>
<outlet property="localPlayerView" destination="rRF-aW-11A" id="i6F-Xt-Eyj"/>
<outlet property="subtitleLabel" destination="0Bp-Yh-mdK" id="2QB-tO-hId"/>
<outlet property="titleLabel" destination="RjS-V6-5ll" id="gYo-f1-TRw"/>
<segue destination="bcu-gx-psd" kind="show" identifier="MediaQueueSegue" id="Pks-CI-9Hx"/>
</connections>
</viewController>
@@ -224,7 +224,7 @@
<rect key="frame" x="0.0" y="28" width="414" height="83"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="pLk-yV-G40" id="BO1-ic-xQq">
<rect key="frame" x="0.0" y="0.0" width="414" height="82.5"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="82"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView userInteractionEnabled="NO" tag="3" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="9C2-mo-1SA" customClass="GCKUIImageView">
@@ -306,6 +306,7 @@
</textAttributes>
</navigationBar>
<toolbar key="toolbar" opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="2hi-Oz-8kL">
<rect key="frame" x="0.0" y="0.0" width="1000" height="1000"/>
<autoresizingMask key="autoresizingMask"/>
</toolbar>
<connections>
@@ -364,8 +365,8 @@
</variation>
</view>
<connections>
<outlet property="_miniMediaControlsContainerView" destination="JWd-gG-RgK" id="Z2D-Xo-QLQ"/>
<outlet property="_miniMediaControlsHeightConstraint" destination="Dff-b3-8s0" id="1Th-Hs-cSK"/>
<outlet property="miniMediaControlsContainerView" destination="JWd-gG-RgK" id="Qke-Ab-ozn"/>
<outlet property="miniMediaControlsHeightConstraint" destination="Dff-b3-8s0" id="Liz-ua-yNF"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="k0B-Qk-DjH" userLabel="First Responder" sceneMemberID="firstResponder"/>

0 comments on commit a6c593e

Please sign in to comment.