[vlc-commits] [Git][videolan/vlc][master] 3 commits: darwinvlc: remove VLA for argv

François Cartegnie (@fcartegnie) gitlab at videolan.org
Fri Sep 27 04:55:02 UTC 2024



François Cartegnie pushed to branch master at VideoLAN / VLC


Commits:
ca7cb8d4 by Alexandre Janniaux at 2024-09-27T04:37:13+00:00
darwinvlc: remove VLA for argv

VLA are not compatible with blocks, and error handling is pretty simple
here, so there's no reason not to use dynamic allocation instead.

- - - - -
3a6bd45b by Alexandre Janniaux at 2024-09-27T04:37:13+00:00
darwinvlc: start interfaces in separate thread

Interfaces from libvlc were started from the main thread directly. But
UI inserting their own event loop inside the main runloop like Qt were
taking over the interface insertion. It was preventing other interfaces
to load correctly, required dedicated code to handle the startup in the
Qt interface and it was not possible to exit the interface correctly.

By moving the creation of the interfaces in a dedicated thread, we can
ensure all UI are created and destroyed correctly, but the macosx
interface must now dispatch its own creation into the main thread to
match Cocoa requirement on main thread usage for UI components.

Note that libvlc_new itself must be moved to the intf_queue given that
it starts additional extraintf.

The macosx interface must now start its own NSApp inside the main loop,
via a dispatch call, which simplify the main loop into running the
default main loop.

- - - - -
9cae3668 by Alexandre Janniaux at 2024-09-27T04:37:13+00:00
qt: setup startup for Darwin

Now that the interfaces are not run from the main thread directly, it's
possible to dispatch the QApplication startup and UI creation to the
main thread directly on Darwin. It matches the behaviour of the
interface on other platform that Darwin, where a thread is created to
handle the interface, except that the thread is already existing as the
main thread for Darwin.

It means that there won't need any specific code (except for Thread()
startup) to handle the specificities of the Qt interface startup on
Darwin anymore.

Ticket #27103 showed issues when leaving the interface with the
medialibrary, because the path releasing the medialibrary was not taken
correctly, but other issues could arise, including deadlocks.

Fixes #27103

- - - - -


3 changed files:

- bin/darwinvlc.m
- modules/gui/macosx/main/VLCMain.m
- modules/gui/qt/qt.cpp


Changes:

=====================================
bin/darwinvlc.m
=====================================
@@ -228,7 +228,10 @@ int main(int i_argc, const char *ppsz_argv[])
 
 
     /* Handle parameters */
-    const char *argv[i_argc + 2];
+    const char **argv = calloc(i_argc + 2, sizeof (argv[0]));
+    if (argv == NULL)
+        exit(1);
+
     int argc = 0;
 
     argv[argc++] = "--no-ignore-config";
@@ -264,22 +267,38 @@ int main(int i_argc, const char *ppsz_argv[])
     argc += i_argc;
     argv[argc] = NULL;
 
-    /* Initialize libvlc */
-    libvlc_instance_t *vlc = libvlc_new(argc, argv);
-    if (vlc == NULL)
-        return 1;
-
+    dispatch_queue_t intf_queue = dispatch_queue_create("org.videolan.vlc", NULL);
+    __block bool intf_started = true;
+    __block libvlc_instance_t *vlc = NULL;
     int ret = 1;
