]> git.sesse.net Git - vlc/commitdiff
Reenables D-Bus one instance code, without needing to modify libvlc structs
authorRafaël Carré <funman@videolan.org>
Tue, 21 Nov 2006 21:13:42 +0000 (21:13 +0000)
committerRafaël Carré <funman@videolan.org>
Tue, 21 Nov 2006 21:13:42 +0000 (21:13 +0000)
Outputs an error and continue if D-Bus control isn't enabled on the first instance
Removes unneeded NewInstance signal
Closes #505

modules/control/dbus.c
modules/control/dbus.h
src/libvlc-common.c
src/libvlc.h

index 345fcbba13f9893aec7996b1c4657ae781d390fb..19229019779268e276a237397570bbf020861997 100644 (file)
@@ -49,9 +49,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <sys/types.h> /* getpid() */
-#include <unistd.h> /* getpid() */
-
 #include "dbus.h"
 
 #include <vlc/vlc.h>
@@ -307,15 +304,6 @@ DBUS_METHOD( TogglePause )
     REPLY_SEND;
 }
 
-DBUS_SIGNAL( NewInstance )
-{ /* emits a signal with vlc pid */
-    SIGNAL_INIT( "NewInstance" );
-    OUT_ARGUMENTS;
-    dbus_uint32_t i_pid = (dbus_uint32_t) getpid();
-    ADD_UINT32( &i_pid );
-    SIGNAL_SEND;
-}
-
 DBUS_METHOD( AddMRL )
 { /* add the string to the playlist, and play it if the boolean is true */
     REPLY_INIT;
@@ -423,17 +411,8 @@ static int Open( vlc_object_t *p_this )
         return VLC_EGENERIC;
     }
 
