diff options
Diffstat (limited to '')
-rw-r--r-- | osdep/mac/application.swift | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/osdep/mac/application.swift b/osdep/mac/application.swift new file mode 100644 index 0000000..30f37a6 --- /dev/null +++ b/osdep/mac/application.swift @@ -0,0 +1,123 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. + */ + +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>?>? + + override init() { + super.init() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func sendEvent(_ event: NSEvent) { + if modalWindow != nil || !appHub.input.processKey(event: event) { + super.sendEvent(event) + } + appHub.input.wakeup() + } + +#if HAVE_MACOS_TOUCHBAR + override func makeTouchBar() -> NSTouchBar? { + return appHub.touchBar + } +#endif + + func application(_ application: NSApplication, open urls: [URL]) { + appHub.open(urls: urls) + } + + func applicationWillFinishLaunching(_ notification: Notification) { + // 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, 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") { + appHub.log.warning("Could not properly shut down mpv") + exit(1) + } + } + + func setupBundle() { + if !isBundle { return } + + // started from finder the first argument after the binary may start with -psn_ + if CommandLine.argc > 1 && CommandLine.arguments[1].hasPrefix("-psn_") { + argc? = 1 + argv?[1] = nil + } + + let path = (ProcessInfo.processInfo.environment["PATH"] ?? "") + + ":/usr/local/bin:/usr/local/sbin:/opt/local/bin:/opt/local/sbin" + appHub.log.verbose("Setting Bundle $PATH to: \(path)") + _ = path.withCString { setenv("PATH", $0, 1) } + } + + let playbackThread: @convention(c) (UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? = { (ptr: UnsafeMutableRawPointer) in + let application: Application = TypeHelper.bridge(ptr: ptr) + mp_thread_set_name("core/playback") + 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 + + 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() + + // 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 + """) + pthread_join(playbackThreadId, nil) + return 1 + } +} |