summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPiotr Brzeziński <piotr@centricular.com>2024-01-26 19:12:18 +0100
committerPiotr Brzeziński <piotr@centricular.com>2024-02-12 18:25:34 +0100
commit6e59282af21e95b6426bb4a0818e9895b0d0fe43 (patch)
tree6fb53c8f7df29a3a480d938b4c21bb923d64e4de
parent2f4e8d14cf52e21091aaa2207da14977c9e15458 (diff)
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: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6103>
-rw-r--r--subprojects/gstreamer/gst/gstmacos.m61
1 files 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 <NSApplicationDelegate>
+@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;
+
+ g_mutex_init (&args.nsapp_mutex);
+ g_cond_init (&args.nsapp_cond);
- [NSApplication sharedApplication];
+ [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));
+
+ g_mutex_clear (&args.nsapp_mutex);
+ g_cond_clear (&args.nsapp_cond);
- return GPOINTER_TO_INT (g_thread_join (gst_thread));
+ return result;
}
/**