1 /*****************************************************************************
2 * dbus_player.c : dbus control module (mpris v1.0) - /Player object
3 *****************************************************************************
4 * Copyright © 2006-2011 Rafaël Carré
5 * Copyright © 2007-2011 Mirsal Ennaime
6 * Copyright © 2009-2011 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>
34 #include <vlc_aout_intf.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_INT64, &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_DEFAULT;
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 d_dbus_vol *= AOUT_VOLUME_DEFAULT;
205 if( d_dbus_vol < 0. )
207 if( d_dbus_vol > AOUT_VOLUME_MAX )
208 d_dbus_vol = AOUT_VOLUME_MAX;
209 aout_VolumeSet( PL, lround(d_dbus_vol) );
215 { /* next playlist item */
222 { /* previous playlist item */
238 input_thread_t *p_input = playlist_CurrentInput( PL );
240 if( !p_input || var_GetInteger( p_input, "state" ) != PLAYING_S )
244 vlc_object_release( p_input );
252 input_thread_t *p_input = playlist_CurrentInput( PL );
254 if( p_input && var_GetInteger(p_input, "state") == PLAYING_S )
255 playlist_Pause( PL );
258 vlc_object_release( p_input );
263 DBUS_METHOD( PlayPause )
266 input_thread_t *p_input = playlist_CurrentInput( PL );
268 if( p_input && var_GetInteger(p_input, "state") == PLAYING_S )
269 playlist_Pause( PL );
274 vlc_object_release( p_input );
279 DBUS_METHOD( OpenUri )
285 dbus_error_init( &error );
287 dbus_message_get_args( p_from, &error,
288 DBUS_TYPE_STRING, &psz_mrl,
291 if( dbus_error_is_set( &error ) )
293 msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
295 dbus_error_free( &error );
296 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
299 playlist_Add( PL, psz_mrl, NULL,
300 PLAYLIST_APPEND | PLAYLIST_GO,
301 PLAYLIST_END, true, false );
307 MarshalCanPlay( intf_thread_t *p_intf, DBusMessageIter *container )
309 playlist_t *p_playlist = p_intf->p_sys->p_playlist;
312 dbus_bool_t b_can_play = playlist_CurrentSize( p_playlist ) > 0;
315 dbus_message_iter_append_basic( container, DBUS_TYPE_BOOLEAN, &b_can_play );
318 DBUS_METHOD( CanPlay )
325 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "b", &v ) )
326 return DBUS_HANDLER_RESULT_NEED_MEMORY;
328 MarshalCanPlay( p_this, &v );
330 if( !dbus_message_iter_close_container( &args, &v ) )
331 return DBUS_HANDLER_RESULT_NEED_MEMORY;
337 MarshalCanPause( intf_thread_t *p_intf, DBusMessageIter *container )
339 dbus_bool_t b_can_pause = FALSE;
340 input_thread_t *p_input;
341 p_input = playlist_CurrentInput( p_intf->p_sys->p_playlist );
345 b_can_pause = var_GetBool( p_input, "can-pause" );
346 vlc_object_release( p_input );
349 dbus_message_iter_append_basic( container, DBUS_TYPE_BOOLEAN,
353 DBUS_METHOD( CanPause )
360 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "b", &v ) )
361 return DBUS_HANDLER_RESULT_NEED_MEMORY;
363 MarshalCanPause( p_this, &v );
365 if( !dbus_message_iter_close_container( &args, &v ) )
366 return DBUS_HANDLER_RESULT_NEED_MEMORY;
371 DBUS_METHOD( CanControl )
373 VLC_UNUSED( p_this );
379 dbus_bool_t b_can_control = TRUE;
381 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT,
383 return DBUS_HANDLER_RESULT_NEED_MEMORY;
385 if( !dbus_message_iter_append_basic( &v, DBUS_TYPE_BOOLEAN,
387 return DBUS_HANDLER_RESULT_NEED_MEMORY;
389 if( !dbus_message_iter_close_container( &args, &v ) )
390 return DBUS_HANDLER_RESULT_NEED_MEMORY;
396 MarshalCanSeek( intf_thread_t *p_intf, DBusMessageIter *container )
398 dbus_bool_t b_can_seek = FALSE;
399 input_thread_t *p_input;
400 p_input = playlist_CurrentInput( p_intf->p_sys->p_playlist );
404 b_can_seek = var_GetBool( p_input, "can-seek" );
405 vlc_object_release( p_input );
408 dbus_message_iter_append_basic( container, DBUS_TYPE_BOOLEAN, &b_can_seek );
411 DBUS_METHOD( CanSeek )
418 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "b", &v ) )
419 return DBUS_HANDLER_RESULT_NEED_MEMORY;
421 MarshalCanSeek( p_this, &v );
427 MarshalShuffle( intf_thread_t *p_intf, DBusMessageIter *container )
429 dbus_bool_t b_shuffle = var_GetBool( p_intf->p_sys->p_playlist, "random" );
430 dbus_message_iter_append_basic( container, DBUS_TYPE_BOOLEAN, &b_shuffle );
433 DBUS_METHOD( ShuffleGet )
440 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "b", &v ) )
441 return DBUS_HANDLER_RESULT_NEED_MEMORY;
443 MarshalShuffle( p_this, &v );
445 if( !dbus_message_iter_close_container( &args, &v ) )
446 return DBUS_HANDLER_RESULT_NEED_MEMORY;
451 DBUS_METHOD( ShuffleSet )
454 dbus_bool_t b_shuffle;
456 if( VLC_SUCCESS != DemarshalSetPropertyValue( p_from, &b_shuffle ) )
457 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
459 var_SetBool( PL, "random", ( b_shuffle == TRUE ) );
465 MarshalPlaybackStatus( intf_thread_t *p_intf, DBusMessageIter *container )
467 input_thread_t *p_input;
468 const char *psz_playback_status;
470 if( ( p_input = playlist_CurrentInput( p_intf->p_sys->p_playlist ) ) )
472 switch( var_GetInteger( p_input, "state" ) )
476 psz_playback_status = PLAYBACK_STATUS_PLAYING;
479 psz_playback_status = PLAYBACK_STATUS_PAUSED;
482 psz_playback_status = PLAYBACK_STATUS_STOPPED;
485 vlc_object_release( (vlc_object_t*) p_input );
488 psz_playback_status = PLAYBACK_STATUS_STOPPED;
490 dbus_message_iter_append_basic( container, DBUS_TYPE_STRING,
491 &psz_playback_status );
494 DBUS_METHOD( PlaybackStatus )
501 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "s", &v ) )
502 return DBUS_HANDLER_RESULT_NEED_MEMORY;
504 MarshalPlaybackStatus( p_this, &v );
506 if( !dbus_message_iter_close_container( &args, &v ) )
507 return DBUS_HANDLER_RESULT_NEED_MEMORY;
513 MarshalRate( intf_thread_t *p_intf, DBusMessageIter *container )
516 input_thread_t *p_input;
517 if( ( p_input = playlist_CurrentInput( p_intf->p_sys->p_playlist ) ) )
519 d_rate = var_GetFloat( p_input, "rate" );
520 vlc_object_release( (vlc_object_t*) p_input );
525 dbus_message_iter_append_basic( container, DBUS_TYPE_DOUBLE, &d_rate );
528 DBUS_METHOD( RateGet )
535 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "d", &v ) )
536 return DBUS_HANDLER_RESULT_NEED_MEMORY;
538 MarshalRate( p_this, &v );
540 if( !dbus_message_iter_close_container( &args, &v ) )
541 return DBUS_HANDLER_RESULT_NEED_MEMORY;
546 DBUS_METHOD( RateSet )
552 if( VLC_SUCCESS != DemarshalSetPropertyValue( p_from, &d_rate ) )
553 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
555 input_thread_t *p_input;
556 if( ( p_input = playlist_CurrentInput( PL ) ) )
558 var_SetFloat( p_input, "rate", (float) d_rate );
559 vlc_object_release( (vlc_object_t*) p_input );
562 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
567 DBUS_METHOD( MinimumRate )
569 VLC_UNUSED( p_this );
575 double d_min_rate = (double) INPUT_RATE_MIN / INPUT_RATE_DEFAULT;
577 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "d", &v ) )
578 return DBUS_HANDLER_RESULT_NEED_MEMORY;
580 if( !dbus_message_iter_append_basic( &v, DBUS_TYPE_DOUBLE, &d_min_rate ) )
581 return DBUS_HANDLER_RESULT_NEED_MEMORY;
583 if( !dbus_message_iter_close_container( &args, &v ) )
584 return DBUS_HANDLER_RESULT_NEED_MEMORY;
589 DBUS_METHOD( MaximumRate )
591 VLC_UNUSED( p_this );
597 double d_max_rate = (double) INPUT_RATE_MAX / INPUT_RATE_DEFAULT;
599 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "d", &v ) )
600 return DBUS_HANDLER_RESULT_NEED_MEMORY;
602 if( !dbus_message_iter_append_basic( &v, DBUS_TYPE_DOUBLE, &d_max_rate ) )
603 return DBUS_HANDLER_RESULT_NEED_MEMORY;
605 if( !dbus_message_iter_close_container( &args, &v ) )
606 return DBUS_HANDLER_RESULT_NEED_MEMORY;
612 MarshalLoopStatus( intf_thread_t *p_intf, DBusMessageIter *container )
614 const char *psz_loop_status;
616 if( var_GetBool( p_intf->p_sys->p_playlist, "repeat" ) )
617 psz_loop_status = LOOP_STATUS_TRACK;
619 else if( var_GetBool( p_intf->p_sys->p_playlist, "loop" ) )
620 psz_loop_status = LOOP_STATUS_PLAYLIST;
623 psz_loop_status = LOOP_STATUS_NONE;
625 dbus_message_iter_append_basic( container, DBUS_TYPE_STRING,
629 DBUS_METHOD( LoopStatusGet )
636 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "s", &v ) )
637 return DBUS_HANDLER_RESULT_NEED_MEMORY;
639 MarshalLoopStatus( p_this, &v );
641 if( !dbus_message_iter_close_container( &args, &v ) )
642 return DBUS_HANDLER_RESULT_NEED_MEMORY;
647 DBUS_METHOD( LoopStatusSet )
650 char *psz_loop_status;
652 if( VLC_SUCCESS != DemarshalSetPropertyValue( p_from, &psz_loop_status ) )
653 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
655 if( !strcmp( psz_loop_status, LOOP_STATUS_NONE ) )
657 var_SetBool( PL, "loop", FALSE );
658 var_SetBool( PL, "repeat", FALSE );
660 else if( !strcmp( psz_loop_status, LOOP_STATUS_TRACK ) )
662 var_SetBool( PL, "loop", FALSE );
663 var_SetBool( PL, "repeat", TRUE );
665 else if( !strcmp( psz_loop_status, LOOP_STATUS_PLAYLIST ) )
667 var_SetBool( PL, "loop", TRUE );
668 var_SetBool( PL, "repeat", FALSE );
671 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
676 DBUS_METHOD( Metadata )
681 DBusMessageIter v, a;
682 playlist_t *p_playlist = PL;
684 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT,
686 return DBUS_HANDLER_RESULT_NEED_MEMORY;
689 playlist_item_t* p_item = playlist_CurrentPlayingItem( p_playlist );
692 GetInputMeta( p_item->p_input, &v );
697 ( !dbus_message_iter_open_container( &v, DBUS_TYPE_ARRAY, "{sv}", &a ) ||
698 !dbus_message_iter_close_container( &v, &a ) ) ) ||
700 !dbus_message_iter_close_container( &args, &v ) ) {
701 return DBUS_HANDLER_RESULT_NEED_MEMORY;
707 /******************************************************************************
708 * Seeked: non-linear playback signal
709 *****************************************************************************/
710 DBUS_SIGNAL( SeekedSignal )
712 SIGNAL_INIT( DBUS_MPRIS_PLAYER_INTERFACE,
713 DBUS_MPRIS_OBJECT_PATH,
718 dbus_int64_t i_pos = 0;
719 intf_thread_t *p_intf = (intf_thread_t*) p_data;
720 input_thread_t *p_input = playlist_CurrentInput( p_intf->p_sys->p_playlist );
724 i_pos = var_GetTime( p_input, "time" );
725 vlc_object_release( p_input );
732 #define PROPERTY_MAPPING_BEGIN if( 0 ) {}
733 #define PROPERTY_FUNC( interface, property, function ) \
734 else if( !strcmp( psz_interface_name, interface ) && \
735 !strcmp( psz_property_name, property ) ) \
736 return function( p_conn, p_from, p_this );
737 #define PROPERTY_MAPPING_END return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
739 DBUS_METHOD( GetProperty )
743 char *psz_interface_name = NULL;
744 char *psz_property_name = NULL;
746 dbus_error_init( &error );
747 dbus_message_get_args( p_from, &error,
748 DBUS_TYPE_STRING, &psz_interface_name,
749 DBUS_TYPE_STRING, &psz_property_name,
752 if( dbus_error_is_set( &error ) )
754 msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
756 dbus_error_free( &error );
757 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
760 msg_Dbg( (vlc_object_t*) p_this, "Getting property %s",
763 PROPERTY_MAPPING_BEGIN
764 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Metadata", Metadata )
765 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Position", Position )
766 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "PlaybackStatus", PlaybackStatus )
767 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "LoopStatus", LoopStatusGet )
768 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Shuffle", ShuffleGet )
769 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Volume", VolumeGet )
770 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Rate", RateGet )
771 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "MinimumRate", MinimumRate )
772 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "MaximumRate", MaximumRate )
773 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "CanControl", CanControl )
774 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "CanPlay", CanPlay )
775 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "CanPause", CanPause )
776 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "CanSeek", CanSeek )
780 DBUS_METHOD( SetProperty )
784 char *psz_interface_name = NULL;
785 char *psz_property_name = NULL;
787 dbus_error_init( &error );
788 dbus_message_get_args( p_from, &error,
789 DBUS_TYPE_STRING, &psz_interface_name,
790 DBUS_TYPE_STRING, &psz_property_name,
793 if( dbus_error_is_set( &error ) )
795 msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
797 dbus_error_free( &error );
798 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
801 PROPERTY_MAPPING_BEGIN
802 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "LoopStatus", LoopStatusSet )
803 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Shuffle", ShuffleSet )
804 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Volume", VolumeSet )
805 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Rate", RateSet )
809 #undef PROPERTY_MAPPING_BEGIN
810 #undef PROPERTY_GET_FUNC
811 #undef PROPERTY_MAPPING_END
813 #define METHOD_FUNC( interface, method, function ) \
814 else if( dbus_message_is_method_call( p_from, interface, method ) )\
815 return function( p_conn, p_from, p_this )
818 handle_player ( DBusConnection *p_conn, DBusMessage *p_from, void *p_this )
821 METHOD_FUNC( DBUS_INTERFACE_PROPERTIES, "Get", GetProperty );
822 METHOD_FUNC( DBUS_INTERFACE_PROPERTIES, "Set", SetProperty );
823 /* METHOD_FUNC( DBUS_INTERFACE_PROPERTIES, "GetAll", GetAllProperties );*/
825 /* here D-Bus method names are associated to an handler */
827 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Previous", Prev );
828 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Next", Next );
829 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Stop", Stop );
830 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Seek", Seek );
831 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Play", Play );
832 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Pause", Pause );
833 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "PlayPause", PlayPause );
834 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "OpenUri", OpenUri );
835 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "SetPosition", SetPosition );
837 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
842 /*****************************************************************************
843 * SeekedEmit: Emits the Seeked signal
844 *****************************************************************************/
845 int SeekedEmit( intf_thread_t * p_intf )
847 if( p_intf->p_sys->b_dead )
850 SeekedSignal( p_intf->p_sys->p_conn, p_intf );
855 * PropertiesChangedSignal() synthetizes and sends the
856 * org.freedesktop.DBus.Properties.PropertiesChanged signal
858 static DBusHandlerResult
859 PropertiesChangedSignal( intf_thread_t *p_intf,
860 vlc_dictionary_t *p_changed_properties )
862 DBusConnection *p_conn = p_intf->p_sys->p_conn;
863 DBusMessageIter changed_properties, invalidated_properties, entry, variant;
864 const char *psz_interface_name = DBUS_MPRIS_PLAYER_INTERFACE;
865 char **ppsz_properties = NULL;
866 int i_properties = 0;
868 SIGNAL_INIT( DBUS_INTERFACE_PROPERTIES,
869 DBUS_MPRIS_OBJECT_PATH,
870 "PropertiesChanged" );
873 ADD_STRING( &psz_interface_name );
874 dbus_message_iter_open_container( &args, DBUS_TYPE_ARRAY, "{sv}",
875 &changed_properties );
877 i_properties = vlc_dictionary_keys_count( p_changed_properties );
878 ppsz_properties = vlc_dictionary_all_keys( p_changed_properties );
880 for( int i = 0; i < i_properties; i++ )
882 dbus_message_iter_open_container( &changed_properties,
883 DBUS_TYPE_DICT_ENTRY, NULL,
886 dbus_message_iter_append_basic( &entry, DBUS_TYPE_STRING,
887 &ppsz_properties[i] );
889 if( !strcmp( ppsz_properties[i], "Metadata" ) )
891 input_thread_t *p_input;
892 p_input = playlist_CurrentInput( p_intf->p_sys->p_playlist );
894 dbus_message_iter_open_container( &entry,
895 DBUS_TYPE_VARIANT, "a{sv}",
900 input_item_t *p_item = input_GetItem( p_input );
901 GetInputMeta( p_item, &variant );
902 vlc_object_release( p_input );
905 dbus_message_iter_close_container( &entry, &variant );
907 else if( !strcmp( ppsz_properties[i], "PlaybackStatus" ) )
909 dbus_message_iter_open_container( &entry,
910 DBUS_TYPE_VARIANT, "s",
912 MarshalPlaybackStatus( p_intf, &variant );
913 dbus_message_iter_close_container( &entry, &variant );
915 else if( !strcmp( ppsz_properties[i], "LoopStatus" ) )
917 dbus_message_iter_open_container( &entry,
918 DBUS_TYPE_VARIANT, "s",
920 MarshalLoopStatus( p_intf, &variant );
921 dbus_message_iter_close_container( &entry, &variant );
923 else if( !strcmp( ppsz_properties[i], "Rate" ) )
925 dbus_message_iter_open_container( &entry,
926 DBUS_TYPE_VARIANT, "d",
928 MarshalRate( p_intf, &variant );
929 dbus_message_iter_close_container( &entry, &variant );
931 else if( !strcmp( ppsz_properties[i], "Shuffle" ) )
933 dbus_message_iter_open_container( &entry,
934 DBUS_TYPE_VARIANT, "b",
936 MarshalShuffle( p_intf, &variant );
937 dbus_message_iter_close_container( &entry, &variant );
939 else if( !strcmp( ppsz_properties[i], "Volume" ) )
941 dbus_message_iter_open_container( &entry,
942 DBUS_TYPE_VARIANT, "d",
944 MarshalVolume( p_intf, &variant );
945 dbus_message_iter_close_container( &entry, &variant );
947 else if( !strcmp( ppsz_properties[i], "CanSeek" ) )
949 dbus_message_iter_open_container( &entry,
950 DBUS_TYPE_VARIANT, "b",
952 MarshalCanSeek( p_intf, &variant );
953 dbus_message_iter_close_container( &entry, &variant );
955 else if( !strcmp( ppsz_properties[i], "CanPlay" ) )
957 dbus_message_iter_open_container( &entry,
958 DBUS_TYPE_VARIANT, "b",
960 MarshalCanPlay( p_intf, &variant );
961 dbus_message_iter_close_container( &entry, &variant );
963 else if( !strcmp( ppsz_properties[i], "CanPause" ) )
965 dbus_message_iter_open_container( &entry,
966 DBUS_TYPE_VARIANT, "b",
968 MarshalCanPause( p_intf, &variant );
969 dbus_message_iter_close_container( &entry, &variant );
971 dbus_message_iter_close_container( &changed_properties, &entry );
972 free( ppsz_properties[i] );
975 dbus_message_iter_close_container( &args, &changed_properties );
976 dbus_message_iter_open_container( &args, DBUS_TYPE_ARRAY, "s",
977 &invalidated_properties );
978 dbus_message_iter_close_container( &args, &invalidated_properties );
979 free( ppsz_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 );