]> git.sesse.net Git - vlc/blobdiff - src/libvlc-common.c
* Do not take and release the structure lock for each element of the list while
[vlc] / src / libvlc-common.c
index 020b1bd37caea0344aa6dc95437e47952cb2e10a..804f3c00076c7ed7beefb0e213be809fb684e281 100644 (file)
  * This file contains functions to create and destroy libvlc instances
  */
 
-/*****************************************************************************
- * Pretend we are a builtin module
- *****************************************************************************/
-#define MODULE_NAME main
-#define MODULE_PATH main
-#define __BUILTIN__
-
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
 #include <vlc/vlc.h>
-#include <libvlc_internal.h>
-#include <vlc/input.h>
+#include "control/libvlc_internal.h"
+#include <vlc_input.h>
+
+#include "misc/modules.h"
+#include "misc/configuration.h"
 
 #include <errno.h>                                                 /* ENOMEM */
 #include <stdio.h>                                              /* sprintf() */
 #   include <locale.h>
 #endif
 
+#ifdef HAVE_DBUS_3
+/* used for one-instance mode */
+#   include <dbus/dbus.h>
+#endif
+
 #ifdef HAVE_HAL
 #   include <hal/libhal.h>
 #endif
 
-#include "vlc_cpu.h"                                        /* CPU detection */
-#include "os_specific.h"
+#include "vlc_os_specific.h"
 
-#include "vlc_error.h"
+#include <vlc_playlist.h>
+#include <vlc_interface.h>
 
-#include "vlc_playlist.h"
-#include "vlc_interface.h"
+#include <vlc_aout.h>
+#include "audio_output/aout_internal.h"
 
-#include "audio_output.h"
+#include <vlc_vout.h>
 
-#include "vlc_video.h"
-#include "video_output.h"
+#include <vlc_sout.h>
+#include "stream_output/stream_output.h"
 
-#include "stream_output.h"
-#include "charset.h"
+#include <vlc_charset.h>
 
 #include "libvlc.h"
 
+#include "playlist/playlist_internal.h"
+
 /*****************************************************************************
  * The evil global variable. We handle it with care, don't worry.
  *****************************************************************************/
@@ -111,8 +113,6 @@ static void Version       ( void );
 #ifdef WIN32
 static void ShowConsole   ( vlc_bool_t );
 static void PauseConsole  ( void );
-extern void __wgetmainargs(int *argc, wchar_t ***wargv, wchar_t ***wenviron,
-                           int expand_wildcards, int *startupinfo);
 #endif
 static int  ConsoleWidth  ( void );
 
@@ -121,6 +121,9 @@ static int  VerboseCallback( vlc_object_t *, char const *,
 
 static void InitDeviceValues( libvlc_int_t * );
 
+/* Refs misc/cpu.c */
+uint32_t CPUCapabilities( void );
+
 /*****************************************************************************
  * vlc_current_object: return the current object.
  *****************************************************************************
@@ -207,7 +210,8 @@ libvlc_int_t * libvlc_InternalCreate( void )
     vlc_mutex_init( p_libvlc, &p_libvlc->quicktime_lock );
     vlc_thread_set_priority( p_libvlc, VLC_THREAD_PRIORITY_LOW );
 #endif
-
+    /* Fake attachment */
+    p_libvlc->b_attached = VLC_TRUE;
     /* Store data for the non-reentrant API */
     p_static_vlc = p_libvlc;
 
@@ -288,7 +292,7 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc, char *ppsz_argv[] )
     }
     p_help_module->psz_object_name = "help";
     p_help_module->psz_longname = N_("Help options");
-    config_Duplicate( p_help_module, p_help_config );
+    config_Duplicate( p_help_module, libvlc_config, libvlc_config_count );
     vlc_object_attach( p_help_module, libvlc_global.p_module_bank );
     /* End hack */
 
@@ -568,6 +572,127 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc, char *ppsz_argv[] )
      */
     system_Configure( p_libvlc, &i_argc, ppsz_argv );
 
