vlc.c 5.99 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
/*****************************************************************************
 * vlc.c: the VLC player
 *****************************************************************************
 * Copyright (C) 1998-2008 the VideoLAN team
 * $Id$
 *
 * Authors: Vincent Seguin <seguin@via.ecp.fr>
 *          Samuel Hocevar <sam@zoy.org>
 *          Gildas Bazin <gbazin@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 <locale.h>
36

37 38 39 40
#ifdef __APPLE__
#include <string.h>
#endif

41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

/* Explicit HACK */
extern void LocaleFree (const char *);
extern char *FromLocale (const char *);

#include <signal.h>
#include <time.h>
#include <pthread.h>
#include <unistd.h>

/*****************************************************************************
 * main: parse command line, start interface and spawn threads.
 *****************************************************************************/
int main( int i_argc, const char *ppsz_argv[] )
{
56 57 58 59 60 61
#ifdef __APPLE__
    /* The so-called POSIX-compliant MacOS X is not. 
     * SIGPIPE fires even when it is blocked in all threads! */
    signal (SIGPIPE, SIG_IGN);
#endif

62
#ifndef ALLOW_RUN_AS_ROOT
63 64 65 66
    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"
67
        "you can use %s-wrapper (make sure it is Set-UID root and\n"
68 69 70
        "cannot be run by non-trusted users first).\n", ppsz_argv[0]);
        return 1;
    }
71
#endif
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

    setlocale (LC_ALL, "");

#ifndef __APPLE__
    /* This clutters OSX GUI error logs */
    fprintf( stderr, "VLC media player %s\n", libvlc_get_version() );
#endif

#ifdef HAVE_PUTENV
#   ifndef NDEBUG
    /* Activate malloc checking routines to detect heap corruptions. */
    putenv( (char*)"MALLOC_CHECK_=2" );

    /* Disable the ugly Gnome crash dialog so that we properly segfault */
    putenv( (char *)"GNOME_DISABLE_CRASH_DIALOG=1" );
#   endif
#endif

    /* Synchronously intercepted POSIX signals.
     *
     * In a threaded program such as VLC, the only sane way to handle signals
     * is to block them in all thread but one - this is the only way to
     * predict which thread will receive them. If any piece of code depends
     * on delivery of one of this signal it is intrinsically not thread-safe
     * and MUST NOT be used in VLC, whether we like it or not.
     * There is only one exception: if the signal is raised with
     * pthread_kill() - we do not use this in LibVLC but some pthread
     * implementations use them internally. You should really use conditions
     * for thread synchronization anyway.
     *
     * Signal 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.
     * Note that we set the signals after the vlc_create call. */
    static const int sigs[] = {
        SIGINT, SIGHUP, SIGQUIT, SIGTERM,
    /* Signals that cause a no-op:
     * - SIGPIPE might happen with sockets and would crash VLC. It MUST be
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
110 111
     *   blocked by any LibVLC-dependent application, not just VLC.
     * - SIGCHLD comes after exec*() (such as httpd CGI support) and must
112 113 114 115 116 117 118 119 120 121 122 123
     *   be dequeued to cleanup zombie processes.
     */
        SIGPIPE, SIGCHLD
    };

    sigset_t set;
    sigemptyset (&set);
    for (unsigned i = 0; i < sizeof (sigs) / sizeof (sigs[0]); i++)
        sigaddset (&set, sigs[i]);

    /* Block all these signals */
    pthread_sigmask (SIG_BLOCK, &set, NULL);
124 125
    sigdelset (&set, SIGPIPE);
    sigdelset (&set, SIGCHLD);
126 127

    /* Note that FromLocale() can be used before libvlc is initialized */
128 129 130
    const char *argv[i_argc + 3];
    int argc = 0;

131
    argv[argc++] = "--no-ignore-config";
132 133 134 135
#ifdef TOP_BUILDDIR
    argv[argc++] = FromLocale ("--plugin-path="TOP_BUILDDIR"/modules");
#endif
#ifdef TOP_SRCDIR
136
    argv[argc++] = FromLocale ("--data-path="TOP_SRCDIR"/share");
137 138
#endif

139 140 141 142 143 144 145 146 147 148
    int i = 1;
#ifdef __APPLE__
    /* 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 >= 2 && !strncmp( ppsz_argv[1] , "-psn" , 4 ))
        i = 2;
#endif
    for (; i < i_argc; i++)
149
        if ((argv[argc++] = FromLocale (ppsz_argv[i])) == NULL)
150
            return 1; // BOOM!
151
    argv[argc] = NULL;
152

153
    libvlc_exception_t ex;
154 155 156
    libvlc_exception_init (&ex);

    /* Initialize libvlc */
157
    libvlc_instance_t *vlc = libvlc_new (argc, argv, &ex);
158 159 160

    if (vlc != NULL)
    {
161
        if (libvlc_add_intf (vlc, "signals"))
162
            pthread_sigmask (SIG_UNBLOCK, &set, NULL);
163
#if !defined (HAVE_MAEMO)
164
        libvlc_add_intf (vlc, "globalhotkeys,none");
165
#endif
166 167
        if (libvlc_add_intf (vlc, NULL) == 0)
        {
168
            libvlc_playlist_play (vlc, -1, 0, NULL);
169 170
            libvlc_wait (vlc);
        }
171 172 173
        libvlc_release (vlc);
    }

174
    for (int i = 1; i < argc; i++)
175
        LocaleFree (argv[i]);
176

177
    return vlc == NULL || libvlc_exception_raised (&ex);
178
}