From ffdec6bc2b4af5ddc6c52c7a6bff51949426b984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Brzezi=C5=84ski?= Date: Fri, 26 Jan 2024 19:12:18 +0100 Subject: [PATCH] macos: Fix gst_macos_main() terminating whole process before returning a value Removes the usage of [NSApp terminate] to avoid killing the process and thus never actually returning a value. The new way is just to use [NSApp stop] and send an event, since stop only happens after an event is processed. Unlike terminate, stop will only halt the event loop, not the whole process. This uses an NSApplicationDelegate to listen for NSApp finishing the launch process, and then signals the 'main' thread to proceed. That makes sure to never call [NSApp stop] before NSApp is actually running, which could happen if the provided 'main' function finished quickly enough. Part-of: --- subprojects/gstreamer/gst/gstmacos.m | 61 ++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/subprojects/gstreamer/gst/gstmacos.m b/subprojects/gstreamer/gst/gstmacos.m index b930bbb0f6..dbdb1a70a3 100644 --- a/subprojects/gstreamer/gst/gstmacos.m +++ b/subprojects/gstreamer/gst/gstmacos.m @@ -9,11 +9,37 @@ struct _ThreadArgs { char **argv; gpointer user_data; gboolean is_simple; + GMutex nsapp_mutex; + GCond nsapp_cond; }; +@interface GstCocoaApplicationDelegate : NSObject +@property (assign) GMutex *nsapp_mutex; +@property (assign) GCond *nsapp_cond; +@end + +@implementation GstCocoaApplicationDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)notification +{ + g_mutex_lock (self.nsapp_mutex); + g_cond_signal (self.nsapp_cond); + g_mutex_unlock (self.nsapp_mutex); +} + +@end + int gst_thread_func (ThreadArgs *args) { + /* Only proceed once NSApp is running, otherwise we could + * attempt to call [NSApp: stop] before it's even started. */ + g_mutex_lock (&args->nsapp_mutex); + while (![[NSRunningApplication currentApplication] isFinishedLaunching]) { + g_cond_wait (&args->nsapp_cond, &args->nsapp_mutex); + } + g_mutex_unlock (&args->nsapp_mutex); + int ret; if (args->is_simple) { ret = ((GstMainFuncSimple) args->main_func) (args->user_data); @@ -21,7 +47,20 @@ gst_thread_func (ThreadArgs *args) ret = ((GstMainFunc) args->main_func) (args->argc, args->argv, args->user_data); } - [NSApp terminate: nil]; + /* Post a message so we'll break out of the message loop */ + NSEvent *event = [NSEvent otherEventWithType: NSEventTypeApplicationDefined + location: NSZeroPoint + modifierFlags: 0 + timestamp: 0 + windowNumber: 0 + context: nil + subtype: NSEventSubtypeApplicationActivated + data1: 0 + data2: 0]; + + [NSApp postEvent:event atStart:YES]; + [NSApp stop:nil]; + return ret; } @@ -29,15 +68,31 @@ int run_main_with_nsapp (ThreadArgs args) { GThread *gst_thread; + GstCocoaApplicationDelegate* delegate; + int result; - [NSApplication sharedApplication]; + g_mutex_init (&args.nsapp_mutex); + g_cond_init (&args.nsapp_cond); + + [NSApplication sharedApplication]; + delegate = [[GstCocoaApplicationDelegate alloc] init]; + delegate.nsapp_mutex = &args.nsapp_mutex; + delegate.nsapp_cond = &args.nsapp_cond; + [NSApp setDelegate:delegate]; + + /* This lets us show an icon in the dock and correctly focus opened windows */ if ([NSApp activationPolicy] == NSApplicationActivationPolicyProhibited) { [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory]; } + gst_thread = g_thread_new ("macos-gst-thread", (GThreadFunc) gst_thread_func, &args); [NSApp run]; + result = GPOINTER_TO_INT (g_thread_join (gst_thread)); - return GPOINTER_TO_INT (g_thread_join (gst_thread)); + g_mutex_clear (&args.nsapp_mutex); + g_cond_clear (&args.nsapp_cond); + + return result; } /**