[vlc-commits] [Git][videolan/vlc][master] 3 commits: DBus control: Extract method ProcessPlaylistChanged
Felix Paul Kühne (@fkuehne)
gitlab at videolan.org
Thu Jan 5 23:26:07 UTC 2023
Felix Paul Kühne pushed to branch master at VideoLAN / VLC
Commits:
b9eb7cc6 by Jorge Bellon-Castro at 2023-01-05T22:44:44+00:00
DBus control: Extract method ProcessPlaylistChanged
Extract switch body for track append and track remove events.
This simplifies adding independent logic to both cases.
- - - - -
b2a5d6cc by Jorge Bellon-Castro at 2023-01-05T22:44:44+00:00
DBus control: do not query index of item if known
The track index is sometimes known when serialising a track's metadata.
This moves the index query outside the metadata serialisation function
when necessary.
- - - - -
c839ffd9 by Jorge Bellon-Castro at 2023-01-05T22:44:44+00:00
DBus control: add more TrackList signals
Implements the following signals for the
org.mpris.MediaPlayer2.TrackList interface:
- TrackAdded: a track was inserted to the list
- TrackRemoved: a track was removed from the list
- - - - -
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
=====================================
@@ -89,6 +89,10 @@ static const DBusObjectPathVTable dbus_mpris_vtable = {
typedef struct
{
int signal;
+ union {
+ tracklist_append_event_t *items_appended;
+ tracklist_remove_event_t *items_removed;
+ };
} callback_info_t;
enum
@@ -595,6 +599,34 @@ static int GetPollFds( intf_thread_t *p_intf, struct pollfd *p_fds )
return i_fds;
}
+
+/**
+ * ProcessPlaylistChanged() reacts to tracks being either inserted or removed from the playlist
+ *
+ * This function must be called by ProcessEvents only
+ *
+ * @param intf_thread_t *p_intf This interface thread state
+ * @param callback_info_t *p_events the list of events to process
+ */
+static void ProcessPlaylistChanged( intf_thread_t *p_intf,
+ vlc_dictionary_t *player_properties,
+ vlc_dictionary_t *tracklist_properties )
+{
+ vlc_playlist_t *playlist = p_intf->p_sys->playlist;
+ vlc_playlist_Lock(playlist);
+ bool b_can_play = vlc_playlist_Count(playlist) > 0;
+ vlc_playlist_Unlock(playlist);
+
+ if( b_can_play != p_intf->p_sys->b_can_play )
+ {
+ p_intf->p_sys->b_can_play = b_can_play;
+ vlc_dictionary_insert( player_properties, "CanPlay", NULL );
+ }
+
+ if( !vlc_dictionary_has_key( tracklist_properties, "Tracks" ) )
+ vlc_dictionary_insert( tracklist_properties, "Tracks", NULL );
+}
+
/**
* ProcessEvents() reacts to a list of events originating from other VLC threads
*
@@ -606,13 +638,19 @@ static int GetPollFds( intf_thread_t *p_intf, struct pollfd *p_fds )
static void ProcessEvents( intf_thread_t *p_intf,
callback_info_t **p_events, int i_events )
{
- bool b_can_play = p_intf->p_sys->b_can_play;
-
vlc_dictionary_t player_properties, tracklist_properties, root_properties;
vlc_dictionary_init( &player_properties, 0 );
vlc_dictionary_init( &tracklist_properties, 0 );
vlc_dictionary_init( &root_properties, 0 );
+ // In case multiple *_ITEM_APPEND or *_ITEM_DELETED events appear on the
+ // list, the elements in their respective map values will be linked in
+ // order.
+ // We keep the tail of the list in order to append the elements to the end
+ // of each list.
+ tracklist_append_event_t *last_append = NULL;
+ tracklist_remove_event_t *last_remove = NULL;
+
for( int i = 0; i < i_events; i++ )
{
switch( p_events[i]->signal )
@@ -627,23 +665,29 @@ static void ProcessEvents( intf_thread_t *p_intf,
vlc_dictionary_insert( &player_properties, "Metadata", NULL );
break;
case SIGNAL_PLAYLIST_ITEM_APPEND:
+ if( !last_append ) {
+ assert (!vlc_dictionary_has_key( &tracklist_properties, "TrackAdded" ) );
+ vlc_dictionary_insert( &tracklist_properties, "TrackAdded", p_events[i]->items_appended );
+
+ last_append = p_events[i]->items_appended;
+ } else {
+ last_append->change_ev.next = &p_events[i]->items_appended->change_ev;
+ last_append = p_events[i]->items_appended;
+ }
+ ProcessPlaylistChanged( p_intf, &player_properties, &tracklist_properties );
+ break;
case SIGNAL_PLAYLIST_ITEM_DELETED:
- {
- vlc_playlist_t *playlist = p_intf->p_sys->playlist;
- vlc_playlist_Lock(playlist);
- b_can_play = vlc_playlist_Count(playlist) > 0;
- vlc_playlist_Unlock(playlist);
-
- if( b_can_play != p_intf->p_sys->b_can_play )
- {
- p_intf->p_sys->b_can_play = b_can_play;
- vlc_dictionary_insert( &player_properties, "CanPlay", NULL );
+ if( !last_remove ) {
+ assert (!vlc_dictionary_has_key( &tracklist_properties, "TrackRemoved" ) );
+ vlc_dictionary_insert( &tracklist_properties, "TrackRemoved", p_events[i]->items_removed );
+
+ last_remove = p_events[i]->items_removed;
+ } else {
+ last_remove->change_ev.next = &p_events[i]->items_removed->change_ev;
+ last_remove = p_events[i]->items_removed;
}
-
- if( !vlc_dictionary_has_key( &tracklist_properties, "Tracks" ) )
- vlc_dictionary_insert( &tracklist_properties, "Tracks", NULL );
+ ProcessPlaylistChanged( p_intf, &player_properties, &tracklist_properties );
break;
- }
case SIGNAL_VOLUME_MUTED:
case SIGNAL_VOLUME_CHANGE:
vlc_dictionary_insert( &player_properties, "Volume", NULL );
@@ -1004,18 +1048,22 @@ 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);
add_event_signal(data,
- &(callback_info_t){ .signal = SIGNAL_PLAYLIST_ITEM_APPEND });
- (void) playlist; (void) index; (void) items; (void) count;
+ &(callback_info_t){ .signal = SIGNAL_PLAYLIST_ITEM_APPEND,
+ .items_appended = append_event });
+ (void) playlist;
}
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);
add_event_signal(data,
- &(callback_info_t){ .signal = SIGNAL_PLAYLIST_ITEM_DELETED });
- (void) playlist; (void) index; (void) count;
+ &(callback_info_t){ .signal = SIGNAL_PLAYLIST_ITEM_DELETED,
+ .items_removed = remove_event });
+ (void) playlist;
}
static void
@@ -1297,7 +1345,7 @@ int DemarshalSetPropertyValue( DBusMessage *p_msg, void *p_arg )
free( psz ); \
}
-int GetInputMeta(vlc_playlist_t *playlist, vlc_playlist_item_t *item, DBusMessageIter *args)
+int GetInputMeta(size_t index, vlc_playlist_item_t *item, DBusMessageIter *args)
{
input_item_t *p_input = vlc_playlist_item_GetMedia(item);
DBusMessageIter dict, dict_entry, variant, list;
@@ -1308,8 +1356,7 @@ int GetInputMeta(vlc_playlist_t *playlist, vlc_playlist_item_t *item, DBusMessag
dbus_int64_t i_length = i_mtime / 1000;
char *psz_trackid;
- if (asprintf(&psz_trackid, MPRIS_TRACKID_FORMAT,
- vlc_playlist_IndexOf(playlist, item)) == -1)
+ if (asprintf(&psz_trackid, MPRIS_TRACKID_FORMAT, index) == -1)
return VLC_ENOMEM;
const char* ppsz_meta_items[] =
=====================================
modules/control/dbus/dbus_common.h
=====================================
@@ -144,7 +144,7 @@ enum
};
int DemarshalSetPropertyValue( DBusMessage *p_msg, void *p_arg );
-int GetInputMeta( vlc_playlist_t *, vlc_playlist_item_t *,
+int GetInputMeta( size_t index, vlc_playlist_item_t *,
DBusMessageIter *args );
int AddProperty ( intf_thread_t *p_intf,
DBusMessageIter *p_container,
=====================================
modules/control/dbus/dbus_player.c
=====================================
@@ -525,13 +525,20 @@ static int
MarshalMetadata( intf_thread_t *p_intf, DBusMessageIter *container )
{
int result = VLC_SUCCESS;
+
+ vlc_playlist_item_t *plitem = NULL;
vlc_playlist_t *playlist = p_intf->p_sys->playlist;
vlc_playlist_Lock(playlist);
ssize_t id = vlc_playlist_GetCurrentIndex(playlist);
- if(id != -1)
+ if (id != -1) {
+ plitem = vlc_playlist_Get(playlist, id);
+ vlc_playlist_item_Hold(plitem);
+ }
+ vlc_playlist_Unlock(playlist);
+ if(plitem)
{
- vlc_playlist_item_t *plitem = vlc_playlist_Get(playlist, id);
- result = GetInputMeta(playlist, plitem, container);
+ result = GetInputMeta(id, plitem, container);
+ vlc_playlist_item_Release(plitem);
}
else
{ // avoid breaking the type marshalling
@@ -541,7 +548,6 @@ MarshalMetadata( intf_thread_t *p_intf, DBusMessageIter *container )
!dbus_message_iter_close_container( container, &a ) )
result = VLC_ENOMEM;
}
- vlc_playlist_Unlock(playlist);
return result;
}
=====================================
modules/control/dbus/dbus_tracklist.c
=====================================
@@ -36,6 +36,42 @@
#include "dbus_tracklist.h"
#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* 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 } };
+ for (size_t i = 0; i < count; ++i) {
+ result->items[i] = items[i];
+ vlc_playlist_item_Hold(items[i]);
+ }
+ 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));
+ if (!result)
+ return result;
+
+ *result = (tracklist_remove_event_t) { .change_ev = { .index = index, .count = count } };
+ 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]);
+ }
+ free(event);
+}
+
+void tracklist_remove_event_destroy(tracklist_remove_event_t *event) {
+ free(event);
+}
+
DBUS_METHOD( AddTrack )
{
REPLY_INIT;
@@ -132,13 +168,20 @@ DBUS_METHOD( GetTracksMetadata )
vlc_playlist_Lock(playlist);
bool id_valid = i_track_id < vlc_playlist_Count(playlist);
+ vlc_playlist_item_t *item = NULL;
if (id_valid)
{
- vlc_playlist_item_t *item = vlc_playlist_Get(playlist, i_track_id);
- GetInputMeta(playlist, item, &meta);
+ item = vlc_playlist_Get(playlist, i_track_id);
+ vlc_playlist_item_Hold(item);
}
vlc_playlist_Unlock(playlist);
- if (!id_valid)
+
+ if (id_valid)
+ {
+ GetInputMeta(i_track_id, item, &meta);
+ vlc_playlist_item_Release(item);
+ }
+ else
{
invalid_track_id:
msg_Err( (vlc_object_t*) p_this, "Invalid track id: %s",
@@ -235,11 +278,29 @@ invalid_track_id:
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
+static int MarshalTrack( DBusMessageIter *iter, size_t index )
+{
+ char *psz_track_id = NULL;
+ int ret = VLC_SUCCESS;
+
+ if (asprintf(&psz_track_id, MPRIS_TRACKID_FORMAT, index) == -1)
+ ret = VLC_ENOMEM;
+
+ if (ret == VLC_SUCCESS &&
+ !dbus_message_iter_append_basic( iter,
+ DBUS_TYPE_OBJECT_PATH,
+ &psz_track_id ) )
+ {
+ ret = VLC_ENOMEM;
+ }
+ free( psz_track_id );
+ return ret;
+}
+
static int
MarshalTracks( intf_thread_t *p_intf, DBusMessageIter *container )
{
DBusMessageIter tracks;
- char *psz_track_id = NULL;
vlc_playlist_t *playlist = p_intf->p_sys->playlist;
dbus_message_iter_open_container( container, DBUS_TYPE_ARRAY, "o",
@@ -250,16 +311,12 @@ MarshalTracks( intf_thread_t *p_intf, DBusMessageIter *container )
vlc_playlist_Unlock(playlist);
for (size_t i = 0; i < pl_size; i++)
{
- if (asprintf(&psz_track_id, MPRIS_TRACKID_FORMAT, i) == -1 ||
- !dbus_message_iter_append_basic( &tracks,
- DBUS_TYPE_OBJECT_PATH,
- &psz_track_id ) )
+ int err = MarshalTrack( &tracks, i );
+ if (err != VLC_SUCCESS)
{
dbus_message_iter_abandon_container( container, &tracks );
- return VLC_ENOMEM;
+ return err;
}
-
- free( psz_track_id );
}
if( !dbus_message_iter_close_container( container, &tracks ) )
@@ -460,8 +517,64 @@ PropertiesChangedSignal( intf_thread_t *p_intf,
}
/**
- * TrackListPropertiesChangedEmit: Emits the
- * org.freedesktop.DBus.Properties.PropertiesChanged signal
+ * TrackAddedSignal: synthetizes and sends the
+ * org.mpris.MediaPlayer2.TrackList.TrackAdded signal
+ */
+static DBusHandlerResult
+TrackAddedSignal( intf_thread_t *p_intf,
+ size_t index,
+ vlc_playlist_item_t *item )
+{
+ DBusConnection *p_conn = p_intf->p_sys->p_conn;
+ DBusMessageIter meta;
+
+ SIGNAL_INIT( "MediaPlayer2.TrackList",
+ 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;
+
+ if ( MarshalTrack( &args, index ) != VLC_SUCCESS )
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+ SIGNAL_SEND;
+}
+
+/**
+ * TrackRemovedSignal: synthetizes and sends the
+ * org.mpris.MediaPlayer2.TrackList.TrackRemoved signal
+ */
+static DBusHandlerResult
+TrackRemovedSignal( intf_thread_t *p_intf, size_t index )
+{
+ DBusConnection *p_conn = p_intf->p_sys->p_conn;
+
+ SIGNAL_INIT( "MediaPlayer2.TrackList",
+ DBUS_MPRIS_OBJECT_PATH,
+ "TrackRemoved" );
+
+ OUT_ARGUMENTS;
+
+ if ( MarshalTrack( &args, index ) != VLC_SUCCESS )
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+ SIGNAL_SEND;
+}
+/**
+ * TrackListPropertiesChangedEmit: Emits the following signals:
+ * - org.freedesktop.DBus.Properties.PropertiesChanged
+ * - org.mpris.MediaPlayer2.TrackList.TrackAdded
*/
int TrackListPropertiesChangedEmit( intf_thread_t * p_intf,
vlc_dictionary_t * p_changed_properties )
@@ -470,5 +583,35 @@ int TrackListPropertiesChangedEmit( intf_thread_t * p_intf,
return VLC_SUCCESS;
PropertiesChangedSignal( p_intf, p_changed_properties );
+
+ if( vlc_dictionary_has_key( p_changed_properties, "TrackAdded" ) ) {
+ tracklist_append_event_t *added_tracks =
+ vlc_dictionary_value_for_key( p_changed_properties, "TrackAdded" );
+
+ while (added_tracks) {
+ 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] );
+ }
+ added_tracks = tracklist_append_event_next(added_tracks);
+ }
+ tracklist_append_event_destroy( added_tracks );
+ }
+
+ if( vlc_dictionary_has_key( p_changed_properties, "TrackRemoved" ) ) {
+ tracklist_remove_event_t *removed_tracks =
+ vlc_dictionary_value_for_key( p_changed_properties, "TrackRemoved" );
+
+ while (removed_tracks) {
+ for (size_t i = 0; i < removed_tracks->change_ev.count; ++i) {
+ TrackRemovedSignal( p_intf, removed_tracks->change_ev.index + i );
+ }
+ removed_tracks = tracklist_remove_event_next(removed_tracks);
+ }
+
+ tracklist_remove_event_destroy( removed_tracks );
+ }
+
return VLC_SUCCESS;
}
=====================================
modules/control/dbus/dbus_tracklist.h
=====================================
@@ -36,6 +36,61 @@
#define DBUS_MPRIS_NOTRACK "/org/mpris/MediaPlayer2/TrackList/NoTrack"
#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;
+ vlc_playlist_item_t *items[];
+};
+
+struct tracklist_remove_event {
+ struct tracklist_change_event change_ev;
+};
+
+typedef struct tracklist_append_event tracklist_append_event_t;
+typedef struct tracklist_remove_event tracklist_remove_event_t;
+
+/* Creates an event holding what items have been appended to a tracklist..
+ * The event data will be used to generate TrackAdded DBus signals later on.
+ */
+tracklist_append_event_t *
+tracklist_append_event_create( size_t index,
+ 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.
+ */
+tracklist_remove_event_t *
+tracklist_remove_event_create( size_t index, size_t count );
+
+/* Releases any resources reserved for this event */
+void tracklist_append_event_destroy( tracklist_append_event_t *event );
+void tracklist_remove_event_destroy( tracklist_remove_event_t *event );
+
+/* Gets next event in the list */
+static tracklist_append_event_t *
+tracklist_append_event_next( tracklist_append_event_t *event ) {
+ if( !event )
+ return NULL;
+ char *p = (char *) event->change_ev.next;
+ return (tracklist_append_event_t *)
+ (p - offsetof(struct tracklist_append_event, change_ev));
+}
+
+static tracklist_remove_event_t *
+tracklist_remove_event_next( tracklist_remove_event_t *event ) {
+ if( !event )
+ return NULL;
+ char *p = (char *) event->change_ev.next;
+ return (tracklist_remove_event_t *)
+ (p - offsetof(struct tracklist_remove_event, change_ev));
+}
+
/* Handle incoming dbus messages */
DBusHandlerResult handle_tracklist ( DBusConnection *p_conn,
DBusMessage *p_from,
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/2adb9f97036ae2820ff38dd15b252e101a7da040...c839ffd9a6e61fb7d119838aac0b54c436a3394b
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/2adb9f97036ae2820ff38dd15b252e101a7da040...c839ffd9a6e61fb7d119838aac0b54c436a3394b
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list