remove hls stream
This commit is contained in:
parent
f18b132b15
commit
d77f59d048
|
@ -41,45 +41,24 @@ extension BaseItemDto {
|
||||||
|
|
||||||
let defaultSubtitleStream = subtitleStreams.first(where: { $0.index! == mediaSource.defaultSubtitleStreamIndex ?? -1 })
|
let defaultSubtitleStream = subtitleStreams.first(where: { $0.index! == mediaSource.defaultSubtitleStreamIndex ?? -1 })
|
||||||
|
|
||||||
let videoStream = mediaSource.mediaStreams!.first(where: { $0.type! == MediaStreamType.video })
|
// MARK: Stream
|
||||||
|
|
||||||
let audioCodecs = mediaSource.mediaStreams!.filter({ $0.type! == MediaStreamType.audio }).map({ $0.codec! })
|
|
||||||
|
|
||||||
// MARK: basic stream
|
|
||||||
var streamURL = URLComponents(string: SessionManager.main.currentLogin.server.currentURI)!
|
var streamURL = URLComponents(string: SessionManager.main.currentLogin.server.currentURI)!
|
||||||
streamURL.path = "/Videos/\(self.id!)/stream"
|
|
||||||
|
let streamType: ServerStreamType
|
||||||
|
|
||||||
|
if let transcodeURL = mediaSource.transcodingUrl {
|
||||||
|
streamType = .transcode
|
||||||
|
streamURL.path = transcodeURL
|
||||||
|
} else {
|
||||||
|
streamType = .direct
|
||||||
|
streamURL.path = "/Videos/\(self.id!)/stream"
|
||||||
|
}
|
||||||
|
|
||||||
streamURL.addQueryItem(name: "Static", value: "true")
|
streamURL.addQueryItem(name: "Static", value: "true")
|
||||||
streamURL.addQueryItem(name: "MediaSourceId", value: self.id!)
|
streamURL.addQueryItem(name: "MediaSourceId", value: self.id!)
|
||||||
streamURL.addQueryItem(name: "Tag", value: self.etag)
|
streamURL.addQueryItem(name: "Tag", value: self.etag)
|
||||||
streamURL.addQueryItem(name: "MinSegments", value: "6")
|
streamURL.addQueryItem(name: "MinSegments", value: "6")
|
||||||
|
|
||||||
// MARK: hls stream
|
|
||||||
var hlsURL = URLComponents(string: SessionManager.main.currentLogin.server.currentURI)!
|
|
||||||
hlsURL.path = "/videos/\(self.id!)/master.m3u8"
|
|
||||||
|
|
||||||
hlsURL.addQueryItem(name: "DeviceId", value: UIDevice.vendorUUIDString)
|
|
||||||
hlsURL.addQueryItem(name: "MediaSourceId", value: self.id!)
|
|
||||||
hlsURL.addQueryItem(name: "VideoCodec", value: videoStream?.codec!)
|
|
||||||
hlsURL.addQueryItem(name: "AudioCodec", value: audioCodecs.joined(separator: ","))
|
|
||||||
hlsURL.addQueryItem(name: "AudioStreamIndex", value: "\(defaultAudioStream!.index!)")
|
|
||||||
hlsURL.addQueryItem(name: "VideoBitrate", value: "\(videoStream!.bitRate!)")
|
|
||||||
hlsURL.addQueryItem(name: "AudioBitrate", value: "\(defaultAudioStream!.bitRate!)")
|
|
||||||
hlsURL.addQueryItem(name: "PlaySessionId", value: response.playSessionId!)
|
|
||||||
hlsURL.addQueryItem(name: "TranscodingMaxAudioChannels", value: "6")
|
|
||||||
hlsURL.addQueryItem(name: "RequireAvc", value: "false")
|
|
||||||
hlsURL.addQueryItem(name: "Tag", value: mediaSource.eTag!)
|
|
||||||
hlsURL.addQueryItem(name: "SegmentContainer", value: "ts")
|
|
||||||
hlsURL.addQueryItem(name: "MinSegments", value: "2")
|
|
||||||
hlsURL.addQueryItem(name: "BreakOnNonKeyFrames", value: "true")
|
|
||||||
hlsURL.addQueryItem(name: "TranscodeReasons", value: "VideoCodecNotSupported,AudioCodecNotSupported")
|
|
||||||
hlsURL.addQueryItem(name: "api_key", value: SessionManager.main.currentLogin.user.accessToken)
|
|
||||||
|
|
||||||
if defaultSubtitleStream?.index != nil {
|
|
||||||
hlsURL.addQueryItem(name: "SubtitleMethod", value: "Encode")
|
|
||||||
hlsURL.addQueryItem(name: "SubtitleStreamIndex", value: "\(defaultSubtitleStream!.index!)")
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: VidoPlayerViewModel Creation
|
// MARK: VidoPlayerViewModel Creation
|
||||||
|
|
||||||
var subtitle: String? = nil
|
var subtitle: String? = nil
|
||||||
|
@ -110,7 +89,7 @@ extension BaseItemDto {
|
||||||
title: modifiedSelfItem.name ?? "",
|
title: modifiedSelfItem.name ?? "",
|
||||||
subtitle: subtitle,
|
subtitle: subtitle,
|
||||||
streamURL: streamURL.url!,
|
streamURL: streamURL.url!,
|
||||||
hlsURL: hlsURL.url!,
|
streamType: streamType,
|
||||||
response: response,
|
response: response,
|
||||||
audioStreams: audioStreams,
|
audioStreams: audioStreams,
|
||||||
subtitleStreams: subtitleStreams,
|
subtitleStreams: subtitleStreams,
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
//
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
enum ServerStreamType {
|
||||||
|
case direct
|
||||||
|
case transcode
|
||||||
|
}
|
|
@ -85,12 +85,12 @@ final class VideoPlayerViewModel: ViewModel {
|
||||||
let title: String
|
let title: String
|
||||||
let subtitle: String?
|
let subtitle: String?
|
||||||
let streamURL: URL
|
let streamURL: URL
|
||||||
let hlsURL: URL
|
|
||||||
let audioStreams: [MediaStream]
|
let audioStreams: [MediaStream]
|
||||||
let subtitleStreams: [MediaStream]
|
let subtitleStreams: [MediaStream]
|
||||||
let overlayType: OverlayType
|
let overlayType: OverlayType
|
||||||
let jumpGesturesEnabled: Bool
|
let jumpGesturesEnabled: Bool
|
||||||
let resumeOffset: Bool
|
let resumeOffset: Bool
|
||||||
|
let streamType: ServerStreamType
|
||||||
|
|
||||||
// MARK: Experimental
|
// MARK: Experimental
|
||||||
let syncSubtitleStateWithAdjacent: Bool
|
let syncSubtitleStateWithAdjacent: Bool
|
||||||
|
@ -141,7 +141,7 @@ final class VideoPlayerViewModel: ViewModel {
|
||||||
title: String,
|
title: String,
|
||||||
subtitle: String?,
|
subtitle: String?,
|
||||||
streamURL: URL,
|
streamURL: URL,
|
||||||
hlsURL: URL,
|
streamType: ServerStreamType,
|
||||||
response: PlaybackInfoResponse,
|
response: PlaybackInfoResponse,
|
||||||
audioStreams: [MediaStream],
|
audioStreams: [MediaStream],
|
||||||
subtitleStreams: [MediaStream],
|
subtitleStreams: [MediaStream],
|
||||||
|
@ -157,7 +157,7 @@ final class VideoPlayerViewModel: ViewModel {
|
||||||
self.title = title
|
self.title = title
|
||||||
self.subtitle = subtitle
|
self.subtitle = subtitle
|
||||||
self.streamURL = streamURL
|
self.streamURL = streamURL
|
||||||
self.hlsURL = hlsURL
|
self.streamType = streamType
|
||||||
self.response = response
|
self.response = response
|
||||||
self.audioStreams = audioStreams
|
self.audioStreams = audioStreams
|
||||||
self.subtitleStreams = subtitleStreams
|
self.subtitleStreams = subtitleStreams
|
|
@ -1,164 +0,0 @@
|
||||||
//
|
|
||||||
/*
|
|
||||||
* 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 AVKit
|
|
||||||
import Combine
|
|
||||||
import JellyfinAPI
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
class NativePlayerViewController: AVPlayerViewController {
|
|
||||||
|
|
||||||
let viewModel: VideoPlayerViewModel
|
|
||||||
|
|
||||||
var timeObserverToken: Any?
|
|
||||||
|
|
||||||
var lastProgressTicks: Int64 = 0
|
|
||||||
|
|
||||||
private var cancellables = Set<AnyCancellable>()
|
|
||||||
|
|
||||||
init(viewModel: VideoPlayerViewModel) {
|
|
||||||
|
|
||||||
self.viewModel = viewModel
|
|
||||||
|
|
||||||
super.init(nibName: nil, bundle: nil)
|
|
||||||
|
|
||||||
let player = AVPlayer(url: viewModel.hlsURL)
|
|
||||||
|
|
||||||
player.appliesMediaSelectionCriteriaAutomatically = false
|
|
||||||
player.currentItem?.externalMetadata = createMetadata()
|
|
||||||
player.currentItem?.navigationMarkerGroups = createNavigationMarkerGroups()
|
|
||||||
|
|
||||||
// let chevron = UIImage(systemName: "chevron.right.circle.fill")!
|
|
||||||
// let testAction = UIAction(title: "Next", image: chevron) { action in
|
|
||||||
// SessionAPI.sendSystemCommand(sessionId: viewModel.response.playSessionId!, command: .setSubtitleStreamIndex)
|
|
||||||
// .sink { completion in
|
|
||||||
// print(completion)
|
|
||||||
// } receiveValue: { _ in
|
|
||||||
// print("idk but we're here")
|
|
||||||
// }
|
|
||||||
// .store(in: &self.cancellables)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// self.transportBarCustomMenuItems = [testAction]
|
|
||||||
|
|
||||||
// self.infoViewActions.append(testAction)
|
|
||||||
|
|
||||||
let timeScale = CMTimeScale(NSEC_PER_SEC)
|
|
||||||
let time = CMTime(seconds: 5, preferredTimescale: timeScale)
|
|
||||||
|
|
||||||
timeObserverToken = player.addPeriodicTimeObserver(forInterval: time, queue: .main) { [weak self] time in
|
|
||||||
// print("Timer timed: \(time)")
|
|
||||||
|
|
||||||
if time.seconds != 0 {
|
|
||||||
self?.sendProgressReport(seconds: time.seconds)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.player = player
|
|
||||||
|
|
||||||
self.allowsPictureInPicturePlayback = true
|
|
||||||
self.player?.allowsExternalPlayback = true
|
|
||||||
}
|
|
||||||
|
|
||||||
private func createMetadata() -> [AVMetadataItem] {
|
|
||||||
let allMetadata: [AVMetadataIdentifier: Any] = [
|
|
||||||
.commonIdentifierTitle: viewModel.title,
|
|
||||||
.iTunesMetadataTrackSubTitle: viewModel.subtitle ?? "",
|
|
||||||
.commonIdentifierArtwork: UIImage(data: try! Data(contentsOf: viewModel.item.getBackdropImage(maxWidth: 200)))?.pngData() as Any,
|
|
||||||
.commonIdentifierDescription: viewModel.item.overview ?? "",
|
|
||||||
.iTunesMetadataContentRating: viewModel.item.officialRating ?? "",
|
|
||||||
.quickTimeMetadataGenre: viewModel.item.genres?.first ?? ""
|
|
||||||
]
|
|
||||||
|
|
||||||
return allMetadata.compactMap { createMetadataItem(for:$0, value:$1) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private func createMetadataItem(for identifier: AVMetadataIdentifier,
|
|
||||||
value: Any) -> AVMetadataItem {
|
|
||||||
let item = AVMutableMetadataItem()
|
|
||||||
item.identifier = identifier
|
|
||||||
item.value = value as? NSCopying & NSObjectProtocol
|
|
||||||
// Specify "und" to indicate an undefined language.
|
|
||||||
item.extendedLanguageTag = "und"
|
|
||||||
return item.copy() as! AVMetadataItem
|
|
||||||
}
|
|
||||||
|
|
||||||
private func createNavigationMarkerGroups() -> [AVNavigationMarkersGroup] {
|
|
||||||
guard let chapters = viewModel.item.chapters else { return [] }
|
|
||||||
|
|
||||||
var metadataGroups: [AVTimedMetadataGroup] = []
|
|
||||||
|
|
||||||
// TODO: Determine range between chapters
|
|
||||||
chapters.forEach { chapterInfo in
|
|
||||||
var chapterMetadata: [AVMetadataItem] = []
|
|
||||||
|
|
||||||
let titleItem = createMetadataItem(for: .commonIdentifierTitle, value: chapterInfo.name ?? "No Name")
|
|
||||||
chapterMetadata.append(titleItem)
|
|
||||||
|
|
||||||
let imageItem = createMetadataItem(for: .commonIdentifierArtwork, value: UIImage(data: try! Data(contentsOf: viewModel.item.getBackdropImage(maxWidth: 200)))?.pngData() as Any)
|
|
||||||
chapterMetadata.append(imageItem)
|
|
||||||
|
|
||||||
let startTime = CMTimeMake(value: chapterInfo.startPositionTicks ?? 0, timescale: 10_000_000)
|
|
||||||
let endTime = CMTimeMake(value: (chapterInfo.startPositionTicks ?? 0) + 50_000_000, timescale: 10_000_000)
|
|
||||||
let timeRange = CMTimeRangeFromTimeToTime(start: startTime, end: endTime)
|
|
||||||
|
|
||||||
metadataGroups.append(AVTimedMetadataGroup(items: chapterMetadata, timeRange: timeRange))
|
|
||||||
}
|
|
||||||
|
|
||||||
return [AVNavigationMarkersGroup(title: nil, timedNavigationMarkers: metadataGroups)]
|
|
||||||
}
|
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
|
||||||
fatalError("init(coder:) has not been implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override func viewDidLoad() {
|
|
||||||
super.viewDidLoad()
|
|
||||||
}
|
|
||||||
|
|
||||||
override func viewWillDisappear(_ animated: Bool) {
|
|
||||||
super.viewWillDisappear(animated)
|
|
||||||
|
|
||||||
stop()
|
|
||||||
removePeriodicTimeObserver()
|
|
||||||
}
|
|
||||||
|
|
||||||
func removePeriodicTimeObserver() {
|
|
||||||
if let timeObserverToken = timeObserverToken {
|
|
||||||
player?.removeTimeObserver(timeObserverToken)
|
|
||||||
self.timeObserverToken = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override func viewDidAppear(_ animated: Bool) {
|
|
||||||
super.viewDidAppear(animated)
|
|
||||||
|
|
||||||
player?.seek(to: CMTimeMake(value: viewModel.item.userData?.playbackPositionTicks ?? 0, timescale: 10_000_000), toleranceBefore: CMTimeMake(value: 5, timescale: 1), toleranceAfter: CMTimeMake(value: 5, timescale: 1), completionHandler: { _ in
|
|
||||||
self.play()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private func play() {
|
|
||||||
player?.play()
|
|
||||||
|
|
||||||
// viewModel.sendPlayReport(startTimeTicks: viewModel.item.userData?.playbackPositionTicks ?? 0)
|
|
||||||
viewModel.sendPlayReport()
|
|
||||||
}
|
|
||||||
|
|
||||||
private func sendProgressReport(seconds: Double) {
|
|
||||||
// viewModel.sendProgressReport(ticks: Int64(seconds) * 10_000_000)
|
|
||||||
viewModel.sendProgressReport()
|
|
||||||
}
|
|
||||||
|
|
||||||
private func stop() {
|
|
||||||
self.player?.pause()
|
|
||||||
viewModel.sendStopReport()
|
|
||||||
// viewModel.sendStopReport(ticks: 10_000_000)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,22 +10,6 @@
|
||||||
import UIKit
|
import UIKit
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct NativePlayerView: UIViewControllerRepresentable {
|
|
||||||
|
|
||||||
let viewModel: VideoPlayerViewModel
|
|
||||||
|
|
||||||
typealias UIViewControllerType = NativePlayerViewController
|
|
||||||
|
|
||||||
func makeUIViewController(context: Context) -> NativePlayerViewController {
|
|
||||||
|
|
||||||
return NativePlayerViewController(viewModel: viewModel)
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateUIViewController(_ uiViewController: NativePlayerViewController, context: Context) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct VLCPlayerView: UIViewControllerRepresentable {
|
struct VLCPlayerView: UIViewControllerRepresentable {
|
||||||
|
|
||||||
let viewModel: VideoPlayerViewModel
|
let viewModel: VideoPlayerViewModel
|
||||||
|
|
|
@ -140,7 +140,7 @@ struct tvOSVLCOverlay_Previews: PreviewProvider {
|
||||||
title: "Glorious Purpose",
|
title: "Glorious Purpose",
|
||||||
subtitle: "Loki - S1E1",
|
subtitle: "Loki - S1E1",
|
||||||
streamURL: URL(string: "www.apple.com")!,
|
streamURL: URL(string: "www.apple.com")!,
|
||||||
hlsURL: URL(string: "www.apple.com")!,
|
streamType: .direct,
|
||||||
response: PlaybackInfoResponse(),
|
response: PlaybackInfoResponse(),
|
||||||
audioStreams: [MediaStream(displayTitle: "English", index: -1)],
|
audioStreams: [MediaStream(displayTitle: "English", index: -1)],
|
||||||
subtitleStreams: [MediaStream(displayTitle: "None", index: -1)],
|
subtitleStreams: [MediaStream(displayTitle: "None", index: -1)],
|
||||||
|
|
|
@ -274,6 +274,8 @@
|
||||||
E122A9132788EAAD0060FA63 /* MediaStreamExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E122A9122788EAAD0060FA63 /* MediaStreamExtension.swift */; };
|
E122A9132788EAAD0060FA63 /* MediaStreamExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E122A9122788EAAD0060FA63 /* MediaStreamExtension.swift */; };
|
||||||
E122A9142788EAAD0060FA63 /* 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 */; };
|
||||||
|
E126F741278A656C00A522BF /* ServerStreamType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E126F740278A656C00A522BF /* ServerStreamType.swift */; };
|
||||||
|
E126F742278A656C00A522BF /* ServerStreamType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E126F740278A656C00A522BF /* ServerStreamType.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 */; };
|
||||||
E131691926C583BC0074BFEE /* LogConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E131691626C583BC0074BFEE /* LogConstructor.swift */; };
|
E131691926C583BC0074BFEE /* LogConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E131691626C583BC0074BFEE /* LogConstructor.swift */; };
|
||||||
|
@ -384,7 +386,6 @@
|
||||||
E1C812C3277A8E5D00918266 /* VLCPlayerOverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C812BB277A8E5D00918266 /* VLCPlayerOverlayView.swift */; };
|
E1C812C3277A8E5D00918266 /* VLCPlayerOverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C812BB277A8E5D00918266 /* VLCPlayerOverlayView.swift */; };
|
||||||
E1C812C5277A90B200918266 /* URLComponentsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C812C4277A90B200918266 /* URLComponentsExtensions.swift */; };
|
E1C812C5277A90B200918266 /* URLComponentsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C812C4277A90B200918266 /* URLComponentsExtensions.swift */; };
|
||||||
E1C812CA277AE40900918266 /* PlayerOverlayDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C812C6277AE40900918266 /* PlayerOverlayDelegate.swift */; };
|
E1C812CA277AE40900918266 /* PlayerOverlayDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C812C6277AE40900918266 /* PlayerOverlayDelegate.swift */; };
|
||||||
E1C812CB277AE40900918266 /* NativePlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C812C7277AE40900918266 /* NativePlayerViewController.swift */; };
|
|
||||||
E1C812CC277AE40A00918266 /* VideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C812C8277AE40900918266 /* VideoPlayerView.swift */; };
|
E1C812CC277AE40A00918266 /* VideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C812C8277AE40900918266 /* VideoPlayerView.swift */; };
|
||||||
E1C812CD277AE40A00918266 /* VideoPlayerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C812C9277AE40900918266 /* VideoPlayerViewModel.swift */; };
|
E1C812CD277AE40A00918266 /* VideoPlayerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C812C9277AE40900918266 /* VideoPlayerViewModel.swift */; };
|
||||||
E1C812CE277AE43100918266 /* VideoPlayerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C812C9277AE40900918266 /* VideoPlayerViewModel.swift */; };
|
E1C812CE277AE43100918266 /* VideoPlayerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C812C9277AE40900918266 /* VideoPlayerViewModel.swift */; };
|
||||||
|
@ -649,6 +650,7 @@
|
||||||
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>"; };
|
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>"; };
|
||||||
|
E126F740278A656C00A522BF /* ServerStreamType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerStreamType.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>"; };
|
||||||
E13D02842788B634000FCB04 /* Swiftfin.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Swiftfin.entitlements; sourceTree = "<group>"; };
|
E13D02842788B634000FCB04 /* Swiftfin.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Swiftfin.entitlements; sourceTree = "<group>"; };
|
||||||
|
@ -710,7 +712,6 @@
|
||||||
E1C812BB277A8E5D00918266 /* VLCPlayerOverlayView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VLCPlayerOverlayView.swift; sourceTree = "<group>"; };
|
E1C812BB277A8E5D00918266 /* VLCPlayerOverlayView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VLCPlayerOverlayView.swift; sourceTree = "<group>"; };
|
||||||
E1C812C4277A90B200918266 /* URLComponentsExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLComponentsExtensions.swift; sourceTree = "<group>"; };
|
E1C812C4277A90B200918266 /* URLComponentsExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLComponentsExtensions.swift; sourceTree = "<group>"; };
|
||||||
E1C812C6277AE40900918266 /* PlayerOverlayDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlayerOverlayDelegate.swift; sourceTree = "<group>"; };
|
E1C812C6277AE40900918266 /* PlayerOverlayDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlayerOverlayDelegate.swift; sourceTree = "<group>"; };
|
||||||
E1C812C7277AE40900918266 /* NativePlayerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NativePlayerViewController.swift; sourceTree = "<group>"; };
|
|
||||||
E1C812C8277AE40900918266 /* VideoPlayerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoPlayerView.swift; sourceTree = "<group>"; };
|
E1C812C8277AE40900918266 /* VideoPlayerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoPlayerView.swift; sourceTree = "<group>"; };
|
||||||
E1C812C9277AE40900918266 /* VideoPlayerViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoPlayerViewModel.swift; sourceTree = "<group>"; };
|
E1C812C9277AE40900918266 /* VideoPlayerViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoPlayerViewModel.swift; sourceTree = "<group>"; };
|
||||||
E1C812D0277AE4E300918266 /* tvOSVideoPlayerCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = tvOSVideoPlayerCoordinator.swift; sourceTree = "<group>"; };
|
E1C812D0277AE4E300918266 /* tvOSVideoPlayerCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = tvOSVideoPlayerCoordinator.swift; sourceTree = "<group>"; };
|
||||||
|
@ -816,7 +817,6 @@
|
||||||
5310694F2684E7EE00CFFDBA /* VideoPlayer */ = {
|
5310694F2684E7EE00CFFDBA /* VideoPlayer */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
E1C812C7277AE40900918266 /* NativePlayerViewController.swift */,
|
|
||||||
E1C812C6277AE40900918266 /* PlayerOverlayDelegate.swift */,
|
E1C812C6277AE40900918266 /* PlayerOverlayDelegate.swift */,
|
||||||
E178859C2780F5300094FBCF /* tvOSSLider */,
|
E178859C2780F5300094FBCF /* tvOSSLider */,
|
||||||
E17885A7278130690094FBCF /* tvOSOverlay */,
|
E17885A7278130690094FBCF /* tvOSOverlay */,
|
||||||
|
@ -850,7 +850,7 @@
|
||||||
E13DD3F82717E961009D4DAF /* UserListViewModel.swift */,
|
E13DD3F82717E961009D4DAF /* UserListViewModel.swift */,
|
||||||
E13DD3EB27178A54009D4DAF /* UserSignInViewModel.swift */,
|
E13DD3EB27178A54009D4DAF /* UserSignInViewModel.swift */,
|
||||||
09389CC626819B4500AE350E /* VideoPlayerModel.swift */,
|
09389CC626819B4500AE350E /* VideoPlayerModel.swift */,
|
||||||
E1C812C9277AE40900918266 /* VideoPlayerViewModel.swift */,
|
E126F73F278A655300A522BF /* VideoPlayerViewModel */,
|
||||||
625CB57B2678CE1000530A6E /* ViewModel.swift */,
|
625CB57B2678CE1000530A6E /* ViewModel.swift */,
|
||||||
);
|
);
|
||||||
path = ViewModels;
|
path = ViewModels;
|
||||||
|
@ -1362,6 +1362,15 @@
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
E126F73F278A655300A522BF /* VideoPlayerViewModel */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E126F740278A656C00A522BF /* ServerStreamType.swift */,
|
||||||
|
E1C812C9277AE40900918266 /* VideoPlayerViewModel.swift */,
|
||||||
|
);
|
||||||
|
path = VideoPlayerViewModel;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
E13DD3BB27163C3E009D4DAF /* App */ = {
|
E13DD3BB27163C3E009D4DAF /* App */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -2041,7 +2050,6 @@
|
||||||
E11D224327378428003F9CB3 /* ServerDetailCoordinator.swift in Sources */,
|
E11D224327378428003F9CB3 /* ServerDetailCoordinator.swift in Sources */,
|
||||||
E1D4BF8B2719D3D000A11E64 /* BasicAppSettingsCoordinator.swift in Sources */,
|
E1D4BF8B2719D3D000A11E64 /* BasicAppSettingsCoordinator.swift in Sources */,
|
||||||
E1E5D53B2783A80900692DFE /* CinematicItemViewTopRow.swift in Sources */,
|
E1E5D53B2783A80900692DFE /* CinematicItemViewTopRow.swift in Sources */,
|
||||||
E1C812CB277AE40900918266 /* NativePlayerViewController.swift in Sources */,
|
|
||||||
E13DD3FA2717E961009D4DAF /* UserListViewModel.swift in Sources */,
|
E13DD3FA2717E961009D4DAF /* UserListViewModel.swift in Sources */,
|
||||||
C40CD926271F8D1E000FB198 /* MovieLibrariesViewModel.swift in Sources */,
|
C40CD926271F8D1E000FB198 /* MovieLibrariesViewModel.swift in Sources */,
|
||||||
62E632DE267D2E170063E547 /* LatestMediaViewModel.swift in Sources */,
|
62E632DE267D2E170063E547 /* LatestMediaViewModel.swift in Sources */,
|
||||||
|
@ -2061,6 +2069,7 @@
|
||||||
E1384944278036C70024FB48 /* VLCPlayerViewController.swift in Sources */,
|
E1384944278036C70024FB48 /* VLCPlayerViewController.swift in Sources */,
|
||||||
091B5A8E268315D400D78B61 /* UDPBroadCastConnection.swift in Sources */,
|
091B5A8E268315D400D78B61 /* UDPBroadCastConnection.swift in Sources */,
|
||||||
E10EAA50277BBCC4000269ED /* CGSizeExtensions.swift in Sources */,
|
E10EAA50277BBCC4000269ED /* CGSizeExtensions.swift in Sources */,
|
||||||
|
E126F742278A656C00A522BF /* ServerStreamType.swift in Sources */,
|
||||||
E1E5D5422783B33900692DFE /* PortraitItemsRowView.swift in Sources */,
|
E1E5D5422783B33900692DFE /* PortraitItemsRowView.swift in Sources */,
|
||||||
E1FCD08926C35A0D007C8DCF /* NetworkError.swift in Sources */,
|
E1FCD08926C35A0D007C8DCF /* NetworkError.swift in Sources */,
|
||||||
531690ED267ABF46005D8AB9 /* ContinueWatchingView.swift in Sources */,
|
531690ED267ABF46005D8AB9 /* ContinueWatchingView.swift in Sources */,
|
||||||
|
@ -2322,6 +2331,7 @@
|
||||||
5389277C263CC3DB0035E14B /* BlurHashDecode.swift in Sources */,
|
5389277C263CC3DB0035E14B /* BlurHashDecode.swift in Sources */,
|
||||||
E1D4BF8A2719D3D000A11E64 /* BasicAppSettingsCoordinator.swift in Sources */,
|
E1D4BF8A2719D3D000A11E64 /* BasicAppSettingsCoordinator.swift in Sources */,
|
||||||
E13DD3F92717E961009D4DAF /* UserListViewModel.swift in Sources */,
|
E13DD3F92717E961009D4DAF /* UserListViewModel.swift in Sources */,
|
||||||
|
E126F741278A656C00A522BF /* ServerStreamType.swift in Sources */,
|
||||||
539B2DA5263BA5B8007FF1A4 /* SettingsView.swift in Sources */,
|
539B2DA5263BA5B8007FF1A4 /* SettingsView.swift in Sources */,
|
||||||
5338F74E263B61370014BF09 /* ConnectToServerView.swift in Sources */,
|
5338F74E263B61370014BF09 /* ConnectToServerView.swift in Sources */,
|
||||||
09389CC726819B4600AE350E /* VideoPlayerModel.swift in Sources */,
|
09389CC726819B4600AE350E /* VideoPlayerModel.swift in Sources */,
|
||||||
|
|
|
@ -382,21 +382,21 @@ struct VLCPlayerOverlayView: View {
|
||||||
struct VLCPlayerCompactOverlayView_Previews: PreviewProvider {
|
struct VLCPlayerCompactOverlayView_Previews: PreviewProvider {
|
||||||
|
|
||||||
static let videoPlayerViewModel = VideoPlayerViewModel(item: BaseItemDto(),
|
static let videoPlayerViewModel = VideoPlayerViewModel(item: BaseItemDto(),
|
||||||
title: "Glorious Purpose",
|
title: "Glorious Purpose",
|
||||||
subtitle: "Loki - S1E1",
|
subtitle: "Loki - S1E1",
|
||||||
streamURL: URL(string: "www.apple.com")!,
|
streamURL: URL(string: "www.apple.com")!,
|
||||||
hlsURL: URL(string: "www.apple.com")!,
|
streamType: .direct,
|
||||||
response: PlaybackInfoResponse(),
|
response: PlaybackInfoResponse(),
|
||||||
audioStreams: [MediaStream(displayTitle: "English", index: -1)],
|
audioStreams: [MediaStream(displayTitle: "English", index: -1)],
|
||||||
subtitleStreams: [MediaStream(displayTitle: "None", index: -1)],
|
subtitleStreams: [MediaStream(displayTitle: "None", index: -1)],
|
||||||
selectedAudioStreamIndex: -1,
|
selectedAudioStreamIndex: -1,
|
||||||
selectedSubtitleStreamIndex: -1,
|
selectedSubtitleStreamIndex: -1,
|
||||||
subtitlesEnabled: true,
|
subtitlesEnabled: true,
|
||||||
autoplayEnabled: false,
|
autoplayEnabled: false,
|
||||||
overlayType: .compact,
|
overlayType: .compact,
|
||||||
shouldShowPlayPreviousItem: true,
|
shouldShowPlayPreviousItem: true,
|
||||||
shouldShowPlayNextItem: true,
|
shouldShowPlayNextItem: true,
|
||||||
shouldShowAutoPlay: true)
|
shouldShowAutoPlay: true)
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
|
|
Loading…
Reference in New Issue