diff --git a/Model/Player/Backends/AVPlayerBackend.swift b/Model/Player/Backends/AVPlayerBackend.swift index 49de8107..91869f06 100644 --- a/Model/Player/Backends/AVPlayerBackend.swift +++ b/Model/Player/Backends/AVPlayerBackend.swift @@ -464,20 +464,24 @@ final class AVPlayerBackend: PlayerBackend { } @objc func itemDidPlayToEndTime() { - model.prepareCurrentItemForHistory(finished: true) + if Defaults[.closeLastItemOnPlaybackEnd] { + model.prepareCurrentItemForHistory(finished: true) + } if model.queue.isEmpty { #if !os(macOS) try? AVAudioSession.sharedInstance().setActive(false) #endif - model.resetQueue() - #if os(tvOS) - controller?.playerView.dismiss(animated: false) { [weak self] in - self?.controller?.dismiss(animated: true) - } - #else - model.hide() - #endif + if Defaults[.closeLastItemOnPlaybackEnd] { + model.resetQueue() + #if os(tvOS) + controller?.playerView.dismiss(animated: false) { [weak self] in + self?.controller?.dismiss(animated: true) + } + #else + model.hide() + #endif + } } else { if model.playingInPictureInPicture { startPictureInPictureOnPlay = true diff --git a/Model/Player/Backends/MPVBackend.swift b/Model/Player/Backends/MPVBackend.swift index f5057482..e3a625f3 100644 --- a/Model/Player/Backends/MPVBackend.swift +++ b/Model/Player/Backends/MPVBackend.swift @@ -376,6 +376,8 @@ final class MPVBackend: PlayerBackend { } func handle(_ event: UnsafePointer!) { + logger.info(.init(stringLiteral: "RECEIVED event: \(String(cString: mpv_event_name(event.pointee.event_id)))")) + switch event.pointee.event_id { case MPV_EVENT_SHUTDOWN: mpv_destroy(client.mpv) @@ -401,9 +403,11 @@ final class MPVBackend: PlayerBackend { onFileLoaded = nil case MPV_EVENT_PAUSE: + isPlaying = false networkStateTimer.resume() case MPV_EVENT_UNPAUSE: + isPlaying = true isLoadingVideo = false isSeeking = false networkStateTimer.resume() @@ -413,7 +417,7 @@ final class MPVBackend: PlayerBackend { case MPV_EVENT_END_FILE: DispatchQueue.main.async { [weak self] in - self?.handleEndOfFile(event) + self?.handleEndOfFile() } default: @@ -421,20 +425,26 @@ final class MPVBackend: PlayerBackend { } } - func handleEndOfFile(_: UnsafePointer!) { + func handleEndOfFile() { guard handleEOF, !isLoadingVideo else { return } - model.prepareCurrentItemForHistory(finished: true) + getClientUpdates() + + if Defaults[.closeLastItemOnPlaybackEnd] { + model.prepareCurrentItemForHistory(finished: true) + } if model.queue.isEmpty { #if !os(macOS) try? AVAudioSession.sharedInstance().setActive(false) #endif - model.resetQueue() - model.hide() + if Defaults[.closeLastItemOnPlaybackEnd] { + model.resetQueue() + model.hide() + } } else { model.advanceToNextItem() } diff --git a/Model/Player/Backends/MPVClient.swift b/Model/Player/Backends/MPVClient.swift index 358c6dd7..f26ccf08 100644 --- a/Model/Player/Backends/MPVClient.swift +++ b/Model/Player/Backends/MPVClient.swift @@ -48,6 +48,7 @@ final class MPVClient: ObservableObject { checkError(mpv_set_option_string(mpv, "cache-pause-initial", "yes")) checkError(mpv_set_option_string(mpv, "cache-secs", "20")) checkError(mpv_set_option_string(mpv, "cache-pause-wait", "2")) + checkError(mpv_set_option_string(mpv, "keep-open", "yes")) checkError(mpv_set_option_string(mpv, "hwdec", "auto-safe")) checkError(mpv_set_option_string(mpv, "vo", "libmpv")) diff --git a/Model/Player/PlayerSponsorBlock.swift b/Model/Player/PlayerSponsorBlock.swift index 0614b02f..d46fbd51 100644 --- a/Model/Player/PlayerSponsorBlock.swift +++ b/Model/Player/PlayerSponsorBlock.swift @@ -41,16 +41,21 @@ extension PlayerModel { return } - self.prepareCurrentItemForHistory(finished: true) self.pause() + if Defaults[.closeLastItemOnPlaybackEnd] { + self.prepareCurrentItemForHistory(finished: true) + } + if self.queue.isEmpty { #if !os(macOS) try? AVAudioSession.sharedInstance().setActive(false) #endif - self.resetQueue() - self.hide() + if Defaults[.closeLastItemOnPlaybackEnd] { + self.resetQueue() + self.hide() + } } else { self.advanceToNextItem() } diff --git a/Shared/Defaults.swift b/Shared/Defaults.swift index 1fc7e29d..5b5b66a6 100644 --- a/Shared/Defaults.swift +++ b/Shared/Defaults.swift @@ -63,6 +63,7 @@ extension Defaults.Keys { static let commentsPlacement = Key("commentsPlacement", default: .separate) #endif static let pauseOnHidingPlayer = Key("pauseOnHidingPlayer", default: defaultForPauseOnHidingPlayer) + static let closeLastItemOnPlaybackEnd = Key("closeLastItemOnPlaybackEnd", default: false) static let closePiPOnNavigation = Key("closePiPOnNavigation", default: false) static let closePiPOnOpeningPlayer = Key("closePiPOnOpeningPlayer", default: false) @@ -98,8 +99,6 @@ extension Defaults.Keys { static let showMPVPlaybackStats = Key("showMPVPlaybackStats", default: false) static let playerDetailsPageButtonLabelStyle = Key("playerDetailsPageButtonLabelStyle", default: defaultForPlayerDetailsPageButtonLabelStyle) - - static let controlsBarInPlayer = Key("controlsBarInPlayer", default: true) } enum ResolutionSetting: String, CaseIterable, Defaults.Serializable { diff --git a/Shared/Player/VideoDetails.swift b/Shared/Player/VideoDetails.swift index b376eb4c..38c713cc 100644 --- a/Shared/Player/VideoDetails.swift +++ b/Shared/Player/VideoDetails.swift @@ -43,7 +43,6 @@ struct VideoDetails: View { @Default(.showKeywords) private var showKeywords @Default(.playerDetailsPageButtonLabelStyle) private var playerDetailsPageButtonLabelStyle - @Default(.controlsBarInPlayer) private var controlsBarInPlayer var currentPage: DetailsPage { DetailsPage.allCases.first { $0.index == page.index } ?? .info diff --git a/Shared/Settings/PlayerSettings.swift b/Shared/Settings/PlayerSettings.swift index 714f32b4..e08af1d1 100644 --- a/Shared/Settings/PlayerSettings.swift +++ b/Shared/Settings/PlayerSettings.swift @@ -15,6 +15,7 @@ struct PlayerSettings: View { @Default(.showHistoryInPlayer) private var showHistory @Default(.showKeywords) private var showKeywords @Default(.pauseOnHidingPlayer) private var pauseOnHidingPlayer + @Default(.closeLastItemOnPlaybackEnd) private var closeLastItemOnPlaybackEnd #if os(iOS) @Default(.honorSystemOrientationLock) private var honorSystemOrientationLock @Default(.lockOrientationInFullScreen) private var lockOrientationInFullScreen @@ -62,6 +63,7 @@ struct PlayerSettings: View { sourcePicker qualityPicker pauseOnHidingPlayerToggle + closeLastItemOnPlaybackEndToggle } Section(header: SettingsHeader(text: "Comments")) { @@ -209,6 +211,10 @@ struct PlayerSettings: View { Toggle("Pause when player is closed", isOn: $pauseOnHidingPlayer) } + private var closeLastItemOnPlaybackEndToggle: some View { + Toggle("Close video after playing last in the queue", isOn: $closeLastItemOnPlaybackEnd) + } + #if os(iOS) private var honorSystemOrientationLockToggle: some View { Toggle("Honor orientation lock", isOn: $honorSystemOrientationLock)