📄 dbus.c
字号:
/***************************************************************************** * dbus.c : D-Bus control interface ***************************************************************************** * Copyright © 2006-2008 Rafaël Carré * Copyright © 2007-2008 Mirsal Ennaime * $Id: 7c8a1c9431258f3661aa1f08d356be6934eaefa7 $ * * Authors: Rafaël Carré <funman at videolanorg> * Mirsal Ennaime <mirsal dot ennaime at gmail dot com> * * 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 * extract: * "If you use this low-level API directly, you're signing up for some pain." * * MPRIS Specification (still drafting on Jan, 23 of 2008): * http://wiki.xmms2.xmms.se/index.php/MPRIS *//***************************************************************************** * Preamble *****************************************************************************/#include <dbus/dbus.h>#include "dbus.h"#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_plugin.h>#include <vlc_aout.h>#include <vlc_interface.h>#include <vlc_meta.h>#include <vlc_input.h>#include <vlc_playlist.h>#include <math.h>#include <assert.h>/***************************************************************************** * Local prototypes. *****************************************************************************/static int Open ( vlc_object_t * );static void Close ( vlc_object_t * );static void Run ( intf_thread_t * );static int StateChange( vlc_object_t *, const char *, vlc_value_t, vlc_value_t, void * );static int TrackChange( vlc_object_t *, const char *, vlc_value_t, vlc_value_t, void * );static int StatusChangeEmit( vlc_object_t *, const char *, vlc_value_t, vlc_value_t, void * );static int TrackListChangeEmit( vlc_object_t *, const char *, vlc_value_t, vlc_value_t, void * );static int GetInputMeta ( input_item_t *, DBusMessageIter * );static int MarshalStatus ( intf_thread_t *, DBusMessageIter *, bool );static int UpdateCaps( intf_thread_t*, bool );/* GetCaps() capabilities */enum{ CAPS_NONE = 0, CAPS_CAN_GO_NEXT = 1 << 0, CAPS_CAN_GO_PREV = 1 << 1, CAPS_CAN_PAUSE = 1 << 2, CAPS_CAN_PLAY = 1 << 3, CAPS_CAN_SEEK = 1 << 4, CAPS_CAN_PROVIDE_METADATA = 1 << 5, CAPS_CAN_HAS_TRACKLIST = 1 << 6};struct intf_sys_t{ DBusConnection *p_conn; bool b_meta_read; dbus_int32_t i_caps;};/***************************************************************************** * Module descriptor *****************************************************************************/vlc_module_begin(); set_shortname( N_("dbus")); set_category( CAT_INTERFACE ); set_subcategory( SUBCAT_INTERFACE_CONTROL ); set_description( N_("D-Bus control interface") ); set_capability( "interface", 0 ); set_callbacks( Open, Close );vlc_module_end();/***************************************************************************** * Methods *****************************************************************************//* Player */DBUS_METHOD( Quit ){ /* exits vlc */ REPLY_INIT; playlist_t *p_playlist = pl_Yield( (vlc_object_t*) p_this ); playlist_Stop( p_playlist ); pl_Release( ((vlc_object_t*) p_this) ); vlc_object_kill(((vlc_object_t*)p_this)->p_libvlc); REPLY_SEND;}DBUS_METHOD( MprisVersion ){ /*implemented version of the mpris spec */ REPLY_INIT; OUT_ARGUMENTS; VLC_UNUSED( p_this ); dbus_uint16_t i_major = VLC_MPRIS_VERSION_MAJOR; dbus_uint16_t i_minor = VLC_MPRIS_VERSION_MINOR; DBusMessageIter version; if( !dbus_message_iter_open_container( &args, DBUS_TYPE_STRUCT, NULL, &version ) ) return DBUS_HANDLER_RESULT_NEED_MEMORY; if( !dbus_message_iter_append_basic( &version, DBUS_TYPE_UINT16, &i_major ) ) return DBUS_HANDLER_RESULT_NEED_MEMORY; if( !dbus_message_iter_append_basic( &version, DBUS_TYPE_UINT16, &i_minor ) ) return DBUS_HANDLER_RESULT_NEED_MEMORY; if( !dbus_message_iter_close_container( &args, &version ) ) return DBUS_HANDLER_RESULT_NEED_MEMORY; REPLY_SEND;}DBUS_METHOD( PositionGet ){ /* returns position in milliseconds */ REPLY_INIT; OUT_ARGUMENTS; vlc_value_t position; dbus_int32_t i_pos; 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 ) i_pos = 0; else { var_Get( p_input, "time", &position ); i_pos = position.i_time / 1000; } PL_UNLOCK; pl_Release( ((vlc_object_t*) p_this) ); ADD_INT32( &i_pos ); REPLY_SEND;}DBUS_METHOD( PositionSet ){ /* set position in milliseconds */ REPLY_INIT; vlc_value_t position; playlist_t* p_playlist = NULL; dbus_int32_t i_pos; DBusError error; dbus_error_init( &error ); dbus_message_get_args( p_from, &error, DBUS_TYPE_INT32, &i_pos, DBUS_TYPE_INVALID ); if( dbus_error_is_set( &error ) ) { msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s\n", error.message ); dbus_error_free( &error ); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } p_playlist = pl_Yield( ((vlc_object_t*) p_this) ); PL_LOCK; input_thread_t *p_input = p_playlist->p_input; if( p_input ) { position.i_time = i_pos * 1000; var_Set( p_input, "time", position ); } PL_UNLOCK; pl_Release( ((vlc_object_t*) p_this) ); REPLY_SEND;}DBUS_METHOD( VolumeGet ){ /* returns volume in percentage */ REPLY_INIT; OUT_ARGUMENTS; dbus_int32_t i_dbus_vol; audio_volume_t i_vol; /* 2nd argument of aout_VolumeGet is int32 */ aout_VolumeGet( (vlc_object_t*) p_this, &i_vol ); double f_vol = 100. * i_vol / AOUT_VOLUME_MAX; i_dbus_vol = round( f_vol ); ADD_INT32( &i_dbus_vol ); REPLY_SEND;}DBUS_METHOD( VolumeSet ){ /* set volume in percentage */ REPLY_INIT; DBusError error; dbus_error_init( &error ); dbus_int32_t i_dbus_vol; audio_volume_t i_vol; dbus_message_get_args( p_from, &error, DBUS_TYPE_INT32, &i_dbus_vol, DBUS_TYPE_INVALID ); if( dbus_error_is_set( &error ) ) { msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s\n", error.message ); dbus_error_free( &error ); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } double f_vol = AOUT_VOLUME_MAX * i_dbus_vol / 100.; i_vol = round( f_vol ); aout_VolumeSet( (vlc_object_t*) p_this, i_vol ); REPLY_SEND;}DBUS_METHOD( Next ){ /* next playlist item */ REPLY_INIT; playlist_t *p_playlist = pl_Yield( ((vlc_object_t*) p_this) ); playlist_Next( p_playlist ); pl_Release( ((vlc_object_t*) p_this) ); REPLY_SEND;}DBUS_METHOD( Prev ){ /* previous playlist item */ REPLY_INIT; playlist_t *p_playlist = pl_Yield( ((vlc_object_t*) p_this) ); playlist_Prev( p_playlist ); pl_Release( ((vlc_object_t*) p_this) ); REPLY_SEND;}DBUS_METHOD( Stop ){ /* stop playing */ REPLY_INIT; playlist_t *p_playlist = pl_Yield( ((vlc_object_t*) p_this) ); playlist_Stop( p_playlist ); pl_Release( ((vlc_object_t*) p_this) ); REPLY_SEND;}DBUS_METHOD( GetStatus ){ /* returns the current status as a struct of 4 ints *//* First 0 = Playing, 1 = Paused, 2 = Stopped. Second 0 = Playing linearly , 1 = Playing randomly. Third 0 = Go to the next element once the current has finished playing , 1 = Repeat the current element Fourth 0 = Stop playing once the last element has been played, 1 = Never give up playing * */ REPLY_INIT; OUT_ARGUMENTS; MarshalStatus( p_this, &args, true ); REPLY_SEND;}DBUS_METHOD( Pause ){ REPLY_INIT; playlist_t *p_playlist = pl_Yield( (vlc_object_t*) p_this ); playlist_Pause( p_playlist ); pl_Release( (vlc_object_t*) p_this ); REPLY_SEND;}DBUS_METHOD( Play ){ REPLY_INIT; 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 ) vlc_object_yield( p_input ); PL_UNLOCK; if( p_input ) { double i_pos = 0; input_Control( p_input, INPUT_SET_POSITION, i_pos ); vlc_object_release( p_input ); } else playlist_Play( p_playlist ); pl_Release( (vlc_object_t*) p_this ); REPLY_SEND;}DBUS_METHOD( GetCurrentMetadata ){ REPLY_INIT; OUT_ARGUMENTS; playlist_t* p_playlist = pl_Yield( (vlc_object_t*) p_this ); PL_LOCK; if( p_playlist->status.p_item ) GetInputMeta( p_playlist->status.p_item->p_input, &args ); PL_UNLOCK; pl_Release( (vlc_object_t*) p_this ); REPLY_SEND;}DBUS_METHOD( GetCaps ){ REPLY_INIT; OUT_ARGUMENTS; ADD_INT32( &((intf_thread_t*)p_this)->p_sys->i_caps ); REPLY_SEND;}/* Media Player information */DBUS_METHOD( Identity ){ VLC_UNUSED(p_this); REPLY_INIT; OUT_ARGUMENTS; char *psz_identity; if( asprintf( &psz_identity, "%s %s", PACKAGE, VERSION ) != -1 ) { ADD_STRING( &psz_identity ); free( psz_identity ); } else return DBUS_HANDLER_RESULT_NEED_MEMORY; REPLY_SEND;}/* TrackList */DBUS_METHOD( AddTrack ){ /* add the string to the playlist, and play it if the boolean is true */ REPLY_INIT; OUT_ARGUMENTS; DBusError error; dbus_error_init( &error ); playlist_t* p_playlist = NULL; 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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -