]> git.sesse.net Git - vlc/blobdiff - src/libvlc.c
real demux: use VLC_FOURCC
[vlc] / src / libvlc.c
index 226147e2fb329f71d1d838c0a01337764ce55ca6..7c053fc21423c9943c03a2ffa9cbf285d499152a 100644 (file)
@@ -68,6 +68,8 @@
 #   include <dbus/dbus.h>
 #endif
 
+
+#include <vlc_media_library.h>
 #include <vlc_playlist.h>
 #include <vlc_interface.h>
 
@@ -78,6 +80,8 @@
 #include <vlc_fs.h>
 #include <vlc_cpu.h>
 #include <vlc_url.h>
+#include <vlc_atomic.h>
+#include <vlc_modules.h>
 
 #include "libvlc.h"
 
@@ -116,18 +120,7 @@ void *vlc_gc_init (gc_object_t *p_gc, void (*pf_destruct) (gc_object_t *))
     assert (pf_destruct);
     p_gc->pf_destructor = pf_destruct;
 
-    p_gc->refs = 1;
-#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
-    __sync_synchronize ();
-#elif defined (WIN32) && defined (__GNUC__)
-#elif defined(__APPLE__)
-    OSMemoryBarrier ();
-#else
-    /* Nobody else can possibly lock the spin - it's there as a barrier */
-    vlc_spin_init (&p_gc->spin);
-    vlc_spin_lock (&p_gc->spin);
-    vlc_spin_unlock (&p_gc->spin);
-#endif
+    vlc_atomic_set (&p_gc->refs, 1);
     return p_gc;
 }
 
@@ -139,22 +132,9 @@ void *vlc_gc_init (gc_object_t *p_gc, void (*pf_destruct) (gc_object_t *))
 void *vlc_hold (gc_object_t * p_gc)
 {
     uintptr_t refs;
+
     assert( p_gc );
-    assert ((((uintptr_t)&p_gc->refs) & (sizeof (void *) - 1)) == 0); /* alignment */
-
-#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
-    refs = __sync_add_and_fetch (&p_gc->refs, 1);
-#elif defined (WIN64)
-    refs = InterlockedIncrement64 (&p_gc->refs);
-#elif defined (WIN32)
-    refs = InterlockedIncrement (&p_gc->refs);
-#elif defined(__APPLE__)
-    refs = OSAtomicIncrement32Barrier((int*)&p_gc->refs);
-#else
-    vlc_spin_lock (&p_gc->spin);
-    refs = ++p_gc->refs;
-    vlc_spin_unlock (&p_gc->spin);
-#endif
+    refs = vlc_atomic_inc (&p_gc->refs);
     assert (refs != 1); /* there had to be a reference already */
     return p_gc;
 }
@@ -165,36 +145,13 @@ void *vlc_hold (gc_object_t * p_gc)
  */
 void vlc_release (gc_object_t *p_gc)
 {
-    unsigned refs;
+    uintptr_t refs;
 
     assert( p_gc );
-    assert ((((uintptr_t)&p_gc->refs) & (sizeof (void *) - 1)) == 0); /* alignment */
-
-#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
-    refs = __sync_sub_and_fetch (&p_gc->refs, 1);
-#elif defined (WIN64)
-    refs = InterlockedDecrement64 (&p_gc->refs);
-#elif defined (WIN32)
-    refs = InterlockedDecrement (&p_gc->refs);
-#elif defined(__APPLE__)
-    refs = OSAtomicDecrement32Barrier((int*)&p_gc->refs);
-#else
-    vlc_spin_lock (&p_gc->spin);
-    refs = --p_gc->refs;
-    vlc_spin_unlock (&p_gc->spin);
-#endif
-
+    refs = vlc_atomic_dec (&p_gc->refs);
     assert (refs != (uintptr_t)(-1)); /* reference underflow?! */
     if (refs == 0)
-    {
-#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
-#elif defined (WIN32) && defined (__GNUC__)
-#elif defined(__APPLE__)
-#else
-        vlc_spin_destroy (&p_gc->spin);
-#endif
         p_gc->pf_destructor (p_gc);
-    }
 }
 
 /*****************************************************************************
@@ -204,7 +161,7 @@ void vlc_release (gc_object_t *p_gc)
     ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
 static void SetLanguage   ( char const * );
 #endif
-static int  GetFilenames  ( libvlc_int_t *, int, const char *[] );
+static void GetFilenames  ( libvlc_int_t *, unsigned, const char *const [] );
 static void Help          ( libvlc_int_t *, char const *psz_help_name );
 static void Usage         ( libvlc_int_t *, char const *psz_search );
 static void ListModules   ( libvlc_int_t *, bool );
@@ -217,6 +174,7 @@ static void PauseConsole  ( void );
 static int  ConsoleWidth  ( void );
 
 static vlc_mutex_t global_lock = VLC_STATIC_MUTEX;
+extern const char psz_vlc_changeset[];
 
 /**
  * Allocate a libvlc instance, initialize global data if needed
@@ -240,7 +198,7 @@ libvlc_int_t * libvlc_InternalCreate( void )
 
     /* Allocate a libvlc instance object */
     p_libvlc = vlc_custom_create( (vlc_object_t *)NULL, sizeof (*priv),
-                                  VLC_OBJECT_GENERIC, "libvlc" );
+                                  "libvlc" );
     if( p_libvlc != NULL )
         i_instances++;
     vlc_mutex_unlock( &global_lock );
