Commit d3abc716 authored by Soomin Lee's avatar Soomin Lee

Chromecast: Initial integration

parent a0520be1
<?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">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<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"/>
</dependencies>
<objects>
......@@ -21,7 +21,7 @@
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews>
<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>
<constraint firstAttribute="height" constant="30" id="Ap6-VL-6UH"/>
<constraint firstAttribute="width" constant="30" id="dEx-l7-vH3"/>
......@@ -40,7 +40,7 @@
</connections>
</button>
<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>
<constraint firstAttribute="height" constant="30" id="fv5-Cp-MOv"/>
</constraints>
......@@ -76,7 +76,7 @@
</connections>
</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">
<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">
<accessibilityTraits key="traits" updatesFrequently="YES"/>
</accessibility>
......@@ -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="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 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"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
......
......@@ -25,6 +25,7 @@
"ONE_SPU_TRACK" = "One subtitles track";
"PLAYING_EXTERNALLY_TITLE" = "TV Connected";
"PLAYING_EXTERNALLY_TITLE_CHROMECAST" = "Chromecast Connected";
"PLAYING_EXTERNALLY_DESC" = "This video is playing on the TV";
"VFILTER_HUE" = "Hue";
......@@ -70,6 +71,9 @@
"PRIVATE_PLAYBACK_TOGGLE" = "Private Playback";
"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";
"UNTITLED_SHOW" = "Untitled Show";
"UNKNOWN" = "Unknown";
......@@ -128,6 +132,7 @@
"SHARING_SUCCESS_CAMERA_ROLL" = "File was successfully saved to the Camera Roll";
"SECTION_HEADER_LIBRARY" = "Media Library";
"HEADER_TITLE_RENDERER" = "Select a casting device";
"SECTION_HEADER_NETWORK" = "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";
UIBarButtonItem *_shareBarButtonItem;
UIBarButtonItem *_removeFromFolderBarButtonItem;
UIBarButtonItem *_deleteSelectedBarButtonItem;
UIBarButtonItem *_rendererBarButton;
NSObject *dragAndDropManager;
}
......@@ -247,6 +248,7 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData";
self.edgesForExtendedLayout = UIRectEdgeNone;
[self setupSearchController];
_rendererBarButton = [[UIBarButtonItem alloc] initWithCustomView:[VLCRendererDiscovererManager.sharedInstance setupRendererButton]];
}
- (void)setupSearchController
......@@ -268,6 +270,13 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData";
[self.collectionView.collectionViewLayout invalidateLayout];
[self setViewFromDeviceOrientation];
[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
......@@ -408,7 +417,7 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData";
self.navigationItem.rightBarButtonItems = @[toggleDisplayedView, self.editButtonItem];
self.displayModeBarButtonItem = toggleDisplayedView;
} else {
self.navigationItem.rightBarButtonItem = self.editButtonItem;
self.navigationItem.rightBarButtonItems = @[self.editButtonItem, _rendererBarButton];
}
}
if (self.usingTableViewToShowData) {
......@@ -1032,13 +1041,20 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData";
_isSelected = NO;
UIBarButtonItem *editButton = self.editButtonItem;
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)]];
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 setSearchBar:!editing resetContent:!editing];
self.tableView.allowsMultipleSelectionDuringEditing = editing;
......
......@@ -96,4 +96,6 @@ typedef NS_ENUM(NSInteger, VLCMovieJumpState) {
- (void)toggleChapterAndTitleSelector;
- (void)hideMenu;
- (void)setupCastWithCurrentRenderer;
@end
......@@ -55,7 +55,7 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
VLCPanTypeProjection
};
@interface VLCMovieViewController () <UIGestureRecognizerDelegate, VLCMultiSelectionViewDelegate, VLCEqualizerViewUIDelegate, VLCPlaybackControllerDelegate, VLCDeviceMotionDelegate>
@interface VLCMovieViewController () <UIGestureRecognizerDelegate, VLCMultiSelectionViewDelegate, VLCEqualizerViewUIDelegate, VLCPlaybackControllerDelegate, VLCDeviceMotionDelegate, VLCRendererDiscovererManagerDelegate>
{
BOOL _controlsHidden;
BOOL _videoFiltersHidden;
......@@ -116,6 +116,9 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
CGPoint _saveLocation;
CGSize _screenPixelSize;
UIInterfaceOrientation _lockedOrientation;
UIStackView *_navigationBarStackView;
UIButton *_rendererButton;
}
@property (nonatomic, strong) VLCMovieViewControlPanelView *controllerPanel;
@property (nonatomic, strong) UIPopoverController *masterPopoverController;
......@@ -193,8 +196,6 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
name:VLCPlaybackControllerPlaybackDidStop
object:nil];
_playingExternallyTitle.text = NSLocalizedString(@"PLAYING_EXTERNALLY_TITLE", nil);
_playingExternallyDescription.text = NSLocalizedString(@"PLAYING_EXTERNALLY_DESC", nil);
if ([[UIDevice currentDevice] VLCHasExternalDisplay])
[self showOnExternalDisplay];
......@@ -241,7 +242,7 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
_screenPixelSize = CGSizeMake(screenBounds.size.width, screenBounds.size.height);
[self setupConstraints];
[self setupRendererDiscovererManager];
}
- (void)setupGestureRecognizers
......@@ -360,7 +361,6 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
- (void)setupNavigationbar
{
//Needs to be a UIButton since we need it to work with constraints
_doneButton = [[UIButton alloc] initWithFrame:CGRectZero];
[_doneButton addTarget:self action:@selector(closePlayback:) forControlEvents:UIControlEventTouchUpInside];
[_doneButton setTitle:NSLocalizedString(@"BUTTON_DONE", nil) forState:UIControlStateNormal];
......@@ -370,21 +370,34 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
self.timeNavigationTitleView = [[[NSBundle mainBundle] loadNibNamed:@"VLCTimeNavigationTitleView" owner:self options:nil] objectAtIndex:0];
self.timeNavigationTitleView.translatesAutoresizingMaskIntoConstraints = NO;
[self.navigationController.navigationBar addSubview:self.timeNavigationTitleView];
[self.navigationController.navigationBar addSubview:_doneButton];
if (_vpc.renderer != nil) {
[_rendererButton setSelected:YES];
}
_navigationBarStackView = [[UIStackView alloc] init];
_navigationBarStackView.translatesAutoresizingMaskIntoConstraints = NO;
_navigationBarStackView.spacing = 8;
_navigationBarStackView.axis = UILayoutConstraintAxisHorizontal;
_navigationBarStackView.alignment = UIStackViewAlignmentCenter;
[_navigationBarStackView addArrangedSubview:_doneButton];
[_navigationBarStackView addArrangedSubview:_timeNavigationTitleView];
[_navigationBarStackView addArrangedSubview:_rendererButton];
[self.navigationController.navigationBar addSubview:_navigationBarStackView];
NSObject *guide = self.navigationController.navigationBar;
if (@available(iOS 11.0, *)) {
guide = self.navigationController.navigationBar.safeAreaLayoutGuide;
}
[self.navigationController.view addConstraints: @[
[NSLayoutConstraint constraintWithItem:_doneButton attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:guide attribute:NSLayoutAttributeLeft multiplier:1 constant:8],
[NSLayoutConstraint constraintWithItem:_doneButton attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.navigationController.navigationBar attribute:NSLayoutAttributeCenterY multiplier:1 constant:0],
[NSLayoutConstraint constraintWithItem:self.timeNavigationTitleView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:_doneButton attribute:NSLayoutAttributeRight multiplier:1 constant:0],
[NSLayoutConstraint constraintWithItem:self.timeNavigationTitleView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:guide attribute:NSLayoutAttributeRight multiplier:1 constant:0],
[NSLayoutConstraint constraintWithItem:self.timeNavigationTitleView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.navigationController.navigationBar attribute:NSLayoutAttributeTop multiplier:1 constant:0],
[NSLayoutConstraint constraintWithItem:self.timeNavigationTitleView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.navigationController.navigationBar attribute:NSLayoutAttributeBottom multiplier:1 constant:0],
]];
[NSLayoutConstraint activateConstraints:@[
[NSLayoutConstraint constraintWithItem:_navigationBarStackView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.navigationController.navigationBar attribute:NSLayoutAttributeCenterY multiplier:1 constant:0],
[NSLayoutConstraint constraintWithItem:_navigationBarStackView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:guide attribute:NSLayoutAttributeLeft multiplier:1 constant:8],
[NSLayoutConstraint constraintWithItem:_navigationBarStackView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:guide attribute:NSLayoutAttributeRight multiplier:1 constant:-8],
[NSLayoutConstraint constraintWithItem:_navigationBarStackView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.navigationController.navigationBar attribute:NSLayoutAttributeTop multiplier:1 constant:0],
[NSLayoutConstraint constraintWithItem:_navigationBarStackView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.navigationController.navigationBar attribute:NSLayoutAttributeBottom multiplier:1 constant:0],
[NSLayoutConstraint constraintWithItem:_timeNavigationTitleView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:_navigationBarStackView attribute:NSLayoutAttributeHeight multiplier:1 constant:0]
]];
}
- (void)resetVideoFiltersSliders
......@@ -417,6 +430,12 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
[self updateDefaults];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateDefaults) name:NSUserDefaultsDidChangeNotification object:nil];
VLCRendererDiscovererManager *manager = [VLCRendererDiscovererManager sharedInstance];
manager.presentingViewController = self;
manager.delegate = self;
[self hidePlayingExternallyViewForRendererIfNeeded];
}
- (void)viewDidAppear:(BOOL)animated
......@@ -433,6 +452,7 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
//Media is loaded in the media player, checking the projection type and configuring accordingly.
[self setupForMediaProjection];
[VLCRendererDiscovererManager.sharedInstance start];
}
- (void)viewDidLayoutSubviews
......@@ -633,7 +653,8 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
_multiSelectionView.chapterSelectorButton,
_multiSelectionView.repeatButton,
_multiSelectionView.shuffleButton,
_controllerPanel.volumeView]];
_controllerPanel.volumeView,
_rendererButton]];
[[UIDevice currentDevice] isiPhoneX] ? [items addObject:_tapToToggleiPhoneXRatioRecognizer]
: [items addObject:_tapToSeekRecognizer];
......@@ -874,6 +895,7 @@ typedef NS_ENUM(NSInteger, VLCPanType) {
- (IBAction)closePlayback:(id)sender
{
_playbackWillClose = YES;
[self hidePlayingExternallyViewForRendererIfNeeded];
[_vpc stopPlayback];
}
......@@ -1058,6 +1080,10 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
[_controllerPanel updateButtons];
_audioOnly = metadata.isAudioOnly;
if (_audioOnly) {
// fixme: _playingExternallyView should be shown in audioOnly as well
_playingExternallyView.hidden = YES;
}