From 0f7dd9f908badfd128cdcd4c83de7e395b6e86a1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rafa=C3=ABl=20Carr=C3=A9?= Date: Tue, 21 Nov 2006 21:13:42 +0000 Subject: [PATCH] Reenables D-Bus one instance code, without needing to modify libvlc structs 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 | 27 +----- modules/control/dbus.h | 9 +- src/libvlc-common.c | 204 +++++++++++++++++++++++++++++++++++++++++ src/libvlc.h | 3 +- 4 files changed, 212 insertions(+), 31 deletions(-) diff --git a/modules/control/dbus.c b/modules/control/dbus.c index 345fcbba13..1922901977 100644 --- a/modules/control/dbus.c +++ b/modules/control/dbus.c @@ -49,9 +49,6 @@ #include #include -#include /* getpid() */ -#include /* getpid() */ - #include "dbus.h" #include @@ -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 ); diff --git a/modules/control/dbus.h b/modules/control/dbus.h index 0acf53dd79..9948770106 100644 --- a/modules/control/dbus.h +++ b/modules/control/dbus.h @@ -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" @@ -40,10 +43,9 @@ #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 ); \ @@ -53,10 +55,9 @@ 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 ); \ diff --git a/src/libvlc-common.c b/src/libvlc-common.c index 318bdcec28..ca82822f9c 100644 --- a/src/libvlc-common.c +++ b/src/libvlc-common.c @@ -66,6 +66,16 @@ # include #endif +#ifdef HAVE_DBUS_3 +# include + +/* 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 #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( "" ) ); + if (!p_root ) return DBUS_HANDLER_RESULT_NEED_MEMORY; + sprintf( p_root, "" ); + + 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 */ diff --git a/src/libvlc.h b/src/libvlc.h index cb772141ca..c93e4bb7c3 100644 --- a/src/libvlc.h +++ b/src/libvlc.h @@ -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, -- 2.39.5