@@ -250,6 +208,7 @@ libvlc_int_t * libvlc_InternalCreate( void )
 
     priv = libvlc_priv (p_libvlc);
     priv->p_playlist = NULL;
+    priv->p_ml = NULL;
     priv->p_dialog_provider = NULL;
     priv->p_vlm = NULL;
 
@@ -271,7 +230,9 @@ libvlc_int_t * libvlc_InternalCreate( void )
 #endif
 
     /* Initialize mutexes */
+    vlc_mutex_init( &priv->ml_lock );
     vlc_mutex_init( &priv->timer_lock );
+    vlc_ExitInit( &priv->exit );
 
     return p_libvlc;
 error:
@@ -307,7 +268,7 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
 #endif
 
     /* System specific initialization code */
-    system_Init( p_libvlc, &i_argc, ppsz_argv );
+    system_Init();
 
     /*
      * Support for gettext
@@ -320,7 +281,7 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
      * options) */
     module_InitBank( p_libvlc );
 
-    if( config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, true ) )
+    if( config_LoadCmdLine( p_libvlc, i_argc, ppsz_argv, NULL ) )
     {
         module_EndBank( p_libvlc, false );
         return VLC_EGENERIC;
@@ -328,8 +289,10 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
 
     priv->i_verbose = var_InheritInteger( p_libvlc, "verbose" );
     /* Announce who we are - Do it only for first instance ? */
+    msg_Dbg( p_libvlc, "VLC media player - %s", VERSION_MESSAGE );
     msg_Dbg( p_libvlc, "%s", COPYRIGHT_MESSAGE );
-    msg_Dbg( p_libvlc, "libvlc was configured with %s", CONFIGURE_LINE );
+    msg_Dbg( p_libvlc, "revision %s", psz_vlc_changeset );
+    msg_Dbg( p_libvlc, "configured with %s", CONFIGURE_LINE );
     /*xgettext: Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
     msg_Dbg( p_libvlc, "translation test: code is \"%s\"", _("C") );
 
@@ -349,7 +312,7 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
     }
 
     /* Check for daemon mode */
-#ifndef WIN32
+#if !defined( WIN32 ) && !defined( __SYMBIAN32__ )
     if( var_InheritBool( p_libvlc, "daemon" ) )
     {
 #ifdef HAVE_DAEMON
@@ -424,7 +387,7 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
      && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
 # if defined (WIN32) || defined (__APPLE__)
     if( !var_InheritBool( p_libvlc, "ignore-config" ) )
-        config_LoadConfigFile( p_libvlc, "main" );
+        config_LoadConfigFile( p_libvlc );
     priv->i_verbose = var_InheritInteger( p_libvlc, "verbose" );
 
     /* Check if the user specified a custom language */
@@ -498,20 +461,9 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
         i_ret = VLC_EEXITSUCCESS;
     }
 
-    /* Check for config file options */
-    if( !var_InheritBool( p_libvlc, "ignore-config" ) )
-    {
-        if( var_InheritBool( p_libvlc, "reset-config" ) )
-        {
-            config_ResetAll( p_libvlc );
-            config_SaveConfigFile( p_libvlc, NULL );
-        }
-    }
-
-    if( module_count <= 1)
+    if( module_count <= 1 )
     {
-        msg_Err( p_libvlc, "No modules were found, refusing to start. Check "
-                "that you properly gave a module path with --plugin-path.");
+        msg_Err( p_libvlc, "No plugins found! Check your VLC installation.");
         b_exit = true;
         i_ret = VLC_ENOITEM;
     }
@@ -526,15 +478,21 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
      * Override default configuration with config file settings
      */
     if( !var_InheritBool( p_libvlc, "ignore-config" ) )
-        config_LoadConfigFile( p_libvlc, NULL );
+    {
+        if( var_InheritBool( p_libvlc, "reset-config" ) )
+        {
+            config_ResetAll( p_libvlc );
+            config_SaveConfigFile( p_libvlc );
+        }
+        else
+            config_LoadConfigFile( p_libvlc );
+    }
 
     /*
      * Override configuration with command line settings
      */
-    /* config_LoadCmdLine(), DBus (below) and Win32-specific use vlc_optind,
-     * vlc_optarg and vlc_optopt globals. This is not thread-safe!! */
-#warning BUG!
-    if( config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, false ) )
+    int vlc_optind;
+    if( config_LoadCmdLine( p_libvlc, i_argc, ppsz_argv, &vlc_optind ) )
     {
 #ifdef WIN32
         ShowConsole( false );
@@ -548,11 +506,6 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
     }
     priv->i_verbose = var_InheritInteger( p_libvlc, "verbose" );
 
