Commit d3abc716 authored by Soomin Lee's avatar Soomin Lee

Chromecast: Initial integration

parent a0520be1
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13189.4" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait"> <device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/> <adaptation id="fullscreen"/>
</device> </device>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13165.3"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<objects> <objects>
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews> <subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Sdb-a5-RTT"> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Sdb-a5-RTT">
<rect key="frame" x="662" y="5" width="30" height="30"/> <rect key="frame" x="670" y="5" width="30" height="30"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="30" id="Ap6-VL-6UH"/> <constraint firstAttribute="height" constant="30" id="Ap6-VL-6UH"/>
<constraint firstAttribute="width" constant="30" id="dEx-l7-vH3"/> <constraint firstAttribute="width" constant="30" id="dEx-l7-vH3"/>
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
</connections> </connections>
</button> </button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="x1t-3m-s0G"> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="x1t-3m-s0G">
<rect key="frame" x="618" y="5" width="44" height="30"/> <rect key="frame" x="626" y="5" width="44" height="30"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="30" id="fv5-Cp-MOv"/> <constraint firstAttribute="height" constant="30" id="fv5-Cp-MOv"/>
</constraints> </constraints>
...@@ -76,7 +76,7 @@ ...@@ -76,7 +76,7 @@
</connections> </connections>
</button> </button>
<slider opaque="NO" contentMode="scaleToFill" semanticContentAttribute="playback" insetsLayoutMarginsFromSafeArea="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="axb-6M-lSX" userLabel="Position Slider" customClass="VLCOBSlider"> <slider opaque="NO" contentMode="scaleToFill" semanticContentAttribute="playback" insetsLayoutMarginsFromSafeArea="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="axb-6M-lSX" userLabel="Position Slider" customClass="VLCOBSlider">
<rect key="frame" x="28" y="5" width="584" height="31"/> <rect key="frame" x="28" y="5" width="592" height="31"/>
<accessibility key="accessibilityConfiguration"> <accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" updatesFrequently="YES"/> <accessibilityTraits key="traits" updatesFrequently="YES"/>
</accessibility> </accessibility>
...@@ -99,7 +99,7 @@ ...@@ -99,7 +99,7 @@
<constraint firstItem="axb-6M-lSX" firstAttribute="trailing" secondItem="x1t-3m-s0G" secondAttribute="leading" constant="-8" id="l05-q4-Dha"/> <constraint firstItem="axb-6M-lSX" firstAttribute="trailing" secondItem="x1t-3m-s0G" secondAttribute="leading" constant="-8" id="l05-q4-Dha"/>
<constraint firstItem="x1t-3m-s0G" firstAttribute="centerY" secondItem="SbC-6V-aXT" secondAttribute="centerY" id="mIZ-5x-1r6"/> <constraint firstItem="x1t-3m-s0G" firstAttribute="centerY" secondItem="SbC-6V-aXT" secondAttribute="centerY" id="mIZ-5x-1r6"/>
<constraint firstItem="SBq-Am-6MD" firstAttribute="leading" secondItem="SbC-6V-aXT" secondAttribute="leading" id="mf3-NF-cwy"/> <constraint firstItem="SBq-Am-6MD" firstAttribute="leading" secondItem="SbC-6V-aXT" secondAttribute="leading" id="mf3-NF-cwy"/>
<constraint firstAttribute="trailing" secondItem="Sdb-a5-RTT" secondAttribute="trailing" constant="8" id="uI1-3o-gyT"/> <constraint firstAttribute="trailing" secondItem="Sdb-a5-RTT" secondAttribute="trailing" id="uI1-3o-gyT"/>
<constraint firstItem="axb-6M-lSX" firstAttribute="leading" secondItem="SBq-Am-6MD" secondAttribute="trailing" id="zQP-Wv-QPC"/> <constraint firstItem="axb-6M-lSX" firstAttribute="leading" secondItem="SBq-Am-6MD" secondAttribute="trailing" id="zQP-Wv-QPC"/>
</constraints> </constraints>
<nil key="simulatedStatusBarMetrics"/> <nil key="simulatedStatusBarMetrics"/>
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
"ONE_SPU_TRACK" = "One subtitles track"; "ONE_SPU_TRACK" = "One subtitles track";
"PLAYING_EXTERNALLY_TITLE" = "TV Connected"; "PLAYING_EXTERNALLY_TITLE" = "TV Connected";
"PLAYING_EXTERNALLY_TITLE_CHROMECAST" = "Chromecast Connected";
"PLAYING_EXTERNALLY_DESC" = "This video is playing on the TV"; "PLAYING_EXTERNALLY_DESC" = "This video is playing on the TV";
"VFILTER_HUE" = "Hue"; "VFILTER_HUE" = "Hue";
...@@ -70,6 +71,9 @@ ...@@ -70,6 +71,9 @@
"PRIVATE_PLAYBACK_TOGGLE" = "Private Playback"; "PRIVATE_PLAYBACK_TOGGLE" = "Private Playback";
"SCAN_SUBTITLE_TOGGLE" = "Scan for Subtitles (http-only)"; "SCAN_SUBTITLE_TOGGLE" = "Scan for Subtitles (http-only)";
"BUTTON_RENDERER" = "Casting devices";
"BUTTON_RENDERER_HINT" = "Show a menu of available casting devices";
"UPGRADING_LIBRARY" = "Upgrading Media Library"; "UPGRADING_LIBRARY" = "Upgrading Media Library";
"UNTITLED_SHOW" = "Untitled Show"; "UNTITLED_SHOW" = "Untitled Show";
"UNKNOWN" = "Unknown"; "UNKNOWN" = "Unknown";
...@@ -128,6 +132,7 @@ ...@@ -128,6 +132,7 @@
"SHARING_SUCCESS_CAMERA_ROLL" = "File was successfully saved to the Camera Roll"; "SHARING_SUCCESS_CAMERA_ROLL" = "File was successfully saved to the Camera Roll";
"SECTION_HEADER_LIBRARY" = "Media Library"; "SECTION_HEADER_LIBRARY" = "Media Library";
"HEADER_TITLE_RENDERER" = "Select a casting device";
"SECTION_HEADER_NETWORK" = "Network"; "SECTION_HEADER_NETWORK" = "Network";
"LOCAL_NETWORK" = "Local Network"; "LOCAL_NETWORK" = "Local Network";
......
/*****************************************************************************
* VLCActionSheet.swift
*
* Copyright © 2018 VLC authors and VideoLAN
* Copyright © 2018 Videolabs
*
* Authors: Soomin Lee <bubu@mikan.io>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
import Foundation
import UIKit
@objc protocol VLCActionSheetDataSource {
@objc func numberOfRows() -> Int
@objc func actionSheet(collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
}
@objc protocol VLCActionSheetDelegate {
@objc optional func headerViewTitle() -> String?
@objc func itemAtIndexPath(_ indexPath: IndexPath) -> Any?
@objc func actionSheet(collectionView: UICollectionView, didSelectItem item: Any, At indexPath: IndexPath)
}
// MARK: VLCActionSheet
class VLCActionSheet: UIViewController {
private let cellHeight: CGFloat = 50
@objc weak var dataSource: VLCActionSheetDataSource?
@objc weak var delegate: VLCActionSheetDelegate?
var action: ((_ item: Any) -> Void)?
lazy var backgroundView: UIView = {
let backgroundView = UIView()
backgroundView.isHidden = true
backgroundView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0.6)
backgroundView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.removeActionSheet)))
return backgroundView
}()
lazy var collectionViewLayout: UICollectionViewFlowLayout = {
let collectionViewLayout = UICollectionViewFlowLayout()
collectionViewLayout.minimumLineSpacing = 1
collectionViewLayout.minimumInteritemSpacing = 0
return collectionViewLayout
}()
lazy var collectionView: UICollectionView = {
let collectionView = UICollectionView(frame: UIScreen.main.bounds, collectionViewLayout: collectionViewLayout)
collectionView.delegate = self
collectionView.dataSource = self
collectionView.backgroundColor = .white
collectionView.alwaysBounceVertical = true
collectionView.showsVerticalScrollIndicator = false
collectionView.register(VLCActionSheetCell.self, forCellWithReuseIdentifier: VLCActionSheetCell.identifier)
collectionView.translatesAutoresizingMaskIntoConstraints = false
return collectionView
}()
lazy var headerView: VLCActionSheetSectionHeader = {
let headerView = VLCActionSheetSectionHeader()
headerView.title.text = delegate?.headerViewTitle?() ?? "Default header title"
headerView.title.textColor = .black
headerView.backgroundColor = .white
headerView.translatesAutoresizingMaskIntoConstraints = false
return headerView
}()
lazy var bottomBackgroundView: UIView = {
let bottomBackgroundView = UIView()
bottomBackgroundView.backgroundColor = .white
bottomBackgroundView.translatesAutoresizingMaskIntoConstraints = false
return bottomBackgroundView
}()
lazy var mainStackView: UIStackView = {
let mainStackView = UIStackView()
mainStackView.spacing = 0
mainStackView.axis = .vertical
mainStackView.alignment = .center
mainStackView.translatesAutoresizingMaskIntoConstraints = false
return mainStackView
}()
fileprivate lazy var maxCollectionViewHeightConstraint: NSLayoutConstraint = {
let maxCollectionViewHeightConstraint = collectionView.heightAnchor.constraint(
lessThanOrEqualToConstant: (view.bounds.height / 2) - cellHeight)
return maxCollectionViewHeightConstraint
}()
fileprivate lazy var collectionViewHeightConstraint: NSLayoutConstraint = {
guard let dataSource = dataSource else {
preconditionFailure("VLCActionSheet: Data source not set correctly!")
}
let collectionViewHeightConstraint = collectionView.heightAnchor.constraint(
equalToConstant: CGFloat(dataSource.numberOfRows()) * cellHeight)
collectionViewHeightConstraint.priority = .required - 1
return collectionViewHeightConstraint
}()
fileprivate lazy var bottomBackgroundViewHeightConstraint: NSLayoutConstraint = {
let bottomBackgroundViewHeightConstraint = bottomBackgroundView.heightAnchor.constraint(equalToConstant: cellHeight)
return bottomBackgroundViewHeightConstraint
}()
@objc func removeActionSheet() {
UIView.transition(with: backgroundView, duration: 0.01, options: .transitionCrossDissolve, animations: {
[weak self] in
self?.backgroundView.isHidden = true
}, completion: { [weak self] finished in
self?.presentingViewController?.dismiss(animated: true, completion: nil)
})
}
// MARK: Private methods
fileprivate func setuplHeaderViewConstraints() {
NSLayoutConstraint.activate([
headerView.heightAnchor.constraint(equalToConstant: cellHeight),
headerView.widthAnchor.constraint(equalTo: view.widthAnchor),
])
}
fileprivate func setupCollectionViewConstraints() {
NSLayoutConstraint.activate([
collectionViewHeightConstraint,
maxCollectionViewHeightConstraint,
collectionView.widthAnchor.constraint(equalTo: view.widthAnchor),
])
}
fileprivate func setupBottomBackgroundView() {
NSLayoutConstraint.activate([
bottomBackgroundViewHeightConstraint,
bottomBackgroundView.widthAnchor.constraint(equalTo: view.widthAnchor)
])
}
fileprivate func setupMainStackViewConstraints() {
NSLayoutConstraint.activate([
mainStackView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
mainStackView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
mainStackView.widthAnchor.constraint(equalTo: view.widthAnchor),
mainStackView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
])
}
override func updateViewConstraints() {
super.updateViewConstraints()
if let presentingViewController = presentingViewController, let dataSource = dataSource {
collectionViewHeightConstraint.constant = CGFloat(dataSource.numberOfRows()) * cellHeight
maxCollectionViewHeightConstraint.constant = presentingViewController.view.frame.size.height / 2
collectionView.setNeedsLayout()
collectionView.layoutIfNeeded()
}
}
@available(iOS 11.0, *)
override func viewSafeAreaInsetsDidChange() {
bottomBackgroundViewHeightConstraint.constant = view.safeAreaInsets.bottom
}
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(backgroundView)
view.addSubview(mainStackView)
mainStackView.addArrangedSubview(headerView)
mainStackView.addArrangedSubview(collectionView)
mainStackView.addArrangedSubview(bottomBackgroundView)
backgroundView.frame = UIScreen.main.bounds
setupMainStackViewConstraints()
setupCollectionViewConstraints()
setuplHeaderViewConstraints()
setupBottomBackgroundView()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
mainStackView.isHidden = true
collectionView.reloadData()
updateViewConstraints()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// This is to avoid a horrible visual glitch!
mainStackView.isHidden = false
UIView.transition(with: backgroundView, duration: 0.2, options: .transitionCrossDissolve, animations: { [weak self] in
self?.backgroundView.isHidden = false
}, completion: nil)
let realMainStackView = mainStackView.frame
mainStackView.frame.origin.y += mainStackView.frame.origin.y
UIView.animate(withDuration: 0.6, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseOut, animations: {
[mainStackView] in
mainStackView.frame = realMainStackView
}, completion: nil)
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { [weak self] _ in
self?.maxCollectionViewHeightConstraint.constant = size.height / 2
self?.collectionView.layoutIfNeeded()
})
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
collectionView.collectionViewLayout.invalidateLayout()
}
@objc func setAction(closure action: @escaping (_ item: Any) -> Void) {
self.action = action
}
}
// MARK: UICollectionViewDelegateFlowLayout
extension VLCActionSheet: UICollectionViewDelegateFlowLayout {
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width, height: cellHeight)
}
}
// MARK: UICollectionViewDelegate
extension VLCActionSheet: UICollectionViewDelegate {
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let delegate = delegate, let item = delegate.itemAtIndexPath(indexPath) {
delegate.actionSheet(collectionView: collectionView, didSelectItem: item, At: indexPath)
action?(item)
}
removeActionSheet()
}
}
// MARK: UICollectionViewDataSource
extension VLCActionSheet: UICollectionViewDataSource {
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if let dataSource = dataSource {
return dataSource.numberOfRows()
}
preconditionFailure("VLCActionSheet: No data source")
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let dataSource = dataSource {
return dataSource.actionSheet(collectionView: collectionView, cellForItemAt: indexPath)
}
preconditionFailure("VLCActionSheet: No data source")
}
}
/*****************************************************************************
* VLCActionSheetCell.swift
*
* Copyright © 2018 VLC authors and VideoLAN
* Copyright © 2018 Videolabs
*
* Authors: Soomin Lee <bubu@mikan.io>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
class VLCActionSheetCell: UICollectionViewCell {
static let identifier = "VLCActionSheetCell"
let icon: UIImageView = {
let icon = UIImageView()
icon.translatesAutoresizingMaskIntoConstraints = false
icon.contentMode = .scaleAspectFit
return icon
}()
let name: UILabel = {
let name = UILabel()
name.textColor = .black
name.font = UIFont.systemFont(ofSize: 15)
name.translatesAutoresizingMaskIntoConstraints = false
return name
}()
let stackView: UIStackView = {
let stackView = UIStackView()
stackView.spacing = 15.0
stackView.axis = .horizontal
stackView.alignment = .center
stackView.translatesAutoresizingMaskIntoConstraints = false
return stackView
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupViews()
}
private func setupViews() {
backgroundColor = .white
stackView.addArrangedSubview(icon)
stackView.addArrangedSubview(name)
addSubview(stackView)
var guide: LayoutAnchorContainer = self
if #available(iOS 11.0, *) {
guide = safeAreaLayoutGuide
}
NSLayoutConstraint.activate([
icon.heightAnchor.constraint(equalToConstant: 25),
icon.widthAnchor.constraint(equalTo: icon.heightAnchor),
name.trailingAnchor.constraint(equalTo: stackView.trailingAnchor),
name.centerYAnchor.constraint(equalTo: stackView.centerYAnchor),
stackView.leadingAnchor.constraint(equalTo: guide.leadingAnchor, constant: 20),
stackView.trailingAnchor.constraint(equalTo: guide.trailingAnchor, constant: -20),
stackView.heightAnchor.constraint(equalTo: heightAnchor),
stackView.topAnchor.constraint(equalTo: topAnchor)
])
}
}
/*****************************************************************************
* VLCActionSheetSectionHeader.swift
*
* Copyright © 2018 VLC authors and VideoLAN
* Copyright © 2018 Videolabs
*
* Authors: Soomin Lee <bubu@mikan.io>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
class VLCActionSheetSectionHeader: UIView {
static let identifier = "VLCActionSheetSectionHeader"
let title: UILabel = {
let title = UILabel()
title.font = UIFont.systemFont(ofSize: 13)
title.translatesAutoresizingMaskIntoConstraints = false
return title
}()
let separator: UIView = {
let separator = UIView()
separator.backgroundColor = .lightGray
separator.translatesAutoresizingMaskIntoConstraints = false
return separator
}()
lazy var guide: LayoutAnchorContainer = {
var guide: LayoutAnchorContainer = self
if #available(iOS 11.0, *) {
guide = safeAreaLayoutGuide
}
return guide
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupTitle()
setupSeparator()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupTitle()
setupSeparator()
}
fileprivate func setupSeparator() {
addSubview(separator)
NSLayoutConstraint.activate([
separator.leadingAnchor.constraint(equalTo: guide.leadingAnchor, constant: 20),
separator.trailingAnchor.constraint(equalTo: guide.trailingAnchor, constant: -20),
separator.heightAnchor.constraint(equalToConstant: 0.5),
separator.topAnchor.constraint(equalTo: bottomAnchor, constant: -1)
])
}
fileprivate func setupTitle() {
addSubview(title)
NSLayoutConstraint.activate([
title.leadingAnchor.constraint(equalTo: guide.leadingAnchor, constant: 20),
title.centerYAnchor.constraint(equalTo: centerYAnchor),
title.centerXAnchor.constraint(equalTo: centerXAnchor),
title.topAnchor.constraint(equalTo: topAnchor)
])
}
}
...@@ -72,6 +72,7 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData"; ...@@ -72,6 +72,7 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData";
UIBarButtonItem *_shareBarButtonItem; UIBarButtonItem *_shareBarButtonItem;
UIBarButtonItem *_removeFromFolderBarButtonItem; UIBarButtonItem *_removeFromFolderBarButtonItem;
UIBarButtonItem *_deleteSelectedBarButtonItem; UIBarButtonItem *_deleteSelectedBarButtonItem;
UIBarButtonItem *_rendererBarButton;
NSObject *dragAndDropManager; NSObject *dragAndDropManager;
} }
...@@ -247,6 +248,7 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData"; ...@@ -247,6 +248,7 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData";
self.edgesForExtendedLayout = UIRectEdgeNone; self.edgesForExtendedLayout = UIRectEdgeNone;
[self setupSearchController]; [self setupSearchController];
_rendererBarButton = [[UIBarButtonItem alloc] initWithCustomView:[VLCRendererDiscovererManager.sharedInstance setupRendererButton]];
} }
- (void)setupSearchController - (void)setupSearchController
...@@ -268,6 +270,13 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData"; ...@@ -268,6 +270,13 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData";
[self.collectionView.collectionViewLayout invalidateLayout]; [self.collectionView.collectionViewLayout invalidateLayout];
[self setViewFromDeviceOrientation]; [self setViewFromDeviceOrientation];
[self updateViewsForCurrentDisplayMode]; [self updateViewsForCurrentDisplayMode];
VLCRendererDiscovererManager *manager = VLCRendererDiscovererManager.sharedInstance;
if (manager.discoverers || manager.discoverers.count) {
// No discoverers has yet been started
[manager start];
}
manager.presentingViewController = self;
} }
- (void)viewDidAppear:(BOOL)animated - (void)viewDidAppear:(BOOL)animated
...@@ -408,7 +417,7 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData"; ...@@ -408,7 +417,7 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData";
self.navigationItem.rightBarButtonItems = @[toggleDisplayedView, self.editButtonItem]; self.navigationItem.rightBarButtonItems = @[toggleDisplayedView, self.editButtonItem];
self.displayModeBarButtonItem = toggleDisplayedView; self.displayModeBarButtonItem = toggleDisplayedView;
} else { } else {
self.navigationItem.rightBarButtonItem = self.editButtonItem; self.navigationItem.rightBarButtonItems = @[self.editButtonItem, _rendererBarButton];
} }
} }
if (self.usingTableViewToShowData) { if (self.usingTableViewToShowData) {
...@@ -1032,13 +1041,20 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData"; ...@@ -1032,13 +1041,20 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData";
_isSelected = NO; _isSelected = NO;
UIBarButtonItem *editButton = self.editButtonItem; UIBarButtonItem *editButton = self.editButtonItem;
editButton.tintColor = [UIColor whiteColor]; editButton.tintColor = [UIColor whiteColor];
if (!editing && self.navigationItem.rightBarButtonItems.lastObject == _selectAllBarButtonItem) if (!editing && self.navigationItem.rightBarButtonItems.lastObject == _selectAllBarButtonItem) {
[self.navigationItem setRightBarButtonItems: [self.navigationItem.rightBarButtonItems subarrayWithRange:NSMakeRange(0, self.navigationItem.rightBarButtonItems.count - 1)]]; [self.navigationItem setRightBarButtonItems: [self.navigationItem.rightBarButtonItems subarrayWithRange:NSMakeRange(0, self.navigationItem.rightBarButtonItems.count - 1)]];
else [self.navigationItem setRightBarButtonItems: [self.navigationItem.rightBarButtonItems arrayByAddingObject:_rendererBarButton]];
}
else {
// ugly workaround since the stackview doesn't seems to be working properly
// setRightBarButtonItem doesn't reset it correctly
[self.navigationItem setRightBarButtonItems:@[editButton]];
[self.navigationItem setRightBarButtonItems:editing ? [self.navigationItem.rightBarButtonItems arrayByAddingObject:_selectAllBarButtonItem] : [self.navigationItem rightBarButtonItems] animated:YES]; [self.navigationItem setRightBarButtonItems:editing ? [self.navigationItem.rightBarButtonItems arrayByAddingObject:_selectAllBarButtonItem] : [self.navigationItem rightBarButtonItems] animated:YES];
}
[self setSearchBar:!editing resetContent:!editing]; [self setSearchBar:!editing resetContent:!editing];
self.tableView.allowsMultipleSelectionDuringEditing = editing; self.tableView.allowsMultipleSelectionDuringEditing = editing;
......
...@@ -96,4 +96,6 @@ typedef NS_ENUM(NSInteger, VLCMovieJumpState) { ...@@ -96,4 +96,6 @@ typedef NS_ENUM(NSInteger, VLCMovieJumpState) {
- (void)toggleChapterAndTitleSelector; - (void)toggleChapterAndTitleSelector;
- (void)hideMenu; - (void)hideMenu;
- (void)setupCastWithCurrentRenderer;
@end @end
...@@ -55,7 +55,7 @@ typedef NS_ENUM(NSInteger, VLCPanType) { ...@@ -55,7 +55,7 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
VLCPanTypeProjection VLCPanTypeProjection
}; };
@interface VLCMovieViewController () <UIGestureRecognizerDelegate, VLCMultiSelectionViewDelegate, VLCEqualizerViewUIDelegate, VLCPlaybackControllerDelegate, VLCDeviceMotionDelegate> @interface VLCMovieViewController () <UIGestureRecognizerDelegate, VLCMultiSelectionViewDelegate, VLCEqualizerViewUIDelegate, VLCPlaybackControllerDelegate, VLCDeviceMotionDelegate, VLCRendererDiscovererManagerDelegate>
{ {
BOOL _controlsHidden; BOOL _controlsHidden;
BOOL _videoFiltersHidden; BOOL _videoFiltersHidden;
...@@ -116,6 +116,9 @@ typedef NS_ENUM(NSInteger, VLCPanType) { ...@@ -116,6 +116,9 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
CGPoint _saveLocation; CGPoint _saveLocation;
CGSize _screenPixelSize; CGSize _screenPixelSize;
UIInterfaceOrientation _lockedOrientation; UIInterfaceOrientation _lockedOrientation;
UIStackView *_navigationBarStackView;
UIButton *_rendererButton;
} }
@property (nonatomic, strong) VLCMovieViewControlPanelView *controllerPanel; @property (nonatomic, strong) VLCMovieViewControlPanelView *controllerPanel;
@property (nonatomic, strong) UIPopoverController *masterPopoverController; @property (nonatomic, strong) UIPopoverController *masterPopoverController;
...@@ -193,8 +196,6 @@ typedef NS_ENUM(NSInteger, VLCPanType) { ...@@ -193,8 +196,6 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
name:VLCPlaybackControllerPlaybackDidStop name:VLCPlaybackControllerPlaybackDidStop
object:nil]; object:nil];
_playingExternallyTitle.text = NSLocalizedString(@"PLAYING_EXTERNALLY_TITLE", nil);
_playingExternallyDescription.text = NSLocalizedString(@"PLAYING_EXTERNALLY_DESC", nil);
if ([[UIDevice currentDevice] VLCHasExternalDisplay]) if ([[UIDevice currentDevice] VLCHasExternalDisplay])
[self showOnExternalDisplay]; [self showOnExternalDisplay];
...@@ -241,7 +242,7 @@ typedef NS_ENUM(NSInteger, VLCPanType) { ...@@ -241,7 +242,7 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
_screenPixelSize = CGSizeMake(screenBounds.size.width, screenBounds.size.height); _screenPixelSize = CGSizeMake(screenBounds.size.width, screenBounds.size.height);
[self setupConstraints]; [self setupConstraints];
[self setupRendererDiscovererManager];
} }
- (void)setupGestureRecognizers - (void)setupGestureRecognizers
...@@ -360,7 +361,6 @@ typedef NS_ENUM(NSInteger, VLCPanType) { ...@@ -360,7 +361,6 @@ typedef NS_ENUM(NSInteger, VLCPanType) {