persist subtitle state across items

This commit is contained in:
Ethan Pippin 2021-12-30 00:54:21 -07:00
parent bc542dad8d
commit 4219ecc8dc
2 changed files with 57 additions and 22 deletions

View File

@ -259,9 +259,6 @@ extension VLCPlayerViewController {
newViewModel.sliderPercentage = startPercentage / 100 newViewModel.sliderPercentage = startPercentage / 100
} }
didSelectSubtitleStream(index: newViewModel.selectedSubtitleStreamIndex)
didSelectAudioStream(index: newViewModel.selectedAudioStreamIndex)
viewModel = newViewModel viewModel = newViewModel
} }
@ -374,6 +371,8 @@ extension VLCPlayerViewController {
// MARK: VLCMediaPlayerDelegate // MARK: VLCMediaPlayerDelegate
extension VLCPlayerViewController: VLCMediaPlayerDelegate { extension VLCPlayerViewController: VLCMediaPlayerDelegate {
// MARK: mediaPlayerStateChanged
func mediaPlayerStateChanged(_ aNotification: Notification!) { func mediaPlayerStateChanged(_ aNotification: Notification!) {
self.viewModel.playerState = vlcMediaPlayer.state self.viewModel.playerState = vlcMediaPlayer.state
@ -383,6 +382,7 @@ extension VLCPlayerViewController: VLCMediaPlayerDelegate {
} }
} }
// MARK: mediaPlayerTimeChanged
func mediaPlayerTimeChanged(_ aNotification: Notification!) { func mediaPlayerTimeChanged(_ aNotification: Notification!) {
guard !viewModel.sliderIsScrubbing else { guard !viewModel.sliderIsScrubbing else {
@ -398,6 +398,12 @@ extension VLCPlayerViewController: VLCMediaPlayerDelegate {
viewModel.playerState = VLCMediaPlayerState.playing viewModel.playerState = VLCMediaPlayerState.playing
} }
// If needing to fix subtitle streams during playback
if vlcMediaPlayer.currentVideoSubTitleIndex != viewModel.selectedSubtitleStreamIndex && viewModel.subtitlesEnabled {
didSelectSubtitleStream(index: viewModel.selectedSubtitleStreamIndex)
didSelectAudioStream(index: viewModel.selectedAudioStreamIndex)
}
lastPlayerTicks = currentPlayerTicks lastPlayerTicks = currentPlayerTicks
// Send progress report every 5 seconds // Send progress report every 5 seconds
@ -414,15 +420,22 @@ extension VLCPlayerViewController: PlayerOverlayDelegate {
func didSelectAudioStream(index: Int) { func didSelectAudioStream(index: Int) {
vlcMediaPlayer.currentAudioTrackIndex = Int32(index) vlcMediaPlayer.currentAudioTrackIndex = Int32(index)
viewModel.sendProgressReport()
lastProgressReportTicks = currentPlayerTicks
} }
func didSelectSubtitleStream(index: Int) { func didSelectSubtitleStream(index: Int) {
vlcMediaPlayer.currentVideoSubTitleIndex = Int32(index) if viewModel.subtitlesEnabled {
vlcMediaPlayer.currentVideoSubTitleIndex = Int32(index)
if index != -1 { } else {
// set in case weren't shown vlcMediaPlayer.currentVideoSubTitleIndex = -1
viewModel.subtitlesEnabled = true
} }
viewModel.sendProgressReport()
lastProgressReportTicks = currentPlayerTicks
} }
func didSelectClose() { func didSelectClose() {

View File

@ -23,7 +23,14 @@ final class VideoPlayerViewModel: ViewModel {
@Published var playerState: VLCMediaPlayerState @Published var playerState: VLCMediaPlayerState
@Published var shouldShowGoogleCast: Bool @Published var shouldShowGoogleCast: Bool
@Published var shouldShowAirplay: Bool @Published var shouldShowAirplay: Bool
@Published var subtitlesEnabled: Bool @Published var subtitlesEnabled: Bool {
didSet {
if subtitlesEnabled != oldValue {
previousItemVideoPlayerViewModel?.matchSubtitlesEnabled(with: self)
nextItemVideoPlayerViewModel?.matchSubtitlesEnabled(with: self)
}
}
}
@Published var leftLabelText: String = "--:--" @Published var leftLabelText: String = "--:--"
@Published var rightLabelText: String = "--:--" @Published var rightLabelText: String = "--:--"
@Published var playbackSpeed: PlaybackSpeed = .one @Published var playbackSpeed: PlaybackSpeed = .one
@ -237,11 +244,15 @@ extension VideoPlayerViewModel {
} }
private func matchSubtitleStream(with masterViewModel: VideoPlayerViewModel) { private func matchSubtitleStream(with masterViewModel: VideoPlayerViewModel) {
guard let currentSubtitleStream = masterViewModel.subtitleStreams.first(where: { $0.index == masterViewModel.selectedSubtitleStreamIndex }) else { return } if !masterViewModel.subtitlesEnabled {
guard let matchingSubtitleStream = self.subtitleStreams.first(where: { mediaStreamAboutEqual($0, currentSubtitleStream) }) else { return } matchSubtitlesEnabled(with: masterViewModel)
}
self.subtitlesEnabled = masterViewModel.subtitlesEnabled guard let masterSubtitleStream = masterViewModel.subtitleStreams.first(where: { $0.index == masterViewModel.selectedSubtitleStreamIndex }),
self.selectedSubtitleStreamIndex = matchingSubtitleStream.index ?? -1 let matchingSubtitleStream = self.subtitleStreams.first(where: { mediaStreamAboutEqual($0, masterSubtitleStream) }),
let matchingSubtitleStreamIndex = matchingSubtitleStream.index else { return }
self.selectedSubtitleStreamIndex = matchingSubtitleStreamIndex
} }
private func matchAudioStream(with masterViewModel: VideoPlayerViewModel) { private func matchAudioStream(with masterViewModel: VideoPlayerViewModel) {
@ -251,12 +262,16 @@ extension VideoPlayerViewModel {
self.selectedAudioStreamIndex = matchingAudioStream.index ?? -1 self.selectedAudioStreamIndex = matchingAudioStream.index ?? -1
} }
private func matchSubtitlesEnabled(with masterViewModel: VideoPlayerViewModel) {
self.subtitlesEnabled = masterViewModel.subtitlesEnabled
}
private func mediaStreamAboutEqual(_ lhs: MediaStream, _ rhs: MediaStream) -> Bool { private func mediaStreamAboutEqual(_ lhs: MediaStream, _ rhs: MediaStream) -> Bool {
return lhs.displayTitle == rhs.displayTitle && lhs.language == rhs.language return lhs.displayTitle == rhs.displayTitle && lhs.language == rhs.language
} }
} }
// MARK: Reports // MARK: Updates
extension VideoPlayerViewModel { extension VideoPlayerViewModel {
@ -265,13 +280,15 @@ extension VideoPlayerViewModel {
self.startTimeTicks = Int64(Date().timeIntervalSince1970) * 10_000_000 self.startTimeTicks = Int64(Date().timeIntervalSince1970) * 10_000_000
let subtitleStreamIndex = subtitlesEnabled ? selectedSubtitleStreamIndex : nil
let startInfo = PlaybackStartInfo(canSeek: true, let startInfo = PlaybackStartInfo(canSeek: true,
item: item, item: item,
itemId: item.id, itemId: item.id,
sessionId: response.playSessionId, sessionId: response.playSessionId,
mediaSourceId: item.id, mediaSourceId: item.id,
audioStreamIndex: audioStreams.first(where: { $0.index! == response.mediaSources?.first?.defaultAudioStreamIndex! })?.index, audioStreamIndex: selectedAudioStreamIndex,
subtitleStreamIndex: subtitleStreams.first(where: { $0.index! == response.mediaSources?.first?.defaultSubtitleStreamIndex ?? -1 })?.index, subtitleStreamIndex: subtitleStreamIndex,
isPaused: false, isPaused: false,
isMuted: false, isMuted: false,
positionTicks: item.userData?.playbackPositionTicks, positionTicks: item.userData?.playbackPositionTicks,
@ -298,13 +315,16 @@ extension VideoPlayerViewModel {
// MARK: sendPauseReport // MARK: sendPauseReport
func sendPauseReport(paused: Bool) { func sendPauseReport(paused: Bool) {
let startInfo = PlaybackStartInfo(canSeek: true,
let subtitleStreamIndex = subtitlesEnabled ? selectedSubtitleStreamIndex : nil
let pauseInfo = PlaybackStartInfo(canSeek: true,
item: item, item: item,
itemId: item.id, itemId: item.id,
sessionId: response.playSessionId, sessionId: response.playSessionId,
mediaSourceId: item.id, mediaSourceId: item.id,
audioStreamIndex: audioStreams.first(where: { $0.index! == response.mediaSources?.first?.defaultAudioStreamIndex! })?.index, audioStreamIndex: selectedAudioStreamIndex,
subtitleStreamIndex: subtitleStreams.first(where: { $0.index! == response.mediaSources?.first?.defaultSubtitleStreamIndex ?? -1 })?.index, subtitleStreamIndex: subtitleStreamIndex,
isPaused: paused, isPaused: paused,
isMuted: false, isMuted: false,
positionTicks: currentSecondTicks, positionTicks: currentSecondTicks,
@ -320,7 +340,7 @@ extension VideoPlayerViewModel {
playlistItemId: "playlistItem0" playlistItemId: "playlistItem0"
) )
PlaystateAPI.reportPlaybackStart(playbackStartInfo: startInfo) PlaystateAPI.reportPlaybackStart(playbackStartInfo: pauseInfo)
.sink { completion in .sink { completion in
self.handleAPIRequestError(completion: completion) self.handleAPIRequestError(completion: completion)
} receiveValue: { _ in } receiveValue: { _ in
@ -332,13 +352,15 @@ extension VideoPlayerViewModel {
// MARK: sendProgressReport // MARK: sendProgressReport
func sendProgressReport() { func sendProgressReport() {
let subtitleStreamIndex = subtitlesEnabled ? selectedSubtitleStreamIndex : nil
let progressInfo = PlaybackProgressInfo(canSeek: true, let progressInfo = PlaybackProgressInfo(canSeek: true,
item: item, item: item,
itemId: item.id, itemId: item.id,
sessionId: response.playSessionId, sessionId: response.playSessionId,
mediaSourceId: item.id, mediaSourceId: item.id,
audioStreamIndex: audioStreams.first(where: { $0.index! == response.mediaSources?.first?.defaultAudioStreamIndex! })?.index, audioStreamIndex: selectedAudioStreamIndex,
subtitleStreamIndex: subtitleStreams.first(where: { $0.index! == response.mediaSources?.first?.defaultSubtitleStreamIndex ?? -1 })?.index, subtitleStreamIndex: subtitleStreamIndex,
isPaused: false, isPaused: false,
isMuted: false, isMuted: false,
positionTicks: currentSecondTicks, positionTicks: currentSecondTicks,