-    /*
-     * System specific configuration
-     */
-    system_Configure( p_libvlc, &i_argc, ppsz_argv );
-
 /* FIXME: could be replaced by using Unix sockets */
 #ifdef HAVE_DBUS
     dbus_threads_init_default();
@@ -580,11 +533,13 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
             /* check if VLC is available on the bus
              * if not: D-Bus control is not enabled on the other
              * instance and we can't pass MRLs to it */
-            DBusMessage *p_test_msg = NULL;
+            DBusMessage *p_test_msg   = NULL;
             DBusMessage *p_test_reply = NULL;
+
             p_test_msg =  dbus_message_new_method_call(
-                    "org.mpris.vlc", "/",
-                    "org.freedesktop.MediaPlayer", "Identity" );
+                    "org.mpris.MediaPlayer2.vlc", "/org/mpris/MediaPlayer2",
+                    "org.freedesktop.DBus.Introspectable", "Introspect" );
+
             /* block until a reply arrives */
             p_test_reply = dbus_connection_send_with_reply_and_block(
                     p_conn, p_test_msg, -1, &dbus_error );
@@ -608,16 +563,31 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
 
                 for( i_input = vlc_optind; i_input < i_argc;i_input++ )
                 {
+                    /* Skip input options, we can't pass them through D-Bus */
+                    if( ppsz_argv[i_input][0] == ':' )
+                    {
+                        msg_Warn( p_libvlc, "Ignoring option %s",
+                                  ppsz_argv[i_input] );
+                        continue;
+                    }
+
+                    /* We need to resolve relative paths in this instance */
+                    char *psz_mrl = make_URI( ppsz_argv[i_input], NULL );
+                    const char *psz_after_track = "/";
+
+                    if( psz_mrl == NULL )
+                        continue;
                     msg_Dbg( p_libvlc, "Adds %s to the running Media Player",
-                            ppsz_argv[i_input] );
+                             psz_mrl );
 
                     p_dbus_msg = dbus_message_new_method_call(
-                            "org.mpris.vlc", "/TrackList",
-                            "org.freedesktop.MediaPlayer", "AddTrack" );
+                        "org.mpris.MediaPlayer2.vlc", "/org/mpris/MediaPlayer2",
+                        "org.mpris.MediaPlayer2.TrackList", "AddTrack" );
 
                     if ( NULL == p_dbus_msg )
                     {
                         msg_Err( p_libvlc, "D-Bus problem" );
+                        free( psz_mrl );
                         system_End( p_libvlc );
                         exit( 1 );
                     }
