[vlc-devel] [PATCH] darwinvlc/macosx: rework binary, start main loop in darwinvlc

david.fuhrmann at gmail.com david.fuhrmann at gmail.com
Sat Jun 13 15:44:39 CEST 2015


From: David Fuhrmann <dfuhrmann at videolan.org>

This moves the main loop out of the macosx interface module.
Instead, the open calback only initializes the interface and the
close callback cleans up stuff. The mainloop is then started in
darwinvlc.m. In case the mac interface is not used, a CoreFoundation
mainloop is solely started to wait for termination events.

Additionally, this cleans up darwinvlc.c, and fixes signal
handling, which was dead code so far (in case the interface was used).
Now, GCD is used to catch SIGINT and SIGTERM in order to allow
ordinary shutdown.

refs #14362
close #6354
---
 bin/Makefile.am                                    |   6 +-
 bin/darwinvlc.c                                    | 259 ------------------
 bin/darwinvlc.m                                    | 294 +++++++++++++++++++++
 .../package/macosx/vlc.xcodeproj/project.pbxproj   |   6 +-
 modules/gui/macosx/intf.m                          |  74 ++----
 modules/gui/macosx/macosx.m                        |   2 +-
 6 files changed, 331 insertions(+), 310 deletions(-)
 delete mode 100644 bin/darwinvlc.c
 create mode 100644 bin/darwinvlc.m

diff --git a/bin/Makefile.am b/bin/Makefile.am
index 02e77ff..aae7fda 100644
--- a/bin/Makefile.am
+++ b/bin/Makefile.am
@@ -22,13 +22,13 @@ endif
 vlc_SOURCES = vlc.c override.c
 endif
 
-EXTRA_vlc_SOURCES = vlc.c winvlc.c darwinvlc.c
+EXTRA_vlc_SOURCES = vlc.c winvlc.c darwinvlc.m
 if HAVE_WIN32
 vlc_SOURCES = winvlc.c
 noinst_DATA += vlc_win32_rc.rc
 endif
 if HAVE_DARWIN
-vlc_SOURCES = darwinvlc.c override.c
+vlc_SOURCES = darwinvlc.m override.c
 endif
 
 vlc_wrapper_SOURCES = rootwrap.c
@@ -36,7 +36,7 @@ vlc_wrapper_LDADD = $(SOCKET_LIBS)
 
 vlc_LDFLAGS = $(LDFLAGS_vlc)
 if HAVE_DARWIN
-vlc_LDFLAGS += -Wl,-framework,CoreFoundation
+vlc_LDFLAGS += -Wl,-framework,CoreFoundation,-framework,Cocoa
 endif
 vlc_LDADD = ../lib/libvlc.la $(LIBPTHREAD)
 