-    /* we request the service org.videolan.vlc */    
-    dbus_bus_request_name( p_conn, VLC_DBUS_SERVICE,
-            DBUS_NAME_FLAG_REPLACE_EXISTING , &error );
-    if (dbus_error_is_set( &error ) )
-    { 
-        msg_Err( p_this, "Error requesting %s service: %s\n", VLC_DBUS_SERVICE,
-                error.message );
-        dbus_error_free( &error );
-        free( p_sys );
-        return VLC_EGENERIC;
-    }
+    /* we unregister the object /, registered by libvlc */
+    dbus_connection_unregister_object_path( p_conn, "/" );
 
     /* we register the object /org/videolan/vlc */
     dbus_connection_register_object_path( p_conn, VLC_DBUS_OBJECT_PATH,
@@ -479,8 +458,6 @@ static void Close   ( vlc_object_t *p_this )
 
 static void Run          ( intf_thread_t *p_intf )
 {
-    NewInstance( p_intf->p_sys->p_conn, NULL );
-
     while( !p_intf->b_die )
     {
         msleep( INTF_IDLE_SLEEP );
index 0acf53dd7961725d24b7b69ebf60be7c3d6fdc18..9948770106db7ce4739c8c7a30bae61c629ff942 100644 (file)
@@ -23,6 +23,9 @@
 
 /* DBUS IDENTIFIERS */
 
+/* this is also defined in src/libvlc-common.c for one-instance mode */
+
+/* name registered on the session bus */
 #define VLC_DBUS_SERVICE        "org.videolan.vlc"
 #define VLC_DBUS_INTERFACE      "org.videolan.vlc"
 #define VLC_DBUS_OBJECT_PATH    "/org/videolan/vlc"
 #define REPLY_INIT \
     DBusMessage* p_msg = dbus_message_new_method_return( p_from ); \
     if( !p_msg ) return DBUS_HANDLER_RESULT_NEED_MEMORY; \
-    dbus_uint32_t i_serial = 0
 
 #define REPLY_SEND \
-    if( !dbus_connection_send( p_conn, p_msg, &i_serial ) ) \
+    if( !dbus_connection_send( p_conn, p_msg, NULL ) ) \
         return DBUS_HANDLER_RESULT_NEED_MEMORY; \
     dbus_connection_flush( p_conn ); \
     dbus_message_unref( p_msg ); \
     DBusMessage *p_msg = dbus_message_new_signal( VLC_DBUS_OBJECT_PATH, \
         VLC_DBUS_INTERFACE, signal ); \
     if( !p_msg ) return DBUS_HANDLER_RESULT_NEED_MEMORY; \
-    dbus_uint32_t i_serial = 0
 
 #define SIGNAL_SEND \
-    if( !dbus_connection_send( p_conn, p_msg, &i_serial ) ) \
+    if( !dbus_connection_send( p_conn, p_msg, NULL ) ) \
     return DBUS_HANDLER_RESULT_NEED_MEMORY; \
     dbus_message_unref( p_msg ); \
     dbus_connection_flush( p_conn ); \
index 318bdcec2890725f6d98c8c25d25e3bb1b8fd0be..ca82822f9c29a1d2bd6a1ae3cbe9e85a2309354d 100644 (file)
 #   include <locale.h>
 #endif
 
+#ifdef HAVE_DBUS_3
+#   include <dbus/dbus.h>
+
+/* this is also defined in modules/control/dbus.h */
+/* names registered on the session bus */
+#define VLC_DBUS_SERVICE        "org.videolan.vlc"
+#define VLC_DBUS_INTERFACE      "org.videolan.vlc"
+#define VLC_DBUS_OBJECT_PATH    "/org/videolan/vlc"
+#endif
+
 #ifdef HAVE_HAL
 #   include <hal/libhal.h>
 #endif
@@ -215,6 +225,40 @@ libvlc_int_t * libvlc_InternalCreate( void )
     return p_libvlc;
 }
 
+/*
+ * D-Bus callback needed in libvlc_InternalInit()
+ */
+#ifdef HAVE_DBUS_3
+/* Handling of messages received on / object */
+static DBusHandlerResult handle_root
+    ( DBusConnection *p_conn, DBusMessage *p_from, void *p_data ) 
+{
+    DBusMessage* p_msg = dbus_message_new_method_return( p_from );
+    if( !p_msg ) return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+    DBusMessageIter args;
+    dbus_message_iter_init_append( p_msg, &args );
+
+    char *p_root = malloc( strlen( "<node name='/'></node>" ) );
+    if (!p_root ) return DBUS_HANDLER_RESULT_NEED_MEMORY;
+    sprintf( p_root, "<node name='/'></node>" );
+
+    if( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING, &p_root ) )
+            return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+    if( !dbus_connection_send( p_conn, p_msg, NULL ) )
+        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+    dbus_connection_flush( p_conn );
+    dbus_message_unref( p_msg );
+    return DBUS_HANDLER_RESULT_HANDLED;
+}
+/* vtable passed to dbus_connection_register_object_path() */
+static DBusObjectPathVTable vlc_dbus_root_vtable = {
+    NULL, handle_root, NULL, NULL, NULL, NULL
+};
+
+#endif
+
 /**
  * Initialize a libvlc instance
  * This function initializes a previously allocated libvlc instance:
@@ -569,6 +613,166 @@ 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
+    /* Initialise D-Bus interface, check for other instances */
+    DBusConnection  *p_conn;
+    DBusError       dbus_error;
+    int             i_dbus_service;
+
+    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 the D-Bus session daemon: %s",
+                dbus_error.message );
+        dbus_error_free( &dbus_error );
+    }
+    else
+    {
+        /* we request the service org.videolan.vlc */
+        i_dbus_service = dbus_bus_request_name( p_conn, VLC_DBUS_SERVICE, 0, 
+                &dbus_error );
+        if( dbus_error_is_set( &dbus_error ) )
+        { 
+            msg_Err( p_libvlc, "Error requesting %s service: %s\n",
+                    VLC_DBUS_SERVICE, dbus_error.message );
+            dbus_error_free( &dbus_error );
+        }
+        else
+        {
+            if( i_dbus_service != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER )
+            { /* the name is already registered by another instance of vlc */
+                if( config_GetInt( p_libvlc, "one-instance" ) )
+                {
+                    /* check if /org/videolan/vlc exists
+                     * 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(
+                            VLC_DBUS_SERVICE, VLC_DBUS_OBJECT_PATH,
+                            VLC_DBUS_INTERFACE, "Nothing" );
+                    /* block unti 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_Err( p_libvlc, "one instance mode has been "
+                                "set but D-Bus control interface is not "
+                                "enabled. Enable it and restart vlc, or "
+                                "disable one instance mode." );
+                    }
+                    else
+                    {
+                        dbus_message_unref( p_test_reply );
+                        msg_Warn( p_libvlc,
+                                "Another vlc instance exists: will now exit");
+
+                        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, "Give %s to other vlc\n",
+                                    ppsz_argv[i_input] );
+
+                            p_dbus_msg = dbus_message_new_method_call(
+                                    VLC_DBUS_SERVICE, VLC_DBUS_OBJECT_PATH,
+                                    VLC_DBUS_INTERFACE, "AddMRL" );
+
+                            if ( NULL == p_dbus_msg )
+                            {
+                                msg_Err( p_libvlc, "D-Bus problem" );
+                                system_End( p_libvlc );
+                                exit( 0 );
+                            }
+
+                            /* 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( 0 );
+                            }
+                            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( 0 );
+                            }
+
+                            /* 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( 0 );
+                            }
+
+                            if ( NULL == p_dbus_pending )
+                            {
+                                msg_Err( p_libvlc, "D-Bus problem" );
+                                dbus_message_unref( p_dbus_msg );
+                                system_End( p_libvlc );
+                                exit( 0 );
+                            }
+                            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( 0 );
+                    }
+                } /* we're not in one-instance mode */
+                else
+                {
+                    msg_Dbg( p_libvlc, 
+                            "%s is already registered on the session bus\n",
+                            VLC_DBUS_SERVICE );
+                }
+            } /* the named is owned by something else */
+            else
+            {
+                /* register "/" object */
+                if( !dbus_connection_register_object_path( p_conn, "/", 
+                        &vlc_dbus_root_vtable, NULL ) )
+                {
+                    msg_Err( p_libvlc, "Out of memory" );
+                }
+                msg_Dbg( p_libvlc, 
+                        "We are the primary owner of %s on the session bus",
+                        VLC_DBUS_SERVICE );
+            }
+        } /* no error when requesting the name on the bus */
+        /* we unreference the connection when we've finished with it */
+        dbus_connection_unref( p_conn );
+    } /* ( p_conn != NULL ) */
+#endif
+
     /*
      * Message queue options
      */
index cb772141ca1c0d23e0e79be35a041020aef6e5b1..c93e4bb7c3b11e66ce683c60319fd5355bcea6a1 100644 (file)
@@ -1622,8 +1622,7 @@ vlc_module_begin();
         change_need_restart();
 #endif
 
-
-#if 0 //defined(HAVE_DBUS_3)
+#if defined(HAVE_DBUS_3)
     add_bool( "one-instance", 0, NULL, ONEINSTANCE_DBUS_TEXT,
               ONEINSTANCE_DBUS_LONGTEXT, VLC_TRUE );
     add_bool( "playlist-enqueue", 0, NULL, PLAYLISTENQUEUE_TEXT,