diff --git a/Shared/Coordinators/VideoPlayerCoordinator/tvOSLiveTVVideoPlayerCoordinator.swift b/Shared/Coordinators/VideoPlayerCoordinator/tvOSLiveTVVideoPlayerCoordinator.swift index dbd8b53b..8adc56fd 100644 --- a/Shared/Coordinators/VideoPlayerCoordinator/tvOSLiveTVVideoPlayerCoordinator.swift +++ b/Shared/Coordinators/VideoPlayerCoordinator/tvOSLiveTVVideoPlayerCoordinator.swift @@ -27,8 +27,14 @@ final class LiveTVVideoPlayerCoordinator: NavigationCoordinatable { @ViewBuilder func makeStart() -> some View { - LiveTVVideoPlayerView(viewModel: viewModel) - .navigationBarHidden(true) - .ignoresSafeArea() + if Defaults[.Experimental.nativePlayer] { + LiveTVNativeVideoPlayerView(viewModel: viewModel) + .navigationBarHidden(true) + .ignoresSafeArea() + } else { + LiveTVVideoPlayerView(viewModel: viewModel) + .navigationBarHidden(true) + .ignoresSafeArea() + } } } diff --git a/Shared/Extensions/JellyfinAPIExtensions/BaseItemDto+VideoPlayerViewModel.swift b/Shared/Extensions/JellyfinAPIExtensions/BaseItemDto+VideoPlayerViewModel.swift index 42f158ce..5069dddc 100644 --- a/Shared/Extensions/JellyfinAPIExtensions/BaseItemDto+VideoPlayerViewModel.swift +++ b/Shared/Extensions/JellyfinAPIExtensions/BaseItemDto+VideoPlayerViewModel.swift @@ -226,14 +226,14 @@ extension BaseItemDto { mediaSourceId: mediaSourceID) directStreamURL = URL(string: directStreamBuilder.URLString)! - if let transcodeURL = currentMediaSource.transcodingUrl { + if let transcodeURL = currentMediaSource.transcodingUrl, !Defaults[.Experimental.forceDirectPlay] { streamType = .transcode transcodedStreamURL = URLComponents(string: SessionManager.main.currentLogin.server.currentURI .appending(transcodeURL))! } else { streamType = .direct transcodedStreamURL = nil - } + } let hlsStreamBuilder = DynamicHlsAPI.getMasterHlsVideoPlaylistWithRequestBuilder(itemId: id ?? "", mediaSourceId: id ?? "", diff --git a/Shared/ViewModels/VideoPlayerViewModel/VideoPlayerViewModel.swift b/Shared/ViewModels/VideoPlayerViewModel/VideoPlayerViewModel.swift index 738eeadc..715292c5 100644 --- a/Shared/ViewModels/VideoPlayerViewModel/VideoPlayerViewModel.swift +++ b/Shared/ViewModels/VideoPlayerViewModel/VideoPlayerViewModel.swift @@ -151,7 +151,8 @@ final class VideoPlayerViewModel: ViewModel { } func setSeconds(_ seconds: Int64) { - let videoDuration = item.runTimeTicks! + guard let runTimeTicks = item.runTimeTicks else { return } + let videoDuration = runTimeTicks let percentage = Double(seconds * 10_000_000) / Double(videoDuration) sliderPercentage = percentage diff --git a/Swiftfin tvOS/Views/LiveTVChannelsView.swift b/Swiftfin tvOS/Views/LiveTVChannelsView.swift index fd778587..d34fb881 100644 --- a/Swiftfin tvOS/Views/LiveTVChannelsView.swift +++ b/Swiftfin tvOS/Views/LiveTVChannelsView.swift @@ -55,15 +55,21 @@ struct LiveTVChannelsView: View { let channel = item.channel if channel.type != "Folder" { Button { + self.viewModel.isLoading = true self.viewModel.fetchVideoPlayerViewModel(item: channel) { playerViewModel in self.router.route(to: \.videoPlayer, playerViewModel) + DispatchQueue.main.asyncAfter(deadline: .now() + 2) { + self.viewModel.isLoading = false + } } } label: { - LiveTVChannelItemElement(channel: channel, + let progressPercent = item.program?.getLiveProgressPercentage() ?? 0 + LiveTVChannelItemElement(channel: channel, program: item.program, startString: item.program?.getLiveStartTimeString(formatter: viewModel.timeFormatter) ?? " ", endString: item.program?.getLiveEndTimeString(formatter: viewModel.timeFormatter) ?? " ", - progressPercent: item.program?.getLiveProgressPercentage() ?? 0) + progressPercent: progressPercent > 1.0 ? 1.0 : progressPercent + ) } .buttonStyle(PlainNavigationLinkButtonStyle()) } diff --git a/Swiftfin tvOS/Views/VideoPlayer/LiveTVNativeVideoPlayerView.swift b/Swiftfin tvOS/Views/VideoPlayer/LiveTVNativeVideoPlayerView.swift new file mode 100644 index 00000000..57fade2e --- /dev/null +++ b/Swiftfin tvOS/Views/VideoPlayer/LiveTVNativeVideoPlayerView.swift @@ -0,0 +1,23 @@ +// +// 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 (c) 2022 Jellyfin & Jellyfin Contributors +// + +import SwiftUI +import UIKit + +struct LiveTVNativeVideoPlayerView: UIViewControllerRepresentable { + + let viewModel: VideoPlayerViewModel + + typealias UIViewControllerType = NativePlayerViewController + + func makeUIViewController(context: Context) -> NativePlayerViewController { + NativePlayerViewController(viewModel: viewModel) + } + + func updateUIViewController(_ uiViewController: NativePlayerViewController, context: Context) {} +} diff --git a/Swiftfin.xcodeproj/project.pbxproj b/Swiftfin.xcodeproj/project.pbxproj index 52af3a75..0c735fdc 100644 --- a/Swiftfin.xcodeproj/project.pbxproj +++ b/Swiftfin.xcodeproj/project.pbxproj @@ -263,6 +263,7 @@ C4AE2C3027498D2300AE13CF /* LiveTVHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AE2C2F27498D2300AE13CF /* LiveTVHomeView.swift */; }; C4AE2C3227498D6A00AE13CF /* LiveTVProgramsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AE2C3127498D6A00AE13CF /* LiveTVProgramsView.swift */; }; C4AE2C3327498DBE00AE13CF /* LiveTVChannelItemElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E52304272CE68800654268 /* LiveTVChannelItemElement.swift */; }; + C4B9B91427E1921B0063535C /* LiveTVNativeVideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B9B91327E1921B0063535C /* LiveTVNativeVideoPlayerView.swift */; }; C4BE0764271FC0BB003F4AD1 /* TVLibrariesCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE0762271FC0BB003F4AD1 /* TVLibrariesCoordinator.swift */; }; C4BE0767271FC109003F4AD1 /* TVLibrariesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE0765271FC109003F4AD1 /* TVLibrariesViewModel.swift */; }; C4BE076A271FC164003F4AD1 /* TVLibrariesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE0768271FC164003F4AD1 /* TVLibrariesView.swift */; }; @@ -741,6 +742,7 @@ C4534984279A40C50045F1E2 /* LiveTVVideoPlayerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LiveTVVideoPlayerView.swift; sourceTree = ""; }; C4AE2C2F27498D2300AE13CF /* LiveTVHomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTVHomeView.swift; sourceTree = ""; }; C4AE2C3127498D6A00AE13CF /* LiveTVProgramsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTVProgramsView.swift; sourceTree = ""; }; + C4B9B91327E1921B0063535C /* LiveTVNativeVideoPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTVNativeVideoPlayerView.swift; sourceTree = ""; }; C4BE0762271FC0BB003F4AD1 /* TVLibrariesCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVLibrariesCoordinator.swift; sourceTree = ""; }; C4BE0765271FC109003F4AD1 /* TVLibrariesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVLibrariesViewModel.swift; sourceTree = ""; }; C4BE0768271FC164003F4AD1 /* TVLibrariesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVLibrariesView.swift; sourceTree = ""; }; @@ -999,6 +1001,7 @@ E17885A7278130690094FBCF /* Overlays */, E1C812C8277AE40900918266 /* VideoPlayerView.swift */, C4534984279A40C50045F1E2 /* LiveTVVideoPlayerView.swift */, + C4B9B91327E1921B0063535C /* LiveTVNativeVideoPlayerView.swift */, C453497E279A2DA50045F1E2 /* LiveTVPlayerViewController.swift */, E1384943278036C70024FB48 /* VLCPlayerViewController.swift */, E13AD72F2798C60F00FDCEE8 /* NativePlayerViewController.swift */, @@ -2171,6 +2174,7 @@ E193D53327193F7D00900D82 /* FilterCoordinator.swift in Sources */, 6267B3DC2671139500A7371D /* ImageExtensions.swift in Sources */, E103A6A9278AB6FF00820EC7 /* CinematicNextUpCardView.swift in Sources */, + C4B9B91427E1921B0063535C /* LiveTVNativeVideoPlayerView.swift in Sources */, E107BB9427880A8F00354E07 /* CollectionItemViewModel.swift in Sources */, C4534985279A40C60045F1E2 /* LiveTVVideoPlayerView.swift in Sources */, E1A2C15A279A7D76005EC829 /* BundleExtensions.swift in Sources */,