diff --git a/bin/darwinvlc.c b/bin/darwinvlc.c
deleted file mode 100644
index 1841aca..0000000
--- a/bin/darwinvlc.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*****************************************************************************
- * darwinvlc.c: the darwin-specific VLC player
- *****************************************************************************
- * Copyright (C) 1998-2013 the VideoLAN team
- * $Id$
- *
- * Authors: Vincent Seguin <seguin at via.ecp.fr>
- *          Samuel Hocevar <sam at zoy.org>
- *          Gildas Bazin <gbazin at videolan.org>
- *          Derk-Jan Hartman <hartman at videolan dot org>
- *          Lots of other people, see the libvlc AUTHORS file
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <vlc/vlc.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <string.h>
-#include <locale.h>
-#include <signal.h>
-#ifdef HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
-#include <unistd.h>
-#include <TargetConditionals.h>
-#import <CoreFoundation/CoreFoundation.h>
-
-extern void vlc_enable_override (void);
-
-static bool signal_ignored (int signum)
-{
-    struct sigaction sa;
-
-    if (sigaction (signum, NULL, &sa))
-        return false;
-    return ((sa.sa_flags & SA_SIGINFO)
-            ? (void *)sa.sa_sigaction : (void *)sa.sa_handler) == SIG_IGN;
-}
-
-static void vlc_kill (void *data)
-{
-    pthread_t *ps = data;
-    pthread_kill (*ps, SIGTERM);
-}
-
-static void exit_timeout (int signum)
-{
-    (void) signum;
-    signal (SIGINT, SIG_DFL);
-}
-
-/*****************************************************************************
- * main: parse command line, start interface and spawn threads.
- *****************************************************************************/
-int main( int i_argc, const char *ppsz_argv[] )
-{
-    /* The so-called POSIX-compliant MacOS X reportedly processes SIGPIPE even
-     * if it is blocked in all thread.
-     * Note: this is NOT an excuse for not protecting against SIGPIPE. If
-     * LibVLC runs outside of VLC, we cannot rely on this code snippet. */
-    signal (SIGPIPE, SIG_IGN);
-    /* Restore SIGCHLD in case our parent process ignores it. */
-    signal (SIGCHLD, SIG_DFL);
-
-#ifndef NDEBUG
-    /* Activate malloc checking routines to detect heap corruptions. */
-    setenv ("MALLOC_CHECK_", "2", 1);
-#endif
-
-#ifdef TOP_BUILDDIR
-    setenv ("VLC_PLUGIN_PATH", TOP_BUILDDIR"/modules", 1);
-    setenv ("VLC_DATA_PATH", TOP_SRCDIR"/share", 1);
-#endif
-
-#ifndef ALLOW_RUN_AS_ROOT
-    if (geteuid () == 0)
-    {
-        fprintf (stderr, "VLC is not supposed to be run as root. Sorry.\n"
-        "If you need to use real-time priorities and/or privileged TCP ports\n"
-        "you can use %s-wrapper (make sure it is Set-UID root and\n"
-        "cannot be run by non-trusted users first).\n", ppsz_argv[0]);
-        return 1;
-    }
-#endif
-
-    setlocale (LC_ALL, "");
-
-    if (isatty (STDERR_FILENO))
-        /* This message clutters error logs. It is printed only on a TTY.
-         * Fortunately, LibVLC prints version info with -vv anyway. */
-        fprintf (stderr, "VLC media player %s (revision %s)\n",
-                 libvlc_get_version(), libvlc_get_changeset());
-
-    sigset_t set;
-
-    sigemptyset (&set);
-    /* VLC uses sigwait() to dequeue interesting signals.
-     * For this to work, those signals must be blocked in all threads,
-     * including the thread calling sigwait() (see the man page for details).
-     *
-     * There are two advantages to sigwait() over traditional signal handlers:
-     *  - delivery is synchronous: no need to worry about async-safety,
-     *  - EINTR is not generated: other threads need not handle that error.
-     * That being said, some LibVLC programs do not use sigwait(). Therefore
-     * EINTR must still be handled cleanly, notably from poll() calls.
-     *
-     * Signals that request a clean shutdown, and force an unclean shutdown
-     * if they are triggered again 2+ seconds later.
-     * We have to handle SIGTERM cleanly because of daemon mode. */
-    sigaddset (&set, SIGINT);
-    sigaddset (&set, SIGHUP);
-    sigaddset (&set, SIGQUIT);
-    sigaddset (&set, SIGTERM);
-
-    /* SIGPIPE can happen and would crash the process. On modern systems,
-     * the MSG_NOSIGNAL flag protects socket write operations against SIGPIPE.
-     * But we still need to block SIGPIPE when:
-     *  - writing to pipes,
-     *  - using write() instead of send() for code not specific to sockets.
-     * LibVLC code assumes that SIGPIPE is blocked. Other LibVLC applications
-     * shall block it (or handle it somehow) too.
-     */
-    sigaddset (&set, SIGPIPE);
-
-    /* SIGCHLD must be dequeued to clean up zombie child processes.
-     * Furthermore the handler must not be set to SIG_IGN (see above).
-     * We cannot pragmatically handle EINTR, short reads and short writes
-     * in every code paths (including underlying libraries). So we just
-     * block SIGCHLD in all threads, and dequeue it below. */
-    sigaddset (&set, SIGCHLD);
-
-    /* Block all these signals */
-    pthread_sigmask (SIG_SETMASK, &set, NULL);
-
-    const char *argv[i_argc + 2];
-    int argc = 0;
-
-    argv[argc++] = "--no-ignore-config";
-    argv[argc++] = "--media-library";
-
-    /* overwrite system language on Mac */
-#if !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR // TARGET_OS_MAC is unspecific
-    char *lang = NULL;
-
-    for (int i = 0; i < i_argc; i++) {
-        if (!strncmp(ppsz_argv[i], "--language", 10)) {
-            lang = strstr(ppsz_argv[i], "=");
-            ppsz_argv++, i_argc--;
-            continue;
-        }
-    }
-    if (lang && strncmp( lang, "auto", 4 )) {
-        char tmp[11];
-        snprintf(tmp, 11, "LANG%s", lang);
-        putenv(tmp);
-    }
-
-    if (!lang) {
-        CFStringRef language;
-        language = (CFStringRef)CFPreferencesCopyAppValue(CFSTR("language"),
-                                                          kCFPreferencesCurrentApplication);
-        if (language) {
-            CFIndex length = CFStringGetLength(language) + 1;
-            if (length > 0) {
-                CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
-                lang = (char *)malloc(maxSize);
-                CFStringGetCString(language, lang, maxSize - 1, kCFStringEncodingUTF8);
-            }
-            if (strncmp( lang, "auto", 4 )) {
-                char tmp[11];
-                snprintf(tmp, 11, "LANG=%s", lang);
-                putenv(tmp);
-            }
-            CFRelease(language);
-        }
-    }
-#endif
-
-    ppsz_argv++; i_argc--; /* skip executable path */
-
-    /* When VLC.app is run by double clicking in Mac OS X, the 2nd arg
-     * is the PSN - process serial number (a unique PID-ish thingie)
-     * still ok for real Darwin & when run from command line
-     * for example -psn_0_9306113 */
-    if (i_argc >= 1 && !strncmp (*ppsz_argv, "-psn" , 4))
-        ppsz_argv++, i_argc--;
-
-    memcpy (argv + argc, ppsz_argv, i_argc * sizeof (*argv));
-    argc += i_argc;
-    argv[argc] = NULL;
-
-    vlc_enable_override ();
-
-    pthread_t self = pthread_self ();
-
-    /* Initialize libvlc */
-    libvlc_instance_t *vlc = libvlc_new (argc, argv);
-    if (vlc == NULL)
-        return 1;
-
-    int ret = 1;
-    libvlc_set_exit_handler (vlc, vlc_kill, &self);
-    libvlc_set_app_id (vlc, "org.VideoLAN.VLC", PACKAGE_VERSION, PACKAGE_NAME);
-    libvlc_set_user_agent (vlc, "VLC media player", "VLC/"PACKAGE_VERSION);
-
-    libvlc_add_intf (vlc, "hotkeys,none");
-
-    libvlc_playlist_play (vlc, -1, 0, NULL);
-    if (libvlc_add_intf (vlc, NULL))
-        goto out;
-
-    /* Qt4 insists on catching SIGCHLD via signal handler. To work around that,
-     * unblock it after all our child threads are created. */
-    sigdelset (&set, SIGCHLD);
-    pthread_sigmask (SIG_SETMASK, &set, NULL);
-
-    /* Do not dequeue SIGHUP if it is ignored (nohup) */
-    if (signal_ignored (SIGHUP))
-        sigdelset (&set, SIGHUP);
-    /* Ignore SIGPIPE */
-    sigdelset (&set, SIGPIPE);
-
-    int signum;
-    sigwait (&set, &signum);
-
-    /* Restore default signal behaviour after 3 seconds */
-    sigemptyset (&set);
-    sigaddset (&set, SIGINT);
-    sigaddset (&set, SIGALRM);
-    signal (SIGINT, SIG_IGN);
-    signal (SIGALRM, exit_timeout);
-    pthread_sigmask (SIG_UNBLOCK, &set, NULL);
-    alarm (3);
-
-    ret = 0;
-    /* Cleanup */
-out:
-    libvlc_release (vlc);
-
-    return ret;
-}
diff --git a/bin/darwinvlc.m b/bin/darwinvlc.m
new file mode 100644
index 0000000..d46bd1f
--- /dev/null
+++ b/bin/darwinvlc.m
@@ -0,0 +1,294 @@
+/*****************************************************************************
+ * darwinvlc.c: the darwin-specific VLC player
+ *****************************************************************************
+ * Copyright (C) 1998-2013 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Vincent Seguin <seguin at via.ecp.fr>
+ *          Samuel Hocevar <sam at zoy.org>
+ *          Gildas Bazin <gbazin at videolan.org>
+ *          Derk-Jan Hartman <hartman at videolan dot org>
+ *          Lots of other people, see the libvlc AUTHORS file
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc/vlc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <locale.h>
+#include <signal.h>
+#ifdef HAVE_PTHREAD_H
+# include <pthread.h>
+#endif
+#include <unistd.h>
+#include <TargetConditionals.h>
+#import <CoreFoundation/CoreFoundation.h>
+#import <Cocoa/Cocoa.h>
+
+
+extern void vlc_enable_override(void);
+
+
+static void vlc_terminate(void *data)
+{
+    dispatch_async(dispatch_get_main_queue(), ^{
+        /*
+         * Stop the main loop. When using the CoreFoundation mainloop, simply
+         * CFRunLoopStop can be used.
+         *
+         * But this does not work when having an interface.
+         * In this case, [NSApp stop:nil] needs to be used, but the used flag is only
+         * evaluated at the end of main loop event processing. This is always true
+         * in the case of code inside a action method. But here, this is
+         * not true and thus we need to send an dummy event to make sure the stop
+         * flag is actually processed by the main loop.
+         */
+        if (NSApp == nil) {
+            CFRunLoopStop(CFRunLoopGetCurrent());
+        } else {
+
+            // the ugly starts
+            [NSApp stop:nil];
+
+            NSEvent* event = [NSEvent otherEventWithType:NSApplicationDefined
+                                                location:NSMakePoint(0,0)
+                                           modifierFlags:0
+                                               timestamp:0.0
+                                            windowNumber:0
+                                                 context:nil
+                                                 subtype:0
+                                                   data1:0
+                                                   data2:0];
+            [NSApp postEvent:event atStart:YES];
+        }
+
+    });
+}
+
+/*****************************************************************************
+ * main: parse command line, start interface and spawn threads.
+ *****************************************************************************/
+int main(int i_argc, const char *ppsz_argv[])
+{
+    /* The so-called POSIX-compliant MacOS X reportedly processes SIGPIPE even
+     * if it is blocked in all thread.
+     * Note: this is NOT an excuse for not protecting against SIGPIPE. If
+     * LibVLC runs outside of VLC, we cannot rely on this code snippet. */
+    signal(SIGPIPE, SIG_IGN);
+    /* Restore SIGCHLD in case our parent process ignores it. */
+    signal(SIGCHLD, SIG_DFL);
+
+#ifndef NDEBUG
+    /* Activate malloc checking routines to detect heap corruptions. */
+    setenv("MALLOC_CHECK_", "2", 1);
+#endif
+
+#ifdef TOP_BUILDDIR
+    setenv("VLC_PLUGIN_PATH", TOP_BUILDDIR"/modules", 1);
+    setenv("VLC_DATA_PATH", TOP_SRCDIR"/share", 1);
+#endif
+
+#ifndef ALLOW_RUN_AS_ROOT
+    if (geteuid() == 0)
+    {
+        fprintf(stderr, "VLC is not supposed to be run as root. Sorry.\n"
+        "If you need to use real-time priorities and/or privileged TCP ports\n"
+        "you can use %s-wrapper (make sure it is Set-UID root and\n"
+        "cannot be run by non-trusted users first).\n", ppsz_argv[0]);
+        return 1;
+    }
+#endif
+
+    setlocale(LC_ALL, "");
+
+    if (isatty(STDERR_FILENO))
+        /* This message clutters error logs. It is printed only on a TTY.
+         * Fortunately, LibVLC prints version info with -vv anyway. */
+        fprintf(stderr, "VLC media player %s (revision %s)\n",
+                 libvlc_get_version(), libvlc_get_changeset());
+
+    sigset_t set;
+
+    sigemptyset(&set);
+    /*
+     * The darwin version of VLC used GCD to dequeue interesting signals.
+     * For this to work, those signals must be blocked.
+     *
+     * There are two advantages over traditional signal handlers:
+     *  - handling is done on a separate thread: no need to worry about async-safety,
+     *  - EINTR is not generated: other threads need not handle that error.
+     * That being said, some LibVLC programs do not use sigwait(). Therefore
+     * EINTR must still be handled cleanly, notably from poll() calls.
+     *
+     * Signals that request a clean shutdown.
+     * We have to handle SIGTERM cleanly because of daemon mode. */
+    sigaddset(&set, SIGINT);
+    sigaddset(&set, SIGTERM);
+
+    /* SIGPIPE can happen and would crash the process. On modern systems,
+     * the MSG_NOSIGNAL flag protects socket write operations against SIGPIPE.
+     * But we still need to block SIGPIPE when:
+     *  - writing to pipes,
+     *  - using write() instead of send() for code not specific to sockets.
+     * LibVLC code assumes that SIGPIPE is blocked. Other LibVLC applications
+     * shall block it (or handle it somehow) too.
+     */
+    sigaddset(&set, SIGPIPE);
+
+    /* SIGCHLD must be dequeued to clean up zombie child processes.
+     * Furthermore the handler must not be set to SIG_IGN (see above).
+     * We cannot pragmatically handle EINTR, short reads and short writes
+     * in every code paths (including underlying libraries). So we just
+     * block SIGCHLD in all threads, and dequeue it below. */
+    sigaddset(&set, SIGCHLD);
+
+    /* Block all these signals */
+    pthread_sigmask(SIG_SETMASK, &set, NULL);
+
+    /* Handle signals with GCD */
+    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+    dispatch_source_t sigIntSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGINT, 0, queue);
+    dispatch_source_t sigTermSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGTERM, 0, queue);
+    dispatch_source_t sigChldSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGCHLD, 0, queue);
+
+    if (!sigIntSource || !sigTermSource || !sigChldSource)
+        abort();
+
+    dispatch_source_set_event_handler(sigIntSource, ^{
+        vlc_terminate(nil);
+    });
+    dispatch_source_set_event_handler(sigTermSource, ^{
+        vlc_terminate(nil);
+    });
+
+    dispatch_source_set_event_handler(sigChldSource, ^{
+        int status;
+        while(waitpid(-1, &status, WNOHANG) > 0)
+            ;
+    });
+
+    dispatch_resume(sigIntSource);
+    dispatch_resume(sigTermSource);
+    dispatch_resume(sigChldSource);
+
+
+    /* Handle parameters */
+    const char *argv[i_argc + 2];
+    int argc = 0;
+
+    argv[argc++] = "--no-ignore-config";
+    argv[argc++] = "--media-library";
+
+    /* overwrite system language on Mac */
+#if !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR // TARGET_OS_MAC is unspecific
+    char *lang = NULL;
+
+    for (int i = 0; i < i_argc; i++) {
+        if (!strncmp(ppsz_argv[i], "--language", 10)) {
+            lang = strstr(ppsz_argv[i], "=");
+            ppsz_argv++, i_argc--;
+            continue;
+        }
+    }
+    if (lang && strncmp( lang, "auto", 4 )) {
+        char tmp[11];
+        snprintf(tmp, 11, "LANG%s", lang);
+        putenv(tmp);
+    }
+
+    if (!lang) {
+        CFStringRef language;
+        language = (CFStringRef)CFPreferencesCopyAppValue(CFSTR("language"),
+                                                          kCFPreferencesCurrentApplication);
+        if (language) {
+            CFIndex length = CFStringGetLength(language) + 1;
+            if (length > 0) {
+                CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
+                lang = (char *)malloc(maxSize);
+                CFStringGetCString(language, lang, maxSize - 1, kCFStringEncodingUTF8);
+            }
+            if (strncmp( lang, "auto", 4 )) {
+                char tmp[11];
+                snprintf(tmp, 11, "LANG=%s", lang);
+                putenv(tmp);
+            }
+            CFRelease(language);
+        }
+    }
+#endif
+
+    ppsz_argv++; i_argc--; /* skip executable path */
+
+    /* When VLC.app is run by double clicking in Mac OS X, the 2nd arg
+     * is the PSN - process serial number (a unique PID-ish thingie)
+     * still ok for real Darwin & when run from command line
+     * for example -psn_0_9306113 */
+    if (i_argc >= 1 && !strncmp(*ppsz_argv, "-psn" , 4))
+        ppsz_argv++, i_argc--;
+
+    memcpy (argv + argc, ppsz_argv, i_argc * sizeof(*argv));
+    argc += i_argc;
+    argv[argc] = NULL;
+
+    vlc_enable_override();
+
+    /* Initialize libvlc */
+    libvlc_instance_t *vlc = libvlc_new(argc, argv);
+    if (vlc == NULL)
+        return 1;
+
+    int ret = 1;
+    libvlc_set_exit_handler(vlc, 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);
+
+    libvlc_add_intf(vlc, "hotkeys,none");
+
+    if (libvlc_add_intf(vlc, NULL))
+        goto out;
+    libvlc_playlist_play(vlc, -1, 0, NULL);
+
+    /*
+     * Run the main loop. If the mac interface is not initialized, only the CoreFoundation
+     * runloop is used. Otherwise, [NSApp run] needs to be called, which setups more stuff
+     * before actually starting the loop.
+     */
+    @autoreleasepool {
+        if(NSApp == nil) {
+            CFRunLoopRun();
+
+        } else {
+            [NSApp run];
+        }
+    }
+
+    ret = 0;
+    /* Cleanup */
+out:
+    dispatch_release(sigIntSource);
+    dispatch_release(sigTermSource);
+    dispatch_release(sigChldSource);
+
+    libvlc_release(vlc);
+
+    return ret;
+}
diff --git a/extras/package/macosx/vlc.xcodeproj/project.pbxproj b/extras/package/macosx/vlc.xcodeproj/project.pbxproj
index 848c7d3..18cf45c 100644
--- a/extras/package/macosx/vlc.xcodeproj/project.pbxproj
+++ b/extras/package/macosx/vlc.xcodeproj/project.pbxproj
@@ -358,6 +358,7 @@
 		1C88BCC219DC7CB300645190 /* ys-fs_volume_slider_knob_highlight.png in Resources */ = {isa = PBXBuildFile; fileRef = 1C88BC8C19DC7CB300645190 /* ys-fs_volume_slider_knob_highlight.png */; };
 		1C88BCC319DC7CB300645190 /* ys-fs_volume_slider_knob_highlight at 2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1C88BC8D19DC7CB300645190 /* ys-fs_volume_slider_knob_highlight at 2x.png */; };
 		1CBB2CC81B06A6DE00110ADA /* Help.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1CBB2CC61B06A6DE00110ADA /* Help.xib */; };