-    libvlc_SetExitHandler(vlc->p_libvlc_int, vlc_terminate, NULL);
-    libvlc_set_app_id(vlc, "org.VideoLAN.VLC", PACKAGE_VERSION, PACKAGE_NAME);
-    libvlc_set_user_agent(vlc, "VLC media player", "VLC/"PACKAGE_VERSION);
+    dispatch_async(intf_queue, ^{
+        /* Initialize libvlc */
+        vlc = libvlc_new(argc, argv);
+        if (vlc == NULL)
+        {
+            dispatch_sync(dispatch_get_main_queue(), ^{
+                intf_started = false;
+                CFRunLoopStop(CFRunLoopGetMain());
+            });
+            return;
+        }
 
-    if (libvlc_InternalAddIntf(vlc->p_libvlc_int, NULL)) {
-        fprintf(stderr, "VLC cannot start any interface. Exiting.\n");
-        goto out;
-    }
+        libvlc_SetExitHandler(vlc->p_libvlc_int, vlc_terminate, NULL);
+        libvlc_set_app_id(vlc, "org.VideoLAN.VLC", PACKAGE_VERSION, PACKAGE_NAME);
+        libvlc_set_user_agent(vlc, "VLC media player", "VLC/"PACKAGE_VERSION);
+
+
+        if (libvlc_InternalAddIntf(vlc->p_libvlc_int, NULL)) {
+            fprintf(stderr, "VLC cannot start any interface. Exiting.\n");
+            dispatch_sync(dispatch_get_main_queue(), ^{
+                intf_started = false;
+                CFRunLoopStop(CFRunLoopGetMain());
+            });
+            return;
+        }
 
-    libvlc_InternalPlay(vlc->p_libvlc_int);
+        libvlc_InternalPlay(vlc->p_libvlc_int);
+    });
 
     /*
      * Run the main loop. If the mac interface is not initialized, only the CoreFoundation
@@ -287,17 +306,18 @@ int main(int i_argc, const char *ppsz_argv[])
      * before actually starting the loop.
      */
     @autoreleasepool {
-        if(NSApp == nil) {
-            CFRunLoopRun();
-
-        } else {
-            [NSApp run];
-        }
+        CFRunLoopRun();
     }
 
+    if (!intf_started)
+        goto out;
+
     ret = 0;
     /* Cleanup */
 out:
+    dispatch_release(intf_queue);
+    free(argv);
+
     dispatch_release(sigIntSource);
     dispatch_release(sigTermSource);
     dispatch_release(sigChldSource);


