[vlc-commits] [Git][videolan/vlc][master] 6 commits: test: iosvlc: start iOS interfaces on a dedicated thread
Steve Lhomme (@robUx4)
gitlab at videolan.org
Sun Aug 9 08:42:43 UTC 2026
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
3c73e356 by Alexandre Janniaux at 2026-08-09T08:30:20+00:00
test: iosvlc: start iOS interfaces on a dedicated thread
The UIKit-dependant interfaces need the main thread, but since we're
starting before the UIApplicationMain(), they might run their own and
block the rest of the code and the startup of other interfaces.
See 3a6bd45b9e8d1f4c5e24b6031a8df44523e6c4b1 for the rationale that was
already applied to the darwinvlc.m port.
- - - - -
b173b902 by Alexandre Janniaux at 2026-08-09T08:30:20+00:00
test: iosvlc: create test UI on interface open
If we open another interface, we don't want to include the test view.
- - - - -
534c4883 by Alexandre Janniaux at 2026-08-09T08:30:20+00:00
test: iosvlc: pass --intf for iosvlc startup
Default to launching the test UI, but allow the launcher to override the
interface being launched via arguments.
- - - - -
00ce4abc by Alexandre Janniaux at 2026-08-09T08:30:20+00:00
test: iosvlc: use root view as drawable container
- - - - -
f595d373 by Alexandre Janniaux at 2026-08-09T08:30:20+00:00
test: iosvlc: defer libvlc initialization
Qt's iOS platform plugin (qios) requires the main CFRunLoop to be
active during plugin loading and would otherwise create it itself, as
this is how applications are supposed to integrate in Qt programs.
By deferring libVLC startup using CFRunLoopPerformBlock, we ensure the
run loop is fully running before any interface starts.
This fixes Qt interface startup on iOS where qios would fail to
properly integrate with UIKit because the run loop wasn't yet
processing events during application:didFinishLaunchingWithOptions:.
- - - - -
b45afaa0 by Alexandre Janniaux at 2026-08-09T08:30:20+00:00
test: iosvlc: release libVLC when interface requests termination
The launcher never registered an exit handler nor released the libVLC
instance, so a termination request from an interface (here reproduced
when exiting from the Qt interface path) had no effect and the instance
was leaked.
Register a libvlc_SetExitHandler() callback that releases the instance
on the interface queue, unloading the interfaces, just like it is done
on the other darwinvlc.m and vlc.c. The way the interfaces are written
makes it mandatory to be able to run the Qt interface on iOS.
Since iOS applications are not meant to exit on their own, this only
provides a shutdown path rather than stopping a main loop as darwinvlc.m
does. The user still needs to stop the application afterwards.
- - - - -
1 changed file:
- test/iosvlc.m
Changes:
=====================================
test/iosvlc.m
=====================================
@@ -37,12 +37,14 @@
#include <vlc_plugin.h>
#include <TargetConditionals.h>
+#include <dispatch/dispatch.h>
#include "../lib/libvlc_internal.h"
@interface AppDelegate : UIResponder <UIApplicationDelegate> {
@public
libvlc_instance_t *_libvlc;
+ dispatch_queue_t _intfQueue;
UIWindow *window;
UIView *subview;
@@ -56,6 +58,24 @@
}
@end
+static void vlc_terminate(void *data)
+{
+ AppDelegate *d = (__bridge AppDelegate *)data;
+
+ __block bool quitting = false;
+ static dispatch_once_t quitToken = 0;
+ dispatch_once(&quitToken, ^{
+ quitting = true;
+ });
+
+ if (!quitting)
+ return;
+
+ dispatch_async(d->_intfQueue, ^{
+ libvlc_release(d->_libvlc);
+ d->_libvlc = NULL;
+ });
+}
@implementation AppDelegate
#if !TARGET_OS_TV
@@ -95,50 +115,48 @@
/* Called after application launch */
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
- /* Store startup arguments to forward them to libvlc */
- NSArray *arguments = [[NSProcessInfo processInfo] arguments];
- unsigned vlc_argc = [arguments count] - 1;
- const char **vlc_argv = malloc(vlc_argc * sizeof *vlc_argv);
- if (vlc_argv == NULL)
- return NO;
-
- for (unsigned i = 0; i < vlc_argc; i++)
- vlc_argv[i] = [[arguments objectAtIndex:i + 1] UTF8String];
-
- /* Initialize libVLC */
- _libvlc = libvlc_new(vlc_argc, (const char * const*)vlc_argv);
- free(vlc_argv);
+ _intfQueue = dispatch_queue_create("org.videolan.vlc.ios.intf",
+ DISPATCH_QUEUE_SERIAL);
+
+ /* Defer libVLC initialization until the main run loop is active.
+ * This prevents interfaces created via libvlc_InternalAddIntf from
+ * creating and owning the eventloop themselves at plugin loading
+ * time (which Qt qios platform does). We don't need those plugins
+ * before the interface is ready to load with an eventloop anyway. */
+ CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopDefaultMode, ^{
+ /* Store startup arguments to forward them to libvlc */
+ NSArray *arguments = [[NSProcessInfo processInfo] arguments];
+ unsigned vlc_argc = [arguments count] - 1;
+ const char *intf_arg = "--intf=" MODULE_STRING;
+ unsigned vlc_argc_with_args = vlc_argc + 1;
+ const char **vlc_argv = malloc(vlc_argc_with_args * sizeof *vlc_argv);
+ if (vlc_argv == NULL)
+ return;
- if (_libvlc == NULL)
- return NO;
+ vlc_argv[0] = intf_arg;
+ for (unsigned i = 0; i < vlc_argc; i++)
+ vlc_argv[i + 1] = [[arguments objectAtIndex:i + 1] UTF8String];
- /* Initialize main window */
-#if TARGET_OS_VISION
- /* UIScreen is unavailable so we need create a size on our own */
- window = [[UIWindow alloc] initWithFrame:CGRectMake(0., 0., 1200., 800.)];
-#else
- window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
-#endif
- window.rootViewController = [[UIViewController alloc] init];
- window.backgroundColor = [UIColor whiteColor];
+ /* Initialize libVLC */
+ self->_libvlc = libvlc_new(vlc_argc_with_args, (const char * const*)vlc_argv);
+ free(vlc_argv);
- subview = [[UIView alloc] initWithFrame:window.bounds];
- subview.backgroundColor = [UIColor blueColor];
- [window addSubview:subview];
- [window makeKeyAndVisible];
-
-#if !TARGET_OS_TV
- _pinchRecognizer = [[UIPinchGestureRecognizer alloc]
- initWithTarget:self action:@selector(pinchRecognized:)];
- [window addGestureRecognizer:_pinchRecognizer];
-#endif
-
- /* Start glue interface, see code below */
+ if (self->_libvlc == NULL) {
+ NSLog(@"Failed to initialize libVLC");
+ return;
+ }
- libvlc_InternalAddIntf(_libvlc->p_libvlc_int, "ios_interface,none");
+ libvlc_SetExitHandler(self->_libvlc->p_libvlc_int, vlc_terminate,
+ (__bridge void *)self);
- /* Start parsing arguments and eventual playback */
- libvlc_InternalPlay(_libvlc->p_libvlc_int);
+ dispatch_async(self->_intfQueue, ^{
+ @autoreleasepool {
+ libvlc_InternalAddIntf(self->_libvlc->p_libvlc_int, NULL);
+ libvlc_InternalPlay(self->_libvlc->p_libvlc_int);
+ }
+ });
+ });
+ CFRunLoopWakeUp(CFRunLoopGetMain());
return YES;
}
@@ -154,7 +172,36 @@ int main(int argc, char * argv[]) {
static int Open(vlc_object_t *obj)
{
AppDelegate *d = (AppDelegate *)[[UIApplication sharedApplication] delegate];
- assert(d != nil && d->subview != nil);
+ if( d == nil )
+ return VLC_EGENERIC;
+
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ if (d->window != nil && d->subview != nil)
+ return;
+
+ /* Initialize main window */
+#if TARGET_OS_VISION
+ /* UIScreen is unavailable so we need create a size on our own */
+ d->window = [[UIWindow alloc] initWithFrame:CGRectMake(0., 0., 1200., 800.)];
+#else
+ d->window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
+#endif
+ d->window.rootViewController = [[UIViewController alloc] init];
+ d->window.backgroundColor = [UIColor whiteColor];
+
+ d->subview = d->window.rootViewController.view;
+ d->subview.frame = d->window.bounds;
+ d->subview.backgroundColor = [UIColor clearColor];
+ [d->window makeKeyAndVisible];
+
+#if !TARGET_OS_TV
+ d->_pinchRecognizer = [[UIPinchGestureRecognizer alloc]
+ initWithTarget:d action:@selector(pinchRecognized:)];
+ [d->window addGestureRecognizer:d->_pinchRecognizer];
+#endif
+ } );
+
+ assert(d->subview != nil);
var_SetAddress(vlc_object_instance(obj), "drawable-nsobject",
(__bridge void *)d->subview);
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/cfcfc0d0d3fb07dff72acf09cd6dbe33b47dc323...b45afaa05496100deb809b009b9b4acb69aba82f
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/cfcfc0d0d3fb07dff72acf09cd6dbe33b47dc323...b45afaa05496100deb809b009b9b4acb69aba82f
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help
More information about the vlc-commits
mailing list