+/* FIXME: could be replaced by using Unix sockets */
+#ifdef HAVE_DBUS_3
+    if( config_GetInt( p_libvlc, "one-instance" ) )
+    {
+        /* Initialise D-Bus interface, check for other instances */
+        DBusConnection  *p_conn;
+        DBusError       dbus_error;
+
+        dbus_threads_init_default();
+        dbus_error_init( &dbus_error );
+
+        /* connect to the session bus */
+        p_conn = dbus_bus_get( DBUS_BUS_SESSION, &dbus_error );
+        if( !p_conn )
+        {
+            msg_Err( p_libvlc, "Failed to connect to D-Bus session daemon: %s",
+                    dbus_error.message );
+            dbus_error_free( &dbus_error );
+        }
+        else
+        {
+            /* check if a Media Player is available
+             * if not: D-Bus control is not enabled on the other
+             * instance and we can't pass MRLs to it */
+            DBusMessage *p_test_msg, *p_test_reply;
+            p_test_msg =  dbus_message_new_method_call(
+                    "org.freedesktop.MediaPlayer", "/",
+                    "org.freedesktop.MediaPlayer", "Identity" );
+            /* block until a reply arrives */
+            p_test_reply = dbus_connection_send_with_reply_and_block(
+                    p_conn, p_test_msg, -1, &dbus_error );
+            dbus_message_unref( p_test_msg );
+            if( p_test_reply == NULL )
+            {
+                dbus_error_free( &dbus_error );
+                msg_Dbg( p_libvlc, "No Media Player is running. "
+                        "Continuing normally." );
+            }
+            else
+            {
+                dbus_message_unref( p_test_reply );
+                msg_Warn( p_libvlc, "Another Media Player is running. Exiting");
+
+                int i_input;
+                DBusMessage* p_dbus_msg;
+                DBusMessageIter dbus_args;
+                DBusPendingCall* p_dbus_pending;
+                dbus_bool_t b_play;
+
+                for( i_input = optind;i_input < i_argc;i_input++ )
+                {
+                    msg_Dbg( p_libvlc, "Adds %s to the running Media Player",
+                            ppsz_argv[i_input] );
+
+                    p_dbus_msg = dbus_message_new_method_call(
+                            "org.freedesktop.MediaPlayer", "/TrackList",
+                            "org.freedesktop.MediaPlayer", "AddTrack" );
+
+                    if ( NULL == p_dbus_msg )
+                    {
+                        msg_Err( p_libvlc, "D-Bus problem" );
+                        system_End( p_libvlc );
+                        exit( VLC_ETIMEOUT );
+                    }
+
+                    /* 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] ) )
+                    {
+                        msg_Err( p_libvlc, "Out of memory" );
+                        dbus_message_unref( p_dbus_msg );
+                        system_End( p_libvlc );
+                        exit( VLC_ENOMEM );
+                    }
+                    b_play = TRUE;
+                    if( config_GetInt( p_libvlc, "playlist-enqueue" ) )
+                        b_play = FALSE;
+                    if ( !dbus_message_iter_append_basic( &dbus_args,
+                                DBUS_TYPE_BOOLEAN, &b_play ) )
+                    {
+                        msg_Err( p_libvlc, "Out of memory" );
+                        dbus_message_unref( p_dbus_msg );
+                        system_End( p_libvlc );
+                        exit( VLC_ENOMEM );
+                    }
+
+                    /* send message and get a handle for a reply */
+                    if ( !dbus_connection_send_with_reply ( p_conn,
+                                p_dbus_msg, &p_dbus_pending, -1 ) )
+                    {
+                        msg_Err( p_libvlc, "D-Bus problem" );
+                        dbus_message_unref( p_dbus_msg );
+                        system_End( p_libvlc );
+                        exit( VLC_ETIMEOUT );
+                    }
+
+                    if ( NULL == p_dbus_pending )
+                    {
+                        msg_Err( p_libvlc, "D-Bus problem" );
+                        dbus_message_unref( p_dbus_msg );
+                        system_End( p_libvlc );
+                        exit( VLC_ETIMEOUT );
+                    }
+                    dbus_connection_flush( p_conn );
+                    dbus_message_unref( p_dbus_msg );
+                    /* block until we receive a reply */
+                    dbus_pending_call_block( p_dbus_pending );
+                    dbus_pending_call_unref( p_dbus_pending );
+                } /* processes all command line MRLs */
+
+                /* bye bye */
+                system_End( p_libvlc );
+                exit( VLC_SUCCESS );
+            }
+        }
+        /* we unreference the connection when we've finished with it */
+        dbus_connection_unref( p_conn );
+    }
+#endif
+
     /*
      * Message queue options
      */
