fix progress
This commit is contained in:
parent
2fe283eb09
commit
98ef133bd9
|
@ -63,7 +63,7 @@ struct ContinueWatchingView: View {
|
||||||
Rectangle()
|
Rectangle()
|
||||||
.fill(Color(red: 172/255, green: 92/255, blue: 195/255))
|
.fill(Color(red: 172/255, green: 92/255, blue: 195/255))
|
||||||
.mask(ProgressBar())
|
.mask(ProgressBar())
|
||||||
.frame(width: CGFloat(item.userData?.playedPercentage ?? 0 * 3.2), height: 7)
|
.frame(width: CGFloat((item.userData?.playedPercentage ?? 0) * 3.2), height: 7)
|
||||||
.padding(0), alignment: .bottomLeading
|
.padding(0), alignment: .bottomLeading
|
||||||
)
|
)
|
||||||
Text(item.seriesName ?? item.name ?? "")
|
Text(item.seriesName ?? item.name ?? "")
|
||||||
|
|
|
@ -144,7 +144,7 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
|
||||||
sendProgressReport(eventName: "unpause")
|
sendProgressReport(eventName: "unpause")
|
||||||
} else {
|
} else {
|
||||||
sendJellyfinCommand(command: "Seek", options: [
|
sendJellyfinCommand(command: "Seek", options: [
|
||||||
"position": secondsScrubbedTo
|
"position": Int(secondsScrubbedTo)
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,6 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
|
||||||
self.castButton.isEnabled = true
|
self.castButton.isEnabled = true
|
||||||
self.castButton.setImage(UIImage(named: "CastDisconnected"), for: .normal)
|
self.castButton.setImage(UIImage(named: "CastDisconnected"), for: .normal)
|
||||||
playerDestination = .local
|
playerDestination = .local
|
||||||
startLocalPlaybackEngine()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,40 +548,43 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
|
||||||
self.sendPlayReport()
|
self.sendPlayReport()
|
||||||
playbackItem = item
|
playbackItem = item
|
||||||
}
|
}
|
||||||
startLocalPlaybackEngine()
|
startLocalPlaybackEngine(true)
|
||||||
})
|
})
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func startLocalPlaybackEngine() {
|
func startLocalPlaybackEngine(_ fetchCaptions: Bool) {
|
||||||
print("Local playback engine starting.")
|
print("Local playback engine starting.")
|
||||||
mediaPlayer = VLCMediaPlayer()
|
|
||||||
mediaPlayer.delegate = self;
|
|
||||||
mediaPlayer.drawable = videoContentView;
|
|
||||||
|
|
||||||
mediaPlayer.media = VLCMedia(url: playbackItem.videoUrl)
|
mediaPlayer.media = VLCMedia(url: playbackItem.videoUrl)
|
||||||
mediaPlayer.play()
|
mediaPlayer.play()
|
||||||
|
|
||||||
// 1 second = 10,000,000 ticks
|
// 1 second = 10,000,000 ticks
|
||||||
|
var startTicks: Int64 = 0;
|
||||||
if(remotePositionTicks == 0) {
|
if(remotePositionTicks == 0) {
|
||||||
print("Using server-reported start time")
|
print("Using server-reported start time")
|
||||||
let rawStartTicks = manifest.userData?.playbackPositionTicks ?? 0
|
startTicks = manifest.userData?.playbackPositionTicks ?? 0
|
||||||
|
|
||||||
if rawStartTicks != 0 {
|
|
||||||
let startSeconds = rawStartTicks / 10_000_000
|
|
||||||
mediaPlayer.jumpForward(Int32(startSeconds))
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
print("Using remote-reported start time")
|
print("Using remote-reported start time")
|
||||||
mediaPlayer.jumpForward(Int32(remotePositionTicks / 10_000_000))
|
startTicks = Int64(remotePositionTicks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if startTicks != 0 {
|
||||||
|
let videoPosition = Double(mediaPlayer.time.intValue / 1000);
|
||||||
|
let secondsScrubbedTo = startTicks / 10_000_000
|
||||||
|
let offset = secondsScrubbedTo - Int64(videoPosition)
|
||||||
|
print("Seeking to position: \(secondsScrubbedTo)")
|
||||||
|
if offset > 0 {
|
||||||
|
mediaPlayer.jumpForward(Int32(offset))
|
||||||
|
} else {
|
||||||
|
mediaPlayer.jumpBackward(Int32(abs(offset)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fetchCaptions) {
|
||||||
// Pause and load captions into memory.
|
// Pause and load captions into memory.
|
||||||
mediaPlayer.pause()
|
mediaPlayer.pause()
|
||||||
|
var shouldHaveSubtitleTracks = 1
|
||||||
var shouldHaveSubtitleTracks = 0
|
|
||||||
subtitleTrackArray.forEach { sub in
|
subtitleTrackArray.forEach { sub in
|
||||||
if sub.id != -1 && sub.delivery == .external && sub.codec != "subrip" {
|
if sub.id != -1 && sub.delivery == .external && sub.codec != "subrip" {
|
||||||
shouldHaveSubtitleTracks = shouldHaveSubtitleTracks + 1
|
shouldHaveSubtitleTracks = shouldHaveSubtitleTracks + 1
|
||||||
|
@ -593,12 +595,16 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
|
||||||
// Wait for captions to load
|
// Wait for captions to load
|
||||||
delegate?.showLoadingView(self)
|
delegate?.showLoadingView(self)
|
||||||
|
|
||||||
while mediaPlayer.numberOfSubtitlesTracks != shouldHaveSubtitleTracks {}
|
while mediaPlayer.numberOfSubtitlesTracks != shouldHaveSubtitleTracks {
|
||||||
|
print("waiting \(String(mediaPlayer.numberOfSubtitlesTracks)) != \(String(shouldHaveSubtitleTracks))")
|
||||||
|
}
|
||||||
|
|
||||||
// Select default track & resume playback
|
// Select default track & resume playback
|
||||||
mediaPlayer.currentVideoSubTitleIndex = selectedCaptionTrack
|
mediaPlayer.currentVideoSubTitleIndex = selectedCaptionTrack
|
||||||
mediaPlayer.pause()
|
mediaPlayer.pause()
|
||||||
mediaPlayer.play()
|
mediaPlayer.play()
|
||||||
|
}
|
||||||
|
|
||||||
self.mediaHasStartedPlaying()
|
self.mediaHasStartedPlaying()
|
||||||
delegate?.hideLoadingView(self)
|
delegate?.hideLoadingView(self)
|
||||||
print("Local engine started.")
|
print("Local engine started.")
|
||||||
|
@ -619,9 +625,10 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
|
||||||
//MARK: - GCKGenericChannelDelegate
|
//MARK: - GCKGenericChannelDelegate
|
||||||
extension PlayerViewController: GCKGenericChannelDelegate {
|
extension PlayerViewController: GCKGenericChannelDelegate {
|
||||||
@objc func updateRemoteTime() {
|
@objc func updateRemoteTime() {
|
||||||
paused = false;
|
|
||||||
castButton.setImage(UIImage(named: "CastConnected"), for: .normal)
|
castButton.setImage(UIImage(named: "CastConnected"), for: .normal)
|
||||||
|
if(!paused) {
|
||||||
remotePositionTicks = remotePositionTicks + 2_000_000; //add 0.2 secs every timer evt.
|
remotePositionTicks = remotePositionTicks + 2_000_000; //add 0.2 secs every timer evt.
|
||||||
|
}
|
||||||
|
|
||||||
if(isSeeking == false) {
|
if(isSeeking == false) {
|
||||||
let remainingTime = (manifest.runTimeTicks! - Int64(remotePositionTicks))/10_000_000
|
let remainingTime = (manifest.runTimeTicks! - Int64(remotePositionTicks))/10_000_000
|
||||||
|
@ -637,6 +644,7 @@ extension PlayerViewController: GCKGenericChannelDelegate {
|
||||||
timeText.text = timeTextStr
|
timeText.text = timeTextStr
|
||||||
|
|
||||||
let playbackProgress = Int64(remotePositionTicks) / manifest.runTimeTicks!
|
let playbackProgress = Int64(remotePositionTicks) / manifest.runTimeTicks!
|
||||||
|
print(playbackProgress)
|
||||||
seekSlider.setValue(Float(playbackProgress), animated: true)
|
seekSlider.setValue(Float(playbackProgress), animated: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -652,6 +660,7 @@ extension PlayerViewController: GCKGenericChannelDelegate {
|
||||||
"position": Int(Float(manifest.runTimeTicks! / 10_000_000) * mediaPlayer.position)
|
"position": Int(Float(manifest.runTimeTicks! / 10_000_000) * mediaPlayer.position)
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
paused = json["data"]["PlayState"]["IsPaused"].boolValue
|
||||||
self.remotePositionTicks = json["data"]["PlayState"]["PositionTicks"].int ?? 0;
|
self.remotePositionTicks = json["data"]["PlayState"]["PositionTicks"].int ?? 0;
|
||||||
if(remoteTimeUpdateTimer == nil) {
|
if(remoteTimeUpdateTimer == nil) {
|
||||||
remoteTimeUpdateTimer = Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(updateRemoteTime), userInfo: nil, repeats: true)
|
remoteTimeUpdateTimer = Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(updateRemoteTime), userInfo: nil, repeats: true)
|
||||||
|
@ -736,7 +745,7 @@ extension PlayerViewController: GCKSessionManagerListener {
|
||||||
videoContentView.isHidden = false;
|
videoContentView.isHidden = false;
|
||||||
remoteTimeUpdateTimer?.invalidate()
|
remoteTimeUpdateTimer?.invalidate()
|
||||||
castButton.setImage(UIImage(named: "CastDisconnected"), for: .normal)
|
castButton.setImage(UIImage(named: "CastDisconnected"), for: .normal)
|
||||||
startLocalPlaybackEngine()
|
startLocalPlaybackEngine(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sessionManager(_ sessionManager: GCKSessionManager, didSuspend session: GCKCastSession, with reason: GCKConnectionSuspendReason) {
|
func sessionManager(_ sessionManager: GCKSessionManager, didSuspend session: GCKCastSession, with reason: GCKConnectionSuspendReason) {
|
||||||
|
@ -745,7 +754,7 @@ extension PlayerViewController: GCKSessionManagerListener {
|
||||||
videoContentView.isHidden = false;
|
videoContentView.isHidden = false;
|
||||||
remoteTimeUpdateTimer?.invalidate()
|
remoteTimeUpdateTimer?.invalidate()
|
||||||
castButton.setImage(UIImage(named: "CastDisconnected"), for: .normal)
|
castButton.setImage(UIImage(named: "CastDisconnected"), for: .normal)
|
||||||
startLocalPlaybackEngine()
|
startLocalPlaybackEngine(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,13 +104,13 @@ extension BaseItemDto {
|
||||||
|
|
||||||
// MARK: Calculations
|
// MARK: Calculations
|
||||||
func getItemRuntime() -> String {
|
func getItemRuntime() -> String {
|
||||||
let seconds: Int = Int(self.runTimeTicks ?? 0) / 10_000_000
|
let seconds = (self.runTimeTicks ?? 0) / 10_000_000
|
||||||
let hours = (seconds / 3600)
|
let hours = (seconds / 3600)
|
||||||
let minutes = ((seconds - (hours * 3600)) / 60)
|
let minutes = ((seconds - (hours * 3600)) / 60)
|
||||||
if hours != 0 {
|
if hours != 0 {
|
||||||
return "\(hours):\(String(minutes).leftPad(toWidth: 2, withString: "0"))"
|
return "\(hours):\(String(minutes).leftPad(toWidth: 2, withString: "0"))"
|
||||||
} else {
|
} else {
|
||||||
return "\(String(minutes).leftPad(toWidth: 2, withString: "0"))m"
|
return "\(String(minutes))m"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,13 +119,13 @@ extension BaseItemDto {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
let remainingSecs = Int(self.runTimeTicks ?? 0 - (self.userData?.playbackPositionTicks ?? 0)) / 10_000_000
|
let remainingSecs = ((self.runTimeTicks ?? 0) - (self.userData?.playbackPositionTicks ?? 0)) / 10_000_000
|
||||||
let proghours = Int(remainingSecs / 3600)
|
let proghours = Int(remainingSecs / 3600)
|
||||||
let progminutes = Int((Int(remainingSecs) - (proghours * 3600)) / 60)
|
let progminutes = Int((Int(remainingSecs) - (proghours * 3600)) / 60)
|
||||||
if proghours != 0 {
|
if proghours != 0 {
|
||||||
return "\(proghours)h \(String(progminutes).leftPad(toWidth: 2, withString: "0"))m"
|
return "\(proghours)h \(String(progminutes).leftPad(toWidth: 2, withString: "0"))m"
|
||||||
} else {
|
} else {
|
||||||
return "\(String(progminutes).leftPad(toWidth: 2, withString: "0"))m"
|
return "\(String(progminutes))m"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue