[vlc-devel] [PATCH] libvlc: merge libvlc_MediaParsedStatus and libvlc_MediaParsedCharged events

Thomas Guillem thomas at gllm.fr
Mon May 23 18:39:32 CEST 2016


Because having two differents events for the same objective is way too
confusing (libvlc_MediaParsedStatus was recently added by me).

libvlc_MediaParsedCharged is now always sent after a call to
libvlc_media_parse_*() (this was not the case if the pre-parsing was skipped).

The core vlc_InputItemPreparsedChanged event is now only attached from the
media player. This allows the libvlc_MediaParsedCharged event to be sent when a
media is parsed from a media player.

/!\ Behavior change in libvlc API /!\

libvlc_event_t.u.media_parsed_changed.new_status changed from an int to a
libvlc_media_parsed_status_t. Before this patch, this value was always set to
true, even in case of parse failure/skipped. Now this value can be skipped (1),
failed (2) or done (3). There should be no changes for users that were checking
if new_status was true, since this events was called for these 3 cases (that
are all > 0).
---
 include/vlc/libvlc_events.h |  7 +---
 include/vlc/libvlc_media.h  | 14 +++----
 lib/event.c                 |  1 -
 lib/media.c                 | 98 +++++++++++++++++++--------------------------
 lib/media_internal.h        |  2 +-
 lib/media_player.c          | 35 ++++++++++++++++
 test/libvlc/media.c         | 10 ++---
 7 files changed, 90 insertions(+), 77 deletions(-)

diff --git a/include/vlc/libvlc_events.h b/include/vlc/libvlc_events.h
index 45ce86e..05666a3 100644
--- a/include/vlc/libvlc_events.h
+++ b/include/vlc/libvlc_events.h
@@ -53,7 +53,6 @@ enum libvlc_event_e {
     libvlc_MediaFreed,
     libvlc_MediaStateChanged,
     libvlc_MediaSubItemTreeAdded,
-    libvlc_MediaParsedStatus,
 
     libvlc_MediaPlayerMediaChanged=0x100,
     libvlc_MediaPlayerNothingSpecial,
@@ -141,7 +140,7 @@ typedef struct libvlc_event_t
         } media_duration_changed;
         struct
         {
-            int new_status;
+            libvlc_media_parsed_status_t new_status;
         } media_parsed_changed;
         struct
         {
@@ -155,10 +154,6 @@ typedef struct libvlc_event_t
         {
             libvlc_media_t * item;
         } media_subitemtree_added;
-        struct
-        {
-            int new_status;
-        } media_parsed_status;
 
         /* media instance */
         struct
diff --git a/include/vlc/libvlc_media.h b/include/vlc/libvlc_media.h
index d05f642..173c78a 100644
--- a/include/vlc/libvlc_media.h
+++ b/include/vlc/libvlc_media.h
@@ -265,10 +265,10 @@ typedef enum libvlc_media_parse_flag_t
  */
 typedef enum libvlc_media_parsed_status_t
 {
-    libvlc_media_parse_init,
-    libvlc_media_parse_skipped,
-    libvlc_media_parse_failed,
-    libvlc_media_parse_done,
+    libvlc_media_parsed_status_init,
+    libvlc_media_parsed_status_skipped,
+    libvlc_media_parsed_status_failed,
+    libvlc_media_parsed_status_done,
 } libvlc_media_parsed_status_t;
 
 /**
@@ -655,7 +655,7 @@ libvlc_media_parse( libvlc_media_t *p_md );
  * This fetches (local or network) art, meta data and/or tracks information.
  * This method is the extended version of libvlc_media_parse_with_options().
  *
- * To track when this is over you can listen to libvlc_MediaParsedStatus
+ * To track when this is over you can listen to libvlc_MediaParsedChanged
  * event. However if this functions returns an error, you will not receive any
  * events.
  *
@@ -663,7 +663,7 @@ libvlc_media_parse( libvlc_media_t *p_md );
  * these flags can be combined. By default, media is parsed if it's a local
  * file.
  *
- * \see libvlc_MediaParsedStatus
+ * \see libvlc_MediaParsedChanged
  * \see libvlc_media_get_meta
  * \see libvlc_media_tracks_get
  * \see libvlc_media_get_parsed_status
@@ -681,7 +681,7 @@ libvlc_media_parse_with_options( libvlc_media_t *p_md,
 /**
  * Get Parsed status for media descriptor object.
  *
- * \see libvlc_MediaParsedStatus
+ * \see libvlc_MediaParsedChanged
  * \see libvlc_media_parsed_status_t
  *
  * \param p_md media descriptor object
diff --git a/lib/event.c b/lib/event.c
index 56db14f..6beeacd 100644
--- a/lib/event.c
+++ b/lib/event.c
@@ -171,7 +171,6 @@ static const event_name_t event_list[] = {
     DEF(MediaFreed)
     DEF(MediaStateChanged)
     DEF(MediaSubItemTreeAdded)
-    DEF(MediaParsedStatus)
 
     DEF(MediaPlayerMediaChanged)
     DEF(MediaPlayerNothingSpecial)
diff --git a/lib/media.c b/lib/media.c
index 0b20aaa..c11f8f9 100644
--- a/lib/media.c
+++ b/lib/media.c
@@ -213,39 +213,49 @@ static void input_item_duration_changed( const vlc_event_t *p_event,
     libvlc_event_send( p_md->p_event_manager, &event );
 }
 
-static void send_preparsed_event(libvlc_media_t *media)
+static void send_parsed_changed( libvlc_media_t *p_md,
+                                 libvlc_media_parsed_status_t new_status )
 {
     libvlc_event_t event;
 
-    /* Eventually notify libvlc_media_parse() */
-    vlc_mutex_lock(&media->parsed_lock);
-    if (media->is_parsed == true)
+    vlc_mutex_lock( &p_md->parsed_lock );
+    if( p_md->parsed_status == new_status )
     {
-        vlc_mutex_unlock(&media->parsed_lock);
+        vlc_mutex_unlock( &p_md->parsed_lock );
         return;
     }
-    media->is_parsed = true;
-    vlc_cond_broadcast(&media->parsed_cond);
-    vlc_mutex_unlock(&media->parsed_lock);
 
+    /* Legacy: notify libvlc_media_parse */
+    if( !p_md->is_parsed )
+    {
+        p_md->is_parsed = true;
+        vlc_cond_broadcast( &p_md->parsed_cond );
+    }
+
+    p_md->parsed_status = new_status;
+    if( p_md->parsed_status == libvlc_media_parsed_status_skipped )
+        p_md->has_asked_preparse = false;
+
+    vlc_mutex_unlock( &p_md->parsed_lock );
+
+    if( new_status == libvlc_media_parsed_status_done )
+    {
+        libvlc_media_list_t *p_subitems = media_get_subitems( p_md, false );
+        if( p_subitems != NULL )
+        {
+            /* notify the media list */
+            libvlc_media_list_lock( p_subitems );
+            libvlc_media_list_internal_end_reached( p_subitems );
+            libvlc_media_list_unlock( p_subitems );
+        }
+    }
 
     /* Construct the event */
     event.type = libvlc_MediaParsedChanged;
-    event.u.media_parsed_changed.new_status = true;
+    event.u.media_parsed_changed.new_status = new_status;
 
     /* Send the event */
-    libvlc_event_send(media->p_event_manager, &event);
-}
-
-/**************************************************************************
- * input_item_preparsed_changed (Private) (vlc event Callback)
- **************************************************************************/
-static void input_item_preparsed_changed(const vlc_event_t *p_event,
-                                         void * user_data)
-{
-    VLC_UNUSED( p_event );
-    libvlc_media_t *media = user_data;
-    send_preparsed_event(media);
+    libvlc_event_send( p_md->p_event_manager, &event );
 }
 
 /**************************************************************************
@@ -254,44 +264,24 @@ static void input_item_preparsed_changed(const vlc_event_t *p_event,
 static void input_item_preparse_ended( const vlc_event_t * p_event,
                                        void * user_data )
 {
-    VLC_UNUSED( p_event );
     libvlc_media_t * p_md = user_data;
-    libvlc_media_list_t *p_subitems = media_get_subitems( p_md, false );
-    libvlc_event_t event;
+    libvlc_media_parsed_status_t new_status;
 
-    event.type = libvlc_MediaParsedStatus;
-
-    vlc_mutex_lock(&p_md->parsed_lock);
-    switch (p_event->u.input_item_preparse_ended.new_status)
+    switch( p_event->u.input_item_preparse_ended.new_status )
     {
         case ITEM_PREPARSE_SKIPPED:
-            p_md->parsed_status = libvlc_media_parse_skipped;
-            p_md->has_asked_preparse = false;
+            new_status = libvlc_media_parsed_status_skipped;
             break;
         case ITEM_PREPARSE_FAILED:
-            p_md->parsed_status = libvlc_media_parse_failed;
+            new_status = libvlc_media_parsed_status_failed;
             break;
         case ITEM_PREPARSE_DONE:
-            p_md->parsed_status = libvlc_media_parse_done;
+            new_status = libvlc_media_parsed_status_done;
             break;
+        default:
+            return;
     }
-    event.u.media_parsed_status.new_status = p_md->parsed_status;
-    vlc_mutex_unlock(&p_md->parsed_lock);
-
-    if( p_subitems != NULL )
-    {
-        /* notify the media list */
-        libvlc_media_list_lock( p_subitems );
-        libvlc_media_list_internal_end_reached( p_subitems );
-        libvlc_media_list_unlock( p_subitems );
-    }
-
-    /* XXX: libVLC 2.2.0 compat: even if case of preparse failure,
-     * libvlc_MediaParsedChanged was sent with a true status. Therefore, send
-     * this event if it was not previously sent */
-    send_preparsed_event(p_md);
-
-    libvlc_event_send(p_md->p_event_manager, &event);
+    send_parsed_changed( p_md, new_status );
 }
 
 /**************************************************************************
@@ -312,10 +302,6 @@ static void install_input_item_observer( libvlc_media_t *p_md )
                       input_item_duration_changed,
                       p_md );
     vlc_event_attach( &p_md->p_input_item->event_manager,
-                      vlc_InputItemPreparsedChanged,
-                      input_item_preparsed_changed,
-                      p_md );
-    vlc_event_attach( &p_md->p_input_item->event_manager,
                       vlc_InputItemSubItemTreeAdded,
                       input_item_subitemtree_added,
                       p_md );
@@ -343,10 +329,6 @@ static void uninstall_input_item_observer( libvlc_media_t *p_md )
                       input_item_duration_changed,
                       p_md );
     vlc_event_detach( &p_md->p_input_item->event_manager,
-                      vlc_InputItemPreparsedChanged,
-                      input_item_preparsed_changed,
-                      p_md );
-    vlc_event_detach( &p_md->p_input_item->event_manager,
                       vlc_InputItemSubItemTreeAdded,
                       input_item_subitemtree_added,
                       p_md );
@@ -756,6 +738,8 @@ static int media_parse(libvlc_media_t *media, bool b_async,
     vlc_mutex_lock(&media->parsed_lock);
     needed = !media->has_asked_preparse;
     media->has_asked_preparse = true;
+    if (needed)
+        media->is_parsed = false;
     vlc_mutex_unlock(&media->parsed_lock);
 
     if (needed)
diff --git a/lib/media_internal.h b/lib/media_internal.h
index dd12176..f063ddb 100644
--- a/lib/media_internal.h
+++ b/lib/media_internal.h
@@ -45,7 +45,7 @@ struct libvlc_media_t
     vlc_mutex_t parsed_lock;
     vlc_mutex_t subitems_lock;
 
-    int  parsed_status;
+    libvlc_media_parsed_status_t parsed_status;
     bool is_parsed;
     bool has_asked_preparse;
 };
diff --git a/lib/media_player.c b/lib/media_player.c
index 4761fee..b561daa 100644
--- a/lib/media_player.c
+++ b/lib/media_player.c
@@ -124,6 +124,35 @@ static inline void unlock_input(libvlc_media_player_t *mp)
     vlc_mutex_unlock(&mp->input.lock);
 }
 
+static void input_item_preparsed_changed( const vlc_event_t *p_event,
+                                          void * user_data )
+{
+    libvlc_media_t *p_md = user_data;
+    if( p_event->u.input_item_preparsed_changed.new_status & ITEM_PREPARSED )
+    {
+        /* Send the event */
+        libvlc_event_t event;
+        event.type = libvlc_MediaParsedChanged;
+        event.u.media_parsed_changed.new_status = libvlc_media_parsed_status_done;
+        libvlc_event_send( p_md->p_event_manager, &event );
+    }
+}
+
+static void media_attach_preparsed_event( libvlc_media_t *p_md )
+{
+    vlc_event_attach( &p_md->p_input_item->event_manager,
+                      vlc_InputItemPreparsedChanged,
+                      input_item_preparsed_changed, p_md );
+}
+
+static void media_detach_preparsed_event( libvlc_media_t *p_md )
+{
+    vlc_event_detach( &p_md->p_input_item->event_manager,
+                      vlc_InputItemPreparsedChanged,
+                      input_item_preparsed_changed,
+                      p_md );
+}
+
 /*
  * Release the associated input thread.
  *
@@ -139,6 +168,8 @@ static void release_input_thread( libvlc_media_player_t *p_mi )
         return;
     p_mi->input.p_thread = NULL;
 
+    media_detach_preparsed_event( p_mi->p_md );
+
     var_DelCallback( p_input_thread, "can-seek",
                      input_seekable_changed, p_mi );
     var_DelCallback( p_input_thread, "can-pause",
@@ -914,12 +945,15 @@ int libvlc_media_player_play( libvlc_media_player_t *p_mi )
         return -1;
     }
 
+    media_attach_preparsed_event( p_mi->p_md );
+
     p_input_thread = input_Create( p_mi, p_mi->p_md->p_input_item, NULL,
                                    p_mi->input.p_resource );
     unlock(p_mi);
     if( !p_input_thread )
     {
         unlock_input(p_mi);
+        media_detach_preparsed_event( p_mi->p_md );
         libvlc_printerr( "Not enough memory" );
         return -1;
     }
@@ -939,6 +973,7 @@ int libvlc_media_player_play( libvlc_media_player_t *p_mi )
         var_DelCallback( p_input_thread, "program-scrambled", input_scrambled_changed, p_mi );
         var_DelCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
         input_Close( p_input_thread );
+        media_detach_preparsed_event( p_mi->p_md );
         libvlc_printerr( "Input initialization failure" );
         return -1;
     }
diff --git a/test/libvlc/media.c b/test/libvlc/media.c
index 51adb6a..f9de060 100644
--- a/test/libvlc/media.c
+++ b/test/libvlc/media.c
@@ -61,7 +61,7 @@ static void test_media_preparsed(int argc, const char** argv,
 
     // Check to see if we are properly receiving the event.
     libvlc_event_manager_t *em = libvlc_media_event_manager (media);
-    libvlc_event_attach (em, libvlc_MediaParsedStatus, media_parse_ended, &sem);
+    libvlc_event_attach (em, libvlc_MediaParsedChanged, media_parse_ended, &sem);
 
     // Parse the media. This is synchronous.
     int i_ret = libvlc_media_parse_with_options(media, libvlc_media_parse_local);
@@ -159,7 +159,7 @@ static void test_media_subitems_media(libvlc_media_t *media, bool play,
     }
     else
     {
-        libvlc_event_attach (em, libvlc_MediaParsedStatus, subitem_parse_ended, &sem);
+        libvlc_event_attach (em, libvlc_MediaParsedChanged, subitem_parse_ended, &sem);
 
         int i_ret = libvlc_media_parse_with_options(media, libvlc_media_parse_local);
         assert(i_ret == 0);
@@ -238,13 +238,13 @@ int main (void)
 
     test_media_preparsed (test_defaults_nargs, test_defaults_args,
                           SRCDIR"/samples/image.jpg", NULL,
-                          libvlc_media_parse_done);
+                          libvlc_media_parsed_status_done);
     test_media_preparsed (test_defaults_nargs, test_defaults_args,
                           NULL, "http://parsing_should_be_skipped.org/video.mp4",
-                          libvlc_media_parse_skipped);
+                          libvlc_media_parsed_status_skipped);
     test_media_preparsed (test_defaults_nargs, test_defaults_args,
                           NULL, "unknown://parsing_should_be_skipped.org/video.mp4",
-                          libvlc_media_parse_skipped);
+                          libvlc_media_parsed_status_skipped);
     test_media_subitems (test_defaults_nargs, test_defaults_args);
 
     return 0;
-- 
2.8.1



More information about the vlc-devel mailing list