bool b_dead;
vlc_array_t *p_events;
vlc_mutex_t lock;
+ input_thread_t *p_input;
+ bool b_unique;
};
typedef struct
/*****************************************************************************
* Module descriptor
*****************************************************************************/
+#define DBUS_UNIQUE_TEXT N_("Unique DBUS service id (org.mpris.vlc-<pid>)")
+#define DBUS_UNIQUE_LONGTEXT N_( \
+ "Use a unique dbus service id to identify this VLC instance on the DBUS bus. " \
+ "The process identifier (PID) is added to the service name: org.mpris.vlc-<pid>" )
vlc_module_begin ()
set_shortname( N_("dbus"))
set_description( N_("D-Bus control interface") )
set_capability( "interface", 0 )
set_callbacks( Open, Close )
+ add_bool( "dbus-unique-service-id", false, NULL,
+ DBUS_UNIQUE_TEXT, DBUS_UNIQUE_LONGTEXT, true )
vlc_module_end ()
/*****************************************************************************
* handle_*: answer to incoming messages
*****************************************************************************/
-#define METHOD_FUNC( method, function ) \
- else if( dbus_message_is_method_call( p_from, MPRIS_DBUS_INTERFACE, method ) )\
+#define METHOD_FUNC( interface, method, function ) \
+ else if( dbus_message_is_method_call( p_from, interface, method ) )\
return function( p_conn, p_from, p_this )
DBUS_METHOD( handle_root )
/* here D-Bus method's names are associated to an handler */
- METHOD_FUNC( "Identity", Identity );
- METHOD_FUNC( "MprisVersion", MprisVersion );
- METHOD_FUNC( "Quit", Quit );
+ METHOD_FUNC( MPRIS_DBUS_ROOT_INTERFACE, "Identity", Identity );
+ METHOD_FUNC( MPRIS_DBUS_ROOT_INTERFACE, "MprisVersion", MprisVersion );
+ METHOD_FUNC( MPRIS_DBUS_ROOT_INTERFACE, "Quit", Quit );
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
/* here D-Bus method's names are associated to an handler */
- METHOD_FUNC( "Prev", Prev );
- METHOD_FUNC( "Next", Next );
- METHOD_FUNC( "Stop", Stop );
- METHOD_FUNC( "Play", Play );
- METHOD_FUNC( "Pause", Pause );
- METHOD_FUNC( "Repeat", Repeat );
- METHOD_FUNC( "VolumeSet", VolumeSet );
- METHOD_FUNC( "VolumeGet", VolumeGet );
- METHOD_FUNC( "PositionSet", PositionSet );
- METHOD_FUNC( "PositionGet", PositionGet );
- METHOD_FUNC( "GetStatus", GetStatus );
- METHOD_FUNC( "GetMetadata", GetCurrentMetadata );
- METHOD_FUNC( "GetCaps", GetCaps );
+ METHOD_FUNC( MPRIS_DBUS_PLAYER_INTERFACE, "Prev", Prev );
+ METHOD_FUNC( MPRIS_DBUS_PLAYER_INTERFACE, "Next", Next );
+ METHOD_FUNC( MPRIS_DBUS_PLAYER_INTERFACE, "Stop", Stop );
+ METHOD_FUNC( MPRIS_DBUS_PLAYER_INTERFACE, "Play", Play );
+ METHOD_FUNC( MPRIS_DBUS_PLAYER_INTERFACE, "Pause", Pause );
+ METHOD_FUNC( MPRIS_DBUS_PLAYER_INTERFACE, "Repeat", Repeat );
+ METHOD_FUNC( MPRIS_DBUS_PLAYER_INTERFACE, "VolumeSet", VolumeSet );
+ METHOD_FUNC( MPRIS_DBUS_PLAYER_INTERFACE, "VolumeGet", VolumeGet );
+ METHOD_FUNC( MPRIS_DBUS_PLAYER_INTERFACE, "PositionSet", PositionSet );
+ METHOD_FUNC( MPRIS_DBUS_PLAYER_INTERFACE, "PositionGet", PositionGet );
+ METHOD_FUNC( MPRIS_DBUS_PLAYER_INTERFACE, "GetStatus", GetStatus );
+ METHOD_FUNC( MPRIS_DBUS_PLAYER_INTERFACE, "GetMetadata", GetCurrentMetadata );
+ METHOD_FUNC( MPRIS_DBUS_PLAYER_INTERFACE, "GetCaps", GetCaps );
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
/* here D-Bus method's names are associated to an handler */
- METHOD_FUNC( "GetMetadata", GetMetadata );
- METHOD_FUNC( "GetCurrentTrack", GetCurrentTrack );
- METHOD_FUNC( "GetLength", GetLength );
- METHOD_FUNC( "AddTrack", AddTrack );
- METHOD_FUNC( "DelTrack", DelTrack );
- METHOD_FUNC( "SetLoop", SetLoop );
- METHOD_FUNC( "SetRandom", SetRandom );
+ METHOD_FUNC( MPRIS_DBUS_TRACKLIST_INTERFACE, "GetMetadata", GetMetadata );
+ METHOD_FUNC( MPRIS_DBUS_TRACKLIST_INTERFACE, "GetCurrentTrack", GetCurrentTrack );
+ METHOD_FUNC( MPRIS_DBUS_TRACKLIST_INTERFACE, "GetLength", GetLength );
+ METHOD_FUNC( MPRIS_DBUS_TRACKLIST_INTERFACE, "AddTrack", AddTrack );
+ METHOD_FUNC( MPRIS_DBUS_TRACKLIST_INTERFACE, "DelTrack", DelTrack );
+ METHOD_FUNC( MPRIS_DBUS_TRACKLIST_INTERFACE, "SetLoop", SetLoop );
+ METHOD_FUNC( MPRIS_DBUS_TRACKLIST_INTERFACE, "SetRandom", SetRandom );
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
playlist_t *p_playlist;
DBusConnection *p_conn;
DBusError error;
+ char *psz_service_name = NULL;
if( !p_sys )
return VLC_ENOMEM;
p_sys->b_meta_read = false;
p_sys->i_caps = CAPS_NONE;
p_sys->b_dead = false;
+ p_sys->p_input = NULL;
+
+ p_sys->b_unique = var_CreateGetBool( p_intf, "dbus-unique-service-id" );
+ if( p_sys->b_unique )
+ {
+ if( asprintf( &psz_service_name, "%s-%d",
+ VLC_MPRIS_DBUS_SERVICE, getpid() ) < 0 )
+ {
+ free( p_sys );
+ return VLC_ENOMEM;
+ }
+ }
+ else
+ {
+ psz_service_name = strdup(VLC_MPRIS_DBUS_SERVICE);
+ }
dbus_error_init( &error );
}
/* register a well-known name on the bus */
- dbus_bus_request_name( p_conn, VLC_MPRIS_DBUS_SERVICE, 0, &error );
+ dbus_bus_request_name( p_conn, psz_service_name, 0, &error );
if( dbus_error_is_set( &error ) )
{
- msg_Err( p_this, "Error requesting service " VLC_MPRIS_DBUS_SERVICE
- ": %s", error.message );
+ msg_Err( p_this, "Error requesting service %s: %s",
+ psz_service_name, error.message );
dbus_error_free( &error );
+ free( psz_service_name );
free( p_sys );
return VLC_EGENERIC;
}
+ msg_Info( p_intf, "listening on dbus as: %s", psz_service_name );
+ free( psz_service_name );
/* we register the objects */
dbus_connection_register_object_path( p_conn, MPRIS_DBUS_ROOT_PATH,
p_sys->p_events = vlc_array_new();
vlc_mutex_init( &p_sys->lock );
- p_playlist = pl_Hold( p_intf );
+ p_playlist = pl_Get( p_intf );
p_sys->p_playlist = p_playlist;
- PL_LOCK;
var_AddCallback( p_playlist, "item-current", AllCallback, p_intf );
var_AddCallback( p_playlist, "intf-change", AllCallback, p_intf );
var_AddCallback( p_playlist, "playlist-item-append", AllCallback, p_intf );
var_AddCallback( p_playlist, "random", AllCallback, p_intf );
var_AddCallback( p_playlist, "repeat", AllCallback, p_intf );
var_AddCallback( p_playlist, "loop", AllCallback, p_intf );
- PL_UNLOCK;
UpdateCaps( p_intf );
intf_thread_t *p_intf = (intf_thread_t*) p_this;
intf_sys_t *p_sys = p_intf->p_sys;
playlist_t *p_playlist = p_sys->p_playlist;
- input_thread_t *p_input;
var_DelCallback( p_playlist, "item-current", AllCallback, p_intf );
var_DelCallback( p_playlist, "intf-change", AllCallback, p_intf );
var_DelCallback( p_playlist, "repeat", AllCallback, p_intf );
var_DelCallback( p_playlist, "loop", AllCallback, p_intf );
- p_input = playlist_CurrentInput( p_playlist );
- if ( p_input )
+ if( p_sys->p_input )
{
- var_DelCallback( p_input, "state", AllCallback, p_intf );
- vlc_object_release( p_input );
+ var_DelCallback( p_sys->p_input, "state", AllCallback, p_intf );
+ vlc_object_release( p_sys->p_input );
}
- pl_Release( p_intf );
dbus_connection_unref( p_sys->p_conn );
*****************************************************************************/
DBUS_SIGNAL( CapsChangeSignal )
{
- SIGNAL_INIT( MPRIS_DBUS_PLAYER_PATH, "CapsChange" );
+ SIGNAL_INIT( MPRIS_DBUS_PLAYER_INTERFACE,
+ MPRIS_DBUS_PLAYER_PATH,
+ "CapsChange" );
+
OUT_ARGUMENTS;
ADD_INT32( &((intf_thread_t*)p_data)->p_sys->i_caps );
*****************************************************************************/
DBUS_SIGNAL( TrackListChangeSignal )
{ /* emit the new tracklist lengh */
- SIGNAL_INIT( MPRIS_DBUS_TRACKLIST_PATH, "TrackListChange");
+ SIGNAL_INIT( MPRIS_DBUS_TRACKLIST_INTERFACE,
+ MPRIS_DBUS_TRACKLIST_PATH,
+ "TrackListChange");
+
OUT_ARGUMENTS;
- /* XXX: locking */
- dbus_int32_t i_elements = ((intf_thread_t*)p_data)->p_sys->p_playlist->current.i_size;
+ playlist_t *p_playlist = ((intf_thread_t*)p_data)->p_sys->p_playlist;
+ PL_LOCK;
+ dbus_int32_t i_elements = p_playlist->current.i_size;
+ PL_UNLOCK;
ADD_INT32( &i_elements );
SIGNAL_SEND;
DBUS_SIGNAL( TrackChangeSignal )
{ /* emit the metadata of the new item */
- SIGNAL_INIT( MPRIS_DBUS_PLAYER_PATH, "TrackChange" );
+ SIGNAL_INIT( MPRIS_DBUS_PLAYER_INTERFACE,
+ MPRIS_DBUS_PLAYER_PATH,
+ "TrackChange" );
+
OUT_ARGUMENTS;
input_item_t *p_item = (input_item_t*) p_data;
DBUS_SIGNAL( StatusChangeSignal )
{ /* send the updated status info on the bus */
- SIGNAL_INIT( MPRIS_DBUS_PLAYER_PATH, "StatusChange" );
+ SIGNAL_INIT( MPRIS_DBUS_PLAYER_INTERFACE,
+ MPRIS_DBUS_PLAYER_PATH,
+ "StatusChange" );
+
OUT_ARGUMENTS;
/* we're called from a callback of input_thread_t, so it can not be
if( p_intf->p_sys->b_dead )
return VLC_SUCCESS;
+ if( p_sys->p_input )
+ {
+ var_DelCallback( p_sys->p_input, "state", AllCallback, p_intf );
+ vlc_object_release( p_sys->p_input );
+ p_sys->p_input = NULL;
+ }
+
p_sys->b_meta_read = false;
p_input = playlist_CurrentInput( p_playlist );
TrackChangeSignal( p_sys->p_conn, p_item );
}
+ p_sys->p_input = p_input;
var_AddCallback( p_input, "state", AllCallback, p_intf );
- vlc_object_release( p_input );
return VLC_SUCCESS;
}
DBusMessageIter *args )
{
DBusMessageIter dict, dict_entry, variant;
- /* We need the track length to be expressed in milli-seconds
- * instead of µ-seconds */
- dbus_int64_t i_length = ( input_item_GetDuration( p_input ) / 1000 );
+ /** The duration of the track can be expressed in second, milli-seconds and
+ µ-seconds */
+ dbus_int64_t i_mtime = input_item_GetDuration( p_input );
+ dbus_uint32_t i_time = i_mtime / 1000000;
+ dbus_int64_t i_length = i_mtime / 1000;
const char* ppsz_meta_items[] =
{
/* Official MPRIS metas */
- "location", "title", "artist", "album", "tracknumber", "genre",
- "rating", "date", "arturl",
+ "location", "title", "artist", "album", "tracknumber", "time", "mtime",
+ "genre", "rating", "date", "arturl",
"audio-bitrate", "audio-samplerate", "video-bitrate",
/* VLC specifics metas */
"audio-codec", "copyright", "description", "encodedby", "language", "length",
ADD_VLC_META_STRING( 2, Artist );
ADD_VLC_META_STRING( 3, Album );
ADD_VLC_META_STRING( 4, TrackNum );
- ADD_VLC_META_STRING( 5, Genre );
- ADD_VLC_META_STRING( 6, Rating );
- ADD_VLC_META_STRING( 7, Date );
- ADD_VLC_META_STRING( 8, ArtURL );
-
- ADD_VLC_META_STRING( 13, Copyright );
- ADD_VLC_META_STRING( 14, Description );
- ADD_VLC_META_STRING( 15, EncodedBy );
- ADD_VLC_META_STRING( 16, Language );
- ADD_META( 17, DBUS_TYPE_INT64, i_length );
- ADD_VLC_META_STRING( 18, NowPlaying );
- ADD_VLC_META_STRING( 19, Publisher );
- ADD_VLC_META_STRING( 20, Setting );
- ADD_VLC_META_STRING( 22, TrackID );
- ADD_VLC_META_STRING( 23, URL );
+ ADD_META( 5, DBUS_TYPE_UINT32, i_time );
+ ADD_META( 6, DBUS_TYPE_UINT32, i_mtime );
+ ADD_VLC_META_STRING( 7, Genre );
+ ADD_VLC_META_STRING( 8, Rating );
+ ADD_VLC_META_STRING( 9, Date );
+ ADD_VLC_META_STRING( 10, ArtURL );
+
+ ADD_VLC_META_STRING( 15, Copyright );
+ ADD_VLC_META_STRING( 16, Description );
+ ADD_VLC_META_STRING( 17, EncodedBy );
+ ADD_VLC_META_STRING( 18, Language );
+ ADD_META( 19, DBUS_TYPE_INT64, i_length );
+ ADD_VLC_META_STRING( 20, NowPlaying );
+ ADD_VLC_META_STRING( 21, Publisher );
+ ADD_VLC_META_STRING( 22, Setting );
+ ADD_VLC_META_STRING( 24, TrackID );
+ ADD_VLC_META_STRING( 25, URL );
vlc_mutex_lock( &p_input->lock );
if( p_input->p_meta )
{
int i_status = vlc_meta_GetStatus( p_input->p_meta );
- ADD_META( 21, DBUS_TYPE_INT32, i_status );
+ ADD_META( 23, DBUS_TYPE_INT32, i_status );
}
vlc_mutex_unlock( &p_input->lock );