mirror of https://github.com/mpv-player/mpv
mac/app: cleanup and optimise App launch and termination
NSApp.terminate() is not a requirement to properly shut down a cocoa App since it only calls exit() internally. though when not used the cocoa termination events won't trigger, which we don't need. this prevented us to exit with a proper exit code. rework the whole termination logic to end up at one point where we can return the exit code from the mpv_main function. Fixes #7456
This commit is contained in:
parent
d6c621b03b
commit
3c51497954
|
@ -19,6 +19,8 @@ import Cocoa
|
|||
|
||||
class Application: NSApplication, NSApplicationDelegate {
|
||||
var appHub: AppHub { get { return AppHub.shared } }
|
||||
var eventManager: NSAppleEventManager { get { return NSAppleEventManager.shared() } }
|
||||
var isBundle: Bool { get { return ProcessInfo.processInfo.environment["MPVBUNDLE"] == "true" } }
|
||||
var playbackThreadId: mp_thread!
|
||||
var argc: Int32?
|
||||
var argv: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>?
|
||||
|
@ -31,34 +33,6 @@ class Application: NSApplication, NSApplicationDelegate {
|
|||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
let eventManager = NSAppleEventManager.shared()
|
||||
eventManager.removeEventHandler(forEventClass: AEEventClass(kCoreEventClass), andEventID: kAEQuitApplication)
|
||||
}
|
||||
|
||||
func initApplication(_ regular: Bool) {
|
||||
NSApp = self
|
||||
NSApp.delegate = self
|
||||
|
||||
// Will be set to Regular from cocoa_common during UI creation so that we
|
||||
// don't create an icon when playing audio only files.
|
||||
NSApp.setActivationPolicy(regular ? .regular : .accessory)
|
||||
|
||||
atexit_b({
|
||||
// Because activation policy has just been set to behave like a real
|
||||
// application, that policy must be reset on exit to prevent, among
|
||||
// other things, the menubar created here from remaining on screen.
|
||||
DispatchQueue.main.async { NSApp.setActivationPolicy(.prohibited) }
|
||||
})
|
||||
}
|
||||
|
||||
func terminateApplication() {
|
||||
DispatchQueue.main.async {
|
||||
NSApp.hide(NSApp)
|
||||
NSApp.terminate(NSApp)
|
||||
}
|
||||
}
|
||||
|
||||
override func sendEvent(_ event: NSEvent) {
|
||||
if modalWindow != nil || !appHub.input.processKey(event: event) {
|
||||
super.sendEvent(event)
|
||||
|
@ -77,29 +51,36 @@ class Application: NSApplication, NSApplicationDelegate {
|
|||
}
|
||||
|
||||
func applicationWillFinishLaunching(_ notification: Notification) {
|
||||
let eventManager = NSAppleEventManager.shared()
|
||||
// register quit and exit events
|
||||
eventManager.setEventHandler(
|
||||
self,
|
||||
andSelector: #selector(handleQuit(event:replyEvent:)),
|
||||
forEventClass: AEEventClass(kCoreEventClass),
|
||||
andEventID: kAEQuitApplication
|
||||
)
|
||||
atexit_b({
|
||||
// clean up after exit() was called
|
||||
DispatchQueue.main.async {
|
||||
NSApp.hide(NSApp)
|
||||
NSApp.setActivationPolicy(.prohibited)
|
||||
self.eventManager.removeEventHandler(forEventClass: AEEventClass(kCoreEventClass), andEventID: kAEQuitApplication)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// quit from App icon
|
||||
// quit from App icon, external quit from NSWorkspace
|
||||
@objc func handleQuit(event: NSAppleEventDescriptor?, replyEvent: NSAppleEventDescriptor?) {
|
||||
// send quit to core, terminates mpv_main called in playbackThread,
|
||||
if !appHub.input.command("quit") {
|
||||
terminateApplication()
|
||||
appHub.log.warning("Could not properly shut down mpv")
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func bundleStartedFromFinder() -> Bool {
|
||||
return ProcessInfo.processInfo.environment["MPVBUNDLE"] == "true"
|
||||
}
|
||||
|
||||
func setupBundle() {
|
||||
if !isBundle { return }
|
||||
|
||||
// started from finder the first argument after the binary may start with -psn_
|
||||
// remove it and all following
|
||||
if CommandLine.argc > 1 && CommandLine.arguments[1].hasPrefix("-psn_") {
|
||||
argc? = 1
|
||||
argv?[1] = nil
|
||||
|
@ -113,28 +94,24 @@ class Application: NSApplication, NSApplicationDelegate {
|
|||
let playbackThread: @convention(c) (UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? = { (ptr: UnsafeMutableRawPointer) in
|
||||
let application: Application = TypeHelper.bridge(ptr: ptr)
|
||||
mp_thread_set_name("core/playback")
|
||||
let r: Int32 = mpv_main(application.argc ?? 1, application.argv)
|
||||
application.terminateApplication()
|
||||
// normally never reached - unless the cocoa mainloop hasn't started yet
|
||||
exit(r)
|
||||
let exitCode: Int32 = mpv_main(application.argc ?? 1, application.argv)
|
||||
// exit of any proper shut down
|
||||
exit(exitCode)
|
||||
}
|
||||
|
||||
@objc func main(_ argc: Int32, _ argv: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>) -> Int {
|
||||
self.argc = argc
|
||||
self.argv = argv
|
||||
|
||||
if bundleStartedFromFinder() {
|
||||
setupBundle()
|
||||
initApplication(true)
|
||||
} else {
|
||||
initApplication(false)
|
||||
}
|
||||
|
||||
NSApp = self
|
||||
NSApp.delegate = self
|
||||
NSApp.setActivationPolicy(isBundle ? .regular : .accessory)
|
||||
setupBundle()
|
||||
pthread_create(&playbackThreadId, nil, playbackThread, TypeHelper.bridge(obj: self))
|
||||
appHub.input.wait()
|
||||
NSApp.run()
|
||||
|
||||
// This should never be reached: NSApp.run() blocks until the process is quit
|
||||
// should never be reached
|
||||
print("""
|
||||
There was either a problem initializing Cocoa or the Runloop was stopped unexpectedly. \
|
||||
Please report this issues to a developer.\n
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
#include "osdep/mac/app_bridge.h"
|
||||
|
||||
// This is needed because Cocoa absolutely requires creating the NSApplication
|
||||
// singleton and running it in the "main" thread. It is apparently not
|
||||
// possible to do this on a separate thread at all. It is not known how
|
||||
// Apple managed this colossal fuckup.
|
||||
// Cocoa absolutely requires creating the NSApplication singleton and running it on the main thread.
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
return cocoa_main(argc, argv);
|
||||
|
|
Loading…
Reference in New Issue