From 08cce2cd5b2bc6e54375121b2d8cab9a37ddbfd8 Mon Sep 17 00:00:00 2001 From: Julien Isorce Date: Sat, 12 Apr 2014 12:42:40 +0100 Subject: [PATCH] gl/cocoa: ensure to call NSApplication:sharedApplication in the main thread "(NSApplication *)sharedApplication This method also makes a connection to the window server and completes other initialization" The implicit thing which is not mentioned is that it required to be called in the main thread. Fix a regression introduces by 82b7c915bb02a9790d256d599452e5a54afda633 When using with gst-launch, it was not possible to click on the close cross of the window anymore which is a bit anoying and also because it's was possible before. Prior to this commit the GstGLContextCocoaClass was initialized in the main thread because gst_gl_context_new was called in the state change function from going from ready to paused. From this commit this call is done from the streaming thread. So that the call to [NSApplication sharedApplication]; was not done in the main thread anymore. We now ensure that by assuming there is a GMainLoop running. It's for debugging purpose so that's ok to do that. Also note we already do this assumtion to run app itereations. The regression had no consequence on the cocoa/videooverlay example (that should be moved from gst-plugins-gl to -bad) because the application is responsible for that necessary call. --- gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m | 91 ++++++++++++++++++++-- gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m | 11 --- 2 files changed, 86 insertions(+), 16 deletions(-) diff --git a/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m index 63c508fd72..40e0dac686 100644 --- a/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m +++ b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m @@ -41,6 +41,40 @@ static GstGLPlatform gst_gl_context_cocoa_get_gl_platform (GstGLContext * contex G_DEFINE_TYPE (GstGLContextCocoa, gst_gl_context_cocoa, GST_GL_TYPE_CONTEXT); #ifndef GNUSTEP +static GMutex nsapp_lock; +static GCond nsapp_cond; + +static gboolean +gst_gl_window_cocoa_init_nsapp (gpointer data) +{ + NSAutoreleasePool *pool = nil; + + g_mutex_lock (&nsapp_lock); + + [[NSAutoreleasePool alloc] init]; + + /* The sharedApplication class method initializes + * the display environment and connects your program + * to the window server and the display server + */ + + /* TODO: so consider to create GstGLDisplayCocoa + * in gst/gl/cocoa/gstgldisplay_cocoa.h/c + */ + + /* has to be called in the main thread */ + [NSApplication sharedApplication]; + + GST_DEBUG ("NSApp initialized from a GTimeoutSource"); + + [pool release]; + + g_cond_signal (&nsapp_cond); + g_mutex_unlock (&nsapp_lock); + + return FALSE; +} + static gboolean gst_gl_window_cocoa_nsapp_iteration (gpointer data) { @@ -67,14 +101,12 @@ gst_gl_window_cocoa_nsapp_iteration (gpointer data) static void gst_gl_context_cocoa_class_init (GstGLContextCocoaClass * klass) { - GstGLContextClass *context_class; + GstGLContextClass *context_class = (GstGLContextClass *) klass; #ifndef GNUSTEP NSAutoreleasePool* pool = nil; #endif - context_class = (GstGLContextClass *) klass; - g_type_class_add_private (klass, sizeof (GstGLContextCocoaPrivate)); context_class->destroy_context = @@ -90,8 +122,57 @@ gst_gl_context_cocoa_class_init (GstGLContextCocoaClass * klass) GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_get_gl_platform); #ifndef GNUSTEP - pool = [[NSAutoreleasePool alloc] init]; - [NSApplication sharedApplication]; + [[NSAutoreleasePool alloc] init]; + + /* [NSApplication sharedApplication] will usually be + * called in your application so it's not necessary + * to do that the following. Except for debugging + * purpose like when using gst-launch. + * So here we handle the two cases where the first + * GstGLContext is either created in the main thread + * or from another thread like a streaming thread + */ + + if ([NSThread isMainThread]) { + /* In the main thread so just do the call now */ + + /* The sharedApplication class method initializes + * the display environment and connects your program + * to the window server and the display server + */ + + /* TODO: so consider to create GstGLDisplayCocoa + * in gst/gl/cocoa/gstgldisplay_cocoa.h/c + */ + + /* has to be called in the main thread */ + [NSApplication sharedApplication]; + + GST_DEBUG ("NSApp initialized"); + } else { + /* Not in the main thread, assume there is a + * glib main loop running this is for debugging + * purposes so that's ok to let us a chance + */ + gboolean is_loop_running = FALSE; + gint64 end_time = 0; + + g_mutex_init (&nsapp_lock); + g_cond_init (&nsapp_cond); + + g_mutex_lock (&nsapp_lock); + g_timeout_add_seconds (0, gst_gl_window_cocoa_init_nsapp, NULL); + end_time = g_get_monotonic_time () + 2 * 1000 * 1000; + is_loop_running = g_cond_wait_until (&nsapp_cond, &nsapp_lock, end_time); + g_mutex_unlock (&nsapp_lock); + + if (!is_loop_running) { + GST_WARNING ("no mainloop running"); + } + + g_cond_clear (&nsapp_cond); + g_mutex_clear (&nsapp_lock); + } [pool release]; #endif diff --git a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m index 271c30d895..02f74b2d31 100644 --- a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m +++ b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m @@ -91,10 +91,6 @@ static void gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass) { GstGLWindowClass *window_class; - -#ifndef GNUSTEP - NSAutoreleasePool* pool = nil; -#endif window_class = (GstGLWindowClass *) klass; @@ -110,13 +106,6 @@ gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass) window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_quit); window_class->send_message_async = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_send_message_async); - -#ifndef GNUSTEP - pool = [[NSAutoreleasePool alloc] init]; - [NSApplication sharedApplication]; - - [pool release]; -#endif } static void