@@ -625,15 +595,27 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
                     /* append MRLs */
                     dbus_message_iter_init_append( p_dbus_msg, &dbus_args );
                     if ( !dbus_message_iter_append_basic( &dbus_args,
-                                DBUS_TYPE_STRING, &ppsz_argv[i_input] ) )
+                                DBUS_TYPE_STRING, &psz_mrl ) )
+                    {
+                        dbus_message_unref( p_dbus_msg );
+                        free( psz_mrl );
+                        system_End( p_libvlc );
+                        exit( 1 );
+                    }
+                    free( psz_mrl );
+
+                    if( !dbus_message_iter_append_basic( &dbus_args,
+                                DBUS_TYPE_OBJECT_PATH, &psz_after_track ) )
                     {
                         dbus_message_unref( p_dbus_msg );
                         system_End( p_libvlc );
                         exit( 1 );
                     }
+
                     b_play = TRUE;
                     if( var_InheritBool( p_libvlc, "playlist-enqueue" ) )
                         b_play = FALSE;
+
                     if ( !dbus_message_iter_append_basic( &dbus_args,
                                 DBUS_TYPE_BOOLEAN, &b_play ) )
                     {
@@ -788,12 +770,10 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
     priv->i_timers = 0;
     priv->pp_timers = NULL;
 
-    priv->i_last_input_id = 0; /* Not very safe, should be removed */
-
     /*
      * Initialize hotkey handling
      */
-    vlc_InitActions( p_libvlc );
+    priv->actions = vlc_InitActions( p_libvlc );
 
     /* Create a variable for showing the fullscreen interface */
     var_Create( p_libvlc, "intf-show", VLC_VAR_BOOL );
@@ -806,6 +786,11 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
     var_Create( p_libvlc, "snapshot-file", VLC_VAR_STRING );
     var_Create( p_libvlc, "record-file", VLC_VAR_STRING );
 
+    /* some default internal settings */
+    var_Create( p_libvlc, "window", VLC_VAR_STRING );
+    var_Create( p_libvlc, "user-agent", VLC_VAR_STRING );
+    var_SetString( p_libvlc, "user-agent", "(LibVLC "VERSION")" );
+
     /* Initialize playlist and get commandline files */
     p_playlist = playlist_Create( VLC_OBJECT(p_libvlc) );
     if( !p_playlist )
@@ -819,6 +804,26 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
         return VLC_EGENERIC;
     }
 
+    /* System specific configuration */
+    system_Configure( p_libvlc, i_argc - vlc_optind, ppsz_argv + vlc_optind );
+
+#if defined(MEDIA_LIBRARY)
+    /* Get the ML */
+    if( var_GetBool( p_libvlc, "load-media-library-on-startup" ) )
+    {
+        priv->p_ml = ml_Create( VLC_OBJECT( p_libvlc ), NULL );
+        if( !priv->p_ml )
+        {
+            msg_Err( p_libvlc, "ML initialization failed" );
+            return VLC_EGENERIC;
+        }
+    }
+    else
+    {
+        priv->p_ml = NULL;
+    }
+#endif
+
     /* Add service discovery modules */
     psz_modules = var_InheritString( p_libvlc, "services-discovery" );
     if( psz_modules )
@@ -929,25 +934,7 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
         intf_Create( p_libvlc, "netsync,none" );
     }
 
-#ifdef WIN32
-    if( var_InheritBool( p_libvlc, "prefer-system-codecs") )
-    {
-        char *psz_codecs = var_CreateGetNonEmptyString( p_libvlc, "codec" );
-        if( psz_codecs )
-        {
-            char *psz_morecodecs;
-            if( asprintf(&psz_morecodecs, "%s,dmo,quicktime", psz_codecs) != -1 )
-            {
-                var_SetString( p_libvlc, "codec", psz_morecodecs);
-                free( psz_morecodecs );
-            }
-            free( psz_codecs );
-        }
-        else
-            var_SetString( p_libvlc, "codec", "dmo,quicktime");
-    }
-#endif
-
+#ifdef __APPLE__
     var_Create( p_libvlc, "drawable-view-top", VLC_VAR_INTEGER );
     var_Create( p_libvlc, "drawable-view-left", VLC_VAR_INTEGER );
     var_Create( p_libvlc, "drawable-view-bottom", VLC_VAR_INTEGER );
@@ -956,14 +943,18 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
     var_Create( p_libvlc, "drawable-clip-left", VLC_VAR_INTEGER );
     var_Create( p_libvlc, "drawable-clip-bottom", VLC_VAR_INTEGER );
     var_Create( p_libvlc, "drawable-clip-right", VLC_VAR_INTEGER );