@@ -655,9 +780,9 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc, char *ppsz_argv[] )
      * Initialize hotkey handling
      */
     var_Create( p_libvlc, "key-pressed", VLC_VAR_INTEGER );
-    p_libvlc->p_hotkeys = malloc( sizeof(p_hotkeys) );
+    p_libvlc->p_hotkeys = malloc( libvlc_hotkeys_size );
     /* Do a copy (we don't need to modify the strings) */
-    memcpy( p_libvlc->p_hotkeys, p_hotkeys, sizeof(p_hotkeys) );
+    memcpy( p_libvlc->p_hotkeys, libvlc_hotkeys, libvlc_hotkeys_size );
 
     /* Initialize playlist and get commandline files */
     playlist_ThreadCreate( p_libvlc );
@@ -677,7 +802,7 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc, char *ppsz_argv[] )
     if( psz_modules && *psz_modules )
     {
         /* Add service discovery modules */
-        playlist_AddSDModules( p_playlist, psz_modules );
+        playlist_ServicesDiscoveryAdd( p_playlist, psz_modules );
     }
     if( psz_modules ) free( psz_modules );
 
@@ -746,7 +871,7 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc, char *ppsz_argv[] )
 #ifdef HAVE_SYSLOG_H
     if( config_GetInt( p_libvlc, "syslog" ) == 1 )
     {
-        char *psz_logmode = "logmode=syslog";
+        const char *psz_logmode = "logmode=syslog";
         libvlc_InternalAddIntf( 0, "logger,none", VLC_FALSE, VLC_FALSE,
                                 1, &psz_logmode );
     }
@@ -903,6 +1028,7 @@ int libvlc_InternalDestroy( libvlc_int_t *p_libvlc, vlc_bool_t b_release )
 
     /* Destroy mutexes */
     vlc_mutex_destroy( &p_libvlc->config_lock );
+    vlc_mutex_destroy( &p_libvlc->timer_lock );
 
     if( b_release ) vlc_object_release( p_libvlc );
     vlc_object_destroy( p_libvlc );
