if test "${enable_dbus}" != "no"
then
- PKG_CHECK_MODULES(DBUS, dbus-1 >= 0.92,
- [ AC_DEFINE( HAVE_DBUS_2, 1, [Define if you have the D-BUS library API >= 0.92] )
+ dnl api stable dbus
+ PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.0.0,
+ [ AC_DEFINE( HAVE_DBUS_3, 1, [Define if you have the D-BUS library API >= 1.0.0] )
+ AC_DEFINE( HAVE_DBUS_2, 1, [Define if you have the D-BUS library API >= 0.92] )
AC_DEFINE( HAVE_DBUS_1, 1, [Define if you have the D-BUS library API >= 0.30] )
AC_DEFINE( HAVE_DBUS, 1, [Define if you have the D-BUS library] )
VLC_ADD_LDFLAGS([screensaver],[$DBUS_LIBS])
- VLC_ADD_CFLAGS([screensaver],[$DBUS_CFLAGS])],
- dnl older dbus
- [ PKG_CHECK_MODULES(DBUS, dbus-1 >= 0.30,
- [ AC_DEFINE( HAVE_DBUS_1, 1, [Define if you have the D-BUS library API >= 0.30 ] )
+ VLC_ADD_CFLAGS([screensaver],[$DBUS_CFLAGS])
+ dnl Check for dbus control interface
+ AC_ARG_ENABLE(dbus-control, [ --enable-dbus-control D-BUS control interface (default disabled)])
+ if test "${enable_dbus_control}" = "yes"
+ then
+ VLC_ADD_PLUGINS([dbus])
+ VLC_ADD_LDFLAGS([dbus],[$DBUS_LIBS])
+ VLC_ADD_CFLAGS([dbus],[$DBUS_CFLAGS])
+ fi],
+ dnl not too old dbus
+ PKG_CHECK_MODULES(DBUS, dbus-1 >= 0.92,
+ [ AC_DEFINE( HAVE_DBUS_2, 1, [Define if you have the D-BUS library API >= 0.92] )
+ AC_DEFINE( HAVE_DBUS_1, 1, [Define if you have the D-BUS library API >= 0.30] )
AC_DEFINE( HAVE_DBUS, 1, [Define if you have the D-BUS library] )
VLC_ADD_LDFLAGS([screensaver],[$DBUS_LIBS])
VLC_ADD_CFLAGS([screensaver],[$DBUS_CFLAGS])],
- dnl much older dbus
- [ PKG_CHECK_MODULES( DBUS, dbus-1,
- [AC_DEFINE(HAVE_DBUS, 1, [Define if you have the D-BUS library])
+ dnl older dbus
+ [ PKG_CHECK_MODULES(DBUS, dbus-1 >= 0.30,
+ [ AC_DEFINE( HAVE_DBUS_1, 1, [Define if you have the D-BUS library API >= 0.30 ] )
+ AC_DEFINE( HAVE_DBUS, 1, [Define if you have the D-BUS library] )
VLC_ADD_LDFLAGS([screensaver],[$DBUS_LIBS])
VLC_ADD_CFLAGS([screensaver],[$DBUS_CFLAGS])],
- [AC_MSG_WARN(DBUS library not found)])
- ]
- )]
+ dnl much older dbus
+ [ PKG_CHECK_MODULES( DBUS, dbus-1,
+ [AC_DEFINE(HAVE_DBUS, 1, [Define if you have the D-BUS library])
+ VLC_ADD_LDFLAGS([screensaver],[$DBUS_LIBS])
+ VLC_ADD_CFLAGS([screensaver],[$DBUS_CFLAGS])],
+ [AC_MSG_WARN(DBUS library not found)])
+ ]
+ )]
+ )
)
fi
--- /dev/null
+/*****************************************************************************
+ * dbus.c : D-Bus control interface
+ *****************************************************************************
+ * Copyright (C) 2006 Rafaël Carré
+ * $Id$
+ *
+ * Author: Rafaël Carré <funman at videolanorg>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*
+ * D-Bus Specification:
+ * http://dbus.freedesktop.org/doc/dbus-specification.html
+ * D-Bus low-level C API (libdbus)
+ * http://dbus.freedesktop.org/doc/dbus/api/html/index.html
+ */
+
+/*
+ * TODO:
+ * properties ?
+ *
+ * macros to read incoming arguments
+ *
+ * explore different possible types (arrays..)
+ *
+ * what must we do if org.videolan.vlc already exist on the bus ?
+ * ( there is more than one vlc instance )
+ */
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+
+#include <dbus/dbus.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h> /* getpid() */
+#include <unistd.h> /* getpid() */
+
+#include "dbus.h"
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc_meta.h>
+#include <vlc_input.h>
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+static void Run ( intf_thread_t * );
+
+
+static int ItemChange( vlc_object_t *p_this, const char *psz_var,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data );
+
+struct intf_sys_t
+{
+ DBusConnection *p_conn;
+};
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+
+vlc_module_begin();
+ set_shortname( _("dbus"));
+ set_category( CAT_INTERFACE );
+ set_subcategory( SUBCAT_INTERFACE_CONTROL );
+ set_description( _("D-Bus control interface") );
+ set_capability( "interface", 0 );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+/*****************************************************************************
+ * Methods
+ *****************************************************************************/
+
+DBUS_METHOD( Nothing )
+{ /* do nothing */
+ REPLY_INIT;
+ REPLY_SEND;
+}
+
+DBUS_METHOD( GetPlayStatus )
+{ /* return a string */
+ REPLY_INIT;
+ OUT_ARGUMENTS;
+
+ char *psz_play;
+ vlc_value_t val;
+ playlist_t *p_playlist = pl_Yield( (vlc_object_t*) p_this );
+ PL_LOCK;
+ input_thread_t *p_input = p_playlist->p_input;
+
+ if( !p_input )
+ psz_play = strdup( "stopped" );
+ else
+ {
+ var_Get( p_input, "state", &val );
+ if( val.i_int == PAUSE_S )
+ psz_play = strdup( "pause" );
+ else if( val.i_int == PLAYING_S )
+ psz_play = strdup( "playing" );
+ else psz_play = strdup( "unknown" );
+ }
+
+ PL_UNLOCK;
+ pl_Release( p_playlist );
+
+ ADD_STRING( &psz_play );
+ free( psz_play );
+ REPLY_SEND;
+}
+
+DBUS_METHOD( TogglePause )
+{ /* return a bool: true if playing */
+ REPLY_INIT;
+ OUT_ARGUMENTS;
+
+ vlc_value_t val;
+ playlist_t *p_playlist = pl_Yield( (vlc_object_t*) p_this );
+ PL_LOCK;
+ input_thread_t *p_input = p_playlist->p_input;
+
+ if( p_input )
+ {
+ var_Get( p_input, "state", &val );
+ if( val.i_int != PAUSE_S )
+ {
+ val.i_int = PAUSE_S;
+ }
+ else
+ {
+ val.i_int = PLAYING_S;
+ }
+ var_Set( p_input, "state", val );
+ }
+ PL_UNLOCK;
+ pl_Release( p_playlist );
+
+ dbus_bool_t pause = ( val.i_int == PLAYING_S ) ? TRUE : FALSE;
+ ADD_BOOL( &pause );
+ 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;
+
+ DBusError error;
+ dbus_error_init( &error );
+
+ intf_thread_t *p_intf = (intf_thread_t*) p_this;
+ char *psz_mrl;
+ dbus_bool_t b_play;
+
+ dbus_message_get_args( p_from, &error,
+ DBUS_TYPE_STRING, &psz_mrl,
+ DBUS_TYPE_BOOLEAN, &b_play,
+ DBUS_TYPE_INVALID );
+
+ if( dbus_error_is_set( &error ) )
+ {
+ printf("error: %s\n", error.message );
+ dbus_error_free( &error );
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ playlist_t *p_playlist = pl_Yield( (vlc_object_t*) p_this );
+ input_item_t *p_item = input_ItemNew( p_intf, psz_mrl, NULL );
+ if( p_item )
+ {
+ playlist_AddInput( p_playlist, p_item,
+ ( b_play == TRUE ) ? PLAYLIST_GO|PLAYLIST_APPEND : PLAYLIST_APPEND,
+ PLAYLIST_END, VLC_TRUE );
+ }
+ pl_Release( p_playlist );
+
+ REPLY_SEND;
+}
+
+/*****************************************************************************
+ * Introspection method
+ *****************************************************************************/
+
+DBUS_METHOD( handle_introspect )
+{ /* handles introspection of /org/videolan/vlc */
+ REPLY_INIT;
+ OUT_ARGUMENTS;
+ ADD_STRING( &psz_introspection_xml_data );
+ REPLY_SEND;
+}
+
+/*****************************************************************************
+ * handle_messages: answer to incoming messages
+ *****************************************************************************/
+
+#define METHOD_FUNC( method, function ) \
+ else if( dbus_message_is_method_call( p_from, VLC_DBUS_INTERFACE, method ) )\
+ return function( p_conn, p_from, p_this )
+
+DBUS_METHOD( handle_messages )
+{ /* the main handler, that call methods */
+
+ if( dbus_message_is_method_call( p_from,
+ DBUS_INTERFACE_INTROSPECTABLE, "Introspect" ) )
+ return handle_introspect( p_conn, p_from, p_this );
+
+ /* here D-Bus method's names are associated to an handler */
+
+ METHOD_FUNC( "GetPlayStatus", GetPlayStatus );
+ METHOD_FUNC( "AddMRL", AddMRL );
+ METHOD_FUNC( "TogglePause", TogglePause );
+ METHOD_FUNC( "Nothing", Nothing );
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+/*****************************************************************************
+ * Open: initialize interface
+ *****************************************************************************/
+
+static int Open( vlc_object_t *p_this )
+{ /* initialisation of the connection */
+ intf_thread_t *p_intf = (intf_thread_t*)p_this;
+ intf_sys_t *p_sys = malloc( sizeof( intf_sys_t ) );
+ playlist_t *p_playlist;
+ DBusConnection *p_conn;
+ DBusError error;
+
+ if( !p_sys )
+ return VLC_ENOMEM;
+
+ dbus_threads_init_default();
+
+ dbus_error_init( &error );
+
+ /* connect to the session bus */
+ p_conn = dbus_bus_get( DBUS_BUS_SESSION, &error );
+ if( !p_conn )
+ {
+ msg_Err( p_this, "Failed to connect to the D-Bus session daemon: %s",
+ error.message );
+ dbus_error_free( &error );
+ free( p_sys );
+ 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 register the object /org/videolan/vlc */
+ dbus_connection_register_object_path( p_conn, VLC_DBUS_OBJECT_PATH,
+ &vlc_dbus_vtable, p_this );
+
+ dbus_connection_flush( p_conn );
+
+ p_playlist = pl_Yield( p_intf );
+ PL_LOCK;
+ var_AddCallback( p_playlist, "playlist-current", ItemChange, p_intf );
+ PL_UNLOCK;
+ pl_Release( p_playlist );
+
+ p_intf->pf_run = Run;
+ p_intf->p_sys = p_sys;
+ p_sys->p_conn = p_conn;
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close: destroy interface
+ *****************************************************************************/
+
+static void Close ( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t*) p_this;
+ playlist_t *p_playlist = pl_Yield( p_intf );;
+
+ PL_LOCK;
+ var_DelCallback( p_playlist, "playlist-current", ItemChange, p_intf );
+ PL_UNLOCK;
+ pl_Release( p_playlist );
+
+ free( p_intf->p_sys );
+}
+
+/*****************************************************************************
+ * Run: main loop
+ *****************************************************************************/
+
+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 );
+ dbus_connection_read_write_dispatch( p_intf->p_sys->p_conn, 0 );
+ }
+}
+
+/*****************************************************************************
+ * ItemChange: Playlist item change callback
+ *****************************************************************************/
+
+DBUS_SIGNAL( ItemChangeSignal )
+{ /* emit the name of the new item */
+ SIGNAL_INIT( "ItemChange" );
+ OUT_ARGUMENTS;
+
+ input_thread_t *p_input = (input_thread_t*) p_data;
+ ADD_STRING( &p_input->input.p_item->psz_name );
+
+ SIGNAL_SEND;
+}
+
+static int ItemChange( vlc_object_t *p_this, const char *psz_var,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+ intf_thread_t *p_intf = ( intf_thread_t* ) p_data;
+ intf_sys_t *p_sys = p_intf->p_sys;
+ playlist_t *p_playlist;
+ input_thread_t *p_input = NULL;
+ (void)p_this; (void)psz_var; (void)oldval; (void)newval;
+
+ p_playlist = pl_Yield( p_intf );
+ PL_LOCK;
+ p_input = p_playlist->p_input;
+
+ if( !p_input )
+ {
+ PL_UNLOCK;
+ pl_Release( p_playlist );
+ return VLC_SUCCESS;
+ }
+
+ vlc_object_yield( p_input );
+ PL_UNLOCK;
+ pl_Release( p_playlist );
+
+ ItemChangeSignal( p_sys->p_conn, p_input );
+
+ vlc_object_release( p_input );
+ return VLC_SUCCESS;
+}
+
--- /dev/null
+/*****************************************************************************
+ * dbus.h : D-Bus control interface
+ *****************************************************************************
+ * Copyright (C) 2006 Rafaël Carré
+ * $Id$
+ *
+ * Author: Rafaël Carré <funman at videolanorg>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/* DBUS IDENTIFIERS */
+
+#define VLC_DBUS_SERVICE "org.videolan.vlc"
+#define VLC_DBUS_INTERFACE "org.videolan.vlc"
+#define VLC_DBUS_OBJECT_PATH "/org/videolan/vlc"
+
+/* MACROS */
+
+#define DBUS_METHOD( method_function ) \
+ static DBusHandlerResult method_function \
+ ( DBusConnection *p_conn, DBusMessage *p_from, void *p_this )
+
+#define DBUS_SIGNAL( signal_function ) \
+ static DBusHandlerResult signal_function \
+ ( DBusConnection *p_conn, void *p_data )
+
+#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 ) ) \
+ return DBUS_HANDLER_RESULT_NEED_MEMORY; \
+ dbus_connection_flush( p_conn ); \
+ dbus_message_unref( p_msg ); \
+ return DBUS_HANDLER_RESULT_HANDLED
+
+#define SIGNAL_INIT( signal ) \
+ 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 ) ) \
+ return DBUS_HANDLER_RESULT_NEED_MEMORY; \
+ dbus_message_unref( p_msg ); \
+ dbus_connection_flush( p_conn ); \
+ return DBUS_HANDLER_RESULT_HANDLED
+
+#define OUT_ARGUMENTS \
+ DBusMessageIter args; \
+ dbus_message_iter_init_append( p_msg, &args )
+
+#define DBUS_ADD( dbus_type, value ) \
+ if( !dbus_message_iter_append_basic( &args, dbus_type, value ) ) \
+ return DBUS_HANDLER_RESULT_NEED_MEMORY
+
+#define ADD_STRING( s ) DBUS_ADD( DBUS_TYPE_STRING, s )
+#define ADD_BOOL( b ) DBUS_ADD( DBUS_TYPE_BOOLEAN, b )
+#define ADD_UINT32( i ) DBUS_ADD( DBUS_TYPE_UINT32, i )
+
+/* XML data to answer org.freedesktop.DBus.Introspectable.Introspect requests */
+
+const char* psz_introspection_xml_data =
+"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
+"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
+"<node>"
+" <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
+" <method name=\"Introspect\">\n"
+" <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
+" </method>\n"
+" </interface>\n"
+" <interface name=\"org.videolan.vlc\">\n"
+" <method name=\"GetPlayStatus\">\n"
+" <arg type=\"s\" direction=\"out\" />\n"
+" </method>\n"
+" <method name=\"TogglePause\">\n"
+" <arg type=\"s\" direction=\"out\" />\n"
+" </method>\n"
+" <method name=\"AddMRL\">\n"
+" <arg type=\"s\" direction=\"in\" />\n"
+" <arg type=\"b\" direction=\"in\" />\n"
+" </method>\n"
+" <method name=\"Nothing\">\n"
+" </method>\n"
+" </interface>\n"
+"</node>\n"
+;
+
+/* Handling of messages received onn VLC_DBUS_OBJECT_PATH */
+DBUS_METHOD( handle_messages ); /* handler function */
+
+/* vtable passed to dbus_connection_register_object_path() */
+static DBusObjectPathVTable vlc_dbus_vtable = {
+ NULL, /* Called when vtable is unregistered or its connection is freed*/
+ handle_messages, /* handler function */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+