+		1CC25CA81B2C585D0003F994 /* darwinvlc.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CC25CA71B2C585D0003F994 /* darwinvlc.m */; };
 		1CCB5F511A62A724004C3E90 /* about.h in Sources */ = {isa = PBXBuildFile; fileRef = 8EE1AF9F044465080059A3A7 /* about.h */; };
 		1CCB5F521A62A724004C3E90 /* about.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EE1AFA0044465080059A3A7 /* about.m */; };
 		1CCB5F531A62A724004C3E90 /* AddonListDataSource.h in Sources */ = {isa = PBXBuildFile; fileRef = 7DF0435E1972E26A0022B534 /* AddonListDataSource.h */; };
@@ -1231,6 +1232,7 @@
 		1C88BC8C19DC7CB300645190 /* ys-fs_volume_slider_knob_highlight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "ys-fs_volume_slider_knob_highlight.png"; sourceTree = "<group>"; };
 		1C88BC8D19DC7CB300645190 /* ys-fs_volume_slider_knob_highlight at 2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "ys-fs_volume_slider_knob_highlight at 2x.png"; sourceTree = "<group>"; };
 		1CBB2CC71B06A6DE00110ADA /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = Resources/English.lproj/Help.xib; sourceTree = "<group>"; };
+		1CC25CA71B2C585D0003F994 /* darwinvlc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = darwinvlc.m; path = ../../../bin/darwinvlc.m; sourceTree = "<group>"; };
 		1CCB5F2F1A62A6A5004C3E90 /* pseudo-vlc.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "pseudo-vlc.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 		1CE5ED1B19DD6AB700FCEFD3 /* lion-window-fullscreen-on.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lion-window-fullscreen-on.png"; sourceTree = "<group>"; };
 		1CE5ED1C19DD6AB700FCEFD3 /* lion-window-fullscreen-on at 2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lion-window-fullscreen-on at 2x.png"; sourceTree = "<group>"; };
@@ -1251,7 +1253,6 @@
 		7D3F652718805297005776C4 /* BWQuincyManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BWQuincyManager.m; path = ../../../modules/gui/macosx/BWQuincyManager.m; sourceTree = SOURCE_ROOT; };
 		7D3F652818805297005776C4 /* BWQuincyUI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BWQuincyUI.h; path = ../../../modules/gui/macosx/BWQuincyUI.h; sourceTree = SOURCE_ROOT; };
 		7D3F652918805297005776C4 /* BWQuincyUI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BWQuincyUI.m; path = ../../../modules/gui/macosx/BWQuincyUI.m; sourceTree = SOURCE_ROOT; };
-		7D7DC2CA182E86D9008C9E3E /* darwinvlc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = darwinvlc.c; path = ../../../bin/darwinvlc.c; sourceTree = "<group>"; };
 		7D8BB0B318302AC000FAE9B7 /* DebugMessageVisualizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DebugMessageVisualizer.h; path = ../../../modules/gui/macosx/DebugMessageVisualizer.h; sourceTree = SOURCE_ROOT; };
 		7D8BB0B418302AC000FAE9B7 /* DebugMessageVisualizer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = DebugMessageVisualizer.m; path = ../../../modules/gui/macosx/DebugMessageVisualizer.m; sourceTree = SOURCE_ROOT; };
 		7D8BB0B61830311300FAE9B7 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = Resources/English.lproj/DebugMessageVisualizer.xib; sourceTree = "<group>"; };
@@ -2877,7 +2878,7 @@
 		CCDDF1AF172FF4D6007729A1 /* core */ = {
 			isa = PBXGroup;
 			children = (
-				7D7DC2CA182E86D9008C9E3E /* darwinvlc.c */,
+				1CC25CA71B2C585D0003F994 /* darwinvlc.m */,
 				CC4D67F71348F601003FCC5B /* specific.c */,
 				CCDDF1AC172FF4C4007729A1 /* netconf.c */,
 				CCDDF1AD172FF4C4007729A1 /* dirs.c */,
@@ -3931,6 +3932,7 @@
 				1CCB5F791A62A724004C3E90 /* open.h in Sources */,
 				1CCB5F7A1A62A724004C3E90 /* open.m in Sources */,
 				1CCB5F7B1A62A724004C3E90 /* output.h in Sources */,
+				1CC25CA81B2C585D0003F994 /* darwinvlc.m in Sources */,
 				1CCB5F7C1A62A724004C3E90 /* output.m in Sources */,
 				1CCB5F7D1A62A724004C3E90 /* playlist.h in Sources */,
 				1CCB5F7E1A62A724004C3E90 /* playlist.m in Sources */,
diff --git a/modules/gui/macosx/intf.m b/modules/gui/macosx/intf.m
index 39ffeb5..dc56363 100644
--- a/modules/gui/macosx/intf.m
+++ b/modules/gui/macosx/intf.m
@@ -77,7 +77,6 @@
 /*****************************************************************************
  * Local prototypes.
  *****************************************************************************/
-static void Run (intf_thread_t *p_intf);
 
 static void updateProgressPanel (void *, const char *, float);
 static bool checkProgressPanel (void *);
@@ -104,6 +103,10 @@ static bool b_intf_starting = false;
 static vlc_mutex_t start_mutex = VLC_STATIC_MUTEX;
 static vlc_cond_t  start_cond = VLC_STATIC_COND;
 
+static NSLock * o_appLock = nil;    // controls access to f_appExit
+static NSLock * o_vout_provider_lock = nil;
+
+
 /*****************************************************************************
  * OpenIntf: initialize interface
  *****************************************************************************/
@@ -114,13 +117,36 @@ int OpenIntf (vlc_object_t *p_this)
 
     intf_thread_t *p_intf = (intf_thread_t*) p_this;
     msg_Dbg(p_intf, "Starting macosx interface");
-    Run(p_intf);
+
+    [VLCApplication sharedApplication];
+
+    o_appLock = [[NSLock alloc] init];
+    o_vout_provider_lock = [[NSLock alloc] init];
+
+    [[VLCMain sharedInstance] setIntf: p_intf];
+
+    vlc_mutex_lock(&start_mutex);
+    b_intf_starting = true;
+    vlc_cond_signal(&start_cond);
+    vlc_mutex_unlock(&start_mutex);
+
+    [NSBundle loadNibNamed: @"MainMenu" owner: NSApp];
 
     [o_pool release];
     return VLC_SUCCESS;
 }
 
-static NSLock * o_vout_provider_lock = nil;
+void CloseIntf (vlc_object_t *p_this)
+{
+    NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
+
+    msg_Dbg(p_this, "Closing macosx interface");
+    [[VLCMain sharedInstance] applicationWillTerminate:nil];
+    [o_appLock release];
+    [o_vout_provider_lock release];
+    o_vout_provider_lock = nil;
+    [o_pool release];
+}
 
 static int WindowControl(vout_window_t *, int i_query, va_list);
 
@@ -306,48 +332,6 @@ void WindowClose(vout_window_t *p_wnd)
     [o_pool release];
 }
 