+    var_Create( p_libvlc, "drawable-nsobject", VLC_VAR_ADDRESS );
+#endif
 #ifdef WIN32
-    var_Create( p_libvlc, "drawable-hwnd", VLC_VAR_ADDRESS );
+    var_Create( p_libvlc, "drawable-hwnd", VLC_VAR_INTEGER );
 #endif
 
     /*
-     * Get input filenames given as commandline arguments
+     * Get input filenames given as commandline arguments.
+     * We assume that the remaining parameters are filenames
+     * and their input options.
      */
-    GetFilenames( p_libvlc, i_argc, ppsz_argv );
+    GetFilenames( p_libvlc, i_argc - vlc_optind, ppsz_argv + vlc_optind );
 
     /*
      * Get --open argument
@@ -1009,9 +1000,18 @@ void libvlc_InternalCleanup( libvlc_int_t *p_libvlc )
     }
 #endif
 
+#if defined(MEDIA_LIBRARY)
+    media_library_t* p_ml = priv->p_ml;
+    if( p_ml )
+    {
+        ml_Destroy( VLC_OBJECT( p_ml ) );
+        vlc_object_release( p_ml );
+        libvlc_priv(p_playlist->p_libvlc)->p_ml = NULL;
+    }
+#endif
+
     /* Free playlist now, all threads are gone */
     playlist_Destroy( p_playlist );
-
     stats_TimersDumpAll( p_libvlc );
     stats_TimersCleanAll( p_libvlc );
 
@@ -1042,10 +1042,14 @@ void libvlc_InternalCleanup( libvlc_int_t *p_libvlc )
         priv->p_memcpy_module = NULL;
     }
 
+    /* Save the configuration */
+    if( !var_InheritBool( p_libvlc, "ignore-config" ) )
+        config_AutoSaveConfigFile( VLC_OBJECT(p_libvlc) );
+
     /* Free module bank. It is refcounted, so we call this each time  */
     module_EndBank( p_libvlc, true );
 
-    vlc_DeinitActions( p_libvlc );
+    vlc_DeinitActions( p_libvlc, priv->actions );
 }
 
 /**
@@ -1072,7 +1076,9 @@ void libvlc_InternalDestroy( libvlc_int_t *p_libvlc )
     msg_Destroy (priv->msg_bank);
 
     /* Destroy mutexes */
+    vlc_ExitDestroy( &priv->exit );
     vlc_mutex_destroy( &priv->timer_lock );
+    vlc_mutex_destroy( &priv->ml_lock );
 
 #ifndef NDEBUG /* Hack to dump leaked objects tree */
     if( vlc_internals( p_libvlc )->i_refcount > 1 )
@@ -1120,40 +1126,6 @@ int libvlc_InternalAddIntf( libvlc_int_t *p_libvlc, char const *psz_module )
     return ret;
 }
 
-#ifndef WIN32
-static vlc_mutex_t exit_lock = VLC_STATIC_MUTEX;
-static vlc_cond_t  exiting = VLC_STATIC_COND;
-#else
-extern vlc_mutex_t super_mutex;
-extern vlc_cond_t  super_variable;
-# define exit_lock super_mutex
-# define exiting   super_variable
-#endif
-
-/**
- * Waits until the LibVLC instance gets an exit signal. Normally, this happens
- * when the user "exits" an interface plugin.
- */
-void libvlc_InternalWait( libvlc_int_t *p_libvlc )
-{
-    vlc_mutex_lock( &exit_lock );
-    while( vlc_object_alive( p_libvlc ) )
-        vlc_cond_wait( &exiting, &exit_lock );
-    vlc_mutex_unlock( &exit_lock );
-}
-
-/**
- * Posts an exit signal to LibVLC instance. This will normally initiate the
- * cleanup and destroy process. It should only be called on behalf of the user.
- */
-void libvlc_Quit( libvlc_int_t *p_libvlc )
-{
-    vlc_mutex_lock( &exit_lock );
-    vlc_object_kill( p_libvlc );
-    vlc_cond_broadcast( &exiting );
-    vlc_mutex_unlock( &exit_lock );
-}
-
 #if defined( ENABLE_NLS ) && (defined (__APPLE__) || defined (WIN32)) && \
     ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
 /*****************************************************************************
@@ -1175,10 +1147,8 @@ static void SetLanguage ( const char *psz_lang )
      * the language at runtime under eg. Windows. Beware that this
      * makes the environment unconsistent when libvlc is unloaded and
      * should probably be moved to a safer place like vlc.c. */
