libvlc.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:71k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * libvlc.c: libvlc instances creation and deletion, interfaces handling
  3.  *****************************************************************************
  4.  * Copyright (C) 1998-2008 the VideoLAN team
  5.  * $Id: b9be376e212c7bb5fb95a22d4cbb14ffeabc73c9 $
  6.  *
  7.  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  8.  *          Samuel Hocevar <sam@zoy.org>
  9.  *          Gildas Bazin <gbazin@videolan.org>
  10.  *          Derk-Jan Hartman <hartman at videolan dot org>
  11.  *          Rémi Denis-Courmont <rem # videolan : org>
  12.  *
  13.  * This program is free software; you can redistribute it and/or modify
  14.  * it under the terms of the GNU General Public License as published by
  15.  * the Free Software Foundation; either version 2 of the License, or
  16.  * (at your option) any later version.
  17.  *
  18.  * This program is distributed in the hope that it will be useful,
  19.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  * GNU General Public License for more details.
  22.  *
  23.  * You should have received a copy of the GNU General Public License
  24.  * along with this program; if not, write to the Free Software
  25.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  26.  *****************************************************************************/
  27. /** file
  28.  * This file contains functions to create and destroy libvlc instances
  29.  */
  30. /*****************************************************************************
  31.  * Preamble
  32.  *****************************************************************************/
  33. #ifdef HAVE_CONFIG_H
  34. # include "config.h"
  35. #endif
  36. #include <vlc_common.h>
  37. #include "control/libvlc_internal.h"
  38. #include <vlc_input.h>
  39. #include "modules/modules.h"
  40. #include "config/configuration.h"
  41. #include <errno.h>                                                 /* ENOMEM */
  42. #include <stdio.h>                                              /* sprintf() */
  43. #include <string.h>
  44. #include <stdlib.h>                                                /* free() */
  45. #ifndef WIN32
  46. #   include <netinet/in.h>                            /* BSD: struct in_addr */
  47. #endif
  48. #ifdef HAVE_UNISTD_H
  49. #   include <unistd.h>
  50. #elif defined( WIN32 ) && !defined( UNDER_CE )
  51. #   include <io.h>
  52. #endif
  53. #ifdef WIN32                       /* optind, getopt(), included in unistd.h */
  54. #   include "extras/getopt.h"
  55. #endif
  56. #ifdef HAVE_LOCALE_H
  57. #   include <locale.h>
  58. #endif
  59. #ifdef ENABLE_NLS
  60. # include <libintl.h> /* bindtextdomain */
  61. #endif
  62. #ifdef HAVE_DBUS
  63. /* used for one-instance mode */
  64. #   include <dbus/dbus.h>
  65. #endif
  66. #ifdef HAVE_HAL
  67. #   include <hal/libhal.h>
  68. #endif
  69. #include <vlc_playlist.h>
  70. #include <vlc_interface.h>
  71. #include <vlc_aout.h>
  72. #include "audio_output/aout_internal.h"
  73. #include <vlc_charset.h>
  74. #include "libvlc.h"
  75. #include "playlist/playlist_internal.h"
  76. #include <vlc_vlm.h>
  77. #ifdef __APPLE__
  78. # include <libkern/OSAtomic.h>
  79. #endif
  80. #include <assert.h>
  81. /*****************************************************************************
  82.  * The evil global variables. We handle them with care, don't worry.
  83.  *****************************************************************************/
  84. static unsigned          i_instances = 0;
  85. #ifndef WIN32
  86. static bool b_daemon = false;
  87. #endif
  88. #undef vlc_gc_init
  89. #undef vlc_hold
  90. #undef vlc_release
  91. /**
  92.  * Atomically set the reference count to 1.
  93.  * @param p_gc reference counted object
  94.  * @param pf_destruct destruction calback
  95.  * @return p_gc.
  96.  */
  97. void *vlc_gc_init (gc_object_t *p_gc, void (*pf_destruct) (gc_object_t *))
  98. {
  99.     /* There is no point in using the GC if there is no destructor... */
  100.     assert (pf_destruct);
  101.     p_gc->pf_destructor = pf_destruct;
  102.     p_gc->refs = 1;
  103. #if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
  104.     __sync_synchronize ();
  105. #elif defined (WIN32) && defined (__GNUC__)
  106. #elif defined(__APPLE__)
  107.     OSMemoryBarrier ();
  108. #else
  109.     /* Nobody else can possibly lock the spin - it's there as a barrier */
  110.     vlc_spin_init (&p_gc->spin);
  111.     vlc_spin_lock (&p_gc->spin);
  112.     vlc_spin_unlock (&p_gc->spin);
  113. #endif
  114.     return p_gc;
  115. }
  116. /**
  117.  * Atomically increment the reference count.
  118.  * @param p_gc reference counted object
  119.  * @return p_gc.
  120.  */
  121. void *vlc_hold (gc_object_t * p_gc)
  122. {
  123.     uintptr_t refs;
  124.     assert( p_gc );
  125.     assert ((((uintptr_t)&p_gc->refs) & (sizeof (void *) - 1)) == 0); /* alignment */
  126. #if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
  127.     refs = __sync_add_and_fetch (&p_gc->refs, 1);
  128. #elif defined (WIN64)
  129.     refs = InterlockedIncrement64 (&p_gc->refs);
  130. #elif defined (WIN32)
  131.     refs = InterlockedIncrement (&p_gc->refs);
  132. #elif defined(__APPLE__)
  133.     refs = OSAtomicIncrement32Barrier((int*)&p_gc->refs);
  134. #else
  135.     vlc_spin_lock (&p_gc->spin);
  136.     refs = ++p_gc->refs;
  137.     vlc_spin_unlock (&p_gc->spin);
  138. #endif
  139.     assert (refs != 1); /* there had to be a reference already */
  140.     return p_gc;
  141. }
  142. /**
  143.  * Atomically decrement the reference count and, if it reaches zero, destroy.
  144.  * @param p_gc reference counted object.
  145.  */
  146. void vlc_release (gc_object_t *p_gc)
  147. {
  148.     unsigned refs;
  149.     assert( p_gc );
  150.     assert ((((uintptr_t)&p_gc->refs) & (sizeof (void *) - 1)) == 0); /* alignment */
  151. #if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
  152.     refs = __sync_sub_and_fetch (&p_gc->refs, 1);
  153. #elif defined (WIN64)
  154.     refs = InterlockedDecrement64 (&p_gc->refs);
  155. #elif defined (WIN32)
  156.     refs = InterlockedDecrement (&p_gc->refs);
  157. #elif defined(__APPLE__)
  158.     refs = OSAtomicDecrement32Barrier((int*)&p_gc->refs);
  159. #else
  160.     vlc_spin_lock (&p_gc->spin);
  161.     refs = --p_gc->refs;
  162.     vlc_spin_unlock (&p_gc->spin);
  163. #endif
  164.     assert (refs != (uintptr_t)(-1)); /* reference underflow?! */
  165.     if (refs == 0)
  166.     {
  167. #if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
  168. #elif defined (WIN32) && defined (__GNUC__)
  169. #elif defined(__APPLE__)
  170. #else
  171.         vlc_spin_destroy (&p_gc->spin);
  172. #endif
  173.         p_gc->pf_destructor (p_gc);
  174.     }
  175. }
  176. /*****************************************************************************
  177.  * Local prototypes
  178.  *****************************************************************************/
  179. #if defined( ENABLE_NLS ) && (defined (__APPLE__) || defined (WIN32)) && 
  180.     ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
  181. static void SetLanguage   ( char const * );
  182. #endif
  183. static inline int LoadMessages (void);
  184. static int  GetFilenames  ( libvlc_int_t *, int, const char *[] );
  185. static void Help          ( libvlc_int_t *, char const *psz_help_name );
  186. static void Usage         ( libvlc_int_t *, char const *psz_search );
  187. static void ListModules   ( libvlc_int_t *, bool );
  188. static void Version       ( void );
  189. #ifdef WIN32
  190. static void ShowConsole   ( bool );
  191. static void PauseConsole  ( void );
  192. #endif
  193. static int  ConsoleWidth  ( void );
  194. static void InitDeviceValues( libvlc_int_t * );
  195. static vlc_mutex_t global_lock = VLC_STATIC_MUTEX;
  196. /**
  197.  * Allocate a libvlc instance, initialize global data if needed
  198.  * It also initializes the threading system
  199.  */
  200. libvlc_int_t * libvlc_InternalCreate( void )
  201. {
  202.     libvlc_int_t *p_libvlc;
  203.     libvlc_priv_t *priv;
  204.     char *psz_env = NULL;
  205.     /* Now that the thread system is initialized, we don't have much, but
  206.      * at least we have variables */
  207.     vlc_mutex_lock( &global_lock );
  208.     if( i_instances == 0 )
  209.     {
  210.         /* Guess what CPU we have */
  211.         cpu_flags = CPUCapabilities();
  212.         /* The module bank will be initialized later */
  213.     }
  214.     /* Allocate a libvlc instance object */
  215.     p_libvlc = __vlc_custom_create( NULL, sizeof (*priv),
  216.                                   VLC_OBJECT_GENERIC, "libvlc" );
  217.     if( p_libvlc != NULL )
  218.         i_instances++;
  219.     vlc_mutex_unlock( &global_lock );
  220.     if( p_libvlc == NULL )
  221.         return NULL;
  222.     priv = libvlc_priv (p_libvlc);
  223.     priv->p_playlist = NULL;
  224.     priv->p_dialog_provider = NULL;
  225.     priv->p_vlm = NULL;
  226.     p_libvlc->psz_object_name = strdup( "libvlc" );
  227.     /* Initialize message queue */
  228.     msg_Create( p_libvlc );
  229.     /* Find verbosity from VLC_VERBOSE environment variable */
  230.     psz_env = getenv( "VLC_VERBOSE" );
  231.     if( psz_env != NULL )
  232.         priv->i_verbose = atoi( psz_env );
  233.     else
  234.         priv->i_verbose = 3;
  235. #if defined( HAVE_ISATTY ) && !defined( WIN32 )
  236.     priv->b_color = isatty( 2 ); /* 2 is for stderr */
  237. #else
  238.     priv->b_color = false;
  239. #endif
  240.     /* Initialize mutexes */
  241.     vlc_mutex_init( &priv->timer_lock );
  242.     vlc_cond_init( &priv->exiting );
  243.     return p_libvlc;
  244. }
  245. /**
  246.  * Initialize a libvlc instance
  247.  * This function initializes a previously allocated libvlc instance:
  248.  *  - CPU detection
  249.  *  - gettext initialization
  250.  *  - message queue, module bank and playlist initialization
  251.  *  - configuration and commandline parsing
  252.  */
  253. int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
  254.                          const char *ppsz_argv[] )
  255. {
  256.     libvlc_priv_t *priv = libvlc_priv (p_libvlc);
  257.     char         p_capabilities[200];
  258.     char *       p_tmp = NULL;
  259.     char *       psz_modules = NULL;
  260.     char *       psz_parser = NULL;
  261.     char *       psz_control = NULL;
  262.     bool   b_exit = false;
  263.     int          i_ret = VLC_EEXIT;
  264.     playlist_t  *p_playlist = NULL;
  265.     vlc_value_t  val;
  266. #if defined( ENABLE_NLS ) 
  267.      && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
  268. # if defined (WIN32) || defined (__APPLE__)
  269.     char *       psz_language;
  270. #endif
  271. #endif
  272.     /* System specific initialization code */
  273.     system_Init( p_libvlc, &i_argc, ppsz_argv );
  274.     /*
  275.      * Support for gettext
  276.      */
  277.     LoadMessages ();
  278.     /* Initialize the module bank and load the configuration of the
  279.      * main module. We need to do this at this stage to be able to display
  280.      * a short help if required by the user. (short help == main module
  281.      * options) */
  282.     module_InitBank( p_libvlc );
  283.     if( config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, true ) )
  284.     {
  285.         module_EndBank( p_libvlc, false );
  286.         return VLC_EGENERIC;
  287.     }
  288.     priv->i_verbose = config_GetInt( p_libvlc, "verbose" );
  289.     /* Announce who we are - Do it only for first instance ? */
  290.     msg_Dbg( p_libvlc, "%s", COPYRIGHT_MESSAGE );
  291.     msg_Dbg( p_libvlc, "libvlc was configured with %s", CONFIGURE_LINE );
  292.     /*xgettext: Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
  293.     msg_Dbg( p_libvlc, "translation test: code is "%s"", _("C") );
  294.     /* Check for short help option */
  295.     if( config_GetInt( p_libvlc, "help" ) > 0 )
  296.     {
  297.         Help( p_libvlc, "help" );
  298.         b_exit = true;
  299.         i_ret = VLC_EEXITSUCCESS;
  300.     }
  301.     /* Check for version option */
  302.     else if( config_GetInt( p_libvlc, "version" ) > 0 )
  303.     {
  304.         Version();
  305.         b_exit = true;
  306.         i_ret = VLC_EEXITSUCCESS;
  307.     }
  308.     /* Check for plugins cache options */
  309.     bool b_cache_delete = config_GetInt( p_libvlc, "reset-plugins-cache" ) > 0;
  310.     /* Check for daemon mode */
  311. #ifndef WIN32
  312.     if( config_GetInt( p_libvlc, "daemon" ) > 0 )
  313.     {
  314. #ifdef HAVE_DAEMON
  315.         char *psz_pidfile = NULL;
  316.         if( daemon( 1, 0) != 0 )
  317.         {
  318.             msg_Err( p_libvlc, "Unable to fork vlc to daemon mode" );
  319.             b_exit = true;
  320.         }
  321.         b_daemon = true;
  322.         /* lets check if we need to write the pidfile */
  323.         psz_pidfile = config_GetPsz( p_libvlc, "pidfile" );
  324.         if( psz_pidfile != NULL )
  325.         {
  326.             FILE *pidfile;
  327.             pid_t i_pid = getpid ();
  328.             msg_Dbg( p_libvlc, "PID is %d, writing it to %s",
  329.                                i_pid, psz_pidfile );
  330.             pidfile = utf8_fopen( psz_pidfile,"w" );
  331.             if( pidfile != NULL )
  332.             {
  333.                 utf8_fprintf( pidfile, "%d", (int)i_pid );
  334.                 fclose( pidfile );
  335.             }
  336.             else
  337.             {
  338.                 msg_Err( p_libvlc, "cannot open pid file for writing: %s (%m)",
  339.                          psz_pidfile );
  340.             }
  341.         }
  342.         free( psz_pidfile );
  343. #else
  344.         pid_t i_pid;
  345.         if( ( i_pid = fork() ) < 0 )
  346.         {
  347.             msg_Err( p_libvlc, "unable to fork vlc to daemon mode" );
  348.             b_exit = true;
  349.         }
  350.         else if( i_pid )
  351.         {
  352.             /* This is the parent, exit right now */
  353.             msg_Dbg( p_libvlc, "closing parent process" );
  354.             b_exit = true;
  355.             i_ret = VLC_EEXITSUCCESS;
  356.         }
  357.         else
  358.         {
  359.             /* We are the child */
  360.             msg_Dbg( p_libvlc, "daemon spawned" );
  361.             close( STDIN_FILENO );
  362.             close( STDOUT_FILENO );
  363.             close( STDERR_FILENO );
  364.             b_daemon = true;
  365.         }
  366. #endif
  367.     }
  368. #endif
  369.     if( b_exit )
  370.     {
  371.         module_EndBank( p_libvlc, false );
  372.         return i_ret;
  373.     }
  374.     /* Check for translation config option */
  375. #if defined( ENABLE_NLS ) 
  376.      && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
  377. # if defined (WIN32) || defined (__APPLE__)
  378.     /* This ain't really nice to have to reload the config here but it seems
  379.      * the only way to do it. */
  380.     if( !config_GetInt( p_libvlc, "ignore-config" ) )
  381.         config_LoadConfigFile( p_libvlc, "main" );
  382.     config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, true );
  383.     priv->i_verbose = config_GetInt( p_libvlc, "verbose" );
  384.     /* Check if the user specified a custom language */
  385.     psz_language = config_GetPsz( p_libvlc, "language" );
  386.     if( psz_language && *psz_language && strcmp( psz_language, "auto" ) )
  387.     {
  388.         /* Reset the default domain */
  389.         SetLanguage( psz_language );
  390.         /* Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
  391.         msg_Dbg( p_libvlc, "translation test: code is "%s"", _("C") );
  392.         module_EndBank( p_libvlc, false );
  393.         module_InitBank( p_libvlc );
  394.         if( !config_GetInt( p_libvlc, "ignore-config" ) )
  395.             config_LoadConfigFile( p_libvlc, "main" );
  396.         config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, true );
  397.         priv->i_verbose = config_GetInt( p_libvlc, "verbose" );
  398.     }
  399.     free( psz_language );
  400. # endif
  401. #endif
  402.     /*
  403.      * Load the builtins and plugins into the module_bank.
  404.      * We have to do it before config_Load*() because this also gets the
  405.      * list of configuration options exported by each module and loads their
  406.      * default values.
  407.      */
  408.     module_LoadPlugins( p_libvlc, b_cache_delete );
  409.     if( p_libvlc->b_die )
  410.     {
  411.         b_exit = true;
  412.     }
  413.     size_t module_count;
  414.     module_t **list = module_list_get( &module_count );
  415.     module_list_free( list );
  416.     msg_Dbg( p_libvlc, "module bank initialized (%zu modules)", module_count );
  417.     /* Check for help on modules */
  418.     if( (p_tmp = config_GetPsz( p_libvlc, "module" )) )
  419.     {
  420.         Help( p_libvlc, p_tmp );
  421.         free( p_tmp );
  422.         b_exit = true;
  423.         i_ret = VLC_EEXITSUCCESS;
  424.     }
  425.     /* Check for full help option */
  426.     else if( config_GetInt( p_libvlc, "full-help" ) > 0 )
  427.     {
  428.         config_PutInt( p_libvlc, "advanced", 1);
  429.         config_PutInt( p_libvlc, "help-verbose", 1);
  430.         Help( p_libvlc, "full-help" );
  431.         b_exit = true;
  432.         i_ret = VLC_EEXITSUCCESS;
  433.     }
  434.     /* Check for long help option */
  435.     else if( config_GetInt( p_libvlc, "longhelp" ) > 0 )
  436.     {
  437.         Help( p_libvlc, "longhelp" );
  438.         b_exit = true;
  439.         i_ret = VLC_EEXITSUCCESS;
  440.     }
  441.     /* Check for module list option */
  442.     else if( config_GetInt( p_libvlc, "list" ) > 0 )
  443.     {
  444.         ListModules( p_libvlc, false );
  445.         b_exit = true;
  446.         i_ret = VLC_EEXITSUCCESS;
  447.     }
  448.     else if( config_GetInt( p_libvlc, "list-verbose" ) > 0 )
  449.     {
  450.         ListModules( p_libvlc, true );
  451.         b_exit = true;
  452.         i_ret = VLC_EEXITSUCCESS;
  453.     }
  454.     /* Check for config file options */
  455.     if( !config_GetInt( p_libvlc, "ignore-config" ) )
  456.     {
  457.         if( config_GetInt( p_libvlc, "reset-config" ) > 0 )
  458.         {
  459.             config_ResetAll( p_libvlc );
  460.             config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, true );
  461.             config_SaveConfigFile( p_libvlc, NULL );
  462.         }
  463.         if( config_GetInt( p_libvlc, "save-config" ) > 0 )
  464.         {
  465.             config_LoadConfigFile( p_libvlc, NULL );
  466.             config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, true );
  467.             config_SaveConfigFile( p_libvlc, NULL );
  468.         }
  469.     }
  470.     if( b_exit )
  471.     {
  472.         module_EndBank( p_libvlc, true );
  473.         return i_ret;
  474.     }
  475.     /*
  476.      * Init device values
  477.      */
  478.     InitDeviceValues( p_libvlc );
  479.     /*
  480.      * Override default configuration with config file settings
  481.      */
  482.     if( !config_GetInt( p_libvlc, "ignore-config" ) )
  483.         config_LoadConfigFile( p_libvlc, NULL );
  484.     /*
  485.      * Override configuration with command line settings
  486.      */
  487.     if( config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, false ) )
  488.     {
  489. #ifdef WIN32
  490.         ShowConsole( false );
  491.         /* Pause the console because it's destroyed when we exit */
  492.         fprintf( stderr, "The command line options couldn't be loaded, check "
  493.                  "that they are valid.n" );
  494.         PauseConsole();
  495. #endif
  496.         module_EndBank( p_libvlc, true );
  497.         return VLC_EGENERIC;
  498.     }
  499.     priv->i_verbose = config_GetInt( p_libvlc, "verbose" );
  500.     /*
  501.      * System specific configuration
  502.      */
  503.     system_Configure( p_libvlc, &i_argc, ppsz_argv );
  504. /* FIXME: could be replaced by using Unix sockets */
  505. #ifdef HAVE_DBUS
  506.     dbus_threads_init_default();
  507.     if( config_GetInt( p_libvlc, "one-instance" ) > 0
  508.         || ( config_GetInt( p_libvlc, "one-instance-when-started-from-file" )
  509.              && config_GetInt( p_libvlc, "started-from-file" ) ) )
  510.     {
  511.         /* Initialise D-Bus interface, check for other instances */
  512.         DBusConnection  *p_conn = NULL;
  513.         DBusError       dbus_error;
  514.         dbus_error_init( &dbus_error );
  515.         /* connect to the session bus */
  516.         p_conn = dbus_bus_get( DBUS_BUS_SESSION, &dbus_error );
  517.         if( !p_conn )
  518.         {
  519.             msg_Err( p_libvlc, "Failed to connect to D-Bus session daemon: %s",
  520.                     dbus_error.message );
  521.             dbus_error_free( &dbus_error );
  522.         }
  523.         else
  524.         {
  525.             /* check if VLC is available on the bus
  526.              * if not: D-Bus control is not enabled on the other
  527.              * instance and we can't pass MRLs to it */
  528.             DBusMessage *p_test_msg = NULL;
  529.             DBusMessage *p_test_reply = NULL;
  530.             p_test_msg =  dbus_message_new_method_call(
  531.                     "org.mpris.vlc", "/",
  532.                     "org.freedesktop.MediaPlayer", "Identity" );
  533.             /* block until a reply arrives */
  534.             p_test_reply = dbus_connection_send_with_reply_and_block(
  535.                     p_conn, p_test_msg, -1, &dbus_error );
  536.             dbus_message_unref( p_test_msg );
  537.             if( p_test_reply == NULL )
  538.             {
  539.                 dbus_error_free( &dbus_error );
  540.                 msg_Dbg( p_libvlc, "No Media Player is running. "
  541.                         "Continuing normally." );
  542.             }
  543.             else
  544.             {
  545.                 int i_input;
  546.                 DBusMessage* p_dbus_msg = NULL;
  547.                 DBusMessageIter dbus_args;
  548.                 DBusPendingCall* p_dbus_pending = NULL;
  549.                 dbus_bool_t b_play;
  550.                 dbus_message_unref( p_test_reply );
  551.                 msg_Warn( p_libvlc, "Another Media Player is running. Exiting");
  552.                 for( i_input = optind;i_input < i_argc;i_input++ )
  553.                 {
  554.                     msg_Dbg( p_libvlc, "Adds %s to the running Media Player",
  555.                             ppsz_argv[i_input] );
  556.                     p_dbus_msg = dbus_message_new_method_call(
  557.                             "org.mpris.vlc", "/TrackList",
  558.                             "org.freedesktop.MediaPlayer", "AddTrack" );
  559.                     if ( NULL == p_dbus_msg )
  560.                     {
  561.                         msg_Err( p_libvlc, "D-Bus problem" );
  562.                         system_End( p_libvlc );
  563.                         exit( VLC_ETIMEOUT );
  564.                     }
  565.                     /* append MRLs */
  566.                     dbus_message_iter_init_append( p_dbus_msg, &dbus_args );
  567.                     if ( !dbus_message_iter_append_basic( &dbus_args,
  568.                                 DBUS_TYPE_STRING, &ppsz_argv[i_input] ) )
  569.                     {
  570.                         dbus_message_unref( p_dbus_msg );
  571.                         system_End( p_libvlc );
  572.                         exit( VLC_ENOMEM );
  573.                     }
  574.                     b_play = TRUE;
  575.                     if( config_GetInt( p_libvlc, "playlist-enqueue" ) > 0 )
  576.                         b_play = FALSE;
  577.                     if ( !dbus_message_iter_append_basic( &dbus_args,
  578.                                 DBUS_TYPE_BOOLEAN, &b_play ) )
  579.                     {
  580.                         dbus_message_unref( p_dbus_msg );
  581.                         system_End( p_libvlc );
  582.                         exit( VLC_ENOMEM );
  583.                     }
  584.                     /* send message and get a handle for a reply */
  585.                     if ( !dbus_connection_send_with_reply ( p_conn,
  586.                                 p_dbus_msg, &p_dbus_pending, -1 ) )
  587.                     {
  588.                         msg_Err( p_libvlc, "D-Bus problem" );
  589.                         dbus_message_unref( p_dbus_msg );
  590.                         system_End( p_libvlc );
  591.                         exit( VLC_ETIMEOUT );
  592.                     }
  593.                     if ( NULL == p_dbus_pending )
  594.                     {
  595.                         msg_Err( p_libvlc, "D-Bus problem" );
  596.                         dbus_message_unref( p_dbus_msg );
  597.                         system_End( p_libvlc );
  598.                         exit( VLC_ETIMEOUT );
  599.                     }
  600.                     dbus_connection_flush( p_conn );
  601.                     dbus_message_unref( p_dbus_msg );
  602.                     /* block until we receive a reply */
  603.                     dbus_pending_call_block( p_dbus_pending );
  604.                     dbus_pending_call_unref( p_dbus_pending );
  605.                 } /* processes all command line MRLs */
  606.                 /* bye bye */
  607.                 system_End( p_libvlc );
  608.                 exit( VLC_SUCCESS );
  609.             }
  610.         }
  611.         /* we unreference the connection when we've finished with it */
  612.         if( p_conn ) dbus_connection_unref( p_conn );
  613.     }
  614. #endif
  615.     /*
  616.      * Message queue options
  617.      */
  618.     char * psz_verbose_objects = config_GetPsz( p_libvlc, "verbose-objects" );
  619.     if( psz_verbose_objects )
  620.     {
  621.         char * psz_object, * iter = psz_verbose_objects;
  622.         while( (psz_object = strsep( &iter, "," )) )
  623.         {
  624.             switch( psz_object[0] )
  625.             {
  626.                 printf("%sn", psz_object+1);
  627.                 case '+': msg_EnableObjectPrinting(p_libvlc, psz_object+1); break;
  628.                 case '-': msg_DisableObjectPrinting(p_libvlc, psz_object+1); break;
  629.                 default:
  630.                     msg_Err( p_libvlc, "verbose-objects usage: n"
  631.                             "--verbose-objects=+printthatobject,"
  632.                             "-dontprintthatonen"
  633.                             "(keyword 'all' to applies to all objects)");
  634.                     free( psz_verbose_objects );
  635.                     /* FIXME: leaks!!!! */
  636.                     return VLC_EGENERIC;
  637.             }
  638.         }
  639.         free( psz_verbose_objects );
  640.     }
  641.     /* Last chance to set the verbosity. Once we start interfaces and other
  642.      * threads, verbosity becomes read-only. */
  643.     var_Create( p_libvlc, "verbose", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  644.     if( config_GetInt( p_libvlc, "quiet" ) > 0 )
  645.     {
  646.         var_SetInteger( p_libvlc, "verbose", -1 );
  647.         priv->i_verbose = -1;
  648.     }
  649.     vlc_threads_setup( p_libvlc );
  650.     if( priv->b_color )
  651.         priv->b_color = config_GetInt( p_libvlc, "color" ) > 0;
  652.     if( !config_GetInt( p_libvlc, "fpu" ) )
  653.         cpu_flags &= ~CPU_CAPABILITY_FPU;
  654. #if defined( __i386__ ) || defined( __x86_64__ )
  655.     if( !config_GetInt( p_libvlc, "mmx" ) )
  656.         cpu_flags &= ~CPU_CAPABILITY_MMX;
  657.     if( !config_GetInt( p_libvlc, "3dn" ) )
  658.         cpu_flags &= ~CPU_CAPABILITY_3DNOW;
  659.     if( !config_GetInt( p_libvlc, "mmxext" ) )
  660.         cpu_flags &= ~CPU_CAPABILITY_MMXEXT;
  661.     if( !config_GetInt( p_libvlc, "sse" ) )
  662.         cpu_flags &= ~CPU_CAPABILITY_SSE;
  663.     if( !config_GetInt( p_libvlc, "sse2" ) )
  664.         cpu_flags &= ~CPU_CAPABILITY_SSE2;
  665. #endif
  666. #if defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc64__ )
  667.     if( !config_GetInt( p_libvlc, "altivec" ) )
  668.         cpu_flags &= ~CPU_CAPABILITY_ALTIVEC;
  669. #endif
  670. #define PRINT_CAPABILITY( capability, string )                              
  671.     if( vlc_CPU() & capability )                                            
  672.     {                                                                       
  673.         strncat( p_capabilities, string " ",                                
  674.                  sizeof(p_capabilities) - strlen(p_capabilities) );         
  675.         p_capabilities[sizeof(p_capabilities) - 1] = '';                  
  676.     }
  677.     p_capabilities[0] = '';
  678.     PRINT_CAPABILITY( CPU_CAPABILITY_486, "486" );
  679.     PRINT_CAPABILITY( CPU_CAPABILITY_586, "586" );
  680.     PRINT_CAPABILITY( CPU_CAPABILITY_PPRO, "Pentium Pro" );
  681.     PRINT_CAPABILITY( CPU_CAPABILITY_MMX, "MMX" );
  682.     PRINT_CAPABILITY( CPU_CAPABILITY_3DNOW, "3DNow!" );
  683.     PRINT_CAPABILITY( CPU_CAPABILITY_MMXEXT, "MMXEXT" );
  684.     PRINT_CAPABILITY( CPU_CAPABILITY_SSE, "SSE" );
  685.     PRINT_CAPABILITY( CPU_CAPABILITY_SSE2, "SSE2" );
  686.     PRINT_CAPABILITY( CPU_CAPABILITY_ALTIVEC, "AltiVec" );
  687.     PRINT_CAPABILITY( CPU_CAPABILITY_FPU, "FPU" );
  688.     msg_Dbg( p_libvlc, "CPU has capabilities %s", p_capabilities );
  689.     /*
  690.      * Choose the best memcpy module
  691.      */
  692.     priv->p_memcpy_module = module_need( p_libvlc, "memcpy", "$memcpy", false );
  693.     priv->b_stats = config_GetInt( p_libvlc, "stats" ) > 0;
  694.     priv->i_timers = 0;
  695.     priv->pp_timers = NULL;
  696.     priv->i_last_input_id = 0; /* Not very safe, should be removed */
  697.     /*
  698.      * Initialize hotkey handling
  699.      */
  700.     var_Create( p_libvlc, "key-pressed", VLC_VAR_INTEGER );
  701.     var_Create( p_libvlc, "key-action", VLC_VAR_INTEGER );
  702.     {
  703.         struct hotkey *p_keys =
  704.             malloc( (libvlc_actions_count + 1) * sizeof (*p_keys) );
  705. /* Initialize from configuration */
  706.         for( size_t i = 0; i < libvlc_actions_count; i++ )
  707.         {
  708.             p_keys[i].psz_action = libvlc_actions[i].name;
  709.             p_keys[i].i_key = config_GetInt( p_libvlc,
  710.                                              libvlc_actions[i].name );
  711.             p_keys[i].i_action = libvlc_actions[i].value;
  712.         }
  713.         p_keys[libvlc_actions_count].psz_action = NULL;
  714.         p_keys[libvlc_actions_count].i_key = 0;
  715.         p_keys[libvlc_actions_count].i_action = 0;
  716.         p_libvlc->p_hotkeys = p_keys;
  717.         var_AddCallback( p_libvlc, "key-pressed", vlc_key_to_action,
  718.                          p_keys );
  719.     }
  720.     /* Initialize playlist and get commandline files */
  721.     p_playlist = playlist_Create( VLC_OBJECT(p_libvlc) );
  722.     if( !p_playlist )
  723.     {
  724.         msg_Err( p_libvlc, "playlist initialization failed" );
  725.         if( priv->p_memcpy_module != NULL )
  726.         {
  727.             module_unneed( p_libvlc, priv->p_memcpy_module );
  728.         }
  729.         module_EndBank( p_libvlc, true );
  730.         return VLC_EGENERIC;
  731.     }
  732.     playlist_Activate( p_playlist );
  733.     vlc_object_attach( p_playlist, p_libvlc );
  734.     /* Add service discovery modules */
  735.     psz_modules = config_GetPsz( p_playlist, "services-discovery" );
  736.     if( psz_modules && *psz_modules )
  737.     {
  738.         char *p = psz_modules, *m;
  739.         while( ( m = strsep( &p, " :," ) ) != NULL )
  740.             playlist_ServicesDiscoveryAdd( p_playlist, m );
  741.     }
  742.     free( psz_modules );
  743. #ifdef ENABLE_VLM
  744.     /* Initialize VLM if vlm-conf is specified */
  745.     psz_parser = config_GetPsz( p_libvlc, "vlm-conf" );
  746.     if( psz_parser && *psz_parser )
  747.     {
  748.         priv->p_vlm = vlm_New( p_libvlc );
  749.         if( !priv->p_vlm )
  750.             msg_Err( p_libvlc, "VLM initialization failed" );
  751.     }
  752.     free( psz_parser );
  753. #endif
  754.     /*
  755.      * Load background interfaces
  756.      */
  757.     psz_modules = config_GetPsz( p_libvlc, "extraintf" );
  758.     psz_control = config_GetPsz( p_libvlc, "control" );
  759.     if( psz_modules && *psz_modules && psz_control && *psz_control )
  760.     {
  761.         char* psz_tmp;
  762.         if( asprintf( &psz_tmp, "%s:%s", psz_modules, psz_control ) != -1 )
  763.         {
  764.             free( psz_modules );
  765.             psz_modules = psz_tmp;
  766.         }
  767.     }
  768.     else if( psz_control && *psz_control )
  769.     {
  770.         free( psz_modules );
  771.         psz_modules = strdup( psz_control );
  772.     }
  773.     psz_parser = psz_modules;
  774.     while ( psz_parser && *psz_parser )
  775.     {
  776.         char *psz_module, *psz_temp;
  777.         psz_module = psz_parser;
  778.         psz_parser = strchr( psz_module, ':' );
  779.         if ( psz_parser )
  780.         {
  781.             *psz_parser = '';
  782.             psz_parser++;
  783.         }
  784.         if( asprintf( &psz_temp, "%s,none", psz_module ) != -1)
  785.         {
  786.             libvlc_InternalAddIntf( p_libvlc, psz_temp );
  787.             free( psz_temp );
  788.         }
  789.     }
  790.     free( psz_modules );
  791.     free( psz_control );
  792.     /*
  793.      * Always load the hotkeys interface if it exists
  794.      */
  795.     libvlc_InternalAddIntf( p_libvlc, "hotkeys,none" );
  796. #ifdef HAVE_DBUS
  797.     /* loads dbus control interface if in one-instance mode
  798.      * we do it only when playlist exists, because dbus module needs it */
  799.     if( config_GetInt( p_libvlc, "one-instance" ) > 0
  800.         || ( config_GetInt( p_libvlc, "one-instance-when-started-from-file" )
  801.              && config_GetInt( p_libvlc, "started-from-file" ) ) )
  802.         libvlc_InternalAddIntf( p_libvlc, "dbus,none" );
  803.     /* Prevents the power management daemon from suspending the system
  804.      * when VLC is active */
  805.     if( config_GetInt( p_libvlc, "inhibit" ) > 0 )
  806.         libvlc_InternalAddIntf( p_libvlc, "inhibit,none" );
  807. #endif
  808.     /*
  809.      * If needed, load the Xscreensaver interface
  810.      * Currently, only for X
  811.      */
  812. #ifdef HAVE_X11_XLIB_H
  813.     if( config_GetInt( p_libvlc, "disable-screensaver" ) )
  814.     {
  815.         libvlc_InternalAddIntf( p_libvlc, "screensaver,none" );
  816.     }
  817. #endif
  818.     if( (config_GetInt( p_libvlc, "file-logging" ) > 0) &&
  819.         !config_GetInt( p_libvlc, "syslog" ) )
  820.     {
  821.         libvlc_InternalAddIntf( p_libvlc, "logger,none" );
  822.     }
  823. #ifdef HAVE_SYSLOG_H
  824.     if( config_GetInt( p_libvlc, "syslog" ) > 0 )
  825.     {
  826.         char *logmode = var_CreateGetString( p_libvlc, "logmode" );
  827.         var_SetString( p_libvlc, "logmode", "syslog" );
  828.         libvlc_InternalAddIntf( p_libvlc, "logger,none" );
  829.         if( logmode )
  830.         {
  831.             var_SetString( p_libvlc, "logmode", logmode );
  832.             free( logmode );
  833.         }
  834.         else
  835.             var_Destroy( p_libvlc, "logmode" );
  836.     }
  837. #endif
  838.     if( config_GetInt( p_libvlc, "show-intf" ) > 0 )
  839.     {
  840.         libvlc_InternalAddIntf( p_libvlc, "showintf,none" );
  841.     }
  842.     if( config_GetInt( p_libvlc, "network-synchronisation") > 0 )
  843.     {
  844.         libvlc_InternalAddIntf( p_libvlc, "netsync,none" );
  845.     }
  846. #ifdef WIN32
  847.     if( config_GetInt( p_libvlc, "prefer-system-codecs") > 0 )
  848.     {
  849.         char *psz_codecs = config_GetPsz( p_playlist, "codec" );
  850.         if( psz_codecs )
  851.         {
  852.             char *psz_morecodecs;
  853.             if( asprintf(&psz_morecodecs, "%s,dmo,quicktime", psz_codecs) != -1 )
  854.             {
  855.                 config_PutPsz( p_libvlc, "codec", psz_morecodecs);
  856.                 free( psz_morecodecs );
  857.             }
  858.         }
  859.         else
  860.             config_PutPsz( p_libvlc, "codec", "dmo,quicktime");
  861.         free( psz_codecs );
  862.     }
  863. #endif
  864.     /*
  865.      * FIXME: kludge to use a p_libvlc-local variable for the Mozilla plugin
  866.      */
  867.     var_Create( p_libvlc, "drawable-xid", VLC_VAR_DOINHERIT|VLC_VAR_INTEGER );
  868.     var_Create( p_libvlc, "drawable-hwnd", VLC_VAR_ADDRESS );
  869.     var_Create( p_libvlc, "drawable-agl", VLC_VAR_INTEGER );
  870.     var_Create( p_libvlc, "drawable-gl", VLC_VAR_INTEGER );
  871.     var_Create( p_libvlc, "drawable-view-top", VLC_VAR_INTEGER );
  872.     var_Create( p_libvlc, "drawable-view-left", VLC_VAR_INTEGER );
  873.     var_Create( p_libvlc, "drawable-view-bottom", VLC_VAR_INTEGER );
  874.     var_Create( p_libvlc, "drawable-view-right", VLC_VAR_INTEGER );
  875.     var_Create( p_libvlc, "drawable-clip-top", VLC_VAR_INTEGER );
  876.     var_Create( p_libvlc, "drawable-clip-left", VLC_VAR_INTEGER );
  877.     var_Create( p_libvlc, "drawable-clip-bottom", VLC_VAR_INTEGER );
  878.     var_Create( p_libvlc, "drawable-clip-right", VLC_VAR_INTEGER );
  879.     /* Create volume callback system. */
  880.     var_Create( p_libvlc, "volume-change", VLC_VAR_BOOL );
  881.     /* Create a variable for showing the interface (moved from playlist). */
  882.     var_Create( p_libvlc, "intf-show", VLC_VAR_BOOL );
  883.     var_SetBool( p_libvlc, "intf-show", true );
  884.     var_Create( p_libvlc, "intf-popupmenu", VLC_VAR_BOOL );
  885.     /*
  886.      * Get input filenames given as commandline arguments
  887.      */
  888.     GetFilenames( p_libvlc, i_argc, ppsz_argv );
  889.     /*
  890.      * Get --open argument
  891.      */
  892.     var_Create( p_libvlc, "open", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
  893.     var_Get( p_libvlc, "open", &val );
  894.     if ( val.psz_string != NULL && *val.psz_string )
  895.     {
  896.         playlist_t *p_playlist = pl_Hold( p_libvlc );
  897.         playlist_AddExt( p_playlist, val.psz_string, NULL, PLAYLIST_INSERT, 0,
  898.                          -1, 0, NULL, 0, true, pl_Unlocked );
  899.         pl_Release( p_libvlc );
  900.     }
  901.     free( val.psz_string );
  902.     return VLC_SUCCESS;
  903. }
  904. /**
  905.  * Cleanup a libvlc instance. The instance is not completely deallocated
  906.  * param p_libvlc the instance to clean
  907.  */
  908. void libvlc_InternalCleanup( libvlc_int_t *p_libvlc )
  909. {
  910.     libvlc_priv_t *priv = libvlc_priv (p_libvlc);
  911.     playlist_t    *p_playlist = priv->p_playlist;
  912.     /* Deactivate the playlist */
  913.     msg_Dbg( p_libvlc, "deactivating the playlist" );
  914.     playlist_Deactivate( p_playlist );
  915.     /* Remove all services discovery */
  916.     msg_Dbg( p_libvlc, "removing all services discovery tasks" );
  917.     playlist_ServicesDiscoveryKillAll( p_playlist );
  918.     /* Ask the interfaces to stop and destroy them */
  919.     msg_Dbg( p_libvlc, "removing all interfaces" );
  920.     intf_thread_t *p_intf;
  921.     while( (p_intf = vlc_object_find( p_libvlc, VLC_OBJECT_INTF, FIND_CHILD )) )
  922.     {
  923.         intf_StopThread( p_intf );
  924.         vlc_object_detach( p_intf );
  925.         vlc_object_release( p_intf ); /* for intf_Create() */
  926.         vlc_object_release( p_intf ); /* for vlc_object_find() */
  927.     }
  928. #ifdef ENABLE_VLM
  929.     /* Destroy VLM if created in libvlc_InternalInit */
  930.     if( priv->p_vlm )
  931.     {
  932.         vlm_Delete( priv->p_vlm );
  933.     }
  934. #endif
  935.     /* Free playlist */
  936.     /* Any thread still running must not assume pl_Hold() succeeds. */
  937.     msg_Dbg( p_libvlc, "removing playlist" );
  938.     libvlc_priv(p_playlist->p_libvlc)->p_playlist = NULL;
  939.     barrier();  /* FIXME is that correct ? */
  940.     vlc_object_release( p_playlist );
  941.     stats_TimersDumpAll( p_libvlc );
  942.     stats_TimersCleanAll( p_libvlc );
  943.     msg_Dbg( p_libvlc, "removing stats" );
  944. #ifndef WIN32
  945.     char* psz_pidfile = NULL;
  946.     if( b_daemon )
  947.     {
  948.         psz_pidfile = config_GetPsz( p_libvlc, "pidfile" );
  949.         if( psz_pidfile != NULL )
  950.         {
  951.             msg_Dbg( p_libvlc, "removing pid file %s", psz_pidfile );
  952.             if( unlink( psz_pidfile ) == -1 )
  953.             {
  954.                 msg_Dbg( p_libvlc, "removing pid file %s: %m",
  955.                         psz_pidfile );
  956.             }
  957.         }
  958.         free( psz_pidfile );
  959.     }
  960. #endif
  961.     if( priv->p_memcpy_module )
  962.     {
  963.         module_unneed( p_libvlc, priv->p_memcpy_module );
  964.         priv->p_memcpy_module = NULL;
  965.     }
  966.     /* Free module bank. It is refcounted, so we call this each time  */
  967.     module_EndBank( p_libvlc, true );
  968.     var_DelCallback( p_libvlc, "key-pressed", vlc_key_to_action,
  969.                      (void *)p_libvlc->p_hotkeys );
  970.     free( (void *)p_libvlc->p_hotkeys );
  971. }
  972. /**
  973.  * Destroy everything.
  974.  * This function requests the running threads to finish, waits for their
  975.  * termination, and destroys their structure.
  976.  * It stops the thread systems: no instance can run after this has run
  977.  * param p_libvlc the instance to destroy
  978.  */
  979. void libvlc_InternalDestroy( libvlc_int_t *p_libvlc )
  980. {
  981.     libvlc_priv_t *priv = libvlc_priv( p_libvlc );
  982.     vlc_mutex_lock( &global_lock );
  983.     i_instances--;
  984.     if( i_instances == 0 )
  985.     {
  986.         /* System specific cleaning code */
  987.         system_End( p_libvlc );
  988.     }
  989.     vlc_mutex_unlock( &global_lock );
  990.     msg_Destroy( p_libvlc );
  991.     /* Destroy mutexes */
  992.     vlc_cond_destroy( &priv->exiting );
  993.     vlc_mutex_destroy( &priv->timer_lock );
  994. #ifndef NDEBUG /* Hack to dump leaked objects tree */
  995.     if( vlc_internals( p_libvlc )->i_refcount > 1 )
  996.         while( vlc_internals( p_libvlc )->i_refcount > 0 )
  997.             vlc_object_release( p_libvlc );
  998. #endif
  999.     assert( vlc_internals( p_libvlc )->i_refcount == 1 );
  1000.     vlc_object_release( p_libvlc );
  1001. }
  1002. /**
  1003.  * Add an interface plugin and run it
  1004.  */
  1005. int libvlc_InternalAddIntf( libvlc_int_t *p_libvlc, char const *psz_module )
  1006. {
  1007.     int i_err;
  1008.     intf_thread_t *p_intf = NULL;
  1009.     if( !p_libvlc )
  1010.         return VLC_EGENERIC;
  1011.     if( !psz_module ) /* requesting the default interface */
  1012.     {
  1013.         char *psz_interface = config_GetPsz( p_libvlc, "intf" );
  1014.         if( !psz_interface || !*psz_interface ) /* "intf" has not been set */
  1015.         {
  1016. #ifndef WIN32
  1017.             if( b_daemon )
  1018.                  /* Daemon mode hack.
  1019.                   * We prefer the dummy interface if none is specified. */
  1020.                 psz_module = "dummy";
  1021.             else
  1022. #endif
  1023.                 msg_Info( p_libvlc, "%s",
  1024.                           _("Running vlc with the default interface. "
  1025.                             "Use 'cvlc' to use vlc without interface.") );
  1026.         }
  1027.         free( psz_interface );
  1028.     }
  1029.     /* Try to create the interface */
  1030.     p_intf = intf_Create( p_libvlc, psz_module ? psz_module : "$intf" );
  1031.     if( p_intf == NULL )
  1032.     {
  1033.         msg_Err( p_libvlc, "interface "%s" initialization failed",
  1034.                  psz_module ? psz_module : "default" );
  1035.         return VLC_EGENERIC;
  1036.     }
  1037.     /* Try to run the interface */
  1038.     i_err = intf_RunThread( p_intf );
  1039.     if( i_err )
  1040.     {
  1041.         vlc_object_detach( p_intf );
  1042.         vlc_object_release( p_intf );
  1043.         return i_err;
  1044.     }
  1045.     return VLC_SUCCESS;
  1046. };
  1047. static vlc_mutex_t exit_lock = VLC_STATIC_MUTEX;
  1048. /**
  1049.  * Waits until the LibVLC instance gets an exit signal. Normally, this happens
  1050.  * when the user "exits" an interface plugin.
  1051.  */
  1052. void libvlc_InternalWait( libvlc_int_t *p_libvlc )
  1053. {
  1054.     libvlc_priv_t *priv = libvlc_priv( p_libvlc );
  1055.     vlc_mutex_lock( &exit_lock );
  1056.     while( vlc_object_alive( p_libvlc ) )
  1057.         vlc_cond_wait( &priv->exiting, &exit_lock );
  1058.     vlc_mutex_unlock( &exit_lock );
  1059. }
  1060. /**
  1061.  * Posts an exit signal to LibVLC instance. This will normally initiate the
  1062.  * cleanup and destroy process. It should only be called on behalf of the user.
  1063.  */
  1064. void libvlc_Quit( libvlc_int_t *p_libvlc )
  1065. {
  1066.     libvlc_priv_t *priv = libvlc_priv( p_libvlc );
  1067.     vlc_mutex_lock( &exit_lock );
  1068.     vlc_object_kill( p_libvlc );
  1069.     vlc_cond_signal( &priv->exiting );
  1070.     vlc_mutex_unlock( &exit_lock );
  1071. }
  1072. #if defined( ENABLE_NLS ) && (defined (__APPLE__) || defined (WIN32)) && 
  1073.     ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
  1074. /*****************************************************************************
  1075.  * SetLanguage: set the interface language.
  1076.  *****************************************************************************
  1077.  * We set the LC_MESSAGES locale category for interface messages and buttons,
  1078.  * as well as the LC_CTYPE category for string sorting and possible wide
  1079.  * character support.
  1080.  *****************************************************************************/
  1081. static void SetLanguage ( const char *psz_lang )
  1082. {
  1083. #ifdef __APPLE__
  1084.     /* I need that under Darwin, please check it doesn't disturb
  1085.      * other platforms. --Meuuh */
  1086.     setenv( "LANG", psz_lang, 1 );
  1087. #else
  1088.     /* We set LC_ALL manually because it is the only way to set
  1089.      * the language at runtime under eg. Windows. Beware that this
  1090.      * makes the environment unconsistent when libvlc is unloaded and
  1091.      * should probably be moved to a safer place like vlc.c. */
  1092.     static char psz_lcall[20];
  1093.     snprintf( psz_lcall, 19, "LC_ALL=%s", psz_lang );
  1094.     psz_lcall[19] = '';
  1095.     putenv( psz_lcall );
  1096. #endif
  1097.     setlocale( LC_ALL, psz_lang );
  1098. }
  1099. #endif
  1100. static inline int LoadMessages (void)
  1101. {
  1102. #if defined( ENABLE_NLS ) 
  1103.      && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
  1104.     /* Specify where to find the locales for current domain */
  1105. #if !defined( __APPLE__ ) && !defined( WIN32 ) && !defined( SYS_BEOS )
  1106.     static const char psz_path[] = LOCALEDIR;
  1107. #else
  1108.     char psz_path[1024];
  1109.     if (snprintf (psz_path, sizeof (psz_path), "%s" DIR_SEP "%s",
  1110.                   config_GetDataDir(), "locale")
  1111.                      >= (int)sizeof (psz_path))
  1112.         return -1;
  1113. #endif
  1114.     if (bindtextdomain (PACKAGE_NAME, psz_path) == NULL)
  1115.     {
  1116.         fprintf (stderr, "Warning: cannot bind text domain "PACKAGE_NAME
  1117.                          " to directory %sn", psz_path);
  1118.         return -1;
  1119.     }
  1120.     /* LibVLC wants all messages in UTF-8.
  1121.      * Unfortunately, we cannot ask UTF-8 for strerror_r(), strsignal_r()
  1122.      * and other functions that are not part of our text domain.
  1123.      */
  1124.     if (bind_textdomain_codeset (PACKAGE_NAME, "UTF-8") == NULL)
  1125.     {
  1126.         fprintf (stderr, "Error: cannot set Unicode encoding for text domain "
  1127.                          PACKAGE_NAME"n");
  1128.         // Unbinds the text domain to avoid broken encoding
  1129.         bindtextdomain (PACKAGE_NAME, "DOES_NOT_EXIST");
  1130.         return -1;
  1131.     }
  1132.     /* LibVLC does NOT set the default textdomain, since it is a library.
  1133.      * This could otherwise break programs using LibVLC (other than VLC).
  1134.      * textdomain (PACKAGE_NAME);
  1135.      */
  1136. #endif
  1137.     return 0;
  1138. }
  1139. /*****************************************************************************
  1140.  * GetFilenames: parse command line options which are not flags
  1141.  *****************************************************************************
  1142.  * Parse command line for input files as well as their associated options.
  1143.  * An option always follows its associated input and begins with a ":".
  1144.  *****************************************************************************/
  1145. static int GetFilenames( libvlc_int_t *p_vlc, int i_argc, const char *ppsz_argv[] )
  1146. {
  1147.     int i_opt, i_options;
  1148.     /* We assume that the remaining parameters are filenames
  1149.      * and their input options */
  1150.     for( i_opt = i_argc - 1; i_opt >= optind; i_opt-- )
  1151.     {
  1152.         i_options = 0;
  1153.         /* Count the input options */
  1154.         while( *ppsz_argv[ i_opt ] == ':' && i_opt > optind )
  1155.         {
  1156.             i_options++;
  1157.             i_opt--;
  1158.         }
  1159.         /* TODO: write an internal function of this one, to avoid
  1160.          *       unnecessary lookups. */
  1161.         playlist_t *p_playlist = pl_Hold( p_vlc );
  1162.         playlist_AddExt( p_playlist, ppsz_argv[i_opt], NULL, PLAYLIST_INSERT,
  1163.                          0, -1,
  1164.                          i_options, ( i_options ? &ppsz_argv[i_opt + 1] : NULL ), VLC_INPUT_OPTION_TRUSTED,
  1165.                          true, pl_Unlocked );
  1166.         pl_Release( p_vlc );
  1167.     }
  1168.     return VLC_SUCCESS;
  1169. }
  1170. /*****************************************************************************
  1171.  * Help: print program help
  1172.  *****************************************************************************
  1173.  * Print a short inline help. Message interface is initialized at this stage.
  1174.  *****************************************************************************/
  1175. static inline void print_help_on_full_help( void )
  1176. {
  1177.     utf8_fprintf( stdout, "n" );
  1178.     utf8_fprintf( stdout, "%sn", _("To get exhaustive help, use '-H'.") );
  1179. }
  1180. static void Help( libvlc_int_t *p_this, char const *psz_help_name )
  1181. {
  1182. #ifdef WIN32
  1183.     ShowConsole( true );
  1184. #endif
  1185.     if( psz_help_name && !strcmp( psz_help_name, "help" ) )
  1186.     {
  1187.         utf8_fprintf( stdout, vlc_usage, "vlc" );
  1188.         Usage( p_this, "=help" );
  1189.         Usage( p_this, "=main" );
  1190.         print_help_on_full_help();
  1191.     }
  1192.     else if( psz_help_name && !strcmp( psz_help_name, "longhelp" ) )
  1193.     {
  1194.         utf8_fprintf( stdout, vlc_usage, "vlc" );
  1195.         Usage( p_this, NULL );
  1196.         print_help_on_full_help();
  1197.     }
  1198.     else if( psz_help_name && !strcmp( psz_help_name, "full-help" ) )
  1199.     {
  1200.         utf8_fprintf( stdout, vlc_usage, "vlc" );
  1201.         Usage( p_this, NULL );
  1202.     }
  1203.     else if( psz_help_name )
  1204.     {
  1205.         Usage( p_this, psz_help_name );
  1206.     }
  1207. #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
  1208.     PauseConsole();
  1209. #endif
  1210. }
  1211. /*****************************************************************************
  1212.  * Usage: print module usage
  1213.  *****************************************************************************
  1214.  * Print a short inline help. Message interface is initialized at this stage.
  1215.  *****************************************************************************/
  1216. #   define COL(x)  "33[" #x ";1m"
  1217. #   define RED     COL(31)
  1218. #   define GREEN   COL(32)
  1219. #   define YELLOW  COL(33)
  1220. #   define BLUE    COL(34)
  1221. #   define MAGENTA COL(35)
  1222. #   define CYAN    COL(36)
  1223. #   define WHITE   COL(0)
  1224. #   define GRAY    "33[0m"
  1225. static void print_help_section( module_config_t *p_item, bool b_color, bool b_description )
  1226. {
  1227.     if( !p_item ) return;
  1228.     if( b_color )
  1229.     {
  1230.         utf8_fprintf( stdout, RED"   %s:n"GRAY,
  1231.                       p_item->psz_text );
  1232.         if( b_description && p_item->psz_longtext )
  1233.             utf8_fprintf( stdout, MAGENTA"   %sn"GRAY,
  1234.                           p_item->psz_longtext );
  1235.     }
  1236.     else
  1237.     {
  1238.         utf8_fprintf( stdout, "   %s:n", p_item->psz_text );
  1239.         if( b_description && p_item->psz_longtext )
  1240.             utf8_fprintf( stdout, "   %sn", p_item->psz_longtext );
  1241.     }
  1242. }
  1243. static void Usage( libvlc_int_t *p_this, char const *psz_search )
  1244. {
  1245. #define FORMAT_STRING "  %s --%s%s%s%s%s%s%s "
  1246.     /* short option ------'    | | | | | | |
  1247.      * option name ------------' | | | | | |
  1248.      * <bra ---------------------' | | | | |
  1249.      * option type or "" ----------' | | | |
  1250.      * ket> -------------------------' | | |
  1251.      * padding spaces -----------------' | |
  1252.      * comment --------------------------' |
  1253.      * comment suffix ---------------------'
  1254.      *
  1255.      * The purpose of having bra and ket is that we might i18n them as well.
  1256.      */
  1257. #define COLOR_FORMAT_STRING (WHITE"  %s --%s"YELLOW"%s%s%s%s%s%s "GRAY)
  1258. #define COLOR_FORMAT_STRING_BOOL (WHITE"  %s --%s%s%s%s%s%s%s "GRAY)
  1259. #define LINE_START 8
  1260. #define PADDING_SPACES 25
  1261. #ifdef WIN32
  1262. #   define OPTION_VALUE_SEP "="
  1263. #else
  1264. #   define OPTION_VALUE_SEP " "
  1265. #endif
  1266.     char psz_spaces_text[PADDING_SPACES+LINE_START+1];
  1267.     char psz_spaces_longtext[LINE_START+3];
  1268.     char psz_format[sizeof(COLOR_FORMAT_STRING)];
  1269.     char psz_format_bool[sizeof(COLOR_FORMAT_STRING_BOOL)];
  1270.     char psz_buffer[10000];
  1271.     char psz_short[4];
  1272.     int i_width = ConsoleWidth() - (PADDING_SPACES+LINE_START+1);
  1273.     int i_width_description = i_width + PADDING_SPACES - 1;
  1274.     bool b_advanced    = config_GetInt( p_this, "advanced" ) > 0;
  1275.     bool b_description = config_GetInt( p_this, "help-verbose" ) > 0;
  1276.     bool b_description_hack;
  1277.     bool b_color       = config_GetInt( p_this, "color" ) > 0;
  1278.     bool b_has_advanced = false;
  1279.     bool b_found       = false;
  1280.     int  i_only_advanced = 0; /* Number of modules ignored because they
  1281.                                * only have advanced options */
  1282.     bool b_strict = psz_search && *psz_search == '=';
  1283.     if( b_strict ) psz_search++;
  1284.     memset( psz_spaces_text, ' ', PADDING_SPACES+LINE_START );
  1285.     psz_spaces_text[PADDING_SPACES+LINE_START] = '';
  1286.     memset( psz_spaces_longtext, ' ', LINE_START+2 );
  1287.     psz_spaces_longtext[LINE_START+2] = '';
  1288. #ifndef WIN32
  1289.     if( !isatty( 1 ) )
  1290. #endif
  1291.         b_color = false; // don't put color control codes in a .txt file
  1292.     if( b_color )
  1293.     {
  1294.         strcpy( psz_format, COLOR_FORMAT_STRING );
  1295.         strcpy( psz_format_bool, COLOR_FORMAT_STRING_BOOL );
  1296.     }
  1297.     else
  1298.     {
  1299.         strcpy( psz_format, FORMAT_STRING );
  1300.         strcpy( psz_format_bool, FORMAT_STRING );
  1301.     }
  1302.     /* List all modules */
  1303.     module_t **list = module_list_get (NULL);
  1304.     if (!list)
  1305.         return;
  1306.     /* Ugly hack to make sure that the help options always come first
  1307.      * (part 1) */
  1308.     if( !psz_search )
  1309.         Usage( p_this, "help" );
  1310.     /* Enumerate the config for each module */
  1311.     for (size_t i = 0; list[i]; i++)
  1312.     {
  1313.         bool b_help_module;
  1314.         module_t *p_parser = list[i];
  1315.         module_config_t *p_item = NULL;
  1316.         module_config_t *p_section = NULL;
  1317.         module_config_t *p_end = p_parser->p_config + p_parser->confsize;
  1318.         if( psz_search &&
  1319.             ( b_strict ? strcmp( psz_search, p_parser->psz_object_name )
  1320.                        : !strstr( p_parser->psz_object_name, psz_search ) ) )
  1321.         {
  1322.             char *const *pp_shortcut = p_parser->pp_shortcuts;
  1323.             while( *pp_shortcut )
  1324.             {
  1325.                 if( b_strict ? !strcmp( psz_search, *pp_shortcut )
  1326.                              : !!strstr( *pp_shortcut, psz_search ) )
  1327.                     break;
  1328.                 pp_shortcut ++;
  1329.             }
  1330.             if( !*pp_shortcut )
  1331.                 continue;
  1332.         }
  1333.         /* Ignore modules without config options */
  1334.         if( !p_parser->i_config_items )
  1335.         {
  1336.             continue;
  1337.         }
  1338.         b_help_module = !strcmp( "help", p_parser->psz_object_name );
  1339.         /* Ugly hack to make sure that the help options always come first
  1340.          * (part 2) */
  1341.         if( !psz_search && b_help_module )
  1342.             continue;
  1343.         /* Ignore modules with only advanced config options if requested */
  1344.         if( !b_advanced )
  1345.         {
  1346.             for( p_item = p_parser->p_config;
  1347.                  p_item < p_end;
  1348.                  p_item++ )
  1349.             {
  1350.                 if( (p_item->i_type & CONFIG_ITEM) &&
  1351.                     !p_item->b_advanced && !p_item->b_removed ) break;
  1352.             }
  1353.             if( p_item == p_end )
  1354.             {
  1355.                 i_only_advanced++;
  1356.                 continue;
  1357.             }
  1358.         }
  1359.         b_found = true;
  1360.         /* Print name of module */
  1361.         if( strcmp( "main", p_parser->psz_object_name ) )
  1362.         {
  1363.             if( b_color )
  1364.                 utf8_fprintf( stdout, "n " GREEN "%s" GRAY " (%s)n",
  1365.                               p_parser->psz_longname,
  1366.                                p_parser->psz_object_name );
  1367.             else
  1368.                 utf8_fprintf( stdout, "n %sn", p_parser->psz_longname );
  1369.         }
  1370.         if( p_parser->psz_help )
  1371.         {
  1372.             if( b_color )
  1373.                 utf8_fprintf( stdout, CYAN" %sn"GRAY, p_parser->psz_help );
  1374.             else
  1375.                 utf8_fprintf( stdout, " %sn", p_parser->psz_help );
  1376.         }
  1377.         /* Print module options */
  1378.         for( p_item = p_parser->p_config;
  1379.              p_item < p_end;
  1380.              p_item++ )
  1381.         {
  1382.             char *psz_text, *psz_spaces = psz_spaces_text;
  1383.             const char *psz_bra = NULL, *psz_type = NULL, *psz_ket = NULL;
  1384.             const char *psz_suf = "", *psz_prefix = NULL;
  1385.             signed int i;
  1386.             size_t i_cur_width;
  1387.             /* Skip removed options */
  1388.             if( p_item->b_removed )
  1389.             {
  1390.                 continue;
  1391.             }
  1392.             /* Skip advanced options if requested */
  1393.             if( p_item->b_advanced && !b_advanced )
  1394.             {
  1395.                 b_has_advanced = true;
  1396.                 continue;
  1397.             }
  1398.             switch( p_item->i_type )
  1399.             {
  1400.             case CONFIG_HINT_CATEGORY:
  1401.             case CONFIG_HINT_USAGE:
  1402.                 if( !strcmp( "main", p_parser->psz_object_name ) )
  1403.                 {
  1404.                     if( b_color )
  1405.                         utf8_fprintf( stdout, GREEN "n %sn" GRAY,
  1406.                                       p_item->psz_text );
  1407.                     else
  1408.                         utf8_fprintf( stdout, "n %sn", p_item->psz_text );
  1409.                 }
  1410.                 if( b_description && p_item->psz_longtext )
  1411.                 {
  1412.                     if( b_color )
  1413.                         utf8_fprintf( stdout, CYAN " %sn" GRAY,
  1414.                                       p_item->psz_longtext );
  1415.                     else
  1416.                         utf8_fprintf( stdout, " %sn", p_item->psz_longtext );
  1417.                 }
  1418.                 break;
  1419.             case CONFIG_HINT_SUBCATEGORY:
  1420.                 if( strcmp( "main", p_parser->psz_object_name ) )
  1421.                     break;
  1422.             case CONFIG_SECTION:
  1423.                 p_section = p_item;
  1424.                 break;
  1425.             case CONFIG_ITEM_STRING:
  1426.             case CONFIG_ITEM_FILE:
  1427.             case CONFIG_ITEM_DIRECTORY:
  1428.             case CONFIG_ITEM_MODULE: /* We could also have "=<" here */
  1429.             case CONFIG_ITEM_MODULE_CAT:
  1430.             case CONFIG_ITEM_MODULE_LIST:
  1431.             case CONFIG_ITEM_MODULE_LIST_CAT:
  1432.             case CONFIG_ITEM_FONT:
  1433.             case CONFIG_ITEM_PASSWORD:
  1434.                 print_help_section( p_section, b_color, b_description );
  1435.                 p_section = NULL;
  1436.                 psz_bra = OPTION_VALUE_SEP "<";
  1437.                 psz_type = _("string");
  1438.                 psz_ket = ">";
  1439.                 if( p_item->ppsz_list )
  1440.                 {
  1441.                     psz_bra = OPTION_VALUE_SEP "{";
  1442.                     psz_type = psz_buffer;
  1443.                     psz_buffer[0] = '';
  1444.                     for( i = 0; p_item->ppsz_list[i]; i++ )
  1445.                     {
  1446.                         if( i ) strcat( psz_buffer, "," );
  1447.                         strcat( psz_buffer, p_item->ppsz_list[i] );
  1448.                     }
  1449.                     psz_ket = "}";
  1450.                 }
  1451.                 break;
  1452.             case CONFIG_ITEM_INTEGER:
  1453.             case CONFIG_ITEM_KEY: /* FIXME: do something a bit more clever */
  1454.                 print_help_section( p_section, b_color, b_description );
  1455.                 p_section = NULL;
  1456.                 psz_bra = OPTION_VALUE_SEP "<";
  1457.                 psz_type = _("integer");
  1458.                 psz_ket = ">";
  1459.                 if( p_item->min.i || p_item->max.i )
  1460.                 {
  1461.                     sprintf( psz_buffer, "%s [%i .. %i]", psz_type,
  1462.                              p_item->min.i, p_item->max.i );
  1463.                     psz_type = psz_buffer;
  1464.                 }
  1465.                 if( p_item->i_list )
  1466.                 {
  1467.                     psz_bra = OPTION_VALUE_SEP "{";
  1468.                     psz_type = psz_buffer;
  1469.                     psz_buffer[0] = '';
  1470.                     for( i = 0; p_item->ppsz_list_text[i]; i++ )
  1471.                     {
  1472.                         if( i ) strcat( psz_buffer, ", " );
  1473.                         sprintf( psz_buffer + strlen(psz_buffer), "%i (%s)",
  1474.                                  p_item->pi_list[i],
  1475.                                  p_item->ppsz_list_text[i] );
  1476.                     }
  1477.                     psz_ket = "}";
  1478.                 }
  1479.                 break;
  1480.             case CONFIG_ITEM_FLOAT:
  1481.                 print_help_section( p_section, b_color, b_description );
  1482.                 p_section = NULL;
  1483.                 psz_bra = OPTION_VALUE_SEP "<";
  1484.                 psz_type = _("float");
  1485.                 psz_ket = ">";
  1486.                 if( p_item->min.f || p_item->max.f )
  1487.                 {
  1488.                     sprintf( psz_buffer, "%s [%f .. %f]", psz_type,
  1489.                              p_item->min.f, p_item->max.f );
  1490.                     psz_type = psz_buffer;
  1491.                 }
  1492.                 break;
  1493.             case CONFIG_ITEM_BOOL:
  1494.                 print_help_section( p_section, b_color, b_description );
  1495.                 p_section = NULL;
  1496.                 psz_bra = ""; psz_type = ""; psz_ket = "";
  1497.                 if( !b_help_module )
  1498.                 {
  1499.                     psz_suf = p_item->value.i ? _(" (default enabled)") :
  1500.                                                 _(" (default disabled)");
  1501.                 }
  1502.                 break;
  1503.             }
  1504.             if( !psz_type )
  1505.             {
  1506.                 continue;
  1507.             }
  1508.             /* Add short option if any */
  1509.             if( p_item->i_short )
  1510.             {
  1511.                 sprintf( psz_short, "-%c,", p_item->i_short );
  1512.             }
  1513.             else
  1514.             {
  1515.                 strcpy( psz_short, "   " );
  1516.             }
  1517.             i = PADDING_SPACES - strlen( p_item->psz_name )
  1518.                  - strlen( psz_bra ) - strlen( psz_type )
  1519.                  - strlen( psz_ket ) - 1;
  1520.             if( p_item->i_type == CONFIG_ITEM_BOOL && !b_help_module )
  1521.             {
  1522.                 psz_prefix =  ", --no-";
  1523.                 i -= strlen( p_item->psz_name ) + strlen( psz_prefix );
  1524.             }
  1525.             if( i < 0 )
  1526.             {
  1527.                 psz_spaces[0] = 'n';
  1528.                 i = 0;
  1529.             }
  1530.             else
  1531.             {
  1532.                 psz_spaces[i] = '';
  1533.             }
  1534.             if( p_item->i_type == CONFIG_ITEM_BOOL && !b_help_module )
  1535.             {
  1536.                 utf8_fprintf( stdout, psz_format_bool, psz_short,
  1537.                               p_item->psz_name, psz_prefix, p_item->psz_name,
  1538.                               psz_bra, psz_type, psz_ket, psz_spaces );
  1539.             }
  1540.             else
  1541.             {
  1542.                 utf8_fprintf( stdout, psz_format, psz_short, p_item->psz_name,
  1543.                          "", "", psz_bra, psz_type, psz_ket, psz_spaces );
  1544.             }
  1545.             psz_spaces[i] = ' ';
  1546.             /* We wrap the rest of the output */
  1547.             sprintf( psz_buffer, "%s%s", p_item->psz_text, psz_suf );
  1548.             b_description_hack = b_description;
  1549.  description:
  1550.             psz_text = psz_buffer;
  1551.             i_cur_width = b_description && !b_description_hack
  1552.                           ? i_width_description
  1553.                           : i_width;
  1554.             while( *psz_text )
  1555.             {
  1556.                 char *psz_parser, *psz_word;
  1557.                 size_t i_end = strlen( psz_text );
  1558.                 /* If the remaining text fits in a line, print it. */
  1559.                 if( i_end <= i_cur_width )
  1560.                 {
  1561.                     if( b_color )
  1562.                     {
  1563.                         if( !b_description || b_description_hack )
  1564.                             utf8_fprintf( stdout, BLUE"%sn"GRAY, psz_text );
  1565.                         else
  1566.                             utf8_fprintf( stdout, "%sn", psz_text );
  1567.                     }
  1568.                     else
  1569.                     {
  1570.                         utf8_fprintf( stdout, "%sn", psz_text );
  1571.                     }
  1572.                     break;
  1573.                 }
  1574.                 /* Otherwise, eat as many words as possible */
  1575.                 psz_parser = psz_text;
  1576.                 do
  1577.                 {
  1578.                     psz_word = psz_parser;
  1579.                     psz_parser = strchr( psz_word, ' ' );
  1580.                     /* If no space was found, we reached the end of the text
  1581.                      * block; otherwise, we skip the space we just found. */
  1582.                     psz_parser = psz_parser ? psz_parser + 1
  1583.                                             : psz_text + i_end;
  1584.                 } while( (size_t)(psz_parser - psz_text) <= i_cur_width );
  1585.                 /* We cut a word in one of these cases:
  1586.                  *  - it's the only word in the line and it's too long.
  1587.                  *  - we used less than 80% of the width and the word we are
  1588.                  *    going to wrap is longer than 40% of the width, and even
  1589.                  *    if the word would have fit in the next line. */
  1590.                 if( psz_word == psz_text
  1591.              || ( (size_t)(psz_word - psz_text) < 80 * i_cur_width / 100
  1592.              && (size_t)(psz_parser - psz_word) > 40 * i_cur_width / 100 ) )
  1593.                 {
  1594.                     char c = psz_text[i_cur_width];
  1595.                     psz_text[i_cur_width] = '';
  1596.                     if( b_color )
  1597.                     {
  1598.                         if( !b_description || b_description_hack )
  1599.                             utf8_fprintf( stdout, BLUE"%sn%s"GRAY,
  1600.                                           psz_text, psz_spaces );
  1601.                         else
  1602.                             utf8_fprintf( stdout, "%sn%s",
  1603.                                           psz_text, psz_spaces );
  1604.                     }
  1605.                     else
  1606.                     {
  1607.                         utf8_fprintf( stdout, "%sn%s", psz_text, psz_spaces );
  1608.                     }
  1609.                     psz_text += i_cur_width;
  1610.                     psz_text[0] = c;
  1611.                 }
  1612.                 else
  1613.                 {
  1614.                     psz_word[-1] = '';
  1615.                     if( b_color )
  1616.                     {
  1617.                         if( !b_description || b_description_hack )
  1618.                             utf8_fprintf( stdout, BLUE"%sn%s"GRAY,
  1619.                                           psz_text, psz_spaces );
  1620.                         else
  1621.                             utf8_fprintf( stdout, "%sn%s",
  1622.                                           psz_text, psz_spaces );
  1623.                     }
  1624.                     else
  1625.                     {
  1626.                         utf8_fprintf( stdout, "%sn%s", psz_text, psz_spaces );
  1627.                     }
  1628.                     psz_text = psz_word;
  1629.                 }
  1630.             }
  1631.             if( b_description_hack && p_item->psz_longtext )
  1632.             {
  1633.                 sprintf( psz_buffer, "%s%s", p_item->psz_longtext, psz_suf );
  1634.                 b_description_hack = false;
  1635.                 psz_spaces = psz_spaces_longtext;
  1636.                 utf8_fprintf( stdout, "%s", psz_spaces );
  1637.                 goto description;
  1638.             }
  1639.         }
  1640.     }
  1641.     if( b_has_advanced )
  1642.     {
  1643.         if( b_color )
  1644.             utf8_fprintf( stdout, "n" WHITE "%s" GRAY " %sn", _( "Note:" ),
  1645.            _( "add --advanced to your command line to see advanced options."));
  1646.         else
  1647.             utf8_fprintf( stdout, "n%s %sn", _( "Note:" ),
  1648.            _( "add --advanced to your command line to see advanced options."));
  1649.     }
  1650.     if( i_only_advanced > 0 )
  1651.     {
  1652.         if( b_color )
  1653.         {
  1654.             utf8_fprintf( stdout, "n" WHITE "%s" GRAY " ", _( "Note:" ) );
  1655.             utf8_fprintf( stdout, _( "%d module(s) were not displayed because they only have advanced options.n" ), i_only_advanced );
  1656.         }
  1657.         else
  1658.         {
  1659.             utf8_fprintf( stdout, "n%s ", _( "Note:" ) );
  1660.             utf8_fprintf( stdout, _( "%d module(s) were not displayed because they only have advanced options.n" ), i_only_advanced );
  1661.         }
  1662.     }
  1663.     else if( !b_found )
  1664.     {
  1665.         if( b_color )
  1666.             utf8_fprintf( stdout, "n" WHITE "%s" GRAY "n",
  1667.                        _( "No matching module found. Use --list or" 
  1668.                           "--list-verbose to list available modules." ) );
  1669.         else
  1670.             utf8_fprintf( stdout, "n%sn",
  1671.                        _( "No matching module found. Use --list or" 
  1672.                           "--list-verbose to list available modules." ) );
  1673.     }
  1674.     /* Release the module list */
  1675.     module_list_free (list);
  1676. }
  1677. /*****************************************************************************
  1678.  * ListModules: list the available modules with their description
  1679.  *****************************************************************************
  1680.  * Print a list of all available modules (builtins and plugins) and a short
  1681.  * description for each one.
  1682.  *****************************************************************************/
  1683. static void ListModules( libvlc_int_t *p_this, bool b_verbose )
  1684. {
  1685.     module_t *p_parser;
  1686.     char psz_spaces[22];
  1687.     bool b_color = config_GetInt( p_this, "color" ) > 0;
  1688.     memset( psz_spaces, ' ', 22 );
  1689. #ifdef WIN32
  1690.     ShowConsole( true );
  1691. #endif
  1692.     /* List all modules */
  1693.     module_t **list = module_list_get (NULL);
  1694.     /* Enumerate each module */
  1695.     for (size_t j = 0; (p_parser = list[j]) != NULL; j++)
  1696.     {
  1697.         int i;
  1698.         /* Nasty hack, but right now I'm too tired to think about a nice
  1699.          * solution */
  1700.         i = 22 - strlen( p_parser->psz_object_name ) - 1;
  1701.         if( i < 0 ) i = 0;
  1702.         psz_spaces[i] = 0;
  1703.         if( b_color )
  1704.             utf8_fprintf( stdout, GREEN"  %s%s "WHITE"%sn"GRAY,
  1705.                           p_parser->psz_object_name,
  1706.                           psz_spaces,
  1707.                           p_parser->psz_longname );
  1708.         else
  1709.             utf8_fprintf( stdout, "  %s%s %sn",
  1710.                           p_parser->psz_object_name,
  1711.                           psz_spaces, p_parser->psz_longname );
  1712.         if( b_verbose )
  1713.         {
  1714.             char *const *pp_shortcut = p_parser->pp_shortcuts;
  1715.             while( *pp_shortcut )
  1716.             {
  1717.                 if( strcmp( *pp_shortcut, p_parser->psz_object_name ) )
  1718.                 {
  1719.                     if( b_color )
  1720.                         utf8_fprintf( stdout, CYAN"   s %sn"GRAY,
  1721.                                       *pp_shortcut );
  1722.                     else
  1723.                         utf8_fprintf( stdout, "   s %sn",
  1724.                                       *pp_shortcut );
  1725.                 }
  1726.                 pp_shortcut++;
  1727.             }
  1728.             if( p_parser->psz_capability )
  1729.             {
  1730.                 if( b_color )
  1731.                     utf8_fprintf( stdout, MAGENTA"   c %s (%d)n"GRAY,
  1732.                                   p_parser->psz_capability,
  1733.                                   p_parser->i_score );
  1734.                 else
  1735.                     utf8_fprintf( stdout, "   c %s (%d)n",
  1736.                                   p_parser->psz_capability,
  1737.                                   p_parser->i_score );
  1738.             }
  1739.         }
  1740.         psz_spaces[i] = ' ';
  1741.     }
  1742.     module_list_free (list);
  1743. #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
  1744.     PauseConsole();
  1745. #endif
  1746. }
  1747. /*****************************************************************************
  1748.  * Version: print complete program version
  1749.  *****************************************************************************
  1750.  * Print complete program version and build number.
  1751.  *****************************************************************************/
  1752. static void Version( void )
  1753. {
  1754. #ifdef WIN32
  1755.     ShowConsole( true );
  1756. #endif
  1757.     utf8_fprintf( stdout, _("VLC version %sn"), VLC_Version() );
  1758.     utf8_fprintf( stdout, _("Compiled by %s@%s.%sn"),
  1759.              VLC_CompileBy(), VLC_CompileHost(), VLC_CompileDomain() );
  1760.     utf8_fprintf( stdout, _("Compiler: %sn"), VLC_Compiler() );
  1761.     utf8_fprintf( stdout, "%s", LICENSE_MSG );
  1762. #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
  1763.     PauseConsole();
  1764. #endif
  1765. }
  1766. /*****************************************************************************
  1767.  * ShowConsole: On Win32, create an output console for debug messages
  1768.  *****************************************************************************
  1769.  * This function is useful only on Win32.
  1770.  *****************************************************************************/
  1771. #ifdef WIN32 /*  */
  1772. static void ShowConsole( bool b_dofile )
  1773. {
  1774. #   ifndef UNDER_CE
  1775.     FILE *f_help = NULL;
  1776.     if( getenv( "PWD" ) && getenv( "PS1" ) ) return; /* cygwin shell */
  1777.     AllocConsole();
  1778.     /* Use the ANSI code page (e.g. Windows-1252) as expected by the LibVLC
  1779.      * Unicode/locale subsystem. By default, we have the obsolecent OEM code
  1780.      * page (e.g. CP437 or CP850). */
  1781.     SetConsoleOutputCP (GetACP ());
  1782.     SetConsoleTitle ("VLC media player version "PACKAGE_VERSION);
  1783.     freopen( "CONOUT$", "w", stderr );
  1784.     freopen( "CONIN$", "r", stdin );
  1785.     if( b_dofile && (f_help = fopen( "vlc-help.txt", "wt" )) )
  1786.     {
  1787.         fclose( f_help );
  1788.         freopen( "vlc-help.txt", "wt", stdout );
  1789.         utf8_fprintf( stderr, _("nDumped content to vlc-help.txt file.n") );
  1790.     }
  1791.     else freopen( "CONOUT$", "w", stdout );
  1792. #   endif
  1793. }
  1794. #endif
  1795. /*****************************************************************************
  1796.  * PauseConsole: On Win32, wait for a key press before closing the console
  1797.  *****************************************************************************
  1798.  * This function is useful only on Win32.
  1799.  *****************************************************************************/
  1800. #ifdef WIN32 /*  */
  1801. static void PauseConsole( void )
  1802. {
  1803. #   ifndef UNDER_CE
  1804.     if( getenv( "PWD" ) && getenv( "PS1" ) ) return; /* cygwin shell */
  1805.     utf8_fprintf( stderr, _("nPress the RETURN key to continue...n") );
  1806.     getchar();
  1807.     fclose( stdout );
  1808. #   endif
  1809. }
  1810. #endif
  1811. /*****************************************************************************
  1812.  * ConsoleWidth: Return the console width in characters
  1813.  *****************************************************************************
  1814.  * We use the stty shell command to get the console width; if this fails or
  1815.  * if the width is less than 80, we default to 80.
  1816.  *****************************************************************************/
  1817. static int ConsoleWidth( void )
  1818. {
  1819.     unsigned i_width = 80;
  1820. #ifndef WIN32
  1821.     FILE *file = popen( "stty size 2>/dev/null", "r" );
  1822.     if (file != NULL)
  1823.     {
  1824.         if (fscanf (file, "%*u %u", &i_width) <= 0)
  1825.             i_width = 80;
  1826.         pclose( file );
  1827.     }
  1828. #elif !defined (UNDER_CE)
  1829.     CONSOLE_SCREEN_BUFFER_INFO buf;
  1830.     if (GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &buf))
  1831.         i_width = buf.dwSize.X;
  1832. #endif
  1833.     return i_width;
  1834. }
  1835. /*****************************************************************************
  1836.  * InitDeviceValues: initialize device values
  1837.  *****************************************************************************
  1838.  * This function inits the dvd, vcd and cd-audio values
  1839.  *****************************************************************************/
  1840. static void InitDeviceValues( libvlc_int_t *p_vlc )
  1841. {
  1842. #ifdef HAVE_HAL
  1843.     LibHalContext * ctx = NULL;
  1844.     int i, i_devices;
  1845.     char **devices = NULL;
  1846.     char *block_dev = NULL;
  1847.     dbus_bool_t b_dvd;
  1848.     DBusConnection *p_connection = NULL;
  1849.     DBusError       error;
  1850.     ctx = libhal_ctx_new();
  1851.     if( !ctx ) return;
  1852.     dbus_error_init( &error );
  1853.     p_connection = dbus_bus_get ( DBUS_BUS_SYSTEM, &error );
  1854.     if( dbus_error_is_set( &error ) || !p_connection )
  1855.     {
  1856.         libhal_ctx_free( ctx );
  1857.         dbus_error_free( &error );
  1858.         return;
  1859.     }
  1860.     libhal_ctx_set_dbus_connection( ctx, p_connection );
  1861.     if( libhal_ctx_init( ctx, &error ) )
  1862.     {
  1863.         if( ( devices = libhal_get_all_devices( ctx, &i_devices, NULL ) ) )
  1864.         {
  1865.             for( i = 0; i < i_devices; i++ )
  1866.             {
  1867.                 if( !libhal_device_property_exists( ctx, devices[i],
  1868.                                                 "storage.cdrom.dvd", NULL ) )
  1869.                 {
  1870.                     continue;
  1871.                 }
  1872.                 b_dvd = libhal_device_get_property_bool( ctx, devices[ i ],
  1873.                                                  "storage.cdrom.dvd", NULL  );
  1874.                 block_dev = libhal_device_get_property_string( ctx,
  1875.                                 devices[ i ], "block.device" , NULL );
  1876.                 if( b_dvd )
  1877.                 {
  1878.                     config_PutPsz( p_vlc, "dvd", block_dev );
  1879.                 }
  1880.                 config_PutPsz( p_vlc, "vcd", block_dev );
  1881.                 config_PutPsz( p_vlc, "cd-audio", block_dev );
  1882.                 libhal_free_string( block_dev );
  1883.             }
  1884.             libhal_free_string_array( devices );
  1885.         }
  1886.         libhal_ctx_shutdown( ctx, NULL );
  1887.         dbus_connection_unref( p_connection );
  1888.         libhal_ctx_free( ctx );
  1889.     }
  1890.     else
  1891.     {
  1892.         msg_Warn( p_vlc, "Unable to get HAL device properties" );
  1893.     }
  1894. #else
  1895.     (void)p_vlc;
  1896. #endif /* HAVE_HAL */
  1897. }
  1898. #include <vlc_avcodec.h>
  1899. void vlc_avcodec_mutex (bool acquire)
  1900. {
  1901.     static vlc_mutex_t lock = VLC_STATIC_MUTEX;
  1902.     if (acquire)
  1903.         vlc_mutex_lock (&lock);
  1904.     else
  1905.         vlc_mutex_unlock (&lock);
  1906. }