Skip to content

Commit

Permalink
Fix cannot apply filters to multiple windows, #4273
Browse files Browse the repository at this point in the history
This commit will:
- Change FilterWindowController to use the active PlayerCore
- Change FilterWindowController.reloadTable to check if the active
  PlayerCore is shutting down
- Disable the ability to add a filter if the active core is stopping
- Change PlayerCore.playbackStopped to clear all audio and video filters
  • Loading branch information
low-batt committed Mar 23, 2023
1 parent 7fd674e commit f98921c
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 8 deletions.
1 change: 1 addition & 0 deletions iina/Base.lproj/FilterWindowController.xib
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="FilterWindowController" customModule="IINA" customModuleProvider="target">
<connections>
<outlet property="addButton" destination="La1-eJ-8B2" id="R96-ah-Qy4"/>
<outlet property="currentFiltersTableView" destination="iTp-t4-bao" id="kgR-wA-2qY"/>
<outlet property="editFilterKeyRecordView" destination="dAY-w3-zCx" id="45M-ij-r6G"/>
<outlet property="editFilterKeyRecordViewLabel" destination="B5v-za-vBd" id="8JH-aQ-LQH"/>
Expand Down
26 changes: 18 additions & 8 deletions iina/FilterWindowController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class FilterWindowController: NSWindowController, NSWindowDelegate {
@IBOutlet weak var editFilterKeyRecordView: KeyRecordView!
@IBOutlet weak var editFilterKeyRecordViewLabel: NSTextField!
@IBOutlet weak var removeButton: NSButton!
@IBOutlet weak var addButton: NSButton!

var loaded = false

Expand All @@ -60,7 +61,7 @@ class FilterWindowController: NSWindowController, NSWindowDelegate {
splitView.setPosition(splitView.frame.height - 140, ofDividerAt: 0)

savedFilters = (Preference.array(for: filterType == MPVProperty.af ? .savedAudioFilters : .savedVideoFilters) ?? []).compactMap(SavedFilter.init(dict:))
filters = PlayerCore.active.mpv.getFilters(filterType)
filters = PlayerCore.lastActive.mpv.getFilters(filterType)
currentFiltersTableView.reloadData()
savedFiltersTableView.reloadData()

Expand All @@ -84,7 +85,13 @@ class FilterWindowController: NSWindowController, NSWindowDelegate {

@objc
func reloadTable() {
filters = PlayerCore.active.mpv.getFilters(filterType)
let pc = PlayerCore.lastActive
// When IINA is terminating player windows are closed, which causes the iinaMainWindowChanged
// notification to be posted and that results in the observer established above calling this
// method. Thus this method may be called after IINA has commanded mpv to shutdown. Once mpv has
// been told to shutdown mpv APIs must not be called as it can trigger a crash in mpv.
guard !pc.isShuttingDown, !pc.isShutdown else { return }
filters = pc.mpv.getFilters(filterType)
filterIsSaved = [Bool](repeatElement(false, count: filters.count))
savedFilters.forEach { savedFilter in
if let asObject = MPVFilter(rawString: savedFilter.filterString),
Expand All @@ -97,10 +104,13 @@ class FilterWindowController: NSWindowController, NSWindowDelegate {
}
currentFiltersTableView.reloadData()
savedFiltersTableView.reloadData()
// Once a player window is being closed the user must not be allowed to add a filter to the
// active player core if it is being stopped and about to be added to the player core cache.
addButton.isEnabled = !pc.isStopping && !pc.isStopped
}

func setFilters() {
PlayerCore.active.mpv.setFilters(filterType, filters: filters)
PlayerCore.lastActive.mpv.setFilters(filterType, filters: filters)
}

deinit {
Expand All @@ -109,12 +119,12 @@ class FilterWindowController: NSWindowController, NSWindowDelegate {

func addFilter(_ filter: MPVFilter) -> Bool {
if filterType == MPVProperty.vf {
guard PlayerCore.active.addVideoFilter(filter) else {
guard PlayerCore.lastActive.addVideoFilter(filter) else {
Utility.showAlert("filter.incorrect", sheetWindow: window)
return false
}
} else {
guard PlayerCore.active.addAudioFilter(filter) else {
guard PlayerCore.lastActive.addAudioFilter(filter) else {
Utility.showAlert("filter.incorrect", sheetWindow: window)
return false
}
Expand Down Expand Up @@ -160,7 +170,7 @@ class FilterWindowController: NSWindowController, NSWindowDelegate {
}

@IBAction func removeFilterAction(_ sender: Any) {
let pc = PlayerCore.active
let pc = PlayerCore.lastActive
let selectedRow = currentFiltersTableView.selectedRow
if selectedRow >= 0 {
let success: Bool
Expand Down Expand Up @@ -190,7 +200,7 @@ class FilterWindowController: NSWindowController, NSWindowDelegate {
@IBAction func toggleSavedFilterAction(_ sender: NSButton) {
let row = savedFiltersTableView.row(for: sender)
let savedFilter = savedFilters[row]
let pc = PlayerCore.active
let pc = PlayerCore.lastActive

// choose appropriate add/remove functions for .af/.vf
var addFilterFunction: (String) -> Bool
Expand Down Expand Up @@ -503,7 +513,7 @@ class NewFilterSheetViewController: NSViewController, NSTableViewDelegate, NSTab
}
// create filter
if filterWindow.addFilter(preset.transformer(instance)) {
PlayerCore.active.sendOSD(.addFilter(preset.localizedName))
PlayerCore.lastActive.sendOSD(.addFilter(preset.localizedName))
}
}

Expand Down
10 changes: 10 additions & 0 deletions iina/PlayerCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ class PlayerCore: NSObject {
/// Whether shutdown of this player has completed (mpv has shutdown).
var isShutdown = false

/// Whether stopping of this player has been initiated.
var isStopping = false

/// Whether mpv playback has stopped and the media has been unloaded.
var isStopped = true

Expand Down Expand Up @@ -590,6 +593,7 @@ class PlayerCore: NSObject {
// initiated directly through mpv.
guard !isStopped else { return }
Logger.log("Stopping playback", subsystem: subsystem)
isStopping = true
mpv.command(.stop)
}

Expand All @@ -600,6 +604,11 @@ class PlayerCore: NSObject {
func playbackStopped() {
Logger.log("Playback has stopped", subsystem: subsystem)
isStopped = true
isStopping = false
// Must clear audio and video filters or they will be applied to the next video if this core is
// reused.
mpv.command(.af, args: ["clr", ""], checkError: false)
mpv.command(.vf, args: ["clr", ""], checkError: false)
postNotification(.iinaPlayerStopped)
}

Expand Down Expand Up @@ -1392,6 +1401,7 @@ class PlayerCore: NSObject {
triedUsingExactSeekForCurrentFile = false
info.fileLoading = false
info.haveDownloadedSub = false
isStopping = false
isStopped = false
checkUnsyncedWindowOptions()
// generate thumbnails if window has loaded video
Expand Down

0 comments on commit f98921c

Please sign in to comment.