-    static char psz_lcall[20];
-    snprintf( psz_lcall, 19, "LC_ALL=%s", psz_lang );
-    psz_lcall[19] = '\0';
-    putenv( psz_lcall );
+    setenv( "LC_ALL", psz_lang, 1 );
+
 #endif
 
     setlocale( LC_ALL, psz_lang );
@@ -1191,36 +1161,33 @@ static void SetLanguage ( const char *psz_lang )
  * Parse command line for input files as well as their associated options.
  * An option always follows its associated input and begins with a ":".
  *****************************************************************************/
-static int GetFilenames( libvlc_int_t *p_vlc, int i_argc, const char *ppsz_argv[] )
+static void GetFilenames( libvlc_int_t *p_vlc, unsigned n,
+                          const char *const args[] )
 {
-    int i_opt, i_options;
-
-    /* We assume that the remaining parameters are filenames
-     * and their input options */
-    for( i_opt = i_argc - 1; i_opt >= vlc_optind; i_opt-- )
+    while( n > 0 )
     {
-        i_options = 0;
-
         /* Count the input options */
-        while( *ppsz_argv[ i_opt ] == ':' && i_opt > vlc_optind )
+        unsigned i_options = 0;
+
+        while( args[--n][0] == ':' )
         {
             i_options++;
-            i_opt--;
+            if( n == 0 )
+            {
+                msg_Warn( p_vlc, "options %s without item", args[n] );
+                return; /* syntax!? */
+            }
         }
 
-        /* TODO: write an internal function of this one, to avoid
-         *       unnecessary lookups. */
-        char *mrl = make_URI( ppsz_argv[i_opt] );
+        char *mrl = make_URI( args[n], NULL );
         if( !mrl )
             continue;
 
         playlist_AddExt( pl_Get( p_vlc ), mrl, NULL, PLAYLIST_INSERT,
-                0, -1, i_options, ( i_options ? &ppsz_argv[i_opt + 1] : NULL ),
+                0, -1, i_options, ( i_options ? &args[n + 1] : NULL ),
                 VLC_INPUT_OPTION_TRUSTED, true, pl_Unlocked );
         free( mrl );
     }
-
-    return VLC_SUCCESS;
 }
 
 /*****************************************************************************
@@ -1298,6 +1265,7 @@ static void Help( libvlc_int_t *p_this, char const *psz_help_name )
 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
     PauseConsole();
 #endif
+    fflush( stdout );
 }
 
 /*****************************************************************************
@@ -1323,7 +1291,7 @@ print_help_section( const module_t *m, const module_config_t *p_item,
     {
         utf8_fprintf( stdout, RED"   %s:\n"GRAY,
                       module_gettext( m, p_item->psz_text ) );
-        if( b_description && p_item->psz_longtext && *p_item->psz_longtext )
+        if( b_description && p_item->psz_longtext )
             utf8_fprintf( stdout, MAGENTA"   %s\n"GRAY,
                           module_gettext( m, p_item->psz_longtext ) );
     }
@@ -1331,7 +1299,7 @@ print_help_section( const module_t *m, const module_config_t *p_item,
     {
         utf8_fprintf( stdout, "   %s:\n",
                       module_gettext( m, p_item->psz_text ) );
-        if( b_description && p_item->psz_longtext && *p_item->psz_longtext )
+        if( b_description && p_item->psz_longtext )
             utf8_fprintf( stdout, "   %s\n",
                           module_gettext(m, p_item->psz_longtext ) );
     }
@@ -1424,15 +1392,15 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search )
             ( b_strict ? strcmp( psz_search, p_parser->psz_object_name )
                        : !strstr( p_parser->psz_object_name, psz_search ) ) )
         {
-            char *const *pp_shortcut = p_parser->pp_shortcuts;
-            while( *pp_shortcut )
+            char *const *pp_shortcuts = p_parser->pp_shortcuts;
+            unsigned i;
+            for( i = 0; i < p_parser->i_shortcuts; i++ )
             {
-                if( b_strict ? !strcmp( psz_search, *pp_shortcut )
-                             : !!strstr( *pp_shortcut, psz_search ) )
+                if( b_strict ? !strcmp( psz_search, pp_shortcuts[i] )
+                             : !!strstr( pp_shortcuts[i], psz_search ) )
                     break;
-                pp_shortcut ++;
             }
-            if( !*pp_shortcut )
+            if( i == p_parser->i_shortcuts )
                 continue;
         }
 
@@ -1455,7 +1423,7 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search )
                  p_item < p_end;
                  p_item++ )
             {
-                if( (p_item->i_type & CONFIG_ITEM) &&
+                if( CONFIG_ITEM(p_item->i_type) &&
                     !p_item->b_advanced && !p_item->b_removed ) break;
             }
 
@@ -1512,47 +1480,43 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search )
                 continue;
             }
 
-            switch( p_item->i_type )
+            switch( CONFIG_CLASS(p_item->i_type) )
             {
-            case CONFIG_HINT_CATEGORY:
-            case CONFIG_HINT_USAGE:
-                if( !strcmp( "main", p_parser->psz_object_name ) )
-                {
-                    if( b_color )
-                        utf8_fprintf( stdout, GREEN "\n %s\n" GRAY,
-                                      module_gettext( p_parser, p_item->psz_text ) );
-                    else
-                        utf8_fprintf( stdout, "\n %s\n",
-                                      module_gettext( p_parser, p_item->psz_text ) );
-                }
-                if( b_description && p_item->psz_longtext
-                 && *p_item->psz_longtext )
+            case 0: // hint class
+                switch( p_item->i_type )
                 {
-                    if( b_color )
-                        utf8_fprintf( stdout, CYAN " %s\n" GRAY,
-                                      module_gettext( p_parser, p_item->psz_longtext ) );
-                    else
-                        utf8_fprintf( stdout, " %s\n",
-                                      module_gettext( p_parser, p_item->psz_longtext ) );
+                case CONFIG_HINT_CATEGORY:
+                case CONFIG_HINT_USAGE:
+                    if( !strcmp( "main", p_parser->psz_object_name ) )
+                    {
+                        if( b_color )
+                            utf8_fprintf( stdout, GREEN "\n %s\n" GRAY,
+                                          module_gettext( p_parser, p_item->psz_text ) );
+                        else
+                            utf8_fprintf( stdout, "\n %s\n",
+                                          module_gettext( p_parser, p_item->psz_text ) );
+                    }
+                    if( b_description && p_item->psz_longtext )
+                    {
+                        if( b_color )
+                            utf8_fprintf( stdout, CYAN " %s\n" GRAY,
+                                          module_gettext( p_parser, p_item->psz_longtext ) );
+                        else
+                            utf8_fprintf( stdout, " %s\n",
+                                          module_gettext( p_parser, p_item->psz_longtext ) );
                 }
                 break;
 
-            case CONFIG_HINT_SUBCATEGORY:
-                if( strcmp( "main", p_parser->psz_object_name ) )
+                case CONFIG_HINT_SUBCATEGORY:
+                    if( strcmp( "main", p_parser->psz_object_name ) )
+                        break;
+                case CONFIG_SECTION:
+                    p_section = p_item;
                     break;
-            case CONFIG_SECTION:
-                p_section = p_item;
+                }
                 break;
 
             case CONFIG_ITEM_STRING:
-            case CONFIG_ITEM_FILE:
-            case CONFIG_ITEM_DIRECTORY:
-            case CONFIG_ITEM_MODULE: /* We could also have "=<" here */
-            case CONFIG_ITEM_MODULE_CAT:
-            case CONFIG_ITEM_MODULE_LIST:
-            case CONFIG_ITEM_MODULE_LIST_CAT:
-            case CONFIG_ITEM_FONT:
-            case CONFIG_ITEM_PASSWORD:
                 print_help_section( p_parser, p_section, b_color,
                                     b_description );
                 p_section = NULL;
