[vlc-commits] [Git][videolan/vlc][master] 3 commits: dbus: multiple fixes related to mpris:trackid URIs
Felix Paul Kühne (@fkuehne)
gitlab at videolan.org
Tue Apr 21 12:49:05 UTC 2026
Felix Paul Kühne pushed to branch master at VideoLAN / VLC
Commits:
4be95896 by Jorge Bellon-Castro at 2026-04-21T13:29:09+02:00
dbus: multiple fixes related to mpris:trackid URIs
Fix org.mpris.MediaPlayer2.TrackList.TrackAdded including the same
mpris:trackid value to both Metadata and AfterTrack fields. Now it
correctly sets the right path when the track is added to the start of
the playlist.
Use playlist item id instead of its index during format and parsing of
mpris:trackid URIs. This will avoid confusion in the event tracks are
replaced or moved around.
- - - - -
9cd0f0b5 by Jorge Bellon-Castro at 2026-04-21T13:29:09+02:00
dbus: fixes to TrackList.TrackAdded signal
Fix signal interface name
Fix signal message body layout to match the protocol specification
- - - - -
674151f4 by Jorge Bellon-Castro at 2026-04-21T13:29:09+02:00
dbus: store removed track ids in place
Avoids potential stack overflow when list of removed tracks is large
- - - - -
5 changed files:
- modules/control/dbus/dbus.c
- modules/control/dbus/dbus_common.h
- modules/control/dbus/dbus_player.c
- modules/control/dbus/dbus_tracklist.c
- modules/control/dbus/dbus_tracklist.h
Changes:
=====================================
modules/control/dbus/dbus.c
=====================================
@@ -1092,7 +1092,11 @@ playlist_on_items_added(vlc_playlist_t *playlist, size_t index,
vlc_playlist_item_t *const items[], size_t count,
void *data)
{
- tracklist_append_event_t *append_event = tracklist_append_event_create(index, items, count);
+ vlc_playlist_item_t *previous_item = NULL;
+ if (index > 0)
+ previous_item = vlc_playlist_Get(playlist, index - 1);
+
+ tracklist_append_event_t *append_event = tracklist_append_event_create(previous_item, items, count);
bool added = add_event_signal(data,
&(callback_info_t){ .signal = SIGNAL_PLAYLIST_ITEM_APPEND,
.items_appended = append_event });
@@ -1105,13 +1109,16 @@ static void
playlist_on_items_removed(vlc_playlist_t *playlist,
size_t index, size_t count, void *data)
{
- tracklist_remove_event_t *remove_event = tracklist_remove_event_create(index, count);
+ if (count == 0)
+ return;
+
+ tracklist_remove_event_t *remove_event = tracklist_remove_event_create( playlist, index, count );
+
bool added = add_event_signal(data,
&(callback_info_t){ .signal = SIGNAL_PLAYLIST_ITEM_DELETED,
.items_removed = remove_event });
if (!added)
tracklist_remove_event_destroy(remove_event);
- (void) playlist;
}
static void
@@ -1389,7 +1396,7 @@ int DemarshalSetPropertyValue( DBusMessage *p_msg, void *p_arg )
free( psz ); \
}
-int GetInputMeta(size_t index, vlc_playlist_item_t *item, DBusMessageIter *args)
+int GetInputMeta(vlc_playlist_item_t *item, DBusMessageIter *args)
{
input_item_t *p_input = vlc_playlist_item_GetMedia(item);
DBusMessageIter dict, dict_entry, variant, list;
@@ -1400,7 +1407,8 @@ int GetInputMeta(size_t index, vlc_playlist_item_t *item, DBusMessageIter *args)
dbus_int64_t i_length = i_mtime / 1000;
char *psz_trackid;
- if (asprintf(&psz_trackid, MPRIS_TRACKID_FORMAT, index) == -1)
+ uint64_t id = vlc_playlist_item_GetId(item);
+ if (asprintf(&psz_trackid, MPRIS_TRACKID_FORMAT, id) == -1)
return VLC_ENOMEM;
const char* ppsz_meta_items[] =
=====================================
modules/control/dbus/dbus_common.h
=====================================
@@ -88,7 +88,7 @@
#define ADD_INT64( i ) DBUS_ADD( DBUS_TYPE_INT64, i )
#define ADD_BYTE( b ) DBUS_ADD( DBUS_TYPE_BYTE, b )
-#define MPRIS_TRACKID_FORMAT "/org/videolan/vlc/playlist/%lu"
+#define MPRIS_TRACKID_FORMAT "/org/videolan/vlc/playlist/%" PRIu64
struct intf_sys_t
{
@@ -145,7 +145,7 @@ enum
};
int DemarshalSetPropertyValue( DBusMessage *p_msg, void *p_arg );
-int GetInputMeta( size_t index, vlc_playlist_item_t *,
+int GetInputMeta( vlc_playlist_item_t *,
DBusMessageIter *args );
int AddProperty ( intf_thread_t *p_intf,
DBusMessageIter *p_container,
=====================================
modules/control/dbus/dbus_player.c
=====================================
@@ -537,7 +537,7 @@ MarshalMetadata( intf_thread_t *p_intf, DBusMessageIter *container )
vlc_playlist_Unlock(playlist);
if(plitem)
{
- result = GetInputMeta(id, plitem, container);
+ result = GetInputMeta(plitem, container);
vlc_playlist_item_Release(plitem);
}
else
=====================================
modules/control/dbus/dbus_tracklist.c
=====================================
@@ -37,12 +37,21 @@
#include "dbus_common.h"
-tracklist_append_event_t *tracklist_append_event_create(size_t index, vlc_playlist_item_t *const items[], size_t count) {
+tracklist_append_event_t *tracklist_append_event_create(vlc_playlist_item_t *after_track, vlc_playlist_item_t *const items[], size_t count) {
tracklist_append_event_t* result = malloc(sizeof(tracklist_append_event_t) + sizeof(vlc_playlist_item_t *[count]));
if (!result)
return result;
- *result = (tracklist_append_event_t) { .change_ev = { .index = index, .count = count } };
+ bool has_previous = after_track != NULL;
+ uint64_t after_id = 0;
+ if( has_previous )
+ after_id = vlc_playlist_item_GetId( after_track );
+
+ *result = (tracklist_append_event_t) {
+ .change_ev = { .count = count },
+ .has_previous = has_previous,
+ .after_track = after_id
+ };
for (size_t i = 0; i < count; ++i) {
result->items[i] = items[i];
vlc_playlist_item_Hold(items[i]);
@@ -50,18 +59,25 @@ tracklist_append_event_t *tracklist_append_event_create(size_t index, vlc_playli
return result;
}
-tracklist_remove_event_t *tracklist_remove_event_create(size_t index, size_t count) {
- tracklist_remove_event_t* result = malloc(sizeof(tracklist_remove_event_t));
+tracklist_remove_event_t *tracklist_remove_event_create(vlc_playlist_t *playlist, size_t first_index, size_t count) {
+ tracklist_remove_event_t* result = malloc(sizeof(tracklist_remove_event_t) + count * sizeof(uint64_t));
if (!result)
return result;
- *result = (tracklist_remove_event_t) { .change_ev = { .index = index, .count = count } };
+ *result = (tracklist_remove_event_t) { .change_ev = { .count = count } };
+
+ for (size_t i = 0; i < count; ++i) {
+ vlc_playlist_item_t *item = vlc_playlist_Get( playlist, first_index + i );
+ result->removed_tracks[i] = vlc_playlist_item_GetId( item );
+ }
+
return result;
}
void tracklist_append_event_destroy(tracklist_append_event_t *event) {
if (!event)
return;
+
for (size_t i = 0; i < event->change_ev.count; ++i) {
vlc_playlist_item_Release(event->items[i]);
}
@@ -166,7 +182,7 @@ DBUS_METHOD( GetTracksMetadata )
REPLY_INIT;
OUT_ARGUMENTS;
- size_t i_track_id;
+ uint64_t i_track_id;
const char *psz_track_id = NULL;
vlc_playlist_t *playlist = PL;
@@ -182,37 +198,38 @@ DBUS_METHOD( GetTracksMetadata )
dbus_message_iter_recurse( &in_args, &track_ids );
dbus_message_iter_open_container( &args, DBUS_TYPE_ARRAY, "a{sv}", &meta );
- bool id_valid = true;
+ ssize_t track_index = -1;
while( DBUS_TYPE_OBJECT_PATH == dbus_message_iter_get_arg_type( &track_ids ) )
{
dbus_message_iter_get_basic( &track_ids, &psz_track_id );
if( 1 != sscanf( psz_track_id, MPRIS_TRACKID_FORMAT, &i_track_id ) )
{
- id_valid = false;
+ track_index = -1;
break;
}
vlc_playlist_item_t *item = NULL;
vlc_playlist_Lock(playlist);
- id_valid = i_track_id < vlc_playlist_Count(playlist);
- if( id_valid )
+ track_index = vlc_playlist_IndexOfId( playlist, i_track_id );
+ if( track_index != -1 )
{
- item = vlc_playlist_Get(playlist, i_track_id);
+ item = vlc_playlist_Get( playlist, track_index );
vlc_playlist_item_Hold(item);
}
vlc_playlist_Unlock(playlist);
- if( !id_valid )
+
+ if( track_index == -1 )
break;
- GetInputMeta(i_track_id, item, &meta);
+ GetInputMeta(item, &meta);
vlc_playlist_item_Release(item);
dbus_message_iter_next( &track_ids );
}
- if( !id_valid )
+ if( track_index == -1 )
{
dbus_message_iter_abandon_container( &args, &meta );
dbus_message_unref(p_msg);
@@ -227,7 +244,7 @@ DBUS_METHOD( GoTo )
{
REPLY_INIT;
- size_t i_track_id;
+ uint64_t i_track_id;
const char *psz_track_id = NULL;
DBusError error;
@@ -250,11 +267,11 @@ DBUS_METHOD( GoTo )
vlc_playlist_t *playlist = PL;
vlc_playlist_Lock(playlist);
- bool id_valid = i_track_id < vlc_playlist_Count(playlist);
- if (id_valid)
- vlc_playlist_PlayAt(playlist, i_track_id);
+ ssize_t track_index = vlc_playlist_IndexOfId( playlist, i_track_id );
+ if ( track_index != -1 )
+ vlc_playlist_PlayAt(playlist, track_index );
vlc_playlist_Unlock(playlist);
- if (!id_valid)
+ if ( track_index == -1 )
goto invalid_track_id;
REPLY_SEND;
@@ -270,7 +287,7 @@ DBUS_METHOD( RemoveTrack )
DBusError error;
dbus_error_init( &error );
- size_t i_id;
+ size_t i_track_id;
char *psz_id = NULL;
dbus_message_get_args( p_from, &error,
@@ -285,16 +302,16 @@ DBUS_METHOD( RemoveTrack )
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
- if( 1 != sscanf( psz_id, MPRIS_TRACKID_FORMAT, &i_id ) )
+ if( 1 != sscanf( psz_id, MPRIS_TRACKID_FORMAT, &i_track_id ) )
goto invalid_track_id;
vlc_playlist_t *playlist = PL;
vlc_playlist_Lock(playlist);
- bool valid_id = i_id < vlc_playlist_Count(playlist);
- if (valid_id)
- vlc_playlist_RemoveOne(playlist, i_id);
+ ssize_t track_index = vlc_playlist_IndexOfId( playlist, i_track_id );
+ if ( track_index != -1 )
+ vlc_playlist_RemoveOne(playlist, track_index);
vlc_playlist_Unlock(playlist);
- if (!valid_id)
+ if ( track_index == -1 )
goto invalid_track_id;
REPLY_SEND;
@@ -303,13 +320,15 @@ invalid_track_id:
return InvalidTrackId(p_conn, p_from, psz_id, p_this);
}
-static int MarshalTrack( DBusMessageIter *iter, size_t index )
+static int MarshalTrack( DBusMessageIter *iter, bool id_valid, uint64_t id )
{
char *psz_track_id = NULL;
int ret = VLC_SUCCESS;
- if (asprintf(&psz_track_id, MPRIS_TRACKID_FORMAT, index) == -1)
+ const char *format = id_valid? MPRIS_TRACKID_FORMAT : DBUS_MPRIS_NOTRACK;
+ if (asprintf(&psz_track_id, format, id) == -1) {
ret = VLC_ENOMEM;
+ }
if (ret == VLC_SUCCESS &&
!dbus_message_iter_append_basic( iter,
@@ -331,23 +350,25 @@ MarshalTracks( intf_thread_t *p_intf, DBusMessageIter *container )
dbus_message_iter_open_container( container, DBUS_TYPE_ARRAY, "o",
&tracks );
+ int err = VLC_SUCCESS;
vlc_playlist_Lock(playlist);
size_t pl_size = vlc_playlist_Count(playlist);
- vlc_playlist_Unlock(playlist);
for (size_t i = 0; i < pl_size; i++)
{
- int err = MarshalTrack( &tracks, i );
+ vlc_playlist_item_t *item = vlc_playlist_Get( playlist, i );
+ uint64_t track_id = vlc_playlist_item_GetId( item );
+ err = MarshalTrack( &tracks, true, track_id );
if (err != VLC_SUCCESS)
- {
- dbus_message_iter_abandon_container( container, &tracks );
- return err;
- }
+ break;
}
+ vlc_playlist_Unlock(playlist);
- if( !dbus_message_iter_close_container( container, &tracks ) )
+ if( err != VLC_SUCCESS )
+ dbus_message_iter_abandon_container( container, &tracks );
+ else if( !dbus_message_iter_close_container( container, &tracks ) )
return VLC_ENOMEM;
- return VLC_SUCCESS;
+ return err;
}
static int
@@ -547,30 +568,21 @@ PropertiesChangedSignal( intf_thread_t *p_intf,
*/
static DBusHandlerResult
TrackAddedSignal( intf_thread_t *p_intf,
- size_t index,
+ bool has_previous,
+ uint64_t previous_item_id,
vlc_playlist_item_t *item )
{
DBusConnection *p_conn = p_intf->p_sys->p_conn;
- DBusMessageIter meta;
- SIGNAL_INIT( "MediaPlayer2.TrackList",
+ SIGNAL_INIT( DBUS_MPRIS_TRACKLIST_INTERFACE,
DBUS_MPRIS_OBJECT_PATH,
"TrackAdded" );
OUT_ARGUMENTS;
- if( unlikely(!dbus_message_iter_open_container( &args,
- DBUS_TYPE_ARRAY, "a{sv}",
- &meta )) )
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
- GetInputMeta(index, item, &meta);
-
- if( unlikely(!dbus_message_iter_close_container( &args,
- &meta )) )
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
+ GetInputMeta(item, &args);
- if ( MarshalTrack( &args, index ) != VLC_SUCCESS )
+ if( MarshalTrack( &args, has_previous, previous_item_id ) != VLC_SUCCESS )
return DBUS_HANDLER_RESULT_NEED_MEMORY;
SIGNAL_SEND;
@@ -581,17 +593,17 @@ TrackAddedSignal( intf_thread_t *p_intf,
* org.mpris.MediaPlayer2.TrackList.TrackRemoved signal
*/
static DBusHandlerResult
-TrackRemovedSignal( intf_thread_t *p_intf, size_t index )
+TrackRemovedSignal( intf_thread_t *p_intf, uint64_t id )
{
DBusConnection *p_conn = p_intf->p_sys->p_conn;
- SIGNAL_INIT( "MediaPlayer2.TrackList",
+ SIGNAL_INIT( DBUS_MPRIS_TRACKLIST_INTERFACE,
DBUS_MPRIS_OBJECT_PATH,
"TrackRemoved" );
OUT_ARGUMENTS;
- if ( MarshalTrack( &args, index ) != VLC_SUCCESS )
+ if ( MarshalTrack( &args, true, id ) != VLC_SUCCESS )
return DBUS_HANDLER_RESULT_NEED_MEMORY;
SIGNAL_SEND;
@@ -600,6 +612,7 @@ TrackRemovedSignal( intf_thread_t *p_intf, size_t index )
* TrackListPropertiesChangedEmit: Emits the following signals:
* - org.freedesktop.DBus.Properties.PropertiesChanged
* - org.mpris.MediaPlayer2.TrackList.TrackAdded
+ * - org.mpris.MediaPlayer2.TrackList.TrackRemoved
*/
int TrackListPropertiesChangedEmit( intf_thread_t * p_intf,
vlc_dictionary_t * p_changed_properties )
@@ -614,10 +627,14 @@ int TrackListPropertiesChangedEmit( intf_thread_t * p_intf,
vlc_dictionary_value_for_key( p_changed_properties, "TrackAdded" );
while ( added_tracks ) {
+ bool has_previous = added_tracks->has_previous;
+ uint64_t previous_id = added_tracks->after_track;
for (size_t i = 0; i < added_tracks->change_ev.count; ++i) {
- TrackAddedSignal( p_intf,
- added_tracks->change_ev.index + i,
- added_tracks->items[i] );
+ vlc_playlist_item_t *item = added_tracks->items[i];
+ TrackAddedSignal( p_intf, has_previous, previous_id, item );
+
+ has_previous = true;
+ previous_id = vlc_playlist_item_GetId( item );
}
tracklist_append_event_t *next = tracklist_append_event_next( added_tracks );
added_tracks = next;
@@ -630,7 +647,7 @@ int TrackListPropertiesChangedEmit( intf_thread_t * p_intf,
while ( removed_tracks ) {
for (size_t i = 0; i < removed_tracks->change_ev.count; ++i) {
- TrackRemovedSignal( p_intf, removed_tracks->change_ev.index + i );
+ TrackRemovedSignal( p_intf, removed_tracks->removed_tracks[i] );
}
tracklist_remove_event_t *next = tracklist_remove_event_next( removed_tracks );
removed_tracks = next;
=====================================
modules/control/dbus/dbus_tracklist.h
=====================================
@@ -38,18 +38,20 @@
#define DBUS_MPRIS_APPEND "/org/mpris/MediaPlayer2/TrackList/Append"
struct tracklist_change_event {
- size_t index;
size_t count;
struct tracklist_change_event *next;
};
struct tracklist_append_event {
struct tracklist_change_event change_ev;
+ bool has_previous; // false when items are inserted at the start of the tracklist
+ uint64_t after_track; // track id, only valid when has_previous is true
vlc_playlist_item_t *items[];
};
struct tracklist_remove_event {
struct tracklist_change_event change_ev;
+ uint64_t removed_tracks[];
};
typedef struct tracklist_append_event tracklist_append_event_t;
@@ -59,15 +61,16 @@ typedef struct tracklist_remove_event tracklist_remove_event_t;
* The event data will be used to generate TrackAdded DBus signals later on.
*/
tracklist_append_event_t *
-tracklist_append_event_create( size_t index,
+tracklist_append_event_create( vlc_playlist_item_t *after_track,
vlc_playlist_item_t *const items[],
size_t count );
/* Creates an event holding what items have been removed from a tracklist.
- * The event data will be used to generate TrackRemoved DBus signals later on.
+ * The event data will be used to generate TrackRemoved DBus signals later on.
+ * Assumes playlist is locked.
*/
tracklist_remove_event_t *
-tracklist_remove_event_create( size_t index, size_t count );
+tracklist_remove_event_create( vlc_playlist_t *playlist, size_t first_index, size_t count );
/* Releases any resources reserved for this event */
void tracklist_append_event_destroy( tracklist_append_event_t *event );
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b9ef042036e636a82983022f1714bf95af92ef6b...674151f4ad8c271271c7dba683ca012ed5ced37f
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b9ef042036e636a82983022f1714bf95af92ef6b...674151f4ad8c271271c7dba683ca012ed5ced37f
You're receiving this email because of your account on code.videolan.org.
More information about the vlc-commits
mailing list