support external subtitles
This commit is contained in:
parent
352907640f
commit
158edb3b5f
|
@ -0,0 +1,22 @@
|
||||||
|
//
|
||||||
|
/*
|
||||||
|
* 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 JellyfinAPI
|
||||||
|
|
||||||
|
extension MediaStream {
|
||||||
|
|
||||||
|
func externalURL(base: String) -> URL? {
|
||||||
|
guard let deliveryURL = deliveryUrl else { return nil }
|
||||||
|
var baseComponents = URLComponents(string: base)
|
||||||
|
baseComponents?.path += deliveryURL
|
||||||
|
|
||||||
|
return baseComponents?.url
|
||||||
|
}
|
||||||
|
}
|
|
@ -67,6 +67,8 @@ final class VideoPlayerViewModel: ViewModel {
|
||||||
}
|
}
|
||||||
@Published var autoplayEnabled: Bool {
|
@Published var autoplayEnabled: Bool {
|
||||||
willSet {
|
willSet {
|
||||||
|
previousItemVideoPlayerViewModel?.autoplayEnabled = newValue
|
||||||
|
nextItemVideoPlayerViewModel?.autoplayEnabled = newValue
|
||||||
Defaults[.autoplayEnabled] = newValue
|
Defaults[.autoplayEnabled] = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,6 +117,16 @@ final class VideoPlayerViewModel: ViewModel {
|
||||||
return Int64(currentSeconds) * 10_000_000
|
return Int64(currentSeconds) * 10_000_000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Helpers
|
||||||
|
|
||||||
|
var currentAudioStream: MediaStream? {
|
||||||
|
return audioStreams.first(where: { $0.index == selectedAudioStreamIndex })
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentSubtitleStream: MediaStream? {
|
||||||
|
return subtitleStreams.first(where: { $0.index == selectedSubtitleStreamIndex })
|
||||||
|
}
|
||||||
|
|
||||||
// Necessary PassthroughSubject to capture manual scrubbing from sliders
|
// Necessary PassthroughSubject to capture manual scrubbing from sliders
|
||||||
let sliderScrubbingSubject = PassthroughSubject<VideoPlayerViewModel, Never>()
|
let sliderScrubbingSubject = PassthroughSubject<VideoPlayerViewModel, Never>()
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ class VLCPlayerViewController: UIViewController {
|
||||||
// MARK: variables
|
// MARK: variables
|
||||||
|
|
||||||
private var viewModel: VideoPlayerViewModel
|
private var viewModel: VideoPlayerViewModel
|
||||||
private var vlcMediaPlayer = VLCMediaPlayer()
|
private var vlcMediaPlayer: VLCMediaPlayer
|
||||||
private var lastPlayerTicks: Int64 = 0
|
private var lastPlayerTicks: Int64 = 0
|
||||||
private var lastProgressReportTicks: Int64 = 0
|
private var lastProgressReportTicks: Int64 = 0
|
||||||
private var viewModelListeners = Set<AnyCancellable>()
|
private var viewModelListeners = Set<AnyCancellable>()
|
||||||
|
@ -59,6 +59,7 @@ class VLCPlayerViewController: UIViewController {
|
||||||
init(viewModel: VideoPlayerViewModel) {
|
init(viewModel: VideoPlayerViewModel) {
|
||||||
|
|
||||||
self.viewModel = viewModel
|
self.viewModel = viewModel
|
||||||
|
self.vlcMediaPlayer = VLCMediaPlayer()
|
||||||
|
|
||||||
super.init(nibName: nil, bundle: nil)
|
super.init(nibName: nil, bundle: nil)
|
||||||
|
|
||||||
|
@ -118,14 +119,6 @@ class VLCPlayerViewController: UIViewController {
|
||||||
|
|
||||||
view.backgroundColor = .black
|
view.backgroundColor = .black
|
||||||
|
|
||||||
// Outside of 'setupMediaPlayer' such that they
|
|
||||||
// aren't unnecessarily set more than once
|
|
||||||
vlcMediaPlayer.delegate = self
|
|
||||||
vlcMediaPlayer.drawable = videoContentView
|
|
||||||
|
|
||||||
// TODO: custom font sizes
|
|
||||||
vlcMediaPlayer.perform(Selector(("setTextRendererFontSize:")), with: 16)
|
|
||||||
|
|
||||||
setupMediaPlayer(newViewModel: viewModel)
|
setupMediaPlayer(newViewModel: viewModel)
|
||||||
|
|
||||||
setupPanGestureRecognizer()
|
setupPanGestureRecognizer()
|
||||||
|
@ -387,6 +380,28 @@ extension VLCPlayerViewController {
|
||||||
/// Use case for this is setting new media within the same VLCPlayerViewController
|
/// Use case for this is setting new media within the same VLCPlayerViewController
|
||||||
func setupMediaPlayer(newViewModel: VideoPlayerViewModel) {
|
func setupMediaPlayer(newViewModel: VideoPlayerViewModel) {
|
||||||
|
|
||||||
|
// remove old player
|
||||||
|
|
||||||
|
if vlcMediaPlayer.media != nil {
|
||||||
|
viewModelListeners.forEach({ $0.cancel() })
|
||||||
|
|
||||||
|
vlcMediaPlayer.stop()
|
||||||
|
viewModel.sendStopReport()
|
||||||
|
viewModel.playerOverlayDelegate = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
vlcMediaPlayer = VLCMediaPlayer()
|
||||||
|
|
||||||
|
// setup with new player and view model
|
||||||
|
|
||||||
|
vlcMediaPlayer = VLCMediaPlayer()
|
||||||
|
|
||||||
|
vlcMediaPlayer.delegate = self
|
||||||
|
vlcMediaPlayer.drawable = videoContentView
|
||||||
|
|
||||||
|
// TODO: Custom subtitle sizes
|
||||||
|
vlcMediaPlayer.perform(Selector(("setTextRendererFontSize:")), with: 16)
|
||||||
|
|
||||||
stopOverlayDismissTimer()
|
stopOverlayDismissTimer()
|
||||||
|
|
||||||
// Stop current media if there is one
|
// Stop current media if there is one
|
||||||
|
@ -436,6 +451,13 @@ extension VLCPlayerViewController {
|
||||||
func startPlayback() {
|
func startPlayback() {
|
||||||
vlcMediaPlayer.play()
|
vlcMediaPlayer.play()
|
||||||
|
|
||||||
|
// Setup external subtitles
|
||||||
|
for externalSubtitle in viewModel.subtitleStreams.filter({ $0.deliveryMethod == .external }) {
|
||||||
|
if let deliveryURL = externalSubtitle.externalURL(base: SessionManager.main.currentLogin.server.currentURI) {
|
||||||
|
vlcMediaPlayer.addPlaybackSlave(deliveryURL, type: .subtitle, enforce: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setMediaPlayerTimeAtCurrentSlider()
|
setMediaPlayerTimeAtCurrentSlider()
|
||||||
|
|
||||||
viewModel.sendPlayReport()
|
viewModel.sendPlayReport()
|
||||||
|
@ -672,7 +694,8 @@ extension VLCPlayerViewController: VLCMediaPlayerDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If needing to fix subtitle streams during playback
|
// 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)
|
didSelectSubtitleStream(index: viewModel.selectedSubtitleStreamIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -274,6 +274,8 @@
|
||||||
E1218C9C271A26C400EA0737 /* Nuke in Frameworks */ = {isa = PBXBuildFile; productRef = E1218C9B271A26C400EA0737 /* Nuke */; };
|
E1218C9C271A26C400EA0737 /* Nuke in Frameworks */ = {isa = PBXBuildFile; productRef = E1218C9B271A26C400EA0737 /* Nuke */; };
|
||||||
E1218C9E271A2CD600EA0737 /* CombineExt in Frameworks */ = {isa = PBXBuildFile; productRef = E1218C9D271A2CD600EA0737 /* CombineExt */; };
|
E1218C9E271A2CD600EA0737 /* CombineExt in Frameworks */ = {isa = PBXBuildFile; productRef = E1218C9D271A2CD600EA0737 /* CombineExt */; };
|
||||||
E1218CA0271A2CF200EA0737 /* Nuke in Frameworks */ = {isa = PBXBuildFile; productRef = E1218C9F271A2CF200EA0737 /* Nuke */; };
|
E1218CA0271A2CF200EA0737 /* Nuke in Frameworks */ = {isa = PBXBuildFile; productRef = E1218C9F271A2CF200EA0737 /* Nuke */; };
|
||||||
|
E122A9132788EAAD0060FA63 /* MediaStreamExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E122A9122788EAAD0060FA63 /* MediaStreamExtension.swift */; };
|
||||||
|
E122A9142788EAAD0060FA63 /* MediaStreamExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E122A9122788EAAD0060FA63 /* MediaStreamExtension.swift */; };
|
||||||
E1267D3E271A1F46003C492E /* PreferenceUIHostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1267D3D271A1F46003C492E /* PreferenceUIHostingController.swift */; };
|
E1267D3E271A1F46003C492E /* PreferenceUIHostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1267D3D271A1F46003C492E /* PreferenceUIHostingController.swift */; };
|
||||||
E131691726C583BC0074BFEE /* LogConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E131691626C583BC0074BFEE /* LogConstructor.swift */; };
|
E131691726C583BC0074BFEE /* LogConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E131691626C583BC0074BFEE /* LogConstructor.swift */; };
|
||||||
E131691826C583BC0074BFEE /* LogConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E131691626C583BC0074BFEE /* LogConstructor.swift */; };
|
E131691826C583BC0074BFEE /* LogConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E131691626C583BC0074BFEE /* LogConstructor.swift */; };
|
||||||
|
@ -645,6 +647,7 @@
|
||||||
E10EAA52277BBD17000269ED /* BaseItemDto+VideoPlayerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BaseItemDto+VideoPlayerViewModel.swift"; sourceTree = "<group>"; };
|
E10EAA52277BBD17000269ED /* BaseItemDto+VideoPlayerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BaseItemDto+VideoPlayerViewModel.swift"; sourceTree = "<group>"; };
|
||||||
E11B1B6B2718CD68006DA3E8 /* JellyfinAPIError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JellyfinAPIError.swift; sourceTree = "<group>"; };
|
E11B1B6B2718CD68006DA3E8 /* JellyfinAPIError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JellyfinAPIError.swift; sourceTree = "<group>"; };
|
||||||
E11D224127378428003F9CB3 /* ServerDetailCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerDetailCoordinator.swift; sourceTree = "<group>"; };
|
E11D224127378428003F9CB3 /* ServerDetailCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerDetailCoordinator.swift; sourceTree = "<group>"; };
|
||||||
|
E122A9122788EAAD0060FA63 /* MediaStreamExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaStreamExtension.swift; sourceTree = "<group>"; };
|
||||||
E1267D3D271A1F46003C492E /* PreferenceUIHostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceUIHostingController.swift; sourceTree = "<group>"; };
|
E1267D3D271A1F46003C492E /* PreferenceUIHostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceUIHostingController.swift; sourceTree = "<group>"; };
|
||||||
E131691626C583BC0074BFEE /* LogConstructor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogConstructor.swift; sourceTree = "<group>"; };
|
E131691626C583BC0074BFEE /* LogConstructor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogConstructor.swift; sourceTree = "<group>"; };
|
||||||
E1384943278036C70024FB48 /* VLCPlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VLCPlayerViewController.swift; sourceTree = "<group>"; };
|
E1384943278036C70024FB48 /* VLCPlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VLCPlayerViewController.swift; sourceTree = "<group>"; };
|
||||||
|
@ -1502,10 +1505,11 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
E18845F426DD631E00B0C5B7 /* BaseItemDto+Stackable.swift */,
|
E18845F426DD631E00B0C5B7 /* BaseItemDto+Stackable.swift */,
|
||||||
E1AD104C26D96CE3003E4A08 /* BaseItemDtoExtensions.swift */,
|
|
||||||
E10EAA52277BBD17000269ED /* BaseItemDto+VideoPlayerViewModel.swift */,
|
E10EAA52277BBD17000269ED /* BaseItemDto+VideoPlayerViewModel.swift */,
|
||||||
|
E1AD104C26D96CE3003E4A08 /* BaseItemDtoExtensions.swift */,
|
||||||
5364F454266CA0DC0026ECBA /* BaseItemPersonExtensions.swift */,
|
5364F454266CA0DC0026ECBA /* BaseItemPersonExtensions.swift */,
|
||||||
E11B1B6B2718CD68006DA3E8 /* JellyfinAPIError.swift */,
|
E11B1B6B2718CD68006DA3E8 /* JellyfinAPIError.swift */,
|
||||||
|
E122A9122788EAAD0060FA63 /* MediaStreamExtension.swift */,
|
||||||
E1AD105E26D9ADDD003E4A08 /* NameGUIDPairExtensions.swift */,
|
E1AD105E26D9ADDD003E4A08 /* NameGUIDPairExtensions.swift */,
|
||||||
);
|
);
|
||||||
path = JellyfinAPIExtensions;
|
path = JellyfinAPIExtensions;
|
||||||
|
@ -1759,7 +1763,7 @@
|
||||||
536D3D82267BEA550004248C /* XCRemoteSwiftPackageReference "ParallaxView" */,
|
536D3D82267BEA550004248C /* XCRemoteSwiftPackageReference "ParallaxView" */,
|
||||||
53649AAB269CFAEA00A2D8B7 /* XCRemoteSwiftPackageReference "Puppy" */,
|
53649AAB269CFAEA00A2D8B7 /* XCRemoteSwiftPackageReference "Puppy" */,
|
||||||
62C29E9A26D0FE4100C1D2E7 /* XCRemoteSwiftPackageReference "stinsen" */,
|
62C29E9A26D0FE4100C1D2E7 /* XCRemoteSwiftPackageReference "stinsen" */,
|
||||||
E13DD3C42716499E009D4DAF /* XCRemoteSwiftPackageReference "CoreStore.git" */,
|
E13DD3C42716499E009D4DAF /* XCRemoteSwiftPackageReference "CoreStore" */,
|
||||||
E13DD3D127168E65009D4DAF /* XCRemoteSwiftPackageReference "Defaults" */,
|
E13DD3D127168E65009D4DAF /* XCRemoteSwiftPackageReference "Defaults" */,
|
||||||
E1267D42271A212C003C492E /* XCRemoteSwiftPackageReference "CombineExt" */,
|
E1267D42271A212C003C492E /* XCRemoteSwiftPackageReference "CombineExt" */,
|
||||||
E1C16B89271A2180009A5D25 /* XCRemoteSwiftPackageReference "SwiftyJSON" */,
|
E1C16B89271A2180009A5D25 /* XCRemoteSwiftPackageReference "SwiftyJSON" */,
|
||||||
|
@ -2051,6 +2055,7 @@
|
||||||
E1C812CC277AE40A00918266 /* VideoPlayerView.swift in Sources */,
|
E1C812CC277AE40A00918266 /* VideoPlayerView.swift in Sources */,
|
||||||
53CD2A40268A49C2002ABD4E /* ItemView.swift in Sources */,
|
53CD2A40268A49C2002ABD4E /* ItemView.swift in Sources */,
|
||||||
53CD2A42268A4B38002ABD4E /* MovieItemView.swift in Sources */,
|
53CD2A42268A4B38002ABD4E /* MovieItemView.swift in Sources */,
|
||||||
|
E122A9142788EAAD0060FA63 /* MediaStreamExtension.swift in Sources */,
|
||||||
E178859E2780F53B0094FBCF /* SliderView.swift in Sources */,
|
E178859E2780F53B0094FBCF /* SliderView.swift in Sources */,
|
||||||
536D3D7F267BDF100004248C /* LatestMediaView.swift in Sources */,
|
536D3D7F267BDF100004248C /* LatestMediaView.swift in Sources */,
|
||||||
E1384944278036C70024FB48 /* VLCPlayerViewController.swift in Sources */,
|
E1384944278036C70024FB48 /* VLCPlayerViewController.swift in Sources */,
|
||||||
|
@ -2191,6 +2196,7 @@
|
||||||
E13DD3F227179378009D4DAF /* UserSignInCoordinator.swift in Sources */,
|
E13DD3F227179378009D4DAF /* UserSignInCoordinator.swift in Sources */,
|
||||||
621338932660107500A81A2A /* StringExtensions.swift in Sources */,
|
621338932660107500A81A2A /* StringExtensions.swift in Sources */,
|
||||||
53FF7F2A263CF3F500585C35 /* LatestMediaView.swift in Sources */,
|
53FF7F2A263CF3F500585C35 /* LatestMediaView.swift in Sources */,
|
||||||
|
E122A9132788EAAD0060FA63 /* MediaStreamExtension.swift in Sources */,
|
||||||
E1C812C5277A90B200918266 /* URLComponentsExtensions.swift in Sources */,
|
E1C812C5277A90B200918266 /* URLComponentsExtensions.swift in Sources */,
|
||||||
62E632EC267D410B0063E547 /* SeriesItemViewModel.swift in Sources */,
|
62E632EC267D410B0063E547 /* SeriesItemViewModel.swift in Sources */,
|
||||||
625CB5732678C32A00530A6E /* HomeViewModel.swift in Sources */,
|
625CB5732678C32A00530A6E /* HomeViewModel.swift in Sources */,
|
||||||
|
@ -2701,7 +2707,7 @@
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 66;
|
CURRENT_PROJECT_VERSION = 66;
|
||||||
DEVELOPMENT_ASSET_PATHS = "";
|
DEVELOPMENT_ASSET_PATHS = "";
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = TY84JMYEFE;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
EXCLUDED_ARCHS = "";
|
EXCLUDED_ARCHS = "";
|
||||||
|
@ -2738,7 +2744,7 @@
|
||||||
CURRENT_PROJECT_VERSION = 66;
|
CURRENT_PROJECT_VERSION = 66;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
DEVELOPMENT_ASSET_PATHS = "";
|
DEVELOPMENT_ASSET_PATHS = "";
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = TY84JMYEFE;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
EXCLUDED_ARCHS = "";
|
EXCLUDED_ARCHS = "";
|
||||||
|
@ -2769,7 +2775,7 @@
|
||||||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 66;
|
CURRENT_PROJECT_VERSION = 66;
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = TY84JMYEFE;
|
||||||
INFOPLIST_FILE = WidgetExtension/Info.plist;
|
INFOPLIST_FILE = WidgetExtension/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
@ -2796,7 +2802,7 @@
|
||||||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 66;
|
CURRENT_PROJECT_VERSION = 66;
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = TY84JMYEFE;
|
||||||
INFOPLIST_FILE = WidgetExtension/Info.plist;
|
INFOPLIST_FILE = WidgetExtension/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
@ -2936,7 +2942,7 @@
|
||||||
minimumVersion = 1.0.0;
|
minimumVersion = 1.0.0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
E13DD3C42716499E009D4DAF /* XCRemoteSwiftPackageReference "CoreStore.git" */ = {
|
E13DD3C42716499E009D4DAF /* XCRemoteSwiftPackageReference "CoreStore" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/JohnEstropia/CoreStore.git";
|
repositoryURL = "https://github.com/JohnEstropia/CoreStore.git";
|
||||||
requirement = {
|
requirement = {
|
||||||
|
@ -3060,17 +3066,17 @@
|
||||||
};
|
};
|
||||||
E13DD3C52716499E009D4DAF /* CoreStore */ = {
|
E13DD3C52716499E009D4DAF /* CoreStore */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = E13DD3C42716499E009D4DAF /* XCRemoteSwiftPackageReference "CoreStore.git" */;
|
package = E13DD3C42716499E009D4DAF /* XCRemoteSwiftPackageReference "CoreStore" */;
|
||||||
productName = CoreStore;
|
productName = CoreStore;
|
||||||
};
|
};
|
||||||
E13DD3CC27164CA7009D4DAF /* CoreStore */ = {
|
E13DD3CC27164CA7009D4DAF /* CoreStore */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = E13DD3C42716499E009D4DAF /* XCRemoteSwiftPackageReference "CoreStore.git" */;
|
package = E13DD3C42716499E009D4DAF /* XCRemoteSwiftPackageReference "CoreStore" */;
|
||||||
productName = CoreStore;
|
productName = CoreStore;
|
||||||
};
|
};
|
||||||
E13DD3CE27164E1F009D4DAF /* CoreStore */ = {
|
E13DD3CE27164E1F009D4DAF /* CoreStore */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = E13DD3C42716499E009D4DAF /* XCRemoteSwiftPackageReference "CoreStore.git" */;
|
package = E13DD3C42716499E009D4DAF /* XCRemoteSwiftPackageReference "CoreStore" */;
|
||||||
productName = CoreStore;
|
productName = CoreStore;
|
||||||
};
|
};
|
||||||
E13DD3D227168E65009D4DAF /* Defaults */ = {
|
E13DD3D227168E65009D4DAF /* Defaults */ = {
|
||||||
|
|
|
@ -24,7 +24,7 @@ class VLCPlayerViewController: UIViewController {
|
||||||
// MARK: variables
|
// MARK: variables
|
||||||
|
|
||||||
private var viewModel: VideoPlayerViewModel
|
private var viewModel: VideoPlayerViewModel
|
||||||
private var vlcMediaPlayer = VLCMediaPlayer()
|
private var vlcMediaPlayer: VLCMediaPlayer
|
||||||
private var lastPlayerTicks: Int64 = 0
|
private var lastPlayerTicks: Int64 = 0
|
||||||
private var lastProgressReportTicks: Int64 = 0
|
private var lastProgressReportTicks: Int64 = 0
|
||||||
private var viewModelListeners = Set<AnyCancellable>()
|
private var viewModelListeners = Set<AnyCancellable>()
|
||||||
|
@ -49,6 +49,7 @@ class VLCPlayerViewController: UIViewController {
|
||||||
init(viewModel: VideoPlayerViewModel) {
|
init(viewModel: VideoPlayerViewModel) {
|
||||||
|
|
||||||
self.viewModel = viewModel
|
self.viewModel = viewModel
|
||||||
|
self.vlcMediaPlayer = VLCMediaPlayer()
|
||||||
|
|
||||||
super.init(nibName: nil, bundle: nil)
|
super.init(nibName: nil, bundle: nil)
|
||||||
|
|
||||||
|
@ -97,14 +98,6 @@ class VLCPlayerViewController: UIViewController {
|
||||||
|
|
||||||
view.backgroundColor = .black
|
view.backgroundColor = .black
|
||||||
|
|
||||||
// These are kept outside of 'setupMediaPlayer' such that
|
|
||||||
// they aren't unnecessarily set more than once
|
|
||||||
vlcMediaPlayer.delegate = self
|
|
||||||
vlcMediaPlayer.drawable = videoContentView
|
|
||||||
|
|
||||||
// TODO: Custom subtitle sizes
|
|
||||||
vlcMediaPlayer.perform(Selector(("setTextRendererFontSize:")), with: 14)
|
|
||||||
|
|
||||||
setupMediaPlayer(newViewModel: viewModel)
|
setupMediaPlayer(newViewModel: viewModel)
|
||||||
|
|
||||||
refreshJumpBackwardOverlayView(with: viewModel.jumpBackwardLength)
|
refreshJumpBackwardOverlayView(with: viewModel.jumpBackwardLength)
|
||||||
|
@ -287,9 +280,8 @@ extension VLCPlayerViewController {
|
||||||
/// Use case for this is setting new media within the same VLCPlayerViewController
|
/// Use case for this is setting new media within the same VLCPlayerViewController
|
||||||
func setupMediaPlayer(newViewModel: VideoPlayerViewModel) {
|
func setupMediaPlayer(newViewModel: VideoPlayerViewModel) {
|
||||||
|
|
||||||
stopOverlayDismissTimer()
|
// remove old player
|
||||||
|
|
||||||
// Stop current media if there is one
|
|
||||||
if vlcMediaPlayer.media != nil {
|
if vlcMediaPlayer.media != nil {
|
||||||
viewModelListeners.forEach({ $0.cancel() })
|
viewModelListeners.forEach({ $0.cancel() })
|
||||||
|
|
||||||
|
@ -298,6 +290,20 @@ extension VLCPlayerViewController {
|
||||||
viewModel.playerOverlayDelegate = nil
|
viewModel.playerOverlayDelegate = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vlcMediaPlayer = VLCMediaPlayer()
|
||||||
|
|
||||||
|
// setup with new player and view model
|
||||||
|
|
||||||
|
vlcMediaPlayer = VLCMediaPlayer()
|
||||||
|
|
||||||
|
vlcMediaPlayer.delegate = self
|
||||||
|
vlcMediaPlayer.drawable = videoContentView
|
||||||
|
|
||||||
|
// TODO: Custom subtitle sizes
|
||||||
|
vlcMediaPlayer.perform(Selector(("setTextRendererFontSize:")), with: 14)
|
||||||
|
|
||||||
|
stopOverlayDismissTimer()
|
||||||
|
|
||||||
lastPlayerTicks = newViewModel.item.userData?.playbackPositionTicks ?? 0
|
lastPlayerTicks = newViewModel.item.userData?.playbackPositionTicks ?? 0
|
||||||
lastProgressReportTicks = newViewModel.item.userData?.playbackPositionTicks ?? 0
|
lastProgressReportTicks = newViewModel.item.userData?.playbackPositionTicks ?? 0
|
||||||
|
|
||||||
|
@ -334,6 +340,13 @@ extension VLCPlayerViewController {
|
||||||
func startPlayback() {
|
func startPlayback() {
|
||||||
vlcMediaPlayer.play()
|
vlcMediaPlayer.play()
|
||||||
|
|
||||||
|
// Setup external subtitles
|
||||||
|
for externalSubtitle in viewModel.subtitleStreams.filter({ $0.deliveryMethod == .external }) {
|
||||||
|
if let deliveryURL = externalSubtitle.externalURL(base: SessionManager.main.currentLogin.server.currentURI) {
|
||||||
|
vlcMediaPlayer.addPlaybackSlave(deliveryURL, type: .subtitle, enforce: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setMediaPlayerTimeAtCurrentSlider()
|
setMediaPlayerTimeAtCurrentSlider()
|
||||||
|
|
||||||
viewModel.sendPlayReport()
|
viewModel.sendPlayReport()
|
||||||
|
@ -526,7 +539,8 @@ extension VLCPlayerViewController: VLCMediaPlayerDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If needing to fix subtitle streams during playback
|
// 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)
|
didSelectSubtitleStream(index: viewModel.selectedSubtitleStreamIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue