add keyCommands to VLCPlayerViewController
This commit is contained in:
parent
6bd07817f7
commit
a5fabe3224
|
@ -54,6 +54,8 @@ internal enum L10n {
|
|||
internal static var chapters: String { return L10n.tr("Localizable", "chapters") }
|
||||
/// Cinematic Views
|
||||
internal static var cinematicViews: String { return L10n.tr("Localizable", "cinematicViews") }
|
||||
/// Close
|
||||
internal static var close: String { return L10n.tr("Localizable", "close") }
|
||||
/// Closed Captions
|
||||
internal static var closedCaptions: String { return L10n.tr("Localizable", "closedCaptions") }
|
||||
/// Compact
|
||||
|
@ -122,8 +124,12 @@ internal enum L10n {
|
|||
internal static var information: String { return L10n.tr("Localizable", "information") }
|
||||
/// Items
|
||||
internal static var items: String { return L10n.tr("Localizable", "items") }
|
||||
/// Jump Backward
|
||||
internal static var jumpBackward: String { return L10n.tr("Localizable", "jumpBackward") }
|
||||
/// Jump Backward Length
|
||||
internal static var jumpBackwardLength: String { return L10n.tr("Localizable", "jumpBackwardLength") }
|
||||
/// Jump Forward
|
||||
internal static var jumpForward: String { return L10n.tr("Localizable", "jumpForward") }
|
||||
/// Jump Forward Length
|
||||
internal static var jumpForwardLength: String { return L10n.tr("Localizable", "jumpForwardLength") }
|
||||
/// Jump Gestures Enabled
|
||||
|
@ -176,6 +182,8 @@ internal enum L10n {
|
|||
internal static var networkTimedOut: String { return L10n.tr("Localizable", "networkTimedOut") }
|
||||
/// Next
|
||||
internal static var next: String { return L10n.tr("Localizable", "next") }
|
||||
/// Next Item
|
||||
internal static var nextItem: String { return L10n.tr("Localizable", "nextItem") }
|
||||
/// Next Up
|
||||
internal static var nextUp: String { return L10n.tr("Localizable", "nextUp") }
|
||||
/// No Cast devices found..
|
||||
|
@ -226,6 +234,8 @@ internal enum L10n {
|
|||
internal static var password: String { return L10n.tr("Localizable", "password") }
|
||||
/// Play
|
||||
internal static var play: String { return L10n.tr("Localizable", "play") }
|
||||
/// Play / Pause
|
||||
internal static var playAndPause: String { return L10n.tr("Localizable", "playAndPause") }
|
||||
/// Playback settings
|
||||
internal static var playbackSettings: String { return L10n.tr("Localizable", "playbackSettings") }
|
||||
/// Playback Speed
|
||||
|
@ -242,6 +252,8 @@ internal enum L10n {
|
|||
internal static var present: String { return L10n.tr("Localizable", "present") }
|
||||
/// Press Down for Menu
|
||||
internal static var pressDownForMenu: String { return L10n.tr("Localizable", "pressDownForMenu") }
|
||||
/// Previous Item
|
||||
internal static var previousItem: String { return L10n.tr("Localizable", "previousItem") }
|
||||
/// Programs
|
||||
internal static var programs: String { return L10n.tr("Localizable", "programs") }
|
||||
/// Rated
|
||||
|
|
|
@ -38,4 +38,46 @@ enum PlaybackSpeed: Double, CaseIterable {
|
|||
return "2x"
|
||||
}
|
||||
}
|
||||
|
||||
var previous: PlaybackSpeed? {
|
||||
switch self {
|
||||
case .quarter:
|
||||
return nil
|
||||
case .half:
|
||||
return .quarter
|
||||
case .threeQuarter:
|
||||
return .half
|
||||
case .one:
|
||||
return .threeQuarter
|
||||
case .oneQuarter:
|
||||
return .one
|
||||
case .oneHalf:
|
||||
return .oneQuarter
|
||||
case .oneThreeQuarter:
|
||||
return .oneHalf
|
||||
case .two:
|
||||
return .oneThreeQuarter
|
||||
}
|
||||
}
|
||||
|
||||
var next: PlaybackSpeed? {
|
||||
switch self {
|
||||
case .quarter:
|
||||
return .half
|
||||
case .half:
|
||||
return .threeQuarter
|
||||
case .threeQuarter:
|
||||
return .one
|
||||
case .one:
|
||||
return .oneQuarter
|
||||
case .oneQuarter:
|
||||
return .oneHalf
|
||||
case .oneHalf:
|
||||
return .oneThreeQuarter
|
||||
case .oneThreeQuarter:
|
||||
return .two
|
||||
case .two:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import UIKit
|
|||
// TODO: Look at making the VLC player layer a view
|
||||
|
||||
class VLCPlayerViewController: UIViewController {
|
||||
|
||||
// MARK: variables
|
||||
|
||||
private var viewModel: VideoPlayerViewModel
|
||||
|
@ -50,10 +49,36 @@ class VLCPlayerViewController: UIViewController {
|
|||
private var currentJumpBackwardOverlayView: UIImageView?
|
||||
private var currentJumpForwardOverlayView: UIImageView?
|
||||
|
||||
override var keyCommands: [UIKeyCommand]? {
|
||||
var commands = [
|
||||
UIKeyCommand(title: L10n.playAndPause, action: #selector(didSelectMain), input: " "),
|
||||
UIKeyCommand(title: L10n.jumpForward, action: #selector(didSelectForward), input: UIKeyCommand.inputRightArrow),
|
||||
UIKeyCommand(title: L10n.jumpBackward, action: #selector(didSelectBackward), input: UIKeyCommand.inputLeftArrow),
|
||||
UIKeyCommand(title: L10n.nextItem, action: #selector(didSelectPlayNextItem), input: UIKeyCommand.inputRightArrow,
|
||||
modifierFlags: .command),
|
||||
UIKeyCommand(title: L10n.previousItem, action: #selector(didSelectPlayPreviousItem), input: UIKeyCommand.inputLeftArrow,
|
||||
modifierFlags: .command),
|
||||
UIKeyCommand(title: L10n.close, action: #selector(didSelectClose), input: UIKeyCommand.inputEscape),
|
||||
]
|
||||
if let previous = viewModel.playbackSpeed.previous {
|
||||
commands.append(.init(title: "\(L10n.playbackSpeed) \(previous.displayTitle)",
|
||||
action: #selector(didSelectPreviousPlaybackSpeed), input: "[", modifierFlags: .command))
|
||||
}
|
||||
if let next = viewModel.playbackSpeed.next {
|
||||
commands.append(.init(title: "\(L10n.playbackSpeed) \(next.displayTitle)", action: #selector(didSelectNextPlaybackSpeed),
|
||||
input: "]", modifierFlags: .command))
|
||||
}
|
||||
if viewModel.playbackSpeed != .one {
|
||||
commands.append(.init(title: "\(L10n.playbackSpeed) \(PlaybackSpeed.one.displayTitle)",
|
||||
action: #selector(didSelectNormalPlaybackSpeed), input: "\\", modifierFlags: .command))
|
||||
}
|
||||
commands.forEach { $0.wantsPriorityOverSystemBehavior = true }
|
||||
return commands
|
||||
}
|
||||
|
||||
// MARK: init
|
||||
|
||||
init(viewModel: VideoPlayerViewModel) {
|
||||
|
||||
self.viewModel = viewModel
|
||||
self.vlcMediaPlayer = VLCMediaPlayer()
|
||||
|
||||
|
@ -190,17 +215,17 @@ class VLCPlayerViewController: UIViewController {
|
|||
|
||||
@objc
|
||||
private func didTap() {
|
||||
self.didGenerallyTap()
|
||||
didGenerallyTap()
|
||||
}
|
||||
|
||||
@objc
|
||||
private func didRightSwipe() {
|
||||
self.didSelectForward()
|
||||
didSelectForward()
|
||||
}
|
||||
|
||||
@objc
|
||||
private func didLeftSwipe() {
|
||||
self.didSelectBackward()
|
||||
didSelectBackward()
|
||||
}
|
||||
|
||||
@objc
|
||||
|
@ -208,10 +233,10 @@ class VLCPlayerViewController: UIViewController {
|
|||
if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {
|
||||
pinchScale = gestureRecognizer.scale
|
||||
} else {
|
||||
if pinchScale > 1 && !isScreenFilled {
|
||||
if pinchScale > 1, !isScreenFilled {
|
||||
isScreenFilled.toggle()
|
||||
fillScreen()
|
||||
} else if pinchScale < 1 && isScreenFilled {
|
||||
} else if pinchScale < 1, isScreenFilled {
|
||||
isScreenFilled.toggle()
|
||||
shrinkScreen()
|
||||
}
|
||||
|
@ -221,7 +246,6 @@ class VLCPlayerViewController: UIViewController {
|
|||
// MARK: setupOverlayHostingController
|
||||
|
||||
private func setupOverlayHostingController(viewModel: VideoPlayerViewModel) {
|
||||
|
||||
// TODO: Look at injecting viewModel into the environment so it updates the current overlay
|
||||
if let currentOverlayHostingController = currentOverlayHostingController {
|
||||
// UX fade-out
|
||||
|
@ -260,7 +284,7 @@ class VLCPlayerViewController: UIViewController {
|
|||
newOverlayHostingController.view.alpha = 1
|
||||
}
|
||||
|
||||
self.currentOverlayHostingController = newOverlayHostingController
|
||||
currentOverlayHostingController = newOverlayHostingController
|
||||
|
||||
if let currentChapterOverlayHostingController = currentChapterOverlayHostingController {
|
||||
UIView.animate(withDuration: 0.5) {
|
||||
|
@ -292,14 +316,13 @@ class VLCPlayerViewController: UIViewController {
|
|||
newChapterOverlayHostingController.view.rightAnchor.constraint(equalTo: videoContentView.rightAnchor),
|
||||
])
|
||||
|
||||
self.currentChapterOverlayHostingController = newChapterOverlayHostingController
|
||||
currentChapterOverlayHostingController = newChapterOverlayHostingController
|
||||
|
||||
// There is a weird behavior when after setting the new overlays that the navigation bar pops up, re-hide it
|
||||
self.navigationController?.isNavigationBarHidden = true
|
||||
navigationController?.isNavigationBarHidden = true
|
||||
}
|
||||
|
||||
private func refreshJumpBackwardOverlayView(with jumpBackwardLength: VideoPlayerJumpLength) {
|
||||
|
||||
if let currentJumpBackwardOverlayView = currentJumpBackwardOverlayView {
|
||||
currentJumpBackwardOverlayView.removeFromSuperview()
|
||||
}
|
||||
|
@ -324,7 +347,6 @@ class VLCPlayerViewController: UIViewController {
|
|||
}
|
||||
|
||||
private func refreshJumpForwardOverlayView(with jumpForwardLength: VideoPlayerJumpLength) {
|
||||
|
||||
if let currentJumpForwardOverlayView = currentJumpForwardOverlayView {
|
||||
currentJumpForwardOverlayView.removeFromSuperview()
|
||||
}
|
||||
|
@ -352,13 +374,11 @@ class VLCPlayerViewController: UIViewController {
|
|||
// MARK: setupMediaPlayer
|
||||
|
||||
extension VLCPlayerViewController {
|
||||
|
||||
/// Main function that handles setting up the media player with the current VideoPlayerViewModel
|
||||
/// and also takes the role of setting the 'viewModel' property with the given viewModel
|
||||
///
|
||||
/// Use case for this is setting new media within the same VLCPlayerViewController
|
||||
func setupMediaPlayer(newViewModel: VideoPlayerViewModel) {
|
||||
|
||||
// remove old player
|
||||
|
||||
if vlcMediaPlayer.media != nil {
|
||||
|
@ -454,7 +474,6 @@ extension VLCPlayerViewController {
|
|||
// MARK: setupViewModelListeners
|
||||
|
||||
private func setupViewModelListeners(viewModel: VideoPlayerViewModel) {
|
||||
|
||||
viewModel.$playbackSpeed.sink { newSpeed in
|
||||
self.vlcMediaPlayer.rate = Float(newSpeed.rawValue)
|
||||
}.store(in: &viewModelListeners)
|
||||
|
@ -508,7 +527,6 @@ extension VLCPlayerViewController {
|
|||
// MARK: Show/Hide Overlay
|
||||
|
||||
extension VLCPlayerViewController {
|
||||
|
||||
private func showOverlay() {
|
||||
guard let overlayHostingController = currentOverlayHostingController else { return }
|
||||
|
||||
|
@ -545,7 +563,6 @@ extension VLCPlayerViewController {
|
|||
// MARK: Show/Hide Jump
|
||||
|
||||
extension VLCPlayerViewController {
|
||||
|
||||
private func flashJumpBackwardOverlay() {
|
||||
guard !displayingOverlay, let currentJumpBackwardOverlayView = currentJumpBackwardOverlayView else { return }
|
||||
|
||||
|
@ -590,7 +607,6 @@ extension VLCPlayerViewController {
|
|||
// MARK: Hide/Show Chapters
|
||||
|
||||
extension VLCPlayerViewController {
|
||||
|
||||
private func showChaptersOverlay() {
|
||||
guard let overlayHostingController = currentChapterOverlayHostingController else { return }
|
||||
|
||||
|
@ -615,40 +631,37 @@ extension VLCPlayerViewController {
|
|||
// MARK: OverlayTimer
|
||||
|
||||
extension VLCPlayerViewController {
|
||||
|
||||
private func restartOverlayDismissTimer(interval: Double = 3) {
|
||||
self.overlayDismissTimer?.invalidate()
|
||||
self.overlayDismissTimer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(dismissTimerFired),
|
||||
userInfo: nil, repeats: false)
|
||||
overlayDismissTimer?.invalidate()
|
||||
overlayDismissTimer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(dismissTimerFired),
|
||||
userInfo: nil, repeats: false)
|
||||
}
|
||||
|
||||
@objc
|
||||
private func dismissTimerFired() {
|
||||
self.hideOverlay()
|
||||
hideOverlay()
|
||||
}
|
||||
|
||||
private func stopOverlayDismissTimer() {
|
||||
self.overlayDismissTimer?.invalidate()
|
||||
overlayDismissTimer?.invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: VLCMediaPlayerDelegate
|
||||
|
||||
extension VLCPlayerViewController: VLCMediaPlayerDelegate {
|
||||
|
||||
// MARK: mediaPlayerStateChanged
|
||||
|
||||
func mediaPlayerStateChanged(_ aNotification: Notification!) {
|
||||
|
||||
// Don't show buffering if paused, usually here while scrubbing
|
||||
if vlcMediaPlayer.state == .buffering && viewModel.playerState == .paused {
|
||||
if vlcMediaPlayer.state == .buffering, viewModel.playerState == .paused {
|
||||
return
|
||||
}
|
||||
|
||||
viewModel.playerState = vlcMediaPlayer.state
|
||||
|
||||
if vlcMediaPlayer.state == VLCMediaPlayerState.ended {
|
||||
if viewModel.autoplayEnabled && viewModel.nextItemVideoPlayerViewModel != nil {
|
||||
if viewModel.autoplayEnabled, viewModel.nextItemVideoPlayerViewModel != nil {
|
||||
didSelectPlayNextItem()
|
||||
} else {
|
||||
didSelectClose()
|
||||
|
@ -659,7 +672,6 @@ extension VLCPlayerViewController: VLCMediaPlayerDelegate {
|
|||
// MARK: mediaPlayerTimeChanged
|
||||
|
||||
func mediaPlayerTimeChanged(_ aNotification: Notification!) {
|
||||
|
||||
if !viewModel.sliderIsScrubbing {
|
||||
viewModel.sliderPercentage = Double(vlcMediaPlayer.position)
|
||||
}
|
||||
|
@ -671,8 +683,8 @@ extension VLCPlayerViewController: VLCMediaPlayerDelegate {
|
|||
}
|
||||
|
||||
// If needing to fix subtitle streams during playback
|
||||
if vlcMediaPlayer.currentVideoSubTitleIndex != viewModel.selectedSubtitleStreamIndex &&
|
||||
viewModel.subtitlesEnabled
|
||||
if vlcMediaPlayer.currentVideoSubTitleIndex != viewModel.selectedSubtitleStreamIndex,
|
||||
viewModel.subtitlesEnabled
|
||||
{
|
||||
didSelectSubtitleStream(index: viewModel.selectedSubtitleStreamIndex)
|
||||
}
|
||||
|
@ -696,7 +708,6 @@ extension VLCPlayerViewController: VLCMediaPlayerDelegate {
|
|||
// MARK: PlayerOverlayDelegate and more
|
||||
|
||||
extension VLCPlayerViewController: PlayerOverlayDelegate {
|
||||
|
||||
func didSelectAudioStream(index: Int) {
|
||||
vlcMediaPlayer.currentAudioTrackIndex = Int32(index)
|
||||
|
||||
|
@ -715,6 +726,7 @@ extension VLCPlayerViewController: PlayerOverlayDelegate {
|
|||
lastProgressReportTicks = currentPlayerTicks
|
||||
}
|
||||
|
||||
@objc
|
||||
func didSelectClose() {
|
||||
vlcMediaPlayer.stop()
|
||||
|
||||
|
@ -741,8 +753,8 @@ extension VLCPlayerViewController: PlayerOverlayDelegate {
|
|||
restartOverlayDismissTimer()
|
||||
}
|
||||
|
||||
@objc
|
||||
func didSelectBackward() {
|
||||
|
||||
flashJumpBackwardOverlay()
|
||||
|
||||
vlcMediaPlayer.jumpBackward(viewModel.jumpBackwardLength.rawValue)
|
||||
|
@ -756,8 +768,8 @@ extension VLCPlayerViewController: PlayerOverlayDelegate {
|
|||
lastProgressReportTicks = currentPlayerTicks
|
||||
}
|
||||
|
||||
@objc
|
||||
func didSelectForward() {
|
||||
|
||||
flashJumpFowardOverlay()
|
||||
|
||||
vlcMediaPlayer.jumpForward(viewModel.jumpForwardLength.rawValue)
|
||||
|
@ -771,8 +783,8 @@ extension VLCPlayerViewController: PlayerOverlayDelegate {
|
|||
lastProgressReportTicks = currentPlayerTicks
|
||||
}
|
||||
|
||||
@objc
|
||||
func didSelectMain() {
|
||||
|
||||
switch viewModel.playerState {
|
||||
case .buffering:
|
||||
vlcMediaPlayer.play()
|
||||
|
@ -809,6 +821,7 @@ extension VLCPlayerViewController: PlayerOverlayDelegate {
|
|||
lastProgressReportTicks = currentPlayerTicks
|
||||
}
|
||||
|
||||
@objc
|
||||
func didSelectPlayPreviousItem() {
|
||||
if let previousItemVideoPlayerViewModel = viewModel.previousItemVideoPlayerViewModel {
|
||||
setupMediaPlayer(newViewModel: previousItemVideoPlayerViewModel)
|
||||
|
@ -816,6 +829,7 @@ extension VLCPlayerViewController: PlayerOverlayDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
func didSelectPlayNextItem() {
|
||||
if let nextItemVideoPlayerViewModel = viewModel.nextItemVideoPlayerViewModel {
|
||||
setupMediaPlayer(newViewModel: nextItemVideoPlayerViewModel)
|
||||
|
@ -823,6 +837,25 @@ extension VLCPlayerViewController: PlayerOverlayDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
func didSelectPreviousPlaybackSpeed() {
|
||||
if let previousPlaybackSpeed = viewModel.playbackSpeed.previous {
|
||||
viewModel.playbackSpeed = previousPlaybackSpeed
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
func didSelectNextPlaybackSpeed() {
|
||||
if let nextPlaybackSpeed = viewModel.playbackSpeed.next {
|
||||
viewModel.playbackSpeed = nextPlaybackSpeed
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
func didSelectNormalPlaybackSpeed() {
|
||||
viewModel.playbackSpeed = .one
|
||||
}
|
||||
|
||||
func didSelectChapters() {
|
||||
if displayingChapterOverlay {
|
||||
hideChaptersOverlay()
|
||||
|
@ -847,7 +880,6 @@ extension VLCPlayerViewController: PlayerOverlayDelegate {
|
|||
}
|
||||
|
||||
func didSelectScreenFill() {
|
||||
|
||||
isScreenFilled.toggle()
|
||||
|
||||
if isScreenFilled {
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue