Fix sendStopReport and sendStartReport

This commit is contained in:
Aiden Vigue 2021-05-23 14:16:14 -04:00
parent 5510e1f723
commit 841f75d80f
2 changed files with 55 additions and 14 deletions

View File

@ -75,7 +75,10 @@ class PlayerUIView: UIView, VLCMediaPlayerDelegate {
sleep(5) sleep(5)
} }
self?.mediaPlayer.wrappedValue.play() self?.mediaPlayer.wrappedValue.play()
self?.mediaPlayer.wrappedValue.jumpForward(Int32(self?.startTime ?? 0/10000000)) if(self?.startTime != 0) {
print(self?.startTime ?? "")
self?.mediaPlayer.wrappedValue.jumpForward(Int32(self!.startTime/10000000))
}
} }
} }
} }

View File

@ -46,6 +46,7 @@ struct VideoPlayerView: View {
@State private var vlcplayer: VLCMediaPlayer = VLCMediaPlayer(options: ["--sub-margin=-50"]); @State private var vlcplayer: VLCMediaPlayer = VLCMediaPlayer(options: ["--sub-margin=-50"]);
@State private var isPlaying = false; @State private var isPlaying = false;
@State private var subtitles: [Subtitle] = []; @State private var subtitles: [Subtitle] = [];
@State private var audioTracks: [Subtitle] = [];
@State private var inactivity: Bool = true; @State private var inactivity: Bool = true;
@State private var lastActivityTime: Double = 0; @State private var lastActivityTime: Double = 0;
@State private var scrub: Double = 0; @State private var scrub: Double = 0;
@ -70,6 +71,7 @@ struct VideoPlayerView: View {
} }
}; };
@State private var selectedCaptionTrack: Int32 = -1; @State private var selectedCaptionTrack: Int32 = -1;
@State private var selectedAudioTrack: Int32 = -1;
var playing: Binding<Bool>; var playing: Binding<Bool>;
init(item: DetailItem, playing: Binding<Bool>) { init(item: DetailItem, playing: Binding<Bool>) {
@ -130,7 +132,7 @@ struct VideoPlayerView: View {
func sendProgressReport() { func sendProgressReport() {
var progressBody: String = ""; var progressBody: String = "";
if(pbitem.videoType == VideoType.direct) { if(pbitem.videoType == VideoType.direct) {
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":\(vlcplayer.state == VLCMediaPlayerState.paused ? "true" : "false"),\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":140000000,\"PositionTicks\":\(Int(vlcplayer.position * Float(item.RuntimeTicks))),\"PlaybackStartTimeTicks\":16209515560670000,\"AudioStreamIndex\":1,\"BufferedRanges\":[{\"start\":0,\"end\":569735888.888889}],\"PlayMethod\":\"\(pbitem.videoType == VideoType.direct ? "DirectStream" : "Transcode")\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem1\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"EventName\":\"timeupdate\"}"; progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":\(vlcplayer.state == VLCMediaPlayerState.paused ? "true" : "false"),\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":140000000,\"PositionTicks\":\(Int(vlcplayer.position * Float(item.RuntimeTicks))),\"PlaybackStartTimeTicks\":16209515560670000,\"AudioStreamIndex\":1,\"BufferedRanges\":[{\"start\":0,\"end\":569735888.888889}],\"PlayMethod\":\"DirectStream\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem1\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"EventName\":\"timeupdate\"}";
} else { } else {
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":\(vlcplayer.state == VLCMediaPlayerState.paused ? "true" : "false"),\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":140000000,\"PositionTicks\":\(Int(vlcplayer.position * Float(item.RuntimeTicks))),\"PlaybackStartTimeTicks\":16209515560670000,\"AudioStreamIndex\":1,\"BufferedRanges\":[{\"start\":0,\"end\":569735888.888889}],\"PlayMethod\":\"Transcode\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem1\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"EventName\":\"timeupdate\"}"; progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":\(vlcplayer.state == VLCMediaPlayerState.paused ? "true" : "false"),\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":140000000,\"PositionTicks\":\(Int(vlcplayer.position * Float(item.RuntimeTicks))),\"PlaybackStartTimeTicks\":16209515560670000,\"AudioStreamIndex\":1,\"BufferedRanges\":[{\"start\":0,\"end\":569735888.888889}],\"PlayMethod\":\"Transcode\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem1\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"EventName\":\"timeupdate\"}";
} }
@ -142,7 +144,8 @@ struct VideoPlayerView: View {
request.messageBody = progressBody.data(using: .ascii); request.messageBody = progressBody.data(using: .ascii);
request.responseData() { (result: Result<RestResponse<Data>, RestError>) in request.responseData() { (result: Result<RestResponse<Data>, RestError>) in
switch result { switch result {
case .success(let _): case .success(let resp):
print(resp.body)
break break
case .failure(let error): case .failure(let error):
debugPrint(error) debugPrint(error)
@ -166,7 +169,8 @@ struct VideoPlayerView: View {
request.messageBody = progressBody.data(using: .ascii); request.messageBody = progressBody.data(using: .ascii);
request.responseData() { (result: Result<RestResponse<Data>, RestError>) in request.responseData() { (result: Result<RestResponse<Data>, RestError>) in
switch result { switch result {
case .success(let _): case .success(let resp):
print(resp.body)
break break
case .failure(let error): case .failure(let error):
debugPrint(error) debugPrint(error)
@ -180,7 +184,7 @@ struct VideoPlayerView: View {
if(pbitem.videoType == VideoType.hls) { if(pbitem.videoType == VideoType.hls) {
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":false,\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":140000000,\"PositionTicks\":0,\"PlaybackStartTimeTicks\":16209515560670000,\"AudioStreamIndex\":1,\"BufferedRanges\":[],\"PlayMethod\":\"Transcode\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem1\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"NowPlayingQueue\":[{\"Id\":\"\(item.Id)\",\"PlaylistItemId\":\"playlistItem1\"}]}"; progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":false,\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":140000000,\"PositionTicks\":0,\"PlaybackStartTimeTicks\":16209515560670000,\"AudioStreamIndex\":1,\"BufferedRanges\":[],\"PlayMethod\":\"Transcode\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem1\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"NowPlayingQueue\":[{\"Id\":\"\(item.Id)\",\"PlaylistItemId\":\"playlistItem1\"}]}";
} else { } else {
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":false,\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":140000000,\"PositionTicks\":0,\"PlaybackStartTimeTicks\":16209515560670000,\"AudioStreamIndex\":1,\"BufferedRanges\":[],\"PlayMethod\":\"Transcode\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem1\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"NowPlayingQueue\":[{\"Id\":\"\(item.Id)\",\"PlaylistItemId\":\"playlistItem1\"}]}"; progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":false,\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":140000000,\"PositionTicks\":0,\"PlaybackStartTimeTicks\":16209515560670000,\"AudioStreamIndex\":1,\"BufferedRanges\":[],\"PlayMethod\":\"DirectStream\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem1\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"NowPlayingQueue\":[{\"Id\":\"\(item.Id)\",\"PlaylistItemId\":\"playlistItem1\"}]}";
} }
let request = RestRequest(method: .post, url: (globalData.server?.baseURI ?? "") + "/Sessions/Playing") let request = RestRequest(method: .post, url: (globalData.server?.baseURI ?? "") + "/Sessions/Playing")
@ -190,7 +194,8 @@ struct VideoPlayerView: View {
request.messageBody = progressBody.data(using: .ascii); request.messageBody = progressBody.data(using: .ascii);
request.responseData() { (result: Result<RestResponse<Data>, RestError>) in request.responseData() { (result: Result<RestResponse<Data>, RestError>) in
switch result { switch result {
case .success(let _): case .success(let resp):
print(resp.body)
break break
case .failure(let error): case .failure(let error):
debugPrint(error) debugPrint(error)
@ -211,7 +216,6 @@ struct VideoPlayerView: View {
_streamLoading.wrappedValue = true; _streamLoading.wrappedValue = true;
let url = (globalData.server?.baseURI ?? "") + "/Items/\(item.Id)/PlaybackInfo?UserId=\(globalData.user?.user_id ?? "")&StartTimeTicks=\(Int(item.Progress))&IsPlayback=true&AutoOpenLiveStream=true&MaxStreamingBitrate=\(DeviceProfile.DeviceProfile.MaxStreamingBitrate)"; let url = (globalData.server?.baseURI ?? "") + "/Items/\(item.Id)/PlaybackInfo?UserId=\(globalData.user?.user_id ?? "")&StartTimeTicks=\(Int(item.Progress))&IsPlayback=true&AutoOpenLiveStream=true&MaxStreamingBitrate=\(DeviceProfile.DeviceProfile.MaxStreamingBitrate)";
print(url)
let request = RestRequest(method: .post, url: url) let request = RestRequest(method: .post, url: url)
request.headerParameters["X-Emby-Authorization"] = globalData.authHeader request.headerParameters["X-Emby-Authorization"] = globalData.authHeader
@ -230,8 +234,6 @@ struct VideoPlayerView: View {
print("Transcoding!") print("Transcoding!")
let streamURL: URL = URL(string: "\(globalData.server?.baseURI ?? "")\((json["MediaSources"][0]["TranscodingUrl"].string ?? "").replacingOccurrences(of: "master.m3u8", with: "main.m3u8"))")! let streamURL: URL = URL(string: "\(globalData.server?.baseURI ?? "")\((json["MediaSources"][0]["TranscodingUrl"].string ?? "").replacingOccurrences(of: "master.m3u8", with: "main.m3u8"))")!
let item = PlaybackItem(videoType: VideoType.hls, videoUrl: streamURL, subtitles: []) let item = PlaybackItem(videoType: VideoType.hls, videoUrl: streamURL, subtitles: [])
print(streamURL)
let disableSubtitleTrack = Subtitle(name: "Disabled", id: -1, url: URL(string: "https://example.com")!, delivery: "Embed") let disableSubtitleTrack = Subtitle(name: "Disabled", id: -1, url: URL(string: "https://example.com")!, delivery: "Embed")
_subtitles.wrappedValue.append(disableSubtitleTrack); _subtitles.wrappedValue.append(disableSubtitleTrack);
for (_,stream):(String, JSON) in json["MediaSources"][0]["MediaStreams"] { for (_,stream):(String, JSON) in json["MediaSources"][0]["MediaStreams"] {
@ -240,10 +242,24 @@ struct VideoPlayerView: View {
let subtitle = Subtitle(name: stream["DisplayTitle"].string ?? "", id: Int32(stream["Index"].int ?? 0), url: deliveryUrl, delivery: stream["DeliveryMethod"].string ?? "") let subtitle = Subtitle(name: stream["DisplayTitle"].string ?? "", id: Int32(stream["Index"].int ?? 0), url: deliveryUrl, delivery: stream["DeliveryMethod"].string ?? "")
_subtitles.wrappedValue.append(subtitle); _subtitles.wrappedValue.append(subtitle);
} }
if(stream["Type"].string == "Audio") {
let deliveryUrl = URL(string: "https://example.com")!
let subtitle = Subtitle(name: stream["DisplayTitle"].string ?? "", id: Int32(stream["Index"].int ?? 0), url: deliveryUrl, delivery: stream["IsExternal"].boolValue ? "External" : "Embed")
if(stream["IsDefault"].boolValue) {
_selectedAudioTrack.wrappedValue = Int32(stream["Index"].int ?? 0);
}
_audioTracks.wrappedValue.append(subtitle);
}
} }
sendPlayReport();
if(_selectedAudioTrack.wrappedValue == -1) {
_selectedAudioTrack.wrappedValue = _audioTracks.wrappedValue[0].id;
}
pbitem = item; pbitem = item;
pbitem.subtitles = subtitles; pbitem.subtitles = subtitles;
sendPlayReport();
_isPlaying.wrappedValue = true; _isPlaying.wrappedValue = true;
} else { } else {
print("Direct playing!"); print("Direct playing!");
@ -257,13 +273,28 @@ struct VideoPlayerView: View {
let subtitle = Subtitle(name: stream["DisplayTitle"].string ?? "", id: Int32(stream["Index"].int ?? 0), url: deliveryUrl, delivery: stream["DeliveryMethod"].string ?? "") let subtitle = Subtitle(name: stream["DisplayTitle"].string ?? "", id: Int32(stream["Index"].int ?? 0), url: deliveryUrl, delivery: stream["DeliveryMethod"].string ?? "")
_subtitles.wrappedValue.append(subtitle); _subtitles.wrappedValue.append(subtitle);
} }
if(stream["Type"].string == "Audio") {
let deliveryUrl = URL(string: "https://example.com")!
let subtitle = Subtitle(name: stream["DisplayTitle"].string ?? "", id: Int32(stream["Index"].int ?? 0), url: deliveryUrl, delivery: stream["IsExternal"].boolValue ? "External" : "Embed")
if(stream["IsDefault"].boolValue) {
_selectedAudioTrack.wrappedValue = Int32(stream["Index"].int ?? 0);
}
_audioTracks.wrappedValue.append(subtitle);
}
} }
if(_selectedAudioTrack.wrappedValue == -1) {
_selectedAudioTrack.wrappedValue = _audioTracks.wrappedValue[0].id;
}
pbitem = item; pbitem = item;
pbitem.subtitles = subtitles; pbitem.subtitles = subtitles;
sendPlayReport();
_isPlaying.wrappedValue = true; _isPlaying.wrappedValue = true;
} }
DispatchQueue.global(qos: .userInteractive).async { [self] in DispatchQueue.global(qos: .utility).async { [self] in
self.keepUpWithPlayerState() self.keepUpWithPlayerState()
} }
} catch { } catch {
@ -283,7 +314,7 @@ struct VideoPlayerView: View {
while(vlcplayer.state == VLCMediaPlayerState.paused) { while(vlcplayer.state == VLCMediaPlayerState.paused) {
let secondsScrubbedTo = round(_scrub.wrappedValue * videoDuration); let secondsScrubbedTo = round(_scrub.wrappedValue * videoDuration);
let scrubRemaining = videoDuration - secondsScrubbedTo; let scrubRemaining = videoDuration - secondsScrubbedTo;
usleep(50000) usleep(100000)
let remainingTime = scrubRemaining; let remainingTime = scrubRemaining;
let hours = floor(remainingTime / 3600); let hours = floor(remainingTime / 3600);
let minutes = (remainingTime.truncatingRemainder(dividingBy: 3600)) / 60; let minutes = (remainingTime.truncatingRemainder(dividingBy: 3600)) / 60;
@ -297,7 +328,6 @@ struct VideoPlayerView: View {
} }
func resetTimer() { func resetTimer() {
print("resetTimer");
if(_inactivity.wrappedValue == false) { if(_inactivity.wrappedValue == false) {
_inactivity.wrappedValue = true; _inactivity.wrappedValue = true;
return; return;
@ -317,6 +347,7 @@ struct VideoPlayerView: View {
HStack() { HStack() {
HStack() { HStack() {
Button() { Button() {
sendStopReport()
self.playing.wrappedValue = false; self.playing.wrappedValue = false;
} label: { } label: {
HStack() { HStack() {
@ -374,7 +405,7 @@ struct VideoPlayerView: View {
let videoDuration = Double(vlcplayer.time.intValue + abs(vlcplayer.remainingTime.intValue)) let videoDuration = Double(vlcplayer.time.intValue + abs(vlcplayer.remainingTime.intValue))
if(bool == true) { if(bool == true) {
vlcplayer.pause() vlcplayer.pause()
DispatchQueue.global(qos: .userInitiated).async { [self] in DispatchQueue.global(qos: .utility).async { [self] in
self.processScrubbingState() self.processScrubbingState()
} }
} else { } else {
@ -423,6 +454,13 @@ struct VideoPlayerView: View {
}.onChange(of: selectedCaptionTrack) { track in }.onChange(of: selectedCaptionTrack) { track in
vlcplayer.currentVideoSubTitleIndex = track; vlcplayer.currentVideoSubTitleIndex = track;
} }
Picker("Audio Track", selection: $selectedAudioTrack) {
ForEach(audioTracks, id: \.id) { caption in
Text(caption.name).tag(caption.id)
}
}.onChange(of: selectedAudioTrack) { track in
vlcplayer.currentAudioTrackIndex = track;
}
} }
Text("Subtitles may take a few moments to appear once selected.") Text("Subtitles may take a few moments to appear once selected.")
.font(.callout) .font(.callout)