[vlc-devel] [PATCH 5/5] lib: media_player: fix libvlc_MediaPlayerMediaChanged event

Thomas Guillem thomas at gllm.fr
Mon Sep 21 14:53:59 CEST 2020


- Don't override the media set by the user from
  on_current_media_changed().

- Don't create a new media from an input_item. This will prevent to send
  media events with a media pointer that is unknown to the caller.

This callback is now always sending a media that is set with
libvlc_media_player_set_media().

Since the player is now fully asynchronous, a call to set_media() +
play() will be processed asynchronously if an older media is playing.
The user might want to know when its new media is actually playing.
Listening to the libvlc_MediaPlayerMediaChanged event is only way to do so.

Here is an example:

1. set_media(A) && play()
  -> get_media() -> A
2. set_media(B) && play()
  -> get_media() -> B
3. libvlc_MediaPlayerMediaChanged(A)
  -> get_media() -> B
4. libvlc_MediaPlayerMediaChanged(B)
  -> get_media() -> B
---
 include/vlc/libvlc_media_player.h | 11 ++++++++++-
 lib/media.c                       |  4 ++--
 lib/media_player.c                | 28 ++++++----------------------
 3 files changed, 18 insertions(+), 25 deletions(-)

diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h
index 7dec44f1af2..8f6447574c9 100644
--- a/include/vlc/libvlc_media_player.h
+++ b/include/vlc/libvlc_media_player.h
@@ -197,16 +197,25 @@ LIBVLC_API void libvlc_media_player_retain( libvlc_media_player_t *p_mi );
  * Set the media that will be used by the media_player. If any,
  * previous md will be released.
  *
+ * \note The user should listen to the libvlc_MediaPlayerMediaChanged event, to
+ * know when the new media is actually used by the player (or to known that the
+ * older media is no longuer used).
+ *
  * \param p_mi the Media Player
  * \param p_md the Media. Afterwards the p_md can be safely
  *        destroyed.
  */
 LIBVLC_API void libvlc_media_player_set_media( libvlc_media_player_t *p_mi,
-                                                   libvlc_media_t *p_md );
+                                               libvlc_media_t *p_md );
 
 /**
  * Get the media used by the media_player.
  *
+ * \warning Calling this function just after libvlc_media_player_set_media()
+ * will return the media that was just set, but this media might not be
+ * currently used internally by the player. To detect such case, the user
+ * should listen to the libvlc_MediaPlayerMediaChanged event.
+ *
  * \param p_mi the Media Player
  * \return the media associated with p_mi, or NULL if no
  *         media is associated
diff --git a/lib/media.c b/lib/media.c
index da0e5777b5c..e8418697498 100644
--- a/lib/media.c
+++ b/lib/media.c
@@ -493,7 +493,7 @@ libvlc_media_create_input_item( libvlc_media_t *p_md, const char *uri, const cha
 {
     input_item_t *p_input_item =
             input_item_NewExt( uri, name, INPUT_DURATION_UNSET,
-                               ITEM_TYPE_UNKNOWN, ITEM_NET_UNKNOWN, NULL );
+                               ITEM_TYPE_UNKNOWN, ITEM_NET_UNKNOWN, p_md );
     return libvlc_media_attach_input_item( p_md, p_input_item );
 }
 
@@ -511,7 +511,7 @@ libvlc_media_t * libvlc_media_new_from_input_item(
     if( p_md == NULL )
         return NULL;
 
-    input_item_t *p_item_copy = input_item_Copy( p_input_item, NULL );
+    input_item_t *p_item_copy = input_item_Copy( p_input_item, p_md );
     if( p_item_copy != NULL )
         return libvlc_media_attach_input_item( p_md, p_item_copy );
     return NULL;
diff --git a/lib/media_player.c b/lib/media_player.c
index 4db7f96af05..bd8ef60388b 100644
--- a/lib/media_player.c
+++ b/lib/media_player.c
@@ -64,34 +64,18 @@ on_current_media_changed(vlc_player_t *player, input_item_t *new_media,
 
     libvlc_media_player_t *mp = data;
 
-    libvlc_media_t *md = mp->p_md;
-
-    input_item_t *media = md ? md->p_input_item : NULL;
-    if (new_media == media)
-        /* no changes */
-        return;
-
-    if (md)
-        media_detach_preparsed_event(md);
-
-    if (new_media)
+    libvlc_media_t *libmedia;
+    if (new_media != NULL)
     {
-        mp->p_md = libvlc_media_new_from_input_item(mp->p_libvlc_instance,
-                                                    new_media);
-        if (!mp->p_md)
-            /* error already printed by the function call */
-            return;
-
-        media_attach_preparsed_event(mp->p_md);
+        libmedia = new_media->owner_data;
+        assert(libmedia != NULL);
     }
     else
-        mp->p_md = NULL;
-
-    libvlc_media_release(md);
+        libmedia = NULL;
 
     libvlc_event_t event;
     event.type = libvlc_MediaPlayerMediaChanged;
-    event.u.media_player_media_changed.new_media = mp->p_md;
+    event.u.media_player_media_changed.new_media = libmedia;
     libvlc_event_send(&mp->event_manager, &event);
 }
 
-- 
2.28.0



More information about the vlc-devel mailing list