-/* Used to abort the app.exec() on OSX after libvlc_Quit is called */
-#include "../../../lib/libvlc_internal.h" /* libvlc_SetExitHandler */
-
-static void QuitVLC( void *obj )
-{
-    [[VLCApplication sharedApplication] performSelectorOnMainThread:@selector(terminate:) withObject:nil waitUntilDone:NO];
-}
-
-/*****************************************************************************
- * Run: main loop
- *****************************************************************************/
-static NSLock * o_appLock = nil;    // controls access to f_appExit
-
-static void Run(intf_thread_t *p_intf)
-{
-    NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
-    [VLCApplication sharedApplication];
-
-    o_appLock = [[NSLock alloc] init];
-    o_vout_provider_lock = [[NSLock alloc] init];
-
-    libvlc_SetExitHandler(p_intf->p_libvlc, QuitVLC, p_intf);
-    [[VLCMain sharedInstance] setIntf: p_intf];
-
-    vlc_mutex_lock(&start_mutex);
-    b_intf_starting = true;
-    vlc_cond_signal(&start_cond);
-    vlc_mutex_unlock(&start_mutex);
-
-    [NSBundle loadNibNamed: @"MainMenu" owner: NSApp];
-
-    [NSApp run];
-    msg_Dbg(p_intf, "Run loop has been stopped");
-    [[VLCMain sharedInstance] applicationWillTerminate:nil];
-    [o_appLock release];
-    [o_vout_provider_lock release];
-    o_vout_provider_lock = nil;
-    [o_pool release];
-
-    raise(SIGTERM);
-}
-
 #pragma mark -
 #pragma mark Variables Callback
 
diff --git a/modules/gui/macosx/macosx.m b/modules/gui/macosx/macosx.m
index 37092c8..a83fe78 100644
--- a/modules/gui/macosx/macosx.m
+++ b/modules/gui/macosx/macosx.m
@@ -148,7 +148,7 @@ static const char *const continue_playback_list_text[] = {
 vlc_module_begin()
     set_description(N_("Mac OS X interface"))
     set_capability("interface", 200)
-    set_callbacks(OpenIntf, NULL)
+    set_callbacks(OpenIntf, CloseIntf)
     set_category(CAT_INTERFACE)
     set_subcategory(SUBCAT_INTERFACE_MAIN)
     cannot_unload_broken_library()
-- 
2.3.2 (Apple Git-55)




More information about the vlc-devel mailing list