[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