Commit 46fb5ca4 authored by Jean-Paul Saman's avatar Jean-Paul Saman

dbus: extend dbus to proposed v2.0 of MPRIS specification.

parent 4a624114
......@@ -4,10 +4,13 @@
* Copyright © 2006-2008 Rafaël Carré
* Copyright © 2007-2008 Mirsal Ennaime
* Copyright © 2009 The VideoLAN team
* Copyright © 2009 M2X BV
*
* $Id$
*
* Authors: Rafaël Carré <funman at videolanorg>
* Mirsal Ennaime <mirsal dot ennaime at gmail dot com>
* Jean-Paul Saman <jean-paul dot saman at m2x dot nl>
*
* 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
......@@ -50,6 +53,7 @@
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_aout.h>
#include <vlc_vout.h>
#include <vlc_interface.h>
#include <vlc_playlist.h>
......@@ -73,20 +77,23 @@ static int TrackListChangeEmit( intf_thread_t *, int, int );
static int AllCallback( vlc_object_t*, const char*, vlc_value_t, vlc_value_t, void* );
static int GetInputMeta ( input_item_t *, DBusMessageIter * );
static int GetInputEsMeta( input_item_t *, int32_t, DBusMessageIter * );
static int MarshalStatus ( intf_thread_t *, DBusMessageIter *, bool );
static int UpdateCaps( intf_thread_t* );
/* GetCaps() capabilities */
enum
{
CAPS_NONE = 0,
CAPS_NONE = 0, /* MPRIS v1.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
CAPS_CAN_HAS_TRACKLIST = 1 << 6,
CAPS_CAN_RATE = 1 << 7, /* MPRIS v2.0 */
CAPS_CAN_PROVIDE_ES = 1 << 8 /* MPRIS v2.0 */
};
// The signal that can be get from the callbacks
......@@ -119,7 +126,6 @@ typedef struct
int i_input_state;
} callback_info_t;
/*****************************************************************************
* Module descriptor
*****************************************************************************/
......@@ -610,6 +616,720 @@ DBUS_METHOD( SetRandom )
REPLY_SEND;
}
DBUS_METHOD( GetRate )
{
REPLY_INIT;
OUT_ARGUMENTS;
float f_rate = 0.0;
playlist_t *p_playlist = pl_Hold( (vlc_object_t*) p_this );
input_thread_t* p_input = playlist_CurrentInput( p_playlist );
if( p_input )
{
int32_t i_rate;
bool b_can_rewind;
i_rate = var_GetInteger( p_input, "rate" );
b_can_rewind = var_GetBool( p_input, "can-rewind" );
if( (i_rate < 0) && !b_can_rewind )
f_rate = 0.0;
else
f_rate = (float)1000.0f/i_rate;
vlc_object_release( p_input );
}
pl_Release( (vlc_object_t*) p_this );
double rate = (double) f_rate;
ADD_DOUBLE( &rate );
REPLY_SEND;
}
DBUS_METHOD( SetRate )
{
REPLY_INIT;
OUT_ARGUMENTS;
DBusError error;
double rate = 0.0;
dbus_int32_t i_success = -1;
dbus_error_init( &error );
dbus_message_get_args( p_from, &error,
DBUS_TYPE_DOUBLE, &rate,
DBUS_TYPE_INVALID );
if( dbus_error_is_set( &error ) )
{
msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
error.message );
dbus_error_free( &error );
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
playlist_t *p_playlist = pl_Hold( (vlc_object_t*) p_this );
input_thread_t* p_input = playlist_CurrentInput( p_playlist );
if( p_input )
{
bool b_can_rewind;
b_can_rewind = var_GetBool( p_input, "can-rewind" );
if( (rate < 0.0) && !b_can_rewind )
i_success = -1;
else
{
int32_t i_rate = 1000.0f/(float)rate;
int i_ret = var_SetInteger( p_input, "rate", i_rate );
if( i_ret == 0 )
i_success = 0;
}
vlc_object_release( p_input );
}
pl_Release( ((vlc_object_t*) p_this) );
ADD_INT32( &i_success );
REPLY_SEND;
}
/*
* /ES object method
*/
DBUS_METHOD( GetVideoES )
{
REPLY_INIT;
OUT_ARGUMENTS;
dbus_int32_t i_es = 0;
playlist_t *p_playlist = pl_Hold( (vlc_object_t*) p_this );
input_thread_t *p_input = playlist_CurrentInput( p_playlist );
if( p_input )
{
vlc_value_t val;
int i_ret = -1;
i_ret = var_Get( p_input, "video-es", &val );
if( i_ret >= 0 )
{
vlc_value_t val_list;
int i;
var_Change( p_input, "video-es", VLC_VAR_GETCHOICES, &val_list, NULL );
for( i = 0; i < val_list.p_list->i_count; i++ )
{
vlc_value_t es_val = val_list.p_list->p_values[i];
if( es_val.i_int == val.i_int )
{
i_es = i;
break;
}
}
}
vlc_object_release( p_input );
}
pl_Release( (vlc_object_t*) p_this );
ADD_INT32( &i_es );
REPLY_SEND;
}
DBUS_METHOD( SetVideoES )
{
REPLY_INIT;
OUT_ARGUMENTS;
DBusError error;
dbus_int32_t i_es = 0;
dbus_int32_t i_success = -1;
dbus_error_init( &error );
dbus_message_get_args( p_from, &error,
DBUS_TYPE_INT32, &i_es,
DBUS_TYPE_INVALID );
if( dbus_error_is_set( &error ) )
{
msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
error.message );
dbus_error_free( &error );
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
playlist_t *p_playlist = pl_Hold( (vlc_object_t*) p_this );
input_thread_t *p_input = playlist_CurrentInput( p_playlist );
if( p_input )
{
vlc_value_t val_list;
vlc_value_t newval;
var_Change( p_input, "video-es", VLC_VAR_GETCHOICES, &val_list, NULL );
if( (i_es < 0) && (i_es >= val_list.p_list->i_count) )
i_es = -1;
else
{
int i_ret = -1;
newval = val_list.p_list->p_values[i_es];
i_ret = var_Set( p_input, "video-es", newval );
if( i_ret >= 0 )
i_success = 0;
}
vlc_object_release( p_input );
}
pl_Release( (vlc_object_t*) p_this );
ADD_INT32( &i_success );
REPLY_SEND;
}
DBUS_METHOD( CountVideoES )
{
REPLY_INIT;
OUT_ARGUMENTS;
dbus_int32_t i_count = 0;
playlist_t *p_playlist = pl_Hold( (vlc_object_t*) p_this );
input_thread_t *p_input = playlist_CurrentInput( p_playlist );
if( p_input )
{
vlc_value_t val_list;
var_Change( p_input, "video-es", VLC_VAR_GETCHOICES, &val_list, NULL );
i_count = val_list.p_list->i_count;
vlc_object_release( p_input );
}
pl_Release( (vlc_object_t*) p_this );
ADD_INT32( &i_count );
REPLY_SEND;
}
DBUS_METHOD( GetAudioES )
{
REPLY_INIT;
OUT_ARGUMENTS;
dbus_int32_t i_es = -1;
playlist_t *p_playlist = pl_Hold( (vlc_object_t*) p_this );
input_thread_t *p_input = playlist_CurrentInput( p_playlist );
if( p_input )
{
vlc_value_t val;
int i_ret = -1;
i_ret = var_Get( p_input, "audio-es", &val );
if( i_ret >= 0 )
{
vlc_value_t val_list;
int i;
var_Change( p_input, "audio-es", VLC_VAR_GETCHOICES, &val_list, NULL );
for( i = 0; i < val_list.p_list->i_count; i++ )
{
vlc_value_t es_val = val_list.p_list->p_values[i];
if( es_val.i_int == val.i_int )
{
i_es = i;
break;
}
}
}
vlc_object_release( p_input );
}
pl_Release( (vlc_object_t*) p_this );
ADD_INT32( &i_es );
REPLY_SEND;
}
DBUS_METHOD( SetAudioES )
{
REPLY_INIT;
OUT_ARGUMENTS;
DBusError error;
dbus_int32_t i_es = 0;
dbus_int32_t i_success = -1;
dbus_error_init( &error );
dbus_message_get_args( p_from, &error,
DBUS_TYPE_INT32, &i_es,
DBUS_TYPE_INVALID );
if( dbus_error_is_set( &error ) )
{
msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
error.message );
dbus_error_free( &error );
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
playlist_t *p_playlist = pl_Hold( (vlc_object_t*) p_this );
input_thread_t *p_input = playlist_CurrentInput( p_playlist );
if( p_input )
{
vlc_value_t val_list;
vlc_value_t newval;
var_Change( p_input, "audio-es", VLC_VAR_GETCHOICES, &val_list, NULL );
if( (i_es < 0) && (i_es >= val_list.p_list->i_count) )
i_es = -1;
else
{
int i_ret = -1;
newval = val_list.p_list->p_values[i_es];
i_ret = var_Set( p_input, "audio-es", newval );
if( i_ret >= 0 )
i_success = 0;;
}
vlc_object_release( p_input );
}
pl_Release( (vlc_object_t*) p_this );
ADD_INT32(&i_success);
REPLY_SEND;
}
DBUS_METHOD( CountAudioES )
{
REPLY_INIT;
OUT_ARGUMENTS;
dbus_int32_t i_count = 0;
playlist_t *p_playlist = pl_Hold( (vlc_object_t*) p_this );
input_thread_t *p_input = playlist_CurrentInput( p_playlist );
if( p_input )
{
vlc_value_t val_list;
var_Change( p_input, "audio-es", VLC_VAR_GETCHOICES, &val_list, NULL );
i_count = val_list.p_list->i_count;
vlc_object_release( p_input );
}
pl_Release( (vlc_object_t*) p_this );
ADD_INT32( &i_count );
REPLY_SEND;
}
DBUS_METHOD( GetSubtitleES )
{
REPLY_INIT;
OUT_ARGUMENTS;
dbus_int32_t i_es = 0;
playlist_t *p_playlist = pl_Hold( (vlc_object_t*) p_this );
input_thread_t *p_input = playlist_CurrentInput( p_playlist );
if( p_input )
{
vlc_value_t val;
int i_ret = -1;
i_ret = var_Get( p_input, "spu-es", &val );
if( i_ret >= 0 )
{
vlc_value_t val_list;
int i;
var_Change( p_input, "spu-es", VLC_VAR_GETCHOICES, &val_list, NULL );
for( i = 0; i < val_list.p_list->i_count; i++ )
{
vlc_value_t spu_val = val_list.p_list->p_values[i];
if( val.i_int == spu_val.i_int )
{
i_es = i;
break;
}
}
}
vlc_object_release( p_input );
}
pl_Release( (vlc_object_t*) p_this );
ADD_INT32( &i_es );
REPLY_SEND;
}
DBUS_METHOD( SetSubtitleES )
{
REPLY_INIT;
OUT_ARGUMENTS;
DBusError error;
dbus_int32_t i_es = 0;
dbus_int32_t i_success = -1;
dbus_error_init( &error );
dbus_message_get_args( p_from, &error,
DBUS_TYPE_INT32, &i_es,
DBUS_TYPE_INVALID );
if( dbus_error_is_set( &error ) )
{
msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
error.message );
dbus_error_free( &error );
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
playlist_t *p_playlist = pl_Hold( (vlc_object_t*) p_this );
input_thread_t *p_input = playlist_CurrentInput( p_playlist );
if( p_input )
{
vlc_value_t val_list;
vlc_value_t newval;
int i_ret = -1;
var_Change( p_input, "spu-es", VLC_VAR_GETCHOICES, &val_list, NULL );
if( val_list.p_list->i_count == 0 )
i_es = -1;
if( (i_es < 0) && (i_es >= val_list.p_list->i_count) )
i_es = -1;
newval = val_list.p_list->p_values[i_es];
i_ret = var_Set( p_input, "spu-es", newval );
if( i_ret < 0 )
i_es = -1;
vlc_object_release( p_input );
}
pl_Release( (vlc_object_t*) p_this );
if( i_es >= 0 )
i_success = 0;
ADD_INT32(&i_success);
REPLY_SEND;
}
DBUS_METHOD( CountSubtitleES )
{
REPLY_INIT;
OUT_ARGUMENTS;
dbus_int32_t i_count = 0;
playlist_t *p_playlist = pl_Hold( (vlc_object_t*) p_this );
input_thread_t *p_input = playlist_CurrentInput( p_playlist );
if( p_input )
{
vlc_value_t val_list;
var_Change( p_input, "spu-es", VLC_VAR_GETCHOICES, &val_list, NULL );
i_count = val_list.p_list->i_count;
vlc_object_release( p_input );
}
pl_Release( (vlc_object_t*) p_this );
ADD_INT32( &i_count );
REPLY_SEND;
}
DBUS_METHOD( GetTeletextPage )
{
REPLY_INIT;
OUT_ARGUMENTS;
dbus_int32_t i_page = 0;
playlist_t *p_playlist = pl_Hold( (vlc_object_t*) p_this );
input_thread_t *p_input = playlist_CurrentInput( p_playlist );
if( p_input )
{
vout_thread_t *p_vout;
p_vout = input_GetVout( p_input );
if( p_vout )
{
vlc_object_t *p_vbi;
p_vbi = (vlc_object_t *) vlc_object_find_name( p_vout, "zvbi",
FIND_CHILD );
if( p_vbi )
{
i_page = var_GetInteger( p_vbi, "vbi-page" );
vlc_object_release( p_vbi );
}
vlc_object_release( p_vout );
}
vlc_object_release( p_input );
}
pl_Release( (vlc_object_t*) p_this );
ADD_INT32( &i_page );
REPLY_SEND;
}
DBUS_METHOD( SetTeletextPage )
{
REPLY_INIT;
OUT_ARGUMENTS;
DBusError error;
dbus_int32_t i_page = 0;
dbus_int32_t i_success = -1;
dbus_error_init( &error );
dbus_message_get_args( p_from, &error,
DBUS_TYPE_INT32, &i_page,
DBUS_TYPE_INVALID );
if( dbus_error_is_set( &error ) )
{
msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
error.message );
dbus_error_free( &error );
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
playlist_t *p_playlist = pl_Hold( (vlc_object_t*) p_this );
input_thread_t *p_input = playlist_CurrentInput( p_playlist );
if( p_input )
{
vout_thread_t *p_vout;
p_vout = input_GetVout( p_input );
if( p_vout )
{
vlc_object_t *p_vbi;
p_vbi = (vlc_object_t *) vlc_object_find_name( p_vout, "zvbi",
FIND_CHILD );
if( p_vbi )
{
int i_ret;
i_ret = var_SetInteger( p_vbi, "vbi-page", i_page );
vlc_object_release( p_vbi );
if( i_ret < 0 )
i_page = 0;
else
i_success = 0;
}
vlc_object_release( p_vout );
}
vlc_object_release( p_input );
}
pl_Release( (vlc_object_t*) p_this );
ADD_INT32(&i_success);
REPLY_SEND;
}
DBUS_METHOD( TransparentTeletext )
{
REPLY_INIT;
OUT_ARGUMENTS;
DBusError error;
dbus_bool_t b_transparent = false;
dbus_error_init( &error );
dbus_message_get_args( p_from, &error,
DBUS_TYPE_BOOLEAN, &b_transparent,
DBUS_TYPE_INVALID );
if( dbus_error_is_set( &error ) )
{
msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
error.message );
dbus_error_free( &error );
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
playlist_t *p_playlist = pl_Hold( (vlc_object_t*) p_this );
input_thread_t *p_input = playlist_CurrentInput( p_playlist );
if( p_input )
{
vout_thread_t *p_vout;
p_vout = input_GetVout( p_input );
if( p_vout )
{
int i_ret = -1;
if( var_CountChoices( p_input, "teletext-es" ) > 0 )
{
const bool b_selected = var_GetInteger( p_input, "teletext-es" ) >= 0;
vlc_object_t *p_vbi;
p_vbi = (vlc_object_t *)vlc_object_find_name( p_input, "zvbi",
FIND_CHILD );
if( p_vbi )
{
if( b_selected )
{
/* FIXME Gni, why that ? */
i_ret = var_SetInteger( p_vbi, "vbi-page",
var_GetInteger( p_vbi, "vbi-page" ) );
if( i_ret < 0 )
b_transparent = false;
}
else
{
/* FIXME Gni^2 */
i_ret = var_SetBool( p_vbi, "vbi-opaque",
!var_GetBool( p_vbi, "vbi-opaque" ) );
if( i_ret < 0 )
b_transparent = false;
}
vlc_object_release( p_vbi );
}
else if( b_selected )
{
var_SetInteger( p_input, "spu-es", -1 );
}
else
{
vlc_value_t list;
if( !var_Change( p_input, "teletext-es", VLC_VAR_GETLIST, &list, NULL ) )
{
if( list.p_list->i_count > 0 )
var_SetInteger( p_input, "spu-es", list.p_list->p_values[0].i_int );
var_Change( p_input, "teletext-es", VLC_VAR_FREELIST, &list, NULL );
}
}
}
vlc_object_release( p_vout );
}
vlc_object_release( p_input );
}
pl_Release( (vlc_object_t*) p_this );
REPLY_SEND;
}
DBUS_METHOD( GetEsMetadata )
{
REPLY_INIT;
OUT_ARGUMENTS;
DBusError error;
dbus_error_init( &error );
dbus_int32_t i_es;
dbus_message_get_args( p_from, &error,
DBUS_TYPE_INT32, &i_es,
DBUS_TYPE_INVALID );
if( dbus_error_is_set( &error ) )
{
msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
error.message );
dbus_error_free( &error );
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
playlist_t *p_playlist = pl_Hold( (vlc_object_t*) p_this );
input_thread_t *p_input = playlist_CurrentInput( p_playlist );
if( p_input )
{
input_item_t *p_item = input_GetItem( p_input );
if( p_item )
{
GetInputEsMeta( p_item, i_es, &args );
}
vlc_object_release( p_input );
}
pl_Release( (vlc_object_t*) p_this );
REPLY_SEND;
}
/*
* /Display object method
*/
DBUS_METHOD( GetVideoPosition )
{
REPLY_INIT;
OUT_ARGUMENTS;
dbus_int32_t i_x = 0;
dbus_int32_t i_y = 0;
dbus_int32_t i_width = 0;
dbus_int32_t i_height = 0;
playlist_t *p_playlist = pl_Hold( (vlc_object_t*) p_this );
input_thread_t *p_input = playlist_CurrentInput( p_playlist );
if( p_input )
{
vout_thread_t *p_vout;
p_vout = input_GetVout( p_input );
if( p_vout )
{
i_x = var_GetInteger( p_vout, "video-x");
i_y = var_GetInteger( p_vout, "video-y" );
i_width = var_GetInteger( p_vout, "width" );
i_width = (i_width == -1) ? p_vout->i_window_width: i_width;
i_height = var_GetInteger( p_vout, "height" );
i_height = (i_height == -1) ? p_vout->i_window_height: i_height;
vlc_object_release( p_vout );
}
vlc_object_release( p_input );
}
pl_Release( (vlc_object_t*) p_this );
ADD_INT32( &i_x );
ADD_INT32( &i_y );
ADD_INT32( &i_width );
ADD_INT32( &i_height );
REPLY_SEND;
}
DBUS_METHOD( SetVideoPosition )
{
REPLY_INIT;
OUT_ARGUMENTS;
DBusError error;
dbus_int32_t i_x = 0;
dbus_int32_t i_y = 0;
dbus_int32_t i_width = 0;
dbus_int32_t i_height = 0;
dbus_int32_t i_success = -1;
dbus_error_init( &error );
dbus_message_get_args( p_from, &error,
DBUS_TYPE_INT32, &i_x,
DBUS_TYPE_INT32, &i_y,
DBUS_TYPE_INT32, &i_width,
DBUS_TYPE_INT32, &i_height,
DBUS_TYPE_INVALID );
if( dbus_error_is_set( &error ) )
{
msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
error.message );
dbus_error_free( &error );
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
playlist_t *p_playlist = pl_Hold( (vlc_object_t*) p_this );
input_thread_t *p_input = playlist_CurrentInput( p_playlist );
if( p_input )
{
vout_thread_t *p_vout;
p_vout = input_GetVout( p_input );
if( p_vout )
{
var_SetInteger( p_vout, "video-x", i_x );
var_SetInteger( p_vout, "video-y", i_y );
var_SetInteger( p_vout, "width", i_width );
var_SetInteger( p_vout, "height", i_height );
int i_ret = vout_Control( p_vout, VOUT_SET_SIZE, i_width, i_height);
if( i_ret >= 0 )
{
i_success = 0;
}
vlc_object_release( p_vout );
}
vlc_object_release( p_input );
}
pl_Release( (vlc_object_t*) p_this );
ADD_INT32(&i_success);
REPLY_SEND;
}
/*****************************************************************************
* Introspection method
*****************************************************************************/
......@@ -641,6 +1361,24 @@ DBUS_METHOD( handle_introspect_tracklist )
REPLY_SEND;
}
DBUS_METHOD( handle_introspect_es )
{
VLC_UNUSED(p_this);
REPLY_INIT;
OUT_ARGUMENTS;
ADD_STRING( &psz_introspection_xml_data_es );
REPLY_SEND;
}
DBUS_METHOD( handle_introspect_display )
{
VLC_UNUSED(p_this);
REPLY_INIT;
OUT_ARGUMENTS;
ADD_STRING( &psz_introspection_xml_data_display );
REPLY_SEND;
}
/*****************************************************************************
* handle_*: answer to incoming messages
*****************************************************************************/
......@@ -665,7 +1403,6 @@ DBUS_METHOD( handle_root )
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
DBUS_METHOD( handle_player )
{
if( dbus_message_is_method_call( p_from,
......@@ -706,6 +1443,51 @@ DBUS_METHOD( handle_tracklist )
METHOD_FUNC( "DelTrack", DelTrack );
METHOD_FUNC( "SetLoop", SetLoop );
METHOD_FUNC( "SetRandom", SetRandom );
METHOD_FUNC( "GetRate", GetRate );
METHOD_FUNC( "SetRate", SetRate );
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
DBUS_METHOD( handle_es )
{
if( dbus_message_is_method_call( p_from,
DBUS_INTERFACE_INTROSPECTABLE, "Introspect" ) )
return handle_introspect_es( p_conn, p_from, p_this );
/* here D-Bus method's names are associated to an handler */
METHOD_FUNC( "GetVideoES", GetVideoES );
METHOD_FUNC( "SetVideoES", SetVideoES );
METHOD_FUNC( "CountVideoES", CountVideoES );
METHOD_FUNC( "GetAudioES", GetAudioES );
METHOD_FUNC( "SetAudioES", SetAudioES );
METHOD_FUNC( "CountAudioES", CountAudioES );
METHOD_FUNC( "GetSubtitleES", GetSubtitleES );
METHOD_FUNC( "SetSubtitleES", SetSubtitleES );
METHOD_FUNC( "CountSubtitles", CountSubtitleES );
METHOD_FUNC( "GetTeletextPage", GetTeletextPage );
METHOD_FUNC( "SetTeletextPage", SetTeletextPage );
METHOD_FUNC( "TransparentTeletext", TransparentTeletext );
METHOD_FUNC( "GetEsMetadata", GetEsMetadata );
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
DBUS_METHOD( handle_display )
{
if( dbus_message_is_method_call( p_from,
DBUS_INTERFACE_INTROSPECTABLE, "Introspect" ) )
return handle_introspect_display( p_conn, p_from, p_this );
/* here D-Bus method's names are associated to an handler */
METHOD_FUNC( "GetVideoPosition", GetVideoPosition );
METHOD_FUNC( "SetVideoPosition", SetVideoPosition );
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
......@@ -760,6 +1542,10 @@ static int Open( vlc_object_t *p_this )
&vlc_dbus_player_vtable, p_this );
dbus_connection_register_object_path( p_conn, MPRIS_DBUS_TRACKLIST_PATH,
&vlc_dbus_tracklist_vtable, p_this );
dbus_connection_register_object_path( p_conn, MPRIS_DBUS_ES_PATH,
&vlc_dbus_es_vtable, p_this );
dbus_connection_register_object_path( p_conn, MPRIS_DBUS_DISPLAY_PATH,
&vlc_dbus_display_vtable, p_this );
dbus_connection_flush( p_conn );
......@@ -1113,7 +1899,7 @@ static int UpdateCaps( intf_thread_t* p_intf )
intf_sys_t* p_sys = p_intf->p_sys;
dbus_int32_t i_caps = CAPS_CAN_HAS_TRACKLIST;
playlist_t* p_playlist = pl_Hold( p_intf );
PL_LOCK;
if( p_playlist->current.i_size > 0 )
i_caps |= CAPS_CAN_PLAY | CAPS_CAN_GO_PREV | CAPS_CAN_GO_NEXT;
......@@ -1185,7 +1971,7 @@ static int GetInputMeta( input_item_t* p_input,
"description", "rating", "date", "setting", "url", "language",
"nowplaying", "publisher", "encodedby", "arturl", "trackid",
"status", "location", "length", "video-codec", "audio-codec",
"video-bitrate", "audio-bitrate", "audio-samplerate"
"video-bitrate", "audio-bitrate", "audio-samplerate", "spu-codec"
};
dbus_message_iter_open_container( args, DBUS_TYPE_ARRAY, "{sv}", &dict );
......@@ -1216,6 +2002,82 @@ static int GetInputMeta( input_item_t* p_input,
ADD_VLC_META_STRING( 18, URI );
ADD_META( 19, DBUS_TYPE_INT64, i_length );
/* Collect all ES information */
for( int i = 0; i < p_input->i_categories ; i++)
{
const char *psz_cat = p_input->pp_categories[i]->psz_name;
for( int j = 0 ; j < p_input->pp_categories[i]->i_infos ; j++ )
{
const char *psz_name = p_input->pp_categories[i]->pp_infos[j]->psz_name;
const char *psz_value = p_input->pp_categories[i]->pp_infos[j]->psz_value;
char *psz_variant = NULL;
dbus_message_iter_open_container( &dict, DBUS_TYPE_DICT_ENTRY,
NULL, &dict_entry );
dbus_message_iter_append_basic( &dict_entry, DBUS_TYPE_STRING,
&psz_cat );
if( asprintf( &psz_variant, "%s : %s", psz_name, psz_value ) != -1 )
{
dbus_message_iter_open_container( &dict_entry, DBUS_TYPE_VARIANT,
DBUS_TYPE_STRING_AS_STRING, &variant );
dbus_message_iter_append_basic( &variant,
DBUS_TYPE_STRING, &psz_variant );
dbus_message_iter_close_container( &dict_entry, &variant );
free( psz_variant );
}
dbus_message_iter_close_container( &dict, &dict_entry );
}
}
dbus_message_iter_close_container( args, &dict );
return VLC_SUCCESS;
}
static int GetInputEsMeta( input_item_t * p_item, int32_t i_es,
DBusMessageIter *args )
{
DBusMessageIter dict, dict_entry, variant;
dbus_message_iter_open_container( args, DBUS_TYPE_ARRAY, "{sv}", &dict );
for( int i = 0; i < p_item->i_categories ; i++)
{
const char *psz_cat = p_item->pp_categories[i]->psz_name;
char *psz_stream = NULL;
if( asprintf( &psz_stream, "Stream %d", i_es ) &&
( strncmp( psz_cat, psz_stream, strlen( psz_stream ) ) == 0 ) )
{
for( int j = 0 ; j < p_item->pp_categories[i]->i_infos ; j++ )
{
const char *psz_name = p_item->pp_categories[i]->pp_infos[j]->psz_name;
const char *psz_value = p_item->pp_categories[i]->pp_infos[j]->psz_value;
char *psz_variant = NULL;
dbus_message_iter_open_container( &dict, DBUS_TYPE_DICT_ENTRY,
NULL, &dict_entry );
dbus_message_iter_append_basic( &dict_entry, DBUS_TYPE_STRING,
&psz_cat );
if( asprintf( &psz_variant, "%s : %s", psz_name, psz_value ) != -1 )
{
dbus_message_iter_open_container( &dict_entry, DBUS_TYPE_VARIANT,
DBUS_TYPE_STRING_AS_STRING, &variant );
dbus_message_iter_append_basic( &variant,
DBUS_TYPE_STRING, &psz_variant );
dbus_message_iter_close_container( &dict_entry, &variant );
free( psz_variant );
}
dbus_message_iter_close_container( &dict, &dict_entry );
}
}
free( psz_stream );
}
dbus_message_iter_close_container( args, &dict );
return VLC_SUCCESS;
}
......@@ -1232,6 +2094,7 @@ static int MarshalStatus( intf_thread_t* p_intf, DBusMessageIter* args,
{ /* This is NOT the right way to do that, it would be better to sore
the status information in p_sys and update it on change, thus
avoiding a long lock */
VLC_UNUSED( lock );
DBusMessageIter status;
dbus_int32_t i_state, i_random, i_repeat, i_loop;
......
/*****************************************************************************
* dbus.h : D-Bus control interface
*****************************************************************************
* Copyright (C) 2006 Rafaël Carré
* Copyright (C) 2006-2009 Rafaël Carré
* Copyright (C) 2009 M2X BV
*
* $Id$
*
* Authors: Rafaël Carré <funman at videolanorg>
* Mirsal ENNAIME <mirsal dot ennaime at gmail dot com>
* Jean-Paul Saman <jean-paul dot saman at m2x dot nl>
*
* 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
......@@ -22,8 +25,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef VLC_DBUS
#define VLC_DBUS
/* MPRIS VERSION */
#define VLC_MPRIS_VERSION_MAJOR 1
#define VLC_MPRIS_VERSION_MAJOR 2
#define VLC_MPRIS_VERSION_MINOR 0
/* DBUS IDENTIFIERS */
......@@ -34,6 +40,8 @@
#define MPRIS_DBUS_ROOT_PATH "/"
#define MPRIS_DBUS_PLAYER_PATH "/Player"
#define MPRIS_DBUS_TRACKLIST_PATH "/TrackList"
#define MPRIS_DBUS_ES_PATH "/ES"
#define MPRIS_DBUS_DISPLAY_PATH "/Display"
/* MACROS */
......@@ -80,6 +88,7 @@
#define ADD_BOOL( b ) DBUS_ADD( DBUS_TYPE_BOOLEAN, b )
#define ADD_INT32( i ) DBUS_ADD( DBUS_TYPE_INT32, i )
#define ADD_BYTE( b ) DBUS_ADD( DBUS_TYPE_BYTE, b )
#define ADD_DOUBLE( d ) DBUS_ADD( DBUS_TYPE_DOUBLE, d )
/* XML data to answer org.freedesktop.DBus.Introspectable.Introspect requests */
......@@ -198,6 +207,13 @@ const char* psz_introspection_xml_data_tracklist =
" <method name=\"SetRandom\">\n"
" <arg type=\"b\" direction=\"in\" />\n"
" </method>\n"
" <method name=\"GetRate\">\n"
" <arg type=\"d\" direction=\"out\" />\n"
" </method>\n"
" <method name=\"SetRate\">\n"
" <arg type=\"d\" direction=\"in\" />\n"
" <arg type=\"i\" direction=\"out\" />\n"
" </method>\n"
" <signal name=\"TrackListChange\">\n"
" <arg type=\"i\" />\n"
" </signal>\n"
......@@ -205,11 +221,91 @@ const char* psz_introspection_xml_data_tracklist =
"</node>\n"
;
const char* psz_introspection_xml_data_es =
"<!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.freedesktop.MediaPlayer\">\n"
" <method name=\"GetVideoES\">\n"
" <arg type=\"i\" direction=\"out\" />\n"
" </method>\n"
" <method name=\"SetVideoES\">\n"
" <arg type=\"i\" direction=\"in\" />\n"
" <arg type=\"i\" direction=\"out\" />\n"
" </method>\n"
" <method name=\"CountVideoES\">\n"
" <arg type=\"i\" direction=\"out\" />\n"
" </method>\n"
" <method name=\"GetAudioES\">\n"
" <arg type=\"i\" direction=\"out\" />\n"
" </method>\n"
" <method name=\"SetAudioES\">\n"
" <arg type=\"i\" direction=\"in\" />\n"
" <arg type=\"i\" direction=\"out\" />\n"
" </method>\n"
" <method name=\"CountAudioES\">\n"
" <arg type=\"s\" direction=\"out\" />\n"
" </method>\n"
" <method name=\"GetSubtitleES\">\n"
" <arg type=\"i\" direction=\"out\" />\n"
" </method>\n"
" <method name=\"SetSubtitleES\">\n"
" <arg type=\"i\" direction=\"in\" />\n"
" <arg type=\"i\" direction=\"out\" />\n"
" </method>\n"
" <method name=\"CountSubtitles\">\n"
" <arg type=\"i\" direction=\"out\" />\n"
" </method>\n"
" <method name=\"GetTeletextPage\">\n"
" <arg type=\"i\" direction=\"out\" />\n"
" </method>\n"
" <method name=\"SetTeletexPage\">\n"
" <arg type=\"i\" direction=\"in\" />\n"
" <arg type=\"i\" direction=\"out\" />\n"
" </method>\n"
" <method name=\"TransparentTeletext\">\n"
" <arg type=\"b\" direction=\"in\" />\n"
" </method>\n"
" <method name=\"GetEsMetadata\">\n"
" <arg type=\"i\" direction=\"in\" />\n"
" <arg type=\"a{sv}\" direction=\"out\" />\n"
" </method>\n"
" </interface>\n"
"</node>\n"
;
const char* psz_introspection_xml_data_display =
"<!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.freedesktop.MediaPlayer\">\n"
" <method name=\"GetVideoPosition\">\n"
" <arg type=\"(iiii)\" direction=\"out\" />\n"
" </method>\n"
" <method name=\"SetVideoPosition\">\n"
" <arg type=\"(iiii)\" direction=\"in\" />\n"
" <arg type=\"i\" direction=\"out\" />\n"
" </method>\n"
" </interface>\n"
"</node>\n"
;
/* Handle messages reception */
DBUS_METHOD( handle_root );
DBUS_METHOD( handle_player );
DBUS_METHOD( handle_tracklist );
DBUS_METHOD( handle_es );
DBUS_METHOD( handle_display );
static const DBusObjectPathVTable vlc_dbus_root_vtable = {
NULL, handle_root, /* handler function */
......@@ -226,3 +322,14 @@ static const DBusObjectPathVTable vlc_dbus_tracklist_vtable = {
NULL, NULL, NULL, NULL
};
static const DBusObjectPathVTable vlc_dbus_es_vtable = {
NULL, handle_es, /* handler function */
NULL, NULL, NULL, NULL
};
static const DBusObjectPathVTable vlc_dbus_display_vtable = {
NULL, handle_display, /* handler function */
NULL, NULL, NULL, NULL
};
#endif /* VLC_DBUS */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment