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

Thomas Guillem thomas at gllm.fr
Fri Sep 18 14:29:32 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                       |  1 +
 lib/media_player.c                | 28 ++++++----------------------
 3 files changed, 17 insertions(+), 23 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 e4c0909c165..7d826783334 100644
--- a/lib/media.c
+++ b/lib/media.c
@@ -483,6 +483,7 @@ libvlc_media_t * libvlc_media_new_from_input_item(
     libvlc_event_manager_init( &p_md->event_manager, p_md );
 
     input_item_Hold( p_md->p_input_item );
+    p_md->p_input_item->owner = p_md;
 
     install_input_item_observer( p_md );
 
diff --git a/lib/media_player.c b/lib/media_player.c
index 4db7f96af05..de7df0b98cb 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;
+        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