summaryrefslogtreecommitdiffstats
path: root/osdep/mac
diff options
context:
space:
mode:
authorder richter <der.richter@gmx.de>2024-03-30 19:26:45 +0100
committerder richter <der.richter@gmx.de>2024-04-01 22:13:39 +0200
commit7619cceb875da939f26b02ae3e1b2f5b3d0f103c (patch)
treededa004068cdaf49add3dc8059bfaf49e80eb385 /osdep/mac
parentb7c5b26d35f9ba4e8776c63be69fd4aefd1afb3c (diff)
downloadmpv-7619cceb875da939f26b02ae3e1b2f5b3d0f103c.tar.bz2
mpv-7619cceb875da939f26b02ae3e1b2f5b3d0f103c.tar.xz
mac/app: rewrite App c main function, startup and termination in swift
also move main invocation into AppHub and completely delete the old Application c implementation.
Diffstat (limited to 'osdep/mac')
-rw-r--r--osdep/mac/app_bridge.h8
-rw-r--r--osdep/mac/app_bridge.m6
-rw-r--r--osdep/mac/app_bridge_objc.h3
-rw-r--r--osdep/mac/app_hub.swift4
-rw-r--r--osdep/mac/application.h21
-rw-r--r--osdep/mac/application.m155
-rw-r--r--osdep/mac/application.swift79
-rw-r--r--osdep/mac/application_objc.h19
8 files changed, 95 insertions, 200 deletions
diff --git a/osdep/mac/app_bridge.h b/osdep/mac/app_bridge.h
index 27cc2413ea..fe1180a7ec 100644
--- a/osdep/mac/app_bridge.h
+++ b/osdep/mac/app_bridge.h
@@ -17,6 +17,12 @@
#pragma once
+#include <stdbool.h>
+#include "options/m_option.h"
+
+struct input_ctx;
+struct mpv_handle;
+
enum {
FRAME_VISIBLE = 0,
FRAME_WHOLE,
@@ -46,5 +52,7 @@ void cocoa_uninit_media_keys(void);
void cocoa_set_input_context(struct input_ctx *input_context);
void cocoa_set_mpv_handle(struct mpv_handle *ctx);
void cocoa_init_cocoa_cb(void);
+// multithreaded wrapper for mpv_main
+int cocoa_main(int argc, char *argv[]);
extern const struct m_sub_options macos_conf;
diff --git a/osdep/mac/app_bridge.m b/osdep/mac/app_bridge.m
index ab8470d9cc..8e9c4a444b 100644
--- a/osdep/mac/app_bridge.m
+++ b/osdep/mac/app_bridge.m
@@ -114,3 +114,9 @@ void cocoa_init_cocoa_cb(void)
{
[[AppHub shared] initCocoaCb];
}
+
+int cocoa_main(int argc, char *argv[])
+{
+ return [(Application *)[Application sharedApplication] main:argc :argv];
+}
+
diff --git a/osdep/mac/app_bridge_objc.h b/osdep/mac/app_bridge_objc.h
index c34b09736c..60201982cf 100644
--- a/osdep/mac/app_bridge_objc.h
+++ b/osdep/mac/app_bridge_objc.h
@@ -15,6 +15,7 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
+#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
#include "player/client.h"
@@ -28,8 +29,8 @@
#include "input/keycodes.h"
#include "video/out/win_state.h"
+#include "osdep/main-fn.h"
#include "osdep/mac/app_bridge.h"
-#include "osdep/mac/application_objc.h"
// complex macros won't get imported to swift so we have to reassign them
static int SWIFT_MBTN_LEFT = MP_MBTN_LEFT;
diff --git a/osdep/mac/app_hub.swift b/osdep/mac/app_hub.swift
index 6d4b00fa4c..0172d3904f 100644
--- a/osdep/mac/app_hub.swift
+++ b/osdep/mac/app_hub.swift
@@ -21,7 +21,7 @@ class AppHub: NSObject {
@objc static let shared = AppHub()
var mpv: OpaquePointer?
- @objc var input: InputHelper
+ var input: InputHelper
var option: OptionHelper?
var event: EventHelper?
var menu: MenuBar?
@@ -29,7 +29,7 @@ class AppHub: NSObject {
var remote: RemoteCommandCenter?
#endif
#if HAVE_MACOS_TOUCHBAR
- @objc var touchBar: TouchBar?
+ var touchBar: TouchBar?
#endif
#if HAVE_MACOS_COCOA_CB
var cocoaCb: CocoaCB?
diff --git a/osdep/mac/application.h b/osdep/mac/application.h
deleted file mode 100644
index 3a87cd42a7..0000000000
--- a/osdep/mac/application.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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/>.
- */
-
-#pragma once
-
-// multithreaded wrapper for mpv_main
-int cocoa_main(int argc, char *argv[]);
diff --git a/osdep/mac/application.m b/osdep/mac/application.m
deleted file mode 100644
index fb2889e92a..0000000000
--- a/osdep/mac/application.m
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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/>.
- */
-
-#include <stdio.h>
-#include "config.h"
-#include "mpv_talloc.h"
-
-#include "common/msg.h"
-#include "input/input.h"
-#include "player/client.h"
-#include "options/m_config.h"
-#include "options/options.h"
-
-#import "osdep/mac/application_objc.h"
-#include "osdep/threads.h"
-#include "osdep/main-fn.h"
-
-#if HAVE_SWIFT
-#include "osdep/mac/swift.h"
-#endif
-
-static mp_thread playback_thread_id;
-
-static Application *mpv_shared_app(void)
-{
- return (Application *)[Application sharedApplication];
-}
-
-static void terminate_cocoa_application(void)
-{
- dispatch_async(dispatch_get_main_queue(), ^{
- [NSApp hide:NSApp];
- [NSApp terminate:NSApp];
- });
-}
-
-struct playback_thread_ctx {
- int *argc;
- char ***argv;
-};
-
-static void cocoa_run_runloop(void)
-{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [NSApp run];
- [pool drain];
-}
-
-static MP_THREAD_VOID playback_thread(void *ctx_obj)
-{
- mp_thread_set_name("core/playback");
- @autoreleasepool {
- struct playback_thread_ctx *ctx = (struct playback_thread_ctx*) ctx_obj;
- int r = mpv_main(*ctx->argc, *ctx->argv);
- terminate_cocoa_application();
- // normally never reached - unless the cocoa mainloop hasn't started yet
- exit(r);
- }
-}
-
-static void init_cocoa_application(bool regular)
-{
- NSApp = mpv_shared_app();
- [NSApp setDelegate:NSApp];
-
- // 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 ?
- NSApplicationActivationPolicyRegular :
- NSApplicationActivationPolicyAccessory];
-
- 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.
- dispatch_async(dispatch_get_main_queue(), ^{
- [NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited];
- });
- });
-}
-
-static bool bundle_started_from_finder()
-{
- NSString* bundle = [[[NSProcessInfo processInfo] environment] objectForKey:@"MPVBUNDLE"];
- return [bundle isEqual:@"true"];
-}
-
-static bool is_psn_argument(char *arg_to_check)
-{
- NSString *arg = [NSString stringWithUTF8String:arg_to_check];
- return [arg hasPrefix:@"-psn_"];
-}
-
-static void setup_bundle(int *argc, char *argv[])
-{
- if (*argc > 1 && is_psn_argument(argv[1])) {
- *argc = 1;
- argv[1] = NULL;
- }
-
- NSDictionary *env = [[NSProcessInfo processInfo] environment];
- NSString *path_bundle = [env objectForKey:@"PATH"];
- NSString *path_new = [NSString stringWithFormat:@"%@:%@:%@:%@:%@",
- path_bundle,
- @"/usr/local/bin",
- @"/usr/local/sbin",
- @"/opt/local/bin",
- @"/opt/local/sbin"];
- setenv("PATH", [path_new UTF8String], 1);
-}
-
-int cocoa_main(int argc, char *argv[])
-{
- @autoreleasepool {
- struct playback_thread_ctx ctx = {0};
- ctx.argc = &argc;
- ctx.argv = &argv;
-
- if (bundle_started_from_finder()) {
- setup_bundle(&argc, argv);
- init_cocoa_application(true);
- } else {
- for (int i = 1; i < argc; i++)
- if (argv[i][0] != '-')
- mpv_shared_app().openCount++;
- init_cocoa_application(false);
- }
-
- mp_thread_create(&playback_thread_id, playback_thread, &ctx);
- [[AppHub shared].input wait];
- cocoa_run_runloop();
-
- // This should never be reached: cocoa_run_runloop blocks until the
- // process is quit
- fprintf(stderr, "There was either a problem "
- "initializing Cocoa or the Runloop was stopped unexpectedly. "
- "Please report this issues to a developer.\n");
- mp_thread_join(playback_thread_id);
- return 1;
- }
-}
diff --git a/osdep/mac/application.swift b/osdep/mac/application.swift
index 6b317be67c..6a1af89cec 100644
--- a/osdep/mac/application.swift
+++ b/osdep/mac/application.swift
@@ -18,12 +18,15 @@
import Cocoa
class Application: NSApplication, NSApplicationDelegate {
- let appHub: AppHub
+ var appHub: AppHub { get { return AppHub.shared } }
let MPV_PROTOCOL: String = "mpv://"
@objc var openCount: Int = 0
+ var playbackThreadId: mp_thread!
+ var argc: Int32?
+ var argv: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>?
+
override init() {
- appHub = AppHub.shared
super.init()
let eventManager = NSAppleEventManager.shared()
@@ -45,6 +48,22 @@ class Application: NSApplication, NSApplicationDelegate {
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)
@@ -75,6 +94,7 @@ class Application: NSApplication, NSApplicationDelegate {
)
}
+ // quit from App icon
@objc func handleQuit(event: NSAppleEventDescriptor?, replyEvent: NSAppleEventDescriptor?) {
if !appHub.input.command("quit") {
terminateApplication()
@@ -103,4 +123,59 @@ class Application: NSApplication, NSApplicationDelegate {
}
appHub.input.open(files: files)
}
+
+ func bundleStartedFromFinder() -> Bool {
+ return ProcessInfo.processInfo.environment["MPVBUNDLE"] == "true"
+ }
+
+ func setupBundle() {
+ // 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
+ }
+
+ let path = (ProcessInfo.processInfo.environment["PATH"] ?? "") +
+ ":/usr/local/bin:/usr/local/sbin:/opt/local/bin:/opt/local/sbin"
+ _ = 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 r: Int32 = mpv_main(application.argc ?? 1, application.argv)
+ application.terminateApplication()
+ // normally never reached - unless the cocoa mainloop hasn't started yet
+ exit(r)
+ }
+
+ @objc func main(_ argc: Int32, _ argv: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>) -> Int {
+ self.argc = argc
+ self.argv = argv
+
+ if bundleStartedFromFinder() {
+ setupBundle()
+ initApplication(true)
+ } else {
+ for argument in CommandLine.arguments.dropFirst() {
+ if !argument.hasPrefix("-") {
+ openCount += 1
+ }
+ }
+ initApplication(false)
+ }
+
+ 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
+ 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
+ }
}
diff --git a/osdep/mac/application_objc.h b/osdep/mac/application_objc.h
deleted file mode 100644
index 255ede8bc2..0000000000
--- a/osdep/mac/application_objc.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * 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/Cocoa.h>
-#include "osdep/mac/application.h"