Skip to content

Commit

Permalink
Fix PlayerCore.active not accessed from main thread, #4251
Browse files Browse the repository at this point in the history
This commit will:
- Change PlayerCore.playbackRestarted to use the main thread to call
  NowPlayingInfoManager.updateInfo
- Remove locking from NowPlayingInfoManager.updateInfo since there is no
  longer a need to coordinate access from multiple threads
- Add comments pointing out the requirement to use the main thread
  • Loading branch information
low-batt authored and uiryuu committed Mar 22, 2023
1 parent 2a80282 commit e6fe6d8
Showing 1 changed file with 19 additions and 9 deletions.
28 changes: 19 additions & 9 deletions iina/PlayerCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class PlayerCore: NSObject {

static private weak var _lastActive: PlayerCore?

/// - Important: Code referencing this property **must** be run on the main thread as getting the value of this property _may_
/// result in a reference the `active` property and that requires use of the main thread.
static var lastActive: PlayerCore {
get {
return _lastActive ?? active
Expand All @@ -26,6 +28,8 @@ class PlayerCore: NSObject {
}
}

/// - Important: Code referencing this property **must** be run on the main thread because it references
/// [NSApplication.mainWindow`](https://developer.apple.com/documentation/appkit/nsapplication/1428723-mainwindow)
static var active: PlayerCore {
if let wc = NSApp.mainWindow?.windowController as? MainWindowController {
return wc.player
Expand Down Expand Up @@ -1463,10 +1467,10 @@ class PlayerCore: NSObject {
mainWindow.videoView.videoLayer.draw(forced: true)

if #available(macOS 10.13, *), RemoteCommandController.useSystemMediaControl {
NowPlayingInfoManager.updateInfo()
DispatchQueue.main.sync {
NowPlayingInfoManager.updateInfo()
}
}


DispatchQueue.main.async {
Timer.scheduledTimer(timeInterval: TimeInterval(0.2), target: self, selector: #selector(self.reEnableOSDAfterFileLoading), userInfo: nil, repeats: false)
}
Expand Down Expand Up @@ -2089,14 +2093,20 @@ extension PlayerCore: FFmpegControllerDelegate {

@available (macOS 10.13, *)
class NowPlayingInfoManager {
static private let lock = NSLock()

/// Update the information shown by macOS in `Now Playing`.
///
/// The macOS [Control Center](https://support.apple.com/guide/mac-help/quickly-change-settings-mchl50f94f8f/mac)
/// contains a `Now Playing` module. This module can also be configured to be directly accessible from the menu bar.
/// `Now Playing` displays the title of the media currently playing and other information about the state of playback. It also can be
/// used to control playback. IINA is fully integrated with the macOS `Now Playing` module.
///
/// - Note: See [Becoming a Now Playable App](https://developer.apple.com/documentation/mediaplayer/becoming_a_now_playable_app)
/// and [MPNowPlayingInfoCenter](https://developer.apple.com/documentation/mediaplayer/mpnowplayinginfocenter)
/// for more information.
///
/// - Important: This method **must** be run on the main thread because it references `PlayerCore.lastActive`.
static func updateInfo(state: MPNowPlayingPlaybackState? = nil, withTitle: Bool = false) {
// This method is called from the main thread and from background threads. Must single thread access.
lock.lock()
defer {
lock.unlock()
}
let center = MPNowPlayingInfoCenter.default()
var info = center.nowPlayingInfo ?? [String: Any]()

Expand Down

0 comments on commit e6fe6d8

Please sign in to comment.