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
7 * Copyright © 2013 Alex Merry
10 * Authors: Mirsal Ennaime <mirsal at mirsal fr>
11 * Rafaël Carré <funman at videolanorg>
12 * Alex Merry <dev at randomguy3 me uk>
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
27 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_playlist.h>
35 #include <vlc_interface.h>
39 #include "dbus_player.h"
40 #include "dbus_common.h"
42 static void MarshalLoopStatus ( intf_thread_t *, DBusMessageIter * );
44 DBUS_METHOD( Position )
45 { /* returns position in microseconds */
51 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "x", &v ) )
52 return DBUS_HANDLER_RESULT_NEED_MEMORY;
54 input_thread_t *p_input = playlist_CurrentInput( PL );
61 i_pos = var_GetTime( p_input, "time" );
62 vlc_object_release( p_input );
65 if( !dbus_message_iter_append_basic( &v, DBUS_TYPE_INT64, &i_pos ) )
66 return DBUS_HANDLER_RESULT_NEED_MEMORY;
68 if( !dbus_message_iter_close_container( &args, &v ) )
69 return DBUS_HANDLER_RESULT_NEED_MEMORY;
74 DBUS_METHOD( SetPosition )
75 { /* set position in microseconds */
80 char *psz_trackid, *psz_dbus_trackid;
84 dbus_error_init( &error );
86 dbus_message_get_args( p_from, &error,
87 DBUS_TYPE_OBJECT_PATH, &psz_dbus_trackid,
88 DBUS_TYPE_INT64, &i_pos,
91 if( dbus_error_is_set( &error ) )
93 msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
95 dbus_error_free( &error );
96 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
99 input_thread_t *p_input = playlist_CurrentInput( PL );
103 if( ( p_item = input_GetItem( p_input ) ) )
105 if( -1 == asprintf( &psz_trackid,
106 MPRIS_TRACKID_FORMAT,
109 vlc_object_release( p_input );
110 return DBUS_HANDLER_RESULT_NEED_MEMORY;
113 if( !strcmp( psz_trackid, psz_dbus_trackid ) )
115 position.i_time = (mtime_t) i_pos;
116 var_Set( p_input, "time", position );
121 vlc_object_release( p_input );
136 dbus_error_init( &error );
138 dbus_message_get_args( p_from, &error,
139 DBUS_TYPE_INT64, &i_step,
142 if( dbus_error_is_set( &error ) )
144 msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
146 dbus_error_free( &error );
147 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
150 input_thread_t *p_input = playlist_CurrentInput( PL );
151 if( p_input && var_GetBool( p_input, "can-seek" ) )
153 i_pos = var_GetTime( p_input, "time" );
154 newpos.i_time = (mtime_t) i_step + i_pos;
156 if( newpos.i_time < 0 )
159 var_Set( p_input, "time", newpos );
163 vlc_object_release( p_input );
169 MarshalVolume( intf_thread_t *p_intf, DBusMessageIter *container )
171 float f_vol = playlist_VolumeGet( p_intf->p_sys->p_playlist );
175 double d_vol = f_vol;
176 dbus_message_iter_append_basic( container, DBUS_TYPE_DOUBLE, &d_vol );
179 DBUS_METHOD( VolumeGet )
186 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "d", &v ) )
187 return DBUS_HANDLER_RESULT_NEED_MEMORY;
189 MarshalVolume( p_this, &v );
191 if( !dbus_message_iter_close_container( &args, &v ) )
192 return DBUS_HANDLER_RESULT_NEED_MEMORY;
197 DBUS_METHOD( VolumeSet )
202 if( VLC_SUCCESS != DemarshalSetPropertyValue( p_from, &d_dbus_vol ) )
203 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
205 d_dbus_vol *= AOUT_VOLUME_DEFAULT;
206 if( d_dbus_vol < 0. )
208 playlist_VolumeSet( PL, d_dbus_vol );
214 { /* next playlist item */
221 { /* previous playlist item */
237 input_thread_t *p_input = playlist_CurrentInput( PL );
239 if( !p_input || var_GetInteger( p_input, "state" ) != PLAYING_S )
243 vlc_object_release( p_input );
251 input_thread_t *p_input = playlist_CurrentInput( PL );
253 if( p_input && var_GetInteger(p_input, "state") == PLAYING_S )
254 playlist_Pause( PL );
257 vlc_object_release( p_input );
262 DBUS_METHOD( PlayPause )
265 input_thread_t *p_input = playlist_CurrentInput( PL );
267 if( p_input && var_GetInteger(p_input, "state") == PLAYING_S )
268 playlist_Pause( PL );
273 vlc_object_release( p_input );
278 DBUS_METHOD( OpenUri )
284 dbus_error_init( &error );
286 dbus_message_get_args( p_from, &error,
287 DBUS_TYPE_STRING, &psz_mrl,
290 if( dbus_error_is_set( &error ) )
292 msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
294 dbus_error_free( &error );
295 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
298 playlist_Add( PL, psz_mrl, NULL,
299 PLAYLIST_APPEND | PLAYLIST_GO,
300 PLAYLIST_END, true, false );
306 MarshalCanPlay( intf_thread_t *p_intf, DBusMessageIter *container )
308 playlist_t *p_playlist = p_intf->p_sys->p_playlist;
311 dbus_bool_t b_can_play = playlist_CurrentSize( p_playlist ) > 0;
314 dbus_message_iter_append_basic( container, DBUS_TYPE_BOOLEAN, &b_can_play );
317 DBUS_METHOD( CanPlay )
324 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "b", &v ) )
325 return DBUS_HANDLER_RESULT_NEED_MEMORY;
327 MarshalCanPlay( p_this, &v );
329 if( !dbus_message_iter_close_container( &args, &v ) )
330 return DBUS_HANDLER_RESULT_NEED_MEMORY;
336 MarshalCanPause( intf_thread_t *p_intf, DBusMessageIter *container )
338 dbus_bool_t b_can_pause = FALSE;
339 input_thread_t *p_input;
340 p_input = playlist_CurrentInput( p_intf->p_sys->p_playlist );
344 b_can_pause = var_GetBool( p_input, "can-pause" );
345 vlc_object_release( p_input );
348 dbus_message_iter_append_basic( container, DBUS_TYPE_BOOLEAN,
352 DBUS_METHOD( CanPause )
359 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "b", &v ) )
360 return DBUS_HANDLER_RESULT_NEED_MEMORY;
362 MarshalCanPause( p_this, &v );
364 if( !dbus_message_iter_close_container( &args, &v ) )
365 return DBUS_HANDLER_RESULT_NEED_MEMORY;
370 DBUS_METHOD( CanControl )
372 VLC_UNUSED( p_this );
378 dbus_bool_t b_can_control = TRUE;
380 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT,
382 return DBUS_HANDLER_RESULT_NEED_MEMORY;
384 if( !dbus_message_iter_append_basic( &v, DBUS_TYPE_BOOLEAN,
386 return DBUS_HANDLER_RESULT_NEED_MEMORY;
388 if( !dbus_message_iter_close_container( &args, &v ) )
389 return DBUS_HANDLER_RESULT_NEED_MEMORY;
395 MarshalCanSeek( intf_thread_t *p_intf, DBusMessageIter *container )
397 dbus_bool_t b_can_seek = FALSE;
398 input_thread_t *p_input;
399 p_input = playlist_CurrentInput( p_intf->p_sys->p_playlist );
403 b_can_seek = var_GetBool( p_input, "can-seek" );
404 vlc_object_release( p_input );
407 dbus_message_iter_append_basic( container, DBUS_TYPE_BOOLEAN, &b_can_seek );
410 DBUS_METHOD( CanSeek )
417 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "b", &v ) )
418 return DBUS_HANDLER_RESULT_NEED_MEMORY;
420 MarshalCanSeek( p_this, &v );
422 if( !dbus_message_iter_close_container( &args, &v ) )
423 return DBUS_HANDLER_RESULT_NEED_MEMORY;
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;
679 MarshalMetadata( intf_thread_t *p_intf, DBusMessageIter *container )
682 input_thread_t *p_input = NULL;
683 input_item_t *p_item = NULL;
685 if( ( p_input = playlist_CurrentInput( p_intf->p_sys->p_playlist ) ) )
687 p_item = input_GetItem( p_input );
691 int result = GetInputMeta( p_item, container );
693 if (result != VLC_SUCCESS)
695 vlc_object_release( (vlc_object_t*) p_input );
700 vlc_object_release( (vlc_object_t*) p_input );
705 // avoid breaking the type marshalling
706 if( !dbus_message_iter_open_container( container, DBUS_TYPE_ARRAY, "{sv}", &a ) ||
707 !dbus_message_iter_close_container( container, &a ) )
714 DBUS_METHOD( Metadata )
721 if( !dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT,
723 return DBUS_HANDLER_RESULT_NEED_MEMORY;
725 if( MarshalMetadata( p_this, &v ) != VLC_SUCCESS ||
726 !dbus_message_iter_close_container( &args, &v ) ) {
727 return DBUS_HANDLER_RESULT_NEED_MEMORY;
733 /******************************************************************************
734 * Seeked: non-linear playback signal
735 *****************************************************************************/
736 DBUS_SIGNAL( SeekedSignal )
738 SIGNAL_INIT( DBUS_MPRIS_PLAYER_INTERFACE,
739 DBUS_MPRIS_OBJECT_PATH,
744 dbus_int64_t i_pos = 0;
745 intf_thread_t *p_intf = (intf_thread_t*) p_data;
746 input_thread_t *p_input = playlist_CurrentInput( p_intf->p_sys->p_playlist );
750 i_pos = var_GetTime( p_input, "time" );
751 vlc_object_release( p_input );
758 #define PROPERTY_MAPPING_BEGIN if( 0 ) {}
759 #define PROPERTY_FUNC( interface, property, function ) \
760 else if( !strcmp( psz_interface_name, interface ) && \
761 !strcmp( psz_property_name, property ) ) \
762 return function( p_conn, p_from, p_this );
763 #define PROPERTY_MAPPING_END return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
765 DBUS_METHOD( GetProperty )
769 char *psz_interface_name = NULL;
770 char *psz_property_name = NULL;
772 dbus_error_init( &error );
773 dbus_message_get_args( p_from, &error,
774 DBUS_TYPE_STRING, &psz_interface_name,
775 DBUS_TYPE_STRING, &psz_property_name,
778 if( dbus_error_is_set( &error ) )
780 msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
782 dbus_error_free( &error );
783 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
786 msg_Dbg( (vlc_object_t*) p_this, "Getting property %s",
789 PROPERTY_MAPPING_BEGIN
790 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Metadata", Metadata )
791 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Position", Position )
792 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "PlaybackStatus", PlaybackStatus )
793 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "LoopStatus", LoopStatusGet )
794 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Shuffle", ShuffleGet )
795 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Volume", VolumeGet )
796 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Rate", RateGet )
797 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "MinimumRate", MinimumRate )
798 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "MaximumRate", MaximumRate )
799 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "CanControl", CanControl )
800 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "CanPlay", CanPlay )
801 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "CanPause", CanPause )
802 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "CanSeek", CanSeek )
806 DBUS_METHOD( SetProperty )
810 char *psz_interface_name = NULL;
811 char *psz_property_name = NULL;
813 dbus_error_init( &error );
814 dbus_message_get_args( p_from, &error,
815 DBUS_TYPE_STRING, &psz_interface_name,
816 DBUS_TYPE_STRING, &psz_property_name,
819 if( dbus_error_is_set( &error ) )
821 msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
823 dbus_error_free( &error );
824 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
827 PROPERTY_MAPPING_BEGIN
828 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "LoopStatus", LoopStatusSet )
829 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Shuffle", ShuffleSet )
830 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Volume", VolumeSet )
831 PROPERTY_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Rate", RateSet )
835 #undef PROPERTY_MAPPING_BEGIN
836 #undef PROPERTY_GET_FUNC
837 #undef PROPERTY_MAPPING_END
839 #define METHOD_FUNC( interface, method, function ) \
840 else if( dbus_message_is_method_call( p_from, interface, method ) )\
841 return function( p_conn, p_from, p_this )
844 handle_player ( DBusConnection *p_conn, DBusMessage *p_from, void *p_this )
847 METHOD_FUNC( DBUS_INTERFACE_PROPERTIES, "Get", GetProperty );
848 METHOD_FUNC( DBUS_INTERFACE_PROPERTIES, "Set", SetProperty );
849 /* METHOD_FUNC( DBUS_INTERFACE_PROPERTIES, "GetAll", GetAllProperties );*/
851 /* here D-Bus method names are associated to an handler */
853 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Previous", Prev );
854 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Next", Next );
855 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Stop", Stop );
856 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Seek", Seek );
857 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Play", Play );
858 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "Pause", Pause );
859 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "PlayPause", PlayPause );
860 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "OpenUri", OpenUri );
861 METHOD_FUNC( DBUS_MPRIS_PLAYER_INTERFACE, "SetPosition", SetPosition );
863 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
868 /*****************************************************************************
869 * SeekedEmit: Emits the Seeked signal
870 *****************************************************************************/
871 int SeekedEmit( intf_thread_t * p_intf )
873 if( p_intf->p_sys->b_dead )
876 SeekedSignal( p_intf->p_sys->p_conn, p_intf );
881 * PropertiesChangedSignal() synthetizes and sends the
882 * org.freedesktop.DBus.Properties.PropertiesChanged signal
884 static DBusHandlerResult
885 PropertiesChangedSignal( intf_thread_t *p_intf,
886 vlc_dictionary_t *p_changed_properties )
888 DBusConnection *p_conn = p_intf->p_sys->p_conn;
889 DBusMessageIter changed_properties, invalidated_properties, entry, variant;
890 const char *psz_interface_name = DBUS_MPRIS_PLAYER_INTERFACE;
891 char **ppsz_properties = NULL;
892 int i_properties = 0;
894 SIGNAL_INIT( DBUS_INTERFACE_PROPERTIES,
895 DBUS_MPRIS_OBJECT_PATH,
896 "PropertiesChanged" );
899 ADD_STRING( &psz_interface_name );
900 dbus_message_iter_open_container( &args, DBUS_TYPE_ARRAY, "{sv}",
901 &changed_properties );
903 i_properties = vlc_dictionary_keys_count( p_changed_properties );
904 ppsz_properties = vlc_dictionary_all_keys( p_changed_properties );
906 for( int i = 0; i < i_properties; i++ )
908 dbus_message_iter_open_container( &changed_properties,
909 DBUS_TYPE_DICT_ENTRY, NULL,
912 dbus_message_iter_append_basic( &entry, DBUS_TYPE_STRING,
913 &ppsz_properties[i] );
915 if( !strcmp( ppsz_properties[i], "Metadata" ) )
917 dbus_message_iter_open_container( &entry,
918 DBUS_TYPE_VARIANT, "a{sv}",
920 MarshalMetadata( p_intf, &variant );
921 dbus_message_iter_close_container( &entry, &variant );
923 else if( !strcmp( ppsz_properties[i], "PlaybackStatus" ) )
925 dbus_message_iter_open_container( &entry,
926 DBUS_TYPE_VARIANT, "s",
928 MarshalPlaybackStatus( p_intf, &variant );
929 dbus_message_iter_close_container( &entry, &variant );
931 else if( !strcmp( ppsz_properties[i], "LoopStatus" ) )
933 dbus_message_iter_open_container( &entry,
934 DBUS_TYPE_VARIANT, "s",
936 MarshalLoopStatus( p_intf, &variant );
937 dbus_message_iter_close_container( &entry, &variant );
939 else if( !strcmp( ppsz_properties[i], "Rate" ) )
941 dbus_message_iter_open_container( &entry,
942 DBUS_TYPE_VARIANT, "d",
944 MarshalRate( p_intf, &variant );
945 dbus_message_iter_close_container( &entry, &variant );
947 else if( !strcmp( ppsz_properties[i], "Shuffle" ) )
949 dbus_message_iter_open_container( &entry,
950 DBUS_TYPE_VARIANT, "b",
952 MarshalShuffle( p_intf, &variant );
953 dbus_message_iter_close_container( &entry, &variant );
955 else if( !strcmp( ppsz_properties[i], "Volume" ) )
957 dbus_message_iter_open_container( &entry,
958 DBUS_TYPE_VARIANT, "d",
960 MarshalVolume( p_intf, &variant );
961 dbus_message_iter_close_container( &entry, &variant );
963 else if( !strcmp( ppsz_properties[i], "CanSeek" ) )
965 dbus_message_iter_open_container( &entry,
966 DBUS_TYPE_VARIANT, "b",
968 MarshalCanSeek( p_intf, &variant );
969 dbus_message_iter_close_container( &entry, &variant );
971 else if( !strcmp( ppsz_properties[i], "CanPlay" ) )
973 dbus_message_iter_open_container( &entry,
974 DBUS_TYPE_VARIANT, "b",
976 MarshalCanPlay( p_intf, &variant );
977 dbus_message_iter_close_container( &entry, &variant );
979 else if( !strcmp( ppsz_properties[i], "CanPause" ) )
981 dbus_message_iter_open_container( &entry,
982 DBUS_TYPE_VARIANT, "b",
984 MarshalCanPause( p_intf, &variant );
985 dbus_message_iter_close_container( &entry, &variant );
987 dbus_message_iter_close_container( &changed_properties, &entry );
988 free( ppsz_properties[i] );
991 dbus_message_iter_close_container( &args, &changed_properties );
992 dbus_message_iter_open_container( &args, DBUS_TYPE_ARRAY, "s",
993 &invalidated_properties );
994 dbus_message_iter_close_container( &args, &invalidated_properties );
995 free( ppsz_properties );
1000 /*****************************************************************************
1001 * PropertiesChangedEmit: Emits the Seeked signal
1002 *****************************************************************************/
1003 int PlayerPropertiesChangedEmit( intf_thread_t * p_intf,
1004 vlc_dictionary_t * p_changed_properties )
1006 if( p_intf->p_sys->b_dead )
1009 PropertiesChangedSignal( p_intf, p_changed_properties );