Add initial cast device selection view.
This commit is contained in:
parent
0e3cd2c689
commit
3f6e91ef2e
|
@ -19,6 +19,7 @@
|
||||||
5321753B2671BCFC005491E6 /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5321753A2671BCFC005491E6 /* SettingsViewModel.swift */; };
|
5321753B2671BCFC005491E6 /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5321753A2671BCFC005491E6 /* SettingsViewModel.swift */; };
|
||||||
5321753E2671DE9C005491E6 /* Typings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 535870AC2669D8DD00D05A09 /* Typings.swift */; };
|
5321753E2671DE9C005491E6 /* Typings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 535870AC2669D8DD00D05A09 /* Typings.swift */; };
|
||||||
532175402671EE4F005491E6 /* LibraryFilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53E4E646263F6CF100F67C6B /* LibraryFilterView.swift */; };
|
532175402671EE4F005491E6 /* LibraryFilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53E4E646263F6CF100F67C6B /* LibraryFilterView.swift */; };
|
||||||
|
532E68CF267D9F6B007B9F13 /* VideoPlayerCastDeviceSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532E68CE267D9F6B007B9F13 /* VideoPlayerCastDeviceSelector.swift */; };
|
||||||
53313B90265EEA6D00947AA3 /* VideoPlayer.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 53313B8F265EEA6D00947AA3 /* VideoPlayer.storyboard */; };
|
53313B90265EEA6D00947AA3 /* VideoPlayer.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 53313B8F265EEA6D00947AA3 /* VideoPlayer.storyboard */; };
|
||||||
53352571265EA0A0006CCA86 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 53352570265EA0A0006CCA86 /* Introspect */; };
|
53352571265EA0A0006CCA86 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 53352570265EA0A0006CCA86 /* Introspect */; };
|
||||||
5338F74E263B61370014BF09 /* ConnectToServerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5338F74D263B61370014BF09 /* ConnectToServerView.swift */; };
|
5338F74E263B61370014BF09 /* ConnectToServerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5338F74D263B61370014BF09 /* ConnectToServerView.swift */; };
|
||||||
|
@ -242,6 +243,7 @@
|
||||||
53192D5C265AA78A008A4215 /* DeviceProfileBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceProfileBuilder.swift; sourceTree = "<group>"; };
|
53192D5C265AA78A008A4215 /* DeviceProfileBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceProfileBuilder.swift; sourceTree = "<group>"; };
|
||||||
531AC8BE26750DE20091C7EB /* ImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageView.swift; sourceTree = "<group>"; };
|
531AC8BE26750DE20091C7EB /* ImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageView.swift; sourceTree = "<group>"; };
|
||||||
5321753A2671BCFC005491E6 /* SettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewModel.swift; sourceTree = "<group>"; };
|
5321753A2671BCFC005491E6 /* SettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewModel.swift; sourceTree = "<group>"; };
|
||||||
|
532E68CE267D9F6B007B9F13 /* VideoPlayerCastDeviceSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerCastDeviceSelector.swift; sourceTree = "<group>"; };
|
||||||
53313B8F265EEA6D00947AA3 /* VideoPlayer.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = VideoPlayer.storyboard; sourceTree = "<group>"; };
|
53313B8F265EEA6D00947AA3 /* VideoPlayer.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = VideoPlayer.storyboard; sourceTree = "<group>"; };
|
||||||
5338F74D263B61370014BF09 /* ConnectToServerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectToServerView.swift; sourceTree = "<group>"; };
|
5338F74D263B61370014BF09 /* ConnectToServerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectToServerView.swift; sourceTree = "<group>"; };
|
||||||
535870602669D21600D05A09 /* JellyfinPlayer tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "JellyfinPlayer tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
535870602669D21600D05A09 /* JellyfinPlayer tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "JellyfinPlayer tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
@ -649,6 +651,7 @@
|
||||||
625CB5672678B6FB00530A6E /* SplashView.swift */,
|
625CB5672678B6FB00530A6E /* SplashView.swift */,
|
||||||
625CB56B2678C0FD00530A6E /* MainTabView.swift */,
|
625CB56B2678C0FD00530A6E /* MainTabView.swift */,
|
||||||
625CB56E2678C23300530A6E /* HomeView.swift */,
|
625CB56E2678C23300530A6E /* HomeView.swift */,
|
||||||
|
532E68CE267D9F6B007B9F13 /* VideoPlayerCastDeviceSelector.swift */,
|
||||||
);
|
);
|
||||||
path = JellyfinPlayer;
|
path = JellyfinPlayer;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -992,6 +995,7 @@
|
||||||
535BAEA5264A151C005FA86D /* VideoPlayer.swift in Sources */,
|
535BAEA5264A151C005FA86D /* VideoPlayer.swift in Sources */,
|
||||||
62E632E6267D3F5B0063E547 /* EpisodeItemViewModel.swift in Sources */,
|
62E632E6267D3F5B0063E547 /* EpisodeItemViewModel.swift in Sources */,
|
||||||
5321753B2671BCFC005491E6 /* SettingsViewModel.swift in Sources */,
|
5321753B2671BCFC005491E6 /* SettingsViewModel.swift in Sources */,
|
||||||
|
532E68CF267D9F6B007B9F13 /* VideoPlayerCastDeviceSelector.swift in Sources */,
|
||||||
532175402671EE4F005491E6 /* LibraryFilterView.swift in Sources */,
|
532175402671EE4F005491E6 /* LibraryFilterView.swift in Sources */,
|
||||||
5362E50A267D4707000E2F71 /* RequestSink.swift in Sources */,
|
5362E50A267D4707000E2F71 /* RequestSink.swift in Sources */,
|
||||||
5377CC01263B596B003A4E83 /* Model.xcdatamodeld in Sources */,
|
5377CC01263B596B003A4E83 /* Model.xcdatamodeld in Sources */,
|
||||||
|
|
|
@ -141,7 +141,6 @@
|
||||||
</state>
|
</state>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="castButtonPressed:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="LwK-pi-uQ2"/>
|
<action selector="castButtonPressed:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="LwK-pi-uQ2"/>
|
||||||
<action selector="settingsButtonTapped:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="snD-hW-TSY"/>
|
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
|
|
@ -56,11 +56,13 @@ class PlayerViewController: UIViewController, VLCMediaDelegate, VLCMediaPlayerDe
|
||||||
var ssTargetValueOffset: Int = 0
|
var ssTargetValueOffset: Int = 0
|
||||||
var ssStartValue: Int = 0
|
var ssStartValue: Int = 0
|
||||||
var optionsVC: VideoPlayerSettingsView?
|
var optionsVC: VideoPlayerSettingsView?
|
||||||
|
var castDeviceVC: VideoPlayerCastDeviceSelectorView?
|
||||||
|
|
||||||
var paused: Bool = true
|
var paused: Bool = true
|
||||||
var lastTime: Float = 0.0
|
var lastTime: Float = 0.0
|
||||||
var startTime: Int = 0
|
var startTime: Int = 0
|
||||||
var controlsAppearTime: Double = 0
|
var controlsAppearTime: Double = 0
|
||||||
|
var discoveredCastDevices: [CastDevice] = []
|
||||||
|
|
||||||
var selectedAudioTrack: Int32 = -1 {
|
var selectedAudioTrack: Int32 = -1 {
|
||||||
didSet {
|
didSet {
|
||||||
|
@ -175,7 +177,24 @@ class PlayerViewController: UIViewController, VLCMediaDelegate, VLCMediaPlayerDe
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func castButtonPressed(_ sender: Any) {
|
@IBAction func castButtonPressed(_ sender: Any) {
|
||||||
|
castDeviceVC = VideoPlayerCastDeviceSelectorView()
|
||||||
|
castDeviceVC?.delegate = self
|
||||||
|
|
||||||
|
castDeviceVC?.modalPresentationStyle = .popover
|
||||||
|
castDeviceVC?.popoverPresentationController?.sourceView = castButton
|
||||||
|
|
||||||
|
// Present the view controller (in a popover).
|
||||||
|
self.present(castDeviceVC!, animated: true) {
|
||||||
|
print("popover visible, pause playback")
|
||||||
|
self.mediaPlayer.pause()
|
||||||
|
self.mainActionButton.setImage(UIImage(systemName: "play"), for: .normal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func castPopoverDismissed() {
|
||||||
|
castDeviceVC?.dismiss(animated: true, completion: nil)
|
||||||
|
self.mediaPlayer.play()
|
||||||
|
self.mainActionButton.setImage(UIImage(systemName: "pause"), for: .normal)
|
||||||
}
|
}
|
||||||
|
|
||||||
func settingsPopoverDismissed() {
|
func settingsPopoverDismissed() {
|
||||||
|
@ -283,7 +302,7 @@ class PlayerViewController: UIViewController, VLCMediaDelegate, VLCMediaPlayerDe
|
||||||
let scanner = CastDeviceScanner()
|
let scanner = CastDeviceScanner()
|
||||||
|
|
||||||
NotificationCenter.default.addObserver(forName: CastDeviceScanner.deviceListDidChange, object: scanner, queue: nil) { _ in
|
NotificationCenter.default.addObserver(forName: CastDeviceScanner.deviceListDidChange, object: scanner, queue: nil) { _ in
|
||||||
dump(scanner.devices)
|
self.discoveredCastDevices = scanner.devices
|
||||||
if !scanner.devices.isEmpty {
|
if !scanner.devices.isEmpty {
|
||||||
self.castButton.isEnabled = true
|
self.castButton.isEnabled = true
|
||||||
self.castButton.setImage(UIImage(named: "CastDisconnected"), for: .normal)
|
self.castButton.setImage(UIImage(named: "CastDisconnected"), for: .normal)
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/* JellyfinPlayer/Swiftfin is subject to the terms of the Mozilla Public
|
||||||
|
* License, v2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* Copyright 2021 Aiden Vigue & Jellyfin Contributors
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
class VideoPlayerCastDeviceSelectorView: UIViewController {
|
||||||
|
private var contentView: UIHostingController<VideoPlayerCastDeviceSelector>!
|
||||||
|
weak var delegate: PlayerViewController?
|
||||||
|
|
||||||
|
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
||||||
|
.landscape
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
contentView = UIHostingController(rootView: VideoPlayerCastDeviceSelector(delegate: self.delegate ?? PlayerViewController()))
|
||||||
|
self.view.addSubview(contentView.view)
|
||||||
|
contentView.view.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
contentView.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
|
||||||
|
contentView.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
|
||||||
|
contentView.view.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
|
||||||
|
contentView.view.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewWillDisappear(_ animated: Bool) {
|
||||||
|
super.viewWillDisappear(animated)
|
||||||
|
self.delegate?.castPopoverDismissed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VideoPlayerCastDeviceSelector: View {
|
||||||
|
weak var delegate: PlayerViewController!
|
||||||
|
|
||||||
|
init(delegate: PlayerViewController) {
|
||||||
|
self.delegate = delegate
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationView {
|
||||||
|
List(delegate.discoveredCastDevices, id: \.id) { device in
|
||||||
|
Text(device.name)
|
||||||
|
}
|
||||||
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
.navigationTitle("Select Cast Destination")
|
||||||
|
.toolbar {
|
||||||
|
ToolbarItemGroup(placement: .navigationBarLeading) {
|
||||||
|
if UIDevice.current.userInterfaceIdiom == .phone {
|
||||||
|
Button {
|
||||||
|
self.delegate?.castPopoverDismissed()
|
||||||
|
} label: {
|
||||||
|
HStack {
|
||||||
|
Image(systemName: "chevron.left")
|
||||||
|
Text("Back").font(.callout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.offset(y: UIDevice.current.userInterfaceIdiom == .pad ? 14 : 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,6 +12,10 @@ class VideoPlayerSettingsView: UIViewController {
|
||||||
private var contentView: UIHostingController<VideoPlayerSettings>!
|
private var contentView: UIHostingController<VideoPlayerSettings>!
|
||||||
weak var delegate: PlayerViewController?
|
weak var delegate: PlayerViewController?
|
||||||
|
|
||||||
|
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
||||||
|
.landscape
|
||||||
|
}
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
contentView = UIHostingController(rootView: VideoPlayerSettings(delegate: self.delegate ?? PlayerViewController()))
|
contentView = UIHostingController(rootView: VideoPlayerSettings(delegate: self.delegate ?? PlayerViewController()))
|
||||||
|
|
Loading…
Reference in New Issue