=====================================
modules/gui/macosx/main/VLCMain.m
=====================================
@@ -141,36 +141,49 @@ intf_thread_t *getIntf()
 
 int OpenIntf (vlc_object_t *p_this)
 {
-    @autoreleasepool {
-        intf_thread_t *p_intf = (intf_thread_t*) p_this;
-        p_interface_thread = p_intf;
-        msg_Dbg(p_intf, "Starting macosx interface");
-
-        @try {
-            VLCApplication * const application = VLCApplication.sharedApplication;
-            NSCAssert(application != nil, @"VLCApplication must not be nil");
-
-            VLCMain * const main = VLCMain.sharedInstance;
-            NSCAssert(main != nil, @"VLCMain must not be nil");
-
-            msg_Dbg(p_intf, "Finished loading macosx interface");
-            return VLC_SUCCESS;
-        } @catch (NSException *exception) {
-            msg_Err(p_intf, "Loading the macosx interface failed. Do you have a valid window server?");
-            return VLC_EGENERIC;
+    __block int retcode = VLC_SUCCESS;
+    dispatch_sync(dispatch_get_main_queue(), ^{
+        @autoreleasepool {
+            intf_thread_t *p_intf = (intf_thread_t*) p_this;
+            p_interface_thread = p_intf;
+            msg_Dbg(p_intf, "Starting macosx interface");
+
+            @try {
+                VLCApplication * const application = VLCApplication.sharedApplication;
+                NSCAssert(application != nil, @"VLCApplication must not be nil");
+
+                VLCMain * const main = VLCMain.sharedInstance;
+                NSCAssert(main != nil, @"VLCMain must not be nil");
+
+                msg_Dbg(p_intf, "Finished loading macosx interface");
+            } @catch (NSException *exception) {
+                msg_Err(p_intf, "Loading the macosx interface failed. Do you have a valid window server?");
+                retcode = VLC_EGENERIC;
+                return;
+            }
+            dispatch_async(dispatch_get_main_queue(), ^{
+                [NSApp run];
+            });
         }
-    }
+    });
+
+    return retcode;
 }
 
 void CloseIntf (vlc_object_t *p_this)
 {
-    @autoreleasepool {
-        msg_Dbg(p_this, "Closing macosx interface");
-        [VLCMain.sharedInstance applicationWillTerminate:nil];
-        [VLCMain killInstance];
-    }
-
-    p_interface_thread = nil;
+    void (^release_intf)() = ^{
+        @autoreleasepool {
+            msg_Dbg(p_this, "Closing macosx interface");
+            [VLCMain.sharedInstance applicationWillTerminate:nil];
+            [VLCMain killInstance];
+        }
+        p_interface_thread = nil;
+    };
+    if (CFRunLoopGetCurrent() == CFRunLoopGetMain())
+        release_intf();
+    else
+        dispatch_sync(dispatch_get_main_queue(), release_intf);
 }
 
 /*****************************************************************************


=====================================
modules/gui/qt/qt.cpp
=====================================
@@ -536,10 +536,13 @@ static void *Thread( void * );
 static void *ThreadCleanup( qt_intf_t *p_intf, CleanupReason cleanupReason );
 
 #ifdef Q_OS_MAC
+static void ThreadDarwin(void *);
 /* Used to abort the app.exec() on OSX after libvlc_Quit is called */
 #include "../../../lib/libvlc_internal.h" /* libvlc_SetExitHandler */
+#include <dispatch/dispatch.h>
 static void Abort( void *obj )
 {
+    (void)obj;
     triggerQuit();
 }
 #endif
@@ -579,7 +582,6 @@ static int OpenInternal( qt_intf_t *p_intf )
     /* Get the playlist before the lock to avoid a lock-order-inversion */
     vlc_playlist_t *playlist = vlc_intf_GetMainPlaylist(p_intf->intf);
 
-#ifndef Q_OS_MAC
     vlc::threads::mutex_locker locker (lock);
     if (busy || open_state == OPEN_STATE_ERROR)
     {
@@ -587,7 +589,6 @@ static int OpenInternal( qt_intf_t *p_intf )
             msg_Err (p_intf, "cannot start Qt multiple times");
         return VLC_EGENERIC;
     }
-#endif
 
     p_intf->p_mi = NULL;
 
@@ -599,7 +600,7 @@ static int OpenInternal( qt_intf_t *p_intf )
 #ifdef Q_OS_MAC
     /* Run mainloop on the main thread as Cocoa requires */
     libvlc_SetExitHandler( vlc_object_instance(p_intf), Abort, p_intf );
-    Thread( (void *)p_intf );
+    dispatch_async_f(dispatch_get_main_queue(), static_cast<void*>(p_intf), ThreadDarwin);
 #else
     if( vlc_clone( &p_intf->thread, Thread, p_intf ) )
     {
@@ -610,10 +611,8 @@ static int OpenInternal( qt_intf_t *p_intf )
     /* Wait for the interface to be ready. This prevents the main
      * LibVLC thread from starting video playback before we can create
      * an embedded video window. */
-#ifndef Q_OS_MAC
     while (open_state == OPEN_STATE_INIT)
         wait_ready.wait(lock);
-#endif
 
     if (open_state == OPEN_STATE_ERROR)
     {
@@ -1053,15 +1052,6 @@ static void *Thread( void *obj )
         open_state = OPEN_STATE_OPENED;
         wait_ready.signal();
     }
-#ifdef Q_OS_MAC
-    /* We took over main thread, register and start here */
-    if( !p_intf->b_isDialogProvider )
-    {
-        vlc_playlist_Lock( p_intf->p_playlist );
-        vlc_playlist_Start( p_intf->p_playlist );
-        vlc_playlist_Unlock( p_intf->p_playlist );
-    }
-#endif
 
     /* Last settings */
     app.setQuitOnLastWindowClosed( false );
@@ -1078,18 +1068,21 @@ static void *Thread( void *obj )
     return ThreadCleanup( p_intf, CLEANUP_APP_TERMINATED );
 }
 
+#ifdef Q_OS_MAC
+static void ThreadDarwin(void *opaque)
+{
+    Thread(opaque);
+}
+#endif
+
 static void *ThreadCleanup( qt_intf_t *p_intf, CleanupReason cleanupReason )
 {
     {
-#ifndef Q_OS_MAC
         vlc::threads::mutex_locker locker (lock);
-#endif
         if( cleanupReason == CLEANUP_ERROR )
         {
             open_state = OPEN_STATE_ERROR;
-#ifndef Q_OS_MAC
             wait_ready.signal();
-#endif
         }
         else
             open_state = OPEN_STATE_INIT;



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/78ae78c044e87086bc976b9c226eb6fa93e4af54...9cae3668c7fc1fc00939f0683c0c2293556a8d39

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/78ae78c044e87086bc976b9c226eb6fa93e4af54...9cae3668c7fc1fc00939f0683c0c2293556a8d39
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list