@@ -1574,7 +1538,6 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search )
                 }
                 break;
             case CONFIG_ITEM_INTEGER:
-            case CONFIG_ITEM_KEY: /* FIXME: do something a bit more clever */
                 print_help_section( p_parser, p_section, b_color,
                                     b_description );
                 p_section = NULL;
@@ -1584,8 +1547,8 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search )
 
                 if( p_item->min.i || p_item->max.i )
                 {
-                    sprintf( psz_buffer, "%s [%i .. %i]", psz_type,
-                             p_item->min.i, p_item->max.i );
+                    sprintf( psz_buffer, "%s [%"PRId64" .. %"PRId64"]",
+                             psz_type, p_item->min.i, p_item->max.i );
                     psz_type = psz_buffer;
                 }
 
@@ -1650,7 +1613,8 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search )
                  - strlen( psz_bra ) - strlen( psz_type )
                  - strlen( psz_ket ) - 1;
 
-            if( p_item->i_type == CONFIG_ITEM_BOOL && !b_help_module )
+            if( CONFIG_CLASS(p_item->i_type) == CONFIG_ITEM_BOOL
+             && !b_help_module )
             {
                 psz_prefix =  ", --no-";
                 i -= strlen( p_item->psz_name ) + strlen( psz_prefix );
@@ -1666,7 +1630,8 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search )
                 psz_spaces[i] = '\0';
             }
 
