1 /*****************************************************************************
2 * dbus-player.h : dbus control module (mpris v1.0) - /Player object
3 *****************************************************************************
4 * Copyright © 2006-2008 Rafaël Carré
5 * Copyright © 2007-2010 Mirsal Ennaime
6 * Copyright © 2009-2010 The VideoLAN team
9 * Authors: Mirsal Ennaime <mirsal at mirsal fr>
10 * Rafaël Carré <funman at videolanorg>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_playlist.h>
33 #include <vlc_interface.h>
38 #include "dbus_player.h"
39 #include "dbus_common.h"
41 static void MarshalLoopStatus ( intf_thread_t *, DBusMessageIter * );
43 DBUS_METHOD( Position )
44 { /* returns position in microseconds */
50 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "i", &v ) )
51 return DBUS_HANDLER_RESULT_NEED_MEMORY;
53 input_thread_t *p_input = playlist_CurrentInput( PL );
60 i_pos = var_GetTime( p_input, "time" );
61 vlc_object_release( p_input );
64 if( !dbus_message_iter_append_basic( &v, DBUS_TYPE_INT32, &i_pos ) )
65 return DBUS_HANDLER_RESULT_NEED_MEMORY;
67 if( !dbus_message_iter_close_container( &args, &v ) )
68 return DBUS_HANDLER_RESULT_NEED_MEMORY;
73 DBUS_METHOD( SetPosition )
74 { /* set position in microseconds */
79 char *psz_trackid, *psz_dbus_trackid;
83 dbus_error_init( &error );
85 dbus_message_get_args( p_from, &error,
86 DBUS_TYPE_OBJECT_PATH, &psz_dbus_trackid,
87 DBUS_TYPE_INT64, &i_pos,
90 if( dbus_error_is_set( &error ) )
92 msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
94 dbus_error_free( &error );
95 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
98 input_thread_t *p_input = playlist_CurrentInput( PL );
102 if( ( p_item = input_GetItem( p_input ) ) )
104 if( -1 == asprintf( &psz_trackid,
105 MPRIS_TRACKID_FORMAT,
108 vlc_object_release( p_input );
109 return DBUS_HANDLER_RESULT_NEED_MEMORY;
112 if( !strcmp( psz_trackid, psz_dbus_trackid ) )
114 position.i_time = (mtime_t) i_pos;
115 var_Set( p_input, "time", position );
120 vlc_object_release( p_input );
135 dbus_error_init( &error );
137 dbus_message_get_args( p_from, &error,
138 DBUS_TYPE_INT32, &i_step,
141 if( dbus_error_is_set( &error ) )
143 msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
145 dbus_error_free( &error );
146 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
149 input_thread_t *p_input = playlist_CurrentInput( PL );
150 if( p_input && var_GetBool( p_input, "can-seek" ) )
152 i_pos = var_GetTime( p_input, "time" );
153 newpos.i_time = (mtime_t) i_step + i_pos;
155 if( newpos.i_time < 0 )
158 var_Set( p_input, "time", newpos );
162 vlc_object_release( p_input );
168 MarshalVolume( intf_thread_t *p_intf, DBusMessageIter *container )
170 audio_volume_t i_vol = aout_VolumeGet( p_intf->p_sys->p_playlist );
172 /* A volume of 1.0 represents a sensible maximum, ie: 0dB */
173 double d_vol = (double) i_vol / ( AOUT_VOLUME_MAX >> 2 );
175 dbus_message_iter_append_basic( container, DBUS_TYPE_DOUBLE, &d_vol );
178 DBUS_METHOD( VolumeGet )
185 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "d", &v ) )
186 return DBUS_HANDLER_RESULT_NEED_MEMORY;
188 MarshalVolume( p_this, &v );
190 if( !dbus_message_iter_close_container( &args, &v ) )
191 return DBUS_HANDLER_RESULT_NEED_MEMORY;
196 DBUS_METHOD( VolumeSet )
201 if( VLC_SUCCESS != DemarshalSetPropertyValue( p_from, &d_dbus_vol ) )
202 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
204 if( d_dbus_vol > 1. )
206 else if( d_dbus_vol < 0. )
209 double d_vol = d_dbus_vol * AOUT_VOLUME_MAX;
210 audio_volume_t i_vol = round( d_vol );
211 aout_VolumeSet( PL, i_vol );
217 { /* next playlist item */
224 { /* previous playlist item */
240 input_thread_t *p_input = playlist_CurrentInput( PL );
242 if( !p_input || var_GetInteger( p_input, "state" ) != PLAYING_S )
246 vlc_object_release( p_input );
254 input_thread_t *p_input = playlist_CurrentInput( PL );
256 if( p_input && var_GetInteger(p_input, "state") == PLAYING_S )
257 playlist_Pause( PL );
260 vlc_object_release( p_input );
265 DBUS_METHOD( PlayPause )
268 input_thread_t *p_input = playlist_CurrentInput( PL );
270 if( p_input && var_GetInteger(p_input, "state") == PLAYING_S )
271 playlist_Pause( PL );
276 vlc_object_release( p_input );
281 DBUS_METHOD( OpenUri )
287 dbus_error_init( &error );
289 dbus_message_get_args( p_from, &error,
290 DBUS_TYPE_STRING, &psz_mrl,
293 if( dbus_error_is_set( &error ) )
295 msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
297 dbus_error_free( &error );
298 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
301 playlist_Add( PL, psz_mrl, NULL,
302 PLAYLIST_APPEND | PLAYLIST_GO,
303 PLAYLIST_END, true, false );
309 MarshalCanPlay( intf_thread_t *p_intf, DBusMessageIter *container )
311 playlist_t *p_playlist = p_intf->p_sys->p_playlist;
314 dbus_bool_t b_can_play = playlist_CurrentSize( p_playlist );
317 dbus_message_iter_append_basic( container, DBUS_TYPE_BOOLEAN, &b_can_play );
320 DBUS_METHOD( CanPlay )
327 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "b", &v ) )
328 return DBUS_HANDLER_RESULT_NEED_MEMORY;
330 MarshalCanPlay( p_this, &v );
332 if( !dbus_message_iter_close_container( &args, &v ) )
333 return DBUS_HANDLER_RESULT_NEED_MEMORY;
339 MarshalCanPause( intf_thread_t *p_intf, DBusMessageIter *container )
341 dbus_bool_t b_can_pause = FALSE;
342 input_thread_t *p_input;
343 p_input = playlist_CurrentInput( p_intf->p_sys->p_playlist );
347 b_can_pause = var_GetBool( p_input, "can-pause" );
348 vlc_object_release( p_input );
351 dbus_message_iter_append_basic( container, DBUS_TYPE_BOOLEAN,
355 DBUS_METHOD( CanPause )
362 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "b", &v ) )
363 return DBUS_HANDLER_RESULT_NEED_MEMORY;
365 MarshalCanPause( p_this, &v );
367 if( !dbus_message_iter_close_container( &args, &v ) )
368 return DBUS_HANDLER_RESULT_NEED_MEMORY;
373 DBUS_METHOD( CanControl )
375 VLC_UNUSED( p_this );
381 dbus_bool_t b_can_control = TRUE;
383 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT,
385 return DBUS_HANDLER_RESULT_NEED_MEMORY;
387 if( !dbus_message_iter_append_basic( &v, DBUS_TYPE_BOOLEAN,
389 return DBUS_HANDLER_RESULT_NEED_MEMORY;
391 if( !dbus_message_iter_close_container( &args, &v ) )
392 return DBUS_HANDLER_RESULT_NEED_MEMORY;
398 MarshalCanSeek( intf_thread_t *p_intf, DBusMessageIter *container )
400 dbus_bool_t b_can_seek = FALSE;
401 input_thread_t *p_input;
402 p_input = playlist_CurrentInput( p_intf->p_sys->p_playlist );
406 b_can_seek = var_GetBool( p_input, "can-seek" );
407 vlc_object_release( p_input );
410 dbus_message_iter_append_basic( container, DBUS_TYPE_BOOLEAN, &b_can_seek );
413 DBUS_METHOD( CanSeek )
420 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "b", &v ) )
421 return DBUS_HANDLER_RESULT_NEED_MEMORY;
423 MarshalCanSeek( p_this, &v );
429 MarshalShuffle( intf_thread_t *p_intf, DBusMessageIter *container )
431 dbus_bool_t b_shuffle = var_GetBool( p_intf->p_sys->p_playlist, "random" );
432 dbus_message_iter_append_basic( container, DBUS_TYPE_BOOLEAN, &b_shuffle );
435 DBUS_METHOD( ShuffleGet )
442 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "b", &v ) )
443 return DBUS_HANDLER_RESULT_NEED_MEMORY;
445 MarshalShuffle( p_this, &v );
447 if( !dbus_message_iter_close_container( &args, &v ) )
448 return DBUS_HANDLER_RESULT_NEED_MEMORY;
453 DBUS_METHOD( ShuffleSet )
456 dbus_bool_t b_shuffle;
458 if( VLC_SUCCESS != DemarshalSetPropertyValue( p_from, &b_shuffle ) )
459 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
461 var_SetBool( PL, "random", ( b_shuffle == TRUE ) );
467 MarshalPlaybackStatus( intf_thread_t *p_intf, DBusMessageIter *container )
469 input_thread_t *p_input;
470 const char *psz_playback_status;
472 if( ( p_input = playlist_CurrentInput( p_intf->p_sys->p_playlist ) ) )
474 switch( var_GetInteger( p_input, "state" ) )
478 psz_playback_status = PLAYBACK_STATUS_PLAYING;
481 psz_playback_status = PLAYBACK_STATUS_PAUSED;
484 psz_playback_status = PLAYBACK_STATUS_STOPPED;
487 vlc_object_release( (vlc_object_t*) p_input );
490 psz_playback_status = PLAYBACK_STATUS_STOPPED;
492 dbus_message_iter_append_basic( container, DBUS_TYPE_STRING,
493 &psz_playback_status );
496 DBUS_METHOD( PlaybackStatus )
503 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "s", &v ) )
504 return DBUS_HANDLER_RESULT_NEED_MEMORY;
506 MarshalPlaybackStatus( p_this, &v );
508 if( !dbus_message_iter_close_container( &args, &v ) )
509 return DBUS_HANDLER_RESULT_NEED_MEMORY;
515 MarshalRate( intf_thread_t *p_intf, DBusMessageIter *container )
518 input_thread_t *p_input;
519 if( ( p_input = playlist_CurrentInput( p_intf->p_sys->p_playlist ) ) )
521 d_rate = var_GetFloat( p_input, "rate" );
522 vlc_object_release( (vlc_object_t*) p_input );
527 dbus_message_iter_append_basic( container, DBUS_TYPE_DOUBLE, &d_rate );
530 DBUS_METHOD( RateGet )
537 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "d", &v ) )
538 return DBUS_HANDLER_RESULT_NEED_MEMORY;
540 MarshalRate( p_this, &v );
542 if( !dbus_message_iter_close_container( &args, &v ) )
543 return DBUS_HANDLER_RESULT_NEED_MEMORY;
548 DBUS_METHOD( RateSet )
554 if( VLC_SUCCESS != DemarshalSetPropertyValue( p_from, &d_rate ) )
555 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
557 input_thread_t *p_input;
558 if( ( p_input = playlist_CurrentInput( PL ) ) )
560 var_SetFloat( p_input, "rate", (float) d_rate );
561 vlc_object_release( (vlc_object_t*) p_input );
564 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
569 DBUS_METHOD( MinimumRate )
571 VLC_UNUSED( p_this );
577 double d_min_rate = (double) INPUT_RATE_MIN / INPUT_RATE_DEFAULT;
579 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "d", &v ) )
580 return DBUS_HANDLER_RESULT_NEED_MEMORY;
582 if( !dbus_message_iter_append_basic( &v, DBUS_TYPE_DOUBLE, &d_min_rate ) )
583 return DBUS_HANDLER_RESULT_NEED_MEMORY;
585 if( !dbus_message_iter_close_container( &args, &v ) )
586 return DBUS_HANDLER_RESULT_NEED_MEMORY;
591 DBUS_METHOD( MaximumRate )
593 VLC_UNUSED( p_this );
599 double d_max_rate = (double) INPUT_RATE_MAX / INPUT_RATE_DEFAULT;
601 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "d", &v ) )
602 return DBUS_HANDLER_RESULT_NEED_MEMORY;
604 if( !dbus_message_iter_append_basic( &v, DBUS_TYPE_DOUBLE, &d_max_rate ) )
605 return DBUS_HANDLER_RESULT_NEED_MEMORY;
607 if( !dbus_message_iter_close_container( &args, &v ) )
608 return DBUS_HANDLER_RESULT_NEED_MEMORY;
614 MarshalLoopStatus( intf_thread_t *p_intf, DBusMessageIter *container )
616 const char *psz_loop_status;
618 if( var_GetBool( p_intf->p_sys->p_playlist, "repeat" ) )
619 psz_loop_status = LOOP_STATUS_TRACK;
621 else if( var_GetBool( p_intf->p_sys->p_playlist, "loop" ) )
622 psz_loop_status = LOOP_STATUS_PLAYLIST;
625 psz_loop_status = LOOP_STATUS_NONE;
627 dbus_message_iter_append_basic( container, DBUS_TYPE_STRING,
631 DBUS_METHOD( LoopStatusGet )
638 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "s", &v ) )
639 return DBUS_HANDLER_RESULT_NEED_MEMORY;
641 MarshalLoopStatus( p_this, &v );
643 if( !dbus_message_iter_close_container( &args, &v ) )
644 return DBUS_HANDLER_RESULT_NEED_MEMORY;
649 DBUS_METHOD( LoopStatusSet )
652 char *psz_loop_status;
654 if( VLC_SUCCESS != DemarshalSetPropertyValue( p_from, &psz_loop_status ) )
655 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
657 if( !strcmp( psz_loop_status, LOOP_STATUS_NONE ) )
659 var_SetBool( PL, "loop", FALSE );
660 var_SetBool( PL, "repeat", FALSE );
662 else if( !strcmp( psz_loop_status, LOOP_STATUS_TRACK ) )
664 var_SetBool( PL, "loop", FALSE );
665 var_SetBool( PL, "repeat", TRUE );
667 else if( !strcmp( psz_loop_status, LOOP_STATUS_PLAYLIST ) )
669 var_SetBool( PL, "loop", TRUE );
670 var_SetBool( PL, "repeat", FALSE );
673 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
678 DBUS_METHOD( Metadata )
683 DBusMessageIter v, a;
684 playlist_t *p_playlist = PL;
686 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT,
688 return DBUS_HANDLER_RESULT_NEED_MEMORY;
691 playlist_item_t* p_item = playlist_CurrentPlayingItem( p_playlist );
694 GetInputMeta( p_item->p_input, &v );
699 ( !dbus_message_iter_open_container( &v, DBUS_TYPE_ARRAY, "{sv}", &a ) ||
700 !dbus_message_iter_close_container( &v, &a ) ) ) ||
702 !dbus_message_iter_close_container( &args, &v ) ) {
703 return DBUS_HANDLER_RESULT_NEED_MEMORY;
709 /******************************************************************************
710 * Seeked: non-linear playback signal
711 *****************************************************************************/
712 DBUS_SIGNAL( SeekedSignal )
714 SIGNAL_INIT( DBUS_MPRIS_PLAYER_INTERFACE,
715 DBUS_MPRIS_OBJECT_PATH,
720 dbus_int64_t i_pos = 0;
721 intf_thread_t *p_intf = (intf_thread_t*) p_data;
722 input_thread_t *p_input = playlist_CurrentInput( p_intf->p_sys->p_playlist );
726 i_pos = var_GetTime( p_input, "time" );
727 vlc_object_release( p_input );
734 #define PROPERTY_MAPPING_BEGIN if( 0 ) {}
735 #define PROPERTY_FUNC( interface, property, function ) \
736 else if( !strcmp( psz_interface_name, interface ) && \
737 !strcmp( psz_property_name, property ) ) \
738 return function( p_conn, p_from, p_this );
739 #define PROPERTY_MAPPING_END return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
741 DBUS_METHOD( GetProperty )
745 char *psz_interface_name = NULL;
746 char *psz_property_name = NULL;
748 dbus_error_init( &error );
749 dbus_message_get_args( p_from, &error,
750 DBUS_TYPE_STRING, &psz_interface_name,
751 DBUS_TYPE_STRING, &psz_property_name,
754 if( dbus_error_is_set( &error ) )
756 msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
758 dbus_error_free( &error );
759 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
762 msg_Dbg( (vlc_object_t*) p_this, "Getting property %s",
765 PROPERTY_MAPPING_BEGIN
766 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Metadata", Metadata )
767 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Position", Position )
768 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "PlaybackStatus", PlaybackStatus )
769 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "LoopStatus", LoopStatusGet )
770 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Shuffle", ShuffleGet )
771 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Volume", VolumeGet )
772 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Rate", RateGet )
773 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "MinimumRate", MinimumRate )
774 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "MaximumRate", MaximumRate )
775 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "CanControl", CanControl )
776 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "CanPlay", CanPlay )
777 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "CanPause", CanPause )
778 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "CanSeek", CanSeek )
782 DBUS_METHOD( SetProperty )
786 char *psz_interface_name = NULL;
787 char *psz_property_name = NULL;
789 dbus_error_init( &error );
790 dbus_message_get_args( p_from, &error,
791 DBUS_TYPE_STRING, &psz_interface_name,
792 DBUS_TYPE_STRING, &psz_property_name,
795 if( dbus_error_is_set( &error ) )
797 msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
799 dbus_error_free( &error );
800 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
803 PROPERTY_MAPPING_BEGIN
804 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "LoopStatus", LoopStatusSet )
805 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Shuffle", ShuffleSet )
806 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Volume", VolumeSet )
807 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Rate", RateSet )
811 #undef PROPERTY_MAPPING_BEGIN
812 #undef PROPERTY_GET_FUNC
813 #undef PROPERTY_MAPPING_END
815 #define METHOD_FUNC( interface, method, function ) \
816 else if( dbus_message_is_method_call( p_from, interface, method ) )\
817 return function( p_conn, p_from, p_this )
820 handle_player ( DBusConnection *p_conn, DBusMessage *p_from, void *p_this )
823 METHOD_FUNC( DBUS_INTERFACE_PROPERTIES, "Get", GetProperty );
824 METHOD_FUNC( DBUS_INTERFACE_PROPERTIES, "Set", SetProperty );
825 /* METHOD_FUNC( DBUS_INTERFACE_PROPERTIES, "GetAll", GetAllProperties );*/
827 /* here D-Bus method names are associated to an handler */
829 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Previous", Prev );
830 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Next", Next );
831 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Stop", Stop );
832 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Seek", Seek );
833 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Play", Play );
834 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Pause", Pause );
835 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "PlayPause", PlayPause );
836 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "OpenUri", OpenUri );
837 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "SetPosition", SetPosition );
839 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
844 /*****************************************************************************
845 * SeekedEmit: Emits the Seeked signal
846 *****************************************************************************/
847 int SeekedEmit( intf_thread_t * p_intf )
849 if( p_intf->p_sys->b_dead )
852 SeekedSignal( p_intf->p_sys->p_conn, p_intf );
857 * PropertiesChangedSignal() synthetizes and sends the
858 * org.freedesktop.DBus.Properties.PropertiesChanged signal
860 static DBusHandlerResult
861 PropertiesChangedSignal( intf_thread_t *p_intf,
862 vlc_dictionary_t *p_changed_properties )
864 DBusConnection *p_conn = p_intf->p_sys->p_conn;
865 DBusMessageIter changed_properties, invalidated_properties, entry, variant;
866 const char *psz_interface_name = DBUS_MPRIS_PLAYER_INTERFACE;
867 char **ppsz_properties = NULL;
868 int i_properties = 0;
870 SIGNAL_INIT( DBUS_INTERFACE_PROPERTIES,
871 DBUS_MPRIS_OBJECT_PATH,
872 "PropertiesChanged" );
875 ADD_STRING( &psz_interface_name );
876 dbus_message_iter_open_container( &args, DBUS_TYPE_ARRAY, "{sv}",
877 &changed_properties );
879 i_properties = vlc_dictionary_keys_count( p_changed_properties );
880 ppsz_properties = vlc_dictionary_all_keys( p_changed_properties );
882 for( int i = 0; i < i_properties; i++ )
884 dbus_message_iter_open_container( &changed_properties,
885 DBUS_TYPE_DICT_ENTRY, NULL,
888 dbus_message_iter_append_basic( &entry, DBUS_TYPE_STRING,
889 &ppsz_properties[i] );
891 if( !strcmp( ppsz_properties[i], "Metadata" ) )
893 input_thread_t *p_input;
894 p_input = playlist_CurrentInput( p_intf->p_sys->p_playlist );
896 dbus_message_iter_open_container( &entry,
897 DBUS_TYPE_VARIANT, "a{sv}",
902 input_item_t *p_item = input_GetItem( p_input );
903 GetInputMeta( p_item, &variant );
904 vlc_object_release( p_input );
907 dbus_message_iter_close_container( &entry, &variant );
909 else if( !strcmp( ppsz_properties[i], "PlaybackStatus" ) )
911 dbus_message_iter_open_container( &entry,
912 DBUS_TYPE_VARIANT, "s",
914 MarshalPlaybackStatus( p_intf, &variant );
915 dbus_message_iter_close_container( &entry, &variant );
917 else if( !strcmp( ppsz_properties[i], "LoopStatus" ) )
919 dbus_message_iter_open_container( &entry,
920 DBUS_TYPE_VARIANT, "s",
922 MarshalLoopStatus( p_intf, &variant );
923 dbus_message_iter_close_container( &entry, &variant );
925 else if( !strcmp( ppsz_properties[i], "Rate" ) )
927 dbus_message_iter_open_container( &entry,
928 DBUS_TYPE_VARIANT, "d",
930 MarshalRate( p_intf, &variant );
931 dbus_message_iter_close_container( &entry, &variant );
933 else if( !strcmp( ppsz_properties[i], "Shuffle" ) )
935 dbus_message_iter_open_container( &entry,
936 DBUS_TYPE_VARIANT, "b",
938 MarshalShuffle( p_intf, &variant );
939 dbus_message_iter_close_container( &entry, &variant );
941 else if( !strcmp( ppsz_properties[i], "Volume" ) )
943 dbus_message_iter_open_container( &entry,
944 DBUS_TYPE_VARIANT, "d",
946 MarshalVolume( p_intf, &variant );
947 dbus_message_iter_close_container( &entry, &variant );
949 else if( !strcmp( ppsz_properties[i], "CanSeek" ) )
951 dbus_message_iter_open_container( &entry,
952 DBUS_TYPE_VARIANT, "b",
954 MarshalCanSeek( p_intf, &variant );
955 dbus_message_iter_close_container( &entry, &variant );
957 else if( !strcmp( ppsz_properties[i], "CanPlay" ) )
959 dbus_message_iter_open_container( &entry,
960 DBUS_TYPE_VARIANT, "b",
962 MarshalCanPlay( p_intf, &variant );
963 dbus_message_iter_close_container( &entry, &variant );
965 else if( !strcmp( ppsz_properties[i], "CanPause" ) )
967 dbus_message_iter_open_container( &entry,
968 DBUS_TYPE_VARIANT, "b",
970 MarshalCanPause( p_intf, &variant );
971 dbus_message_iter_close_container( &entry, &variant );
973 dbus_message_iter_close_container( &changed_properties, &entry );
976 dbus_message_iter_close_container( &args, &changed_properties );
977 dbus_message_iter_open_container( &args, DBUS_TYPE_ARRAY, "s",
978 &invalidated_properties );
979 dbus_message_iter_close_container( &args, &invalidated_properties );
984 /*****************************************************************************
985 * PropertiesChangedEmit: Emits the Seeked signal
986 *****************************************************************************/
987 int PlayerPropertiesChangedEmit( intf_thread_t * p_intf,
988 vlc_dictionary_t * p_changed_properties )
990 if( p_intf->p_sys->b_dead )
993 PropertiesChangedSignal( p_intf, p_changed_properties );