1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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
}
}
|