-            if( p_item->i_type == CONFIG_ITEM_BOOL && !b_help_module )
+            if( CONFIG_CLASS(p_item->i_type) == CONFIG_ITEM_BOOL
+             && !b_help_module )
             {
                 utf8_fprintf( stdout, psz_format_bool, psz_short,
                               p_item->psz_name, psz_prefix, p_item->psz_name,
@@ -1690,6 +1655,7 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search )
             i_cur_width = b_description && !b_description_hack
                           ? i_width_description
                           : i_width;
+            if( !*psz_text ) strcpy(psz_text, " ");
             while( *psz_text )
             {
                 char *psz_parser, *psz_word;
@@ -1772,8 +1738,7 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search )
                 }
             }
 
-            if( b_description_hack && p_item->psz_longtext
-             && *p_item->psz_longtext )
+            if( b_description_hack && p_item->psz_longtext )
             {
                 sprintf( psz_buffer, "%s%s",
                          module_gettext( p_parser, p_item->psz_longtext ),
@@ -1862,19 +1827,18 @@ static void ListModules( libvlc_int_t *p_this, bool b_verbose )
 
         if( b_verbose )
         {
-            char *const *pp_shortcut = p_parser->pp_shortcuts;
-            while( *pp_shortcut )
+            char *const *pp_shortcuts = p_parser->pp_shortcuts;
+            for( unsigned i = 0; i < p_parser->i_shortcuts; i++ )
             {
-                if( strcmp( *pp_shortcut, p_parser->psz_object_name ) )
+                if( strcmp( pp_shortcuts[i], p_parser->psz_object_name ) )
                 {
                     if( b_color )
                         utf8_fprintf( stdout, CYAN"   s %s\n"GRAY,
-                                      *pp_shortcut );
+                                      pp_shortcuts[i] );
                     else
                         utf8_fprintf( stdout, "   s %s\n",
-                                      *pp_shortcut );
+                                      pp_shortcuts[i] );
                 }
-                pp_shortcut++;
             }
             if( p_parser->psz_capability )
             {
@@ -1903,12 +1867,11 @@ static void ListModules( libvlc_int_t *p_this, bool b_verbose )
  *****************************************************************************/
 static void Version( void )
 {
-    extern const char psz_vlc_changeset[];
 #ifdef WIN32
     ShowConsole( true );
 #endif
 
-    utf8_fprintf( stdout, _("VLC version %s (%s)\n"), VLC_Version(),
+    utf8_fprintf( stdout, _("VLC version %s (%s)\n"), VERSION_MESSAGE,
                   psz_vlc_changeset );
     utf8_fprintf( stdout, _("Compiled by %s on %s (%s)\n"),
              VLC_CompileBy(), VLC_CompileHost(), __DATE__" "__TIME__ );
@@ -2002,15 +1965,3 @@ static int ConsoleWidth( void )
 
     return i_width;
 }
-
-#include <vlc_avcodec.h>
-
-void vlc_avcodec_mutex (bool acquire)
-{
-    static vlc_mutex_t lock = VLC_STATIC_MUTEX;
-
-    if (acquire)
-        vlc_mutex_lock (&lock);
-    else
-        vlc_mutex_unlock (&lock);
-}