@@ -921,7 +1047,7 @@ int libvlc_InternalDestroy( libvlc_int_t *p_libvlc, vlc_bool_t b_release )
 int libvlc_InternalAddIntf( libvlc_int_t *p_libvlc,
                             char const *psz_module,
                             vlc_bool_t b_block, vlc_bool_t b_play,
-                            int i_options, char **ppsz_options )
+                            int i_options, const char *const *ppsz_options )
 {
     int i_err;
     intf_thread_t *p_intf;
@@ -978,7 +1104,7 @@ static void SetLanguage ( char const *psz_lang )
 #if defined( ENABLE_NLS ) \
      && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
 
-    char *          psz_path;
+    const char *          psz_path;
 #if defined( __APPLE__ ) || defined ( WIN32 ) || defined( SYS_BEOS )
     char            psz_tmp[1024];
 #endif
@@ -1040,17 +1166,6 @@ static int GetFilenames( libvlc_int_t *p_vlc, int i_argc, char *ppsz_argv[] )
 {
     int i_opt, i_options;
 
-#ifdef WIN32
-    wchar_t **wargv, **wenvp;
-    int si = { 0 };
-
-    if( GetVersion() < 0x80000000 )
-    {
-        /* fetch unicode argv[] for Windows NT and above */
-        __wgetmainargs(&i_opt, &wargv, &wenvp, 0, &si);
-    }
-#endif
-
     /* We assume that the remaining parameters are filenames
      * and their input options */
     for( i_opt = i_argc - 1; i_opt >= optind; i_opt-- )
@@ -1072,12 +1187,10 @@ static int GetFilenames( libvlc_int_t *p_vlc, int i_argc, char *ppsz_argv[] )
 #ifdef WIN32
         if( GetVersion() < 0x80000000 )
         {
-            psz_target = FromWide( wargv[ i_opt ] );
-            VLC_AddTarget( p_vlc->i_object_id, psz_target,
+            VLC_AddTarget( p_vlc->i_object_id, ppsz_argv[i_opt],
                        (char const **)( i_options ? &ppsz_argv[i_opt + 1] :
                                         NULL ), i_options,
                        PLAYLIST_INSERT, 0 );
-            free( psz_target );
         }
         else
 #endif
@@ -1107,13 +1220,13 @@ static void Help( libvlc_int_t *p_this, char const *psz_help_name )
 
     if( psz_help_name && !strcmp( psz_help_name, "help" ) )
     {
-        utf8_fprintf( stdout, VLC_USAGE, p_this->psz_object_name );
+        utf8_fprintf( stdout, vlc_usage, p_this->psz_object_name );
         Usage( p_this, "help" );
         Usage( p_this, "main" );
     }
     else if( psz_help_name && !strcmp( psz_help_name, "longhelp" ) )
     {
-        utf8_fprintf( stdout, VLC_USAGE, p_this->psz_object_name );
+        utf8_fprintf( stdout, vlc_usage, p_this->psz_object_name );
         Usage( p_this, NULL );
     }
     else if( psz_help_name )
@@ -1147,9 +1260,12 @@ static void Usage( libvlc_int_t *p_this, char const *psz_module_name )
      */
 #define LINE_START 8
 #define PADDING_SPACES 25
+#ifdef WIN32
+#   define OPTION_VALUE_SEP "="
+#else
+#   define OPTION_VALUE_SEP " "
+#endif
     vlc_list_t *p_list;
-    module_t *p_parser;
-    module_config_t *p_item;
     char psz_spaces_text[PADDING_SPACES+LINE_START+1];
     char psz_spaces_longtext[LINE_START+3];
     char psz_format[sizeof(FORMAT_STRING)];
@@ -1174,8 +1290,9 @@ static void Usage( libvlc_int_t *p_this, char const *psz_module_name )
     for( i_index = 0; i_index < p_list->i_count; i_index++ )
     {
         vlc_bool_t b_help_module;
-
-        p_parser = (module_t *)p_list->p_values[i_index].p_object ;
+        module_t *p_parser = (module_t *)p_list->p_values[i_index].p_object;
+        module_config_t *p_item,
+                        *p_end = p_parser->p_config + p_parser->confsize;
 
         if( psz_module_name && strcmp( psz_module_name,
                                        p_parser->psz_object_name ) )
@@ -1193,13 +1310,12 @@ static void Usage( libvlc_int_t *p_this, char const *psz_module_name )
         if( !b_advanced )
         {
             for( p_item = p_parser->p_config;
-                 p_item->i_type != CONFIG_HINT_END;
+                 p_item < p_end;
                  p_item++ )
             {
                 if( (p_item->i_type & CONFIG_ITEM) &&
                     !p_item->b_advanced ) break;
             }
-            if( p_item->i_type == CONFIG_HINT_END ) continue;
         }
 
         /* Print name of module */
@@ -1210,12 +1326,12 @@ static void Usage( libvlc_int_t *p_this, char const *psz_module_name )
 
         /* Print module options */
         for( p_item = p_parser->p_config;
-             p_item->i_type != CONFIG_HINT_END;
+             p_item < p_end;
              p_item++ )
         {
             char *psz_text, *psz_spaces = psz_spaces_text;
-            char *psz_bra = NULL, *psz_type = NULL, *psz_ket = NULL;
-            char *psz_suf = "", *psz_prefix = NULL;
+            const char *psz_bra = NULL, *psz_type = NULL, *psz_ket = NULL;
+            const char *psz_suf = "", *psz_prefix = NULL;
             signed int i;
 
             /* Skip deprecated options */
@@ -1244,34 +1360,38 @@ static void Usage( libvlc_int_t *p_this, char const *psz_module_name )
             case CONFIG_ITEM_MODULE_CAT:
             case CONFIG_ITEM_MODULE_LIST:
             case CONFIG_ITEM_MODULE_LIST_CAT:
-                psz_bra = " <"; psz_type = _("string"); psz_ket = ">";
+                psz_bra = OPTION_VALUE_SEP "<";
+                psz_type = _("string");
+                psz_ket = ">";
 
                 if( p_item->ppsz_list )
                 {
-                    psz_bra = {";
+                    psz_bra = OPTION_VALUE_SEP "{";
                     psz_type = psz_buffer;
-                    psz_type[0] = '\0';
+                    psz_buffer[0] = '\0';
                     for( i = 0; p_item->ppsz_list[i]; i++ )
                     {
-                        if( i ) strcat( psz_type, "," );
-                        strcat( psz_type, p_item->ppsz_list[i] );
+                        if( i ) strcat( psz_buffer, "," );
+                        strcat( psz_buffer, p_item->ppsz_list[i] );
                     }
                     psz_ket = "}";
                 }
                 break;
             case CONFIG_ITEM_INTEGER:
             case CONFIG_ITEM_KEY: /* FIXME: do something a bit more clever */
-                psz_bra = " <"; psz_type = _("integer"); psz_ket = ">";
+                psz_bra = OPTION_VALUE_SEP "<";
+                psz_type = _("integer");
+                psz_ket = ">";
 
                 if( p_item->i_list )
                 {
-                    psz_bra = {";
+                    psz_bra = OPTION_VALUE_SEP "{";
                     psz_type = psz_buffer;
-                    psz_type[0] = '\0';
+                    psz_buffer[0] = '\0';
                     for( i = 0; p_item->ppsz_list_text[i]; i++ )
                     {
-                        if( i ) strcat( psz_type, ", " );
-                        sprintf( psz_type + strlen(psz_type), "%i (%s)",
+                        if( i ) strcat( psz_buffer, ", " );
+                        sprintf( psz_buffer + strlen(psz_buffer), "%i (%s)",
                                  p_item->pi_list[i],
                                  p_item->ppsz_list_text[i] );
                     }
@@ -1279,13 +1399,15 @@ static void Usage( libvlc_int_t *p_this, char const *psz_module_name )
                 }
                 break;
             case CONFIG_ITEM_FLOAT:
-                psz_bra = " <"; psz_type = _("float"); psz_ket = ">";
+                psz_bra = OPTION_VALUE_SEP "<";
+                psz_type = _("float");
+                psz_ket = ">";
                 break;
             case CONFIG_ITEM_BOOL:
                 psz_bra = ""; psz_type = ""; psz_ket = "";
                 if( !b_help_module )
                 {
-                    psz_suf = p_item->i_value ? _(" (default enabled)") :
+                    psz_suf = p_item->value.i ? _(" (default enabled)") :
                                                 _(" (default disabled)");
                 }
                 break;
@@ -1670,6 +1792,7 @@ static void InitDeviceValues( libvlc_int_t *p_vlc )
 
 #ifdef HAVE_HAL_1
         libhal_ctx_shutdown( ctx, NULL );
+        dbus_connection_unref( p_connection );
 #else
         hal_shutdown( ctx );
 #endif