[vlc-devel] [PATCH 08/14] libvlc: receive events from input thread

Romain Vimont rom1v at videolabs.io
Thu Aug 16 16:02:05 CEST 2018


Replace listeners on the input item by preparser callbacks (for
preparsing) and input thread callbacks (for normal playback).
---
 lib/media.c          | 44 ++++++++++++++++++++------------------------
 lib/media_internal.h |  1 +
 lib/media_player.c   | 19 ++++++++++++++++++-
 test/libvlc/media.c  | 14 ++++++++------
 4 files changed, 47 insertions(+), 31 deletions(-)

diff --git a/lib/media.c b/lib/media.c
index 81c39436cb..17deae436e 100644
--- a/lib/media.c
+++ b/lib/media.c
@@ -200,13 +200,17 @@ static void input_item_add_subnode( libvlc_media_t *md,
 /**************************************************************************
  * input_item_subitemtree_added (Private) (vlc event Callback)
  **************************************************************************/
-static void input_item_subitemtree_added( const vlc_event_t * p_event,
-                                          void * user_data )
+static void input_item_subtree_added(input_item_t *item,
+                                     input_item_node_t *node,
+                                     void *user_data)
 {
+    VLC_UNUSED(item);
     libvlc_media_t * p_md = user_data;
-    libvlc_event_t event;
-    input_item_node_t *node = p_event->u.input_item_subitem_tree_added.p_root;
+    libvlc_media_add_subtree(p_md, node);
+}
 
+void libvlc_media_add_subtree(libvlc_media_t *p_md, input_item_node_t *node)
+{
     /* FIXME FIXME FIXME
      * Recursive function calls seem much simpler for this. But playlists are
      * untrusted and can be arbitrarily deep (e.g. with XSPF). So recursion can
@@ -214,6 +218,7 @@ static void input_item_subitemtree_added( const vlc_event_t * p_event,
     input_item_add_subnode( p_md, node );
 
     /* Construct the event */
+    libvlc_event_t event;
     event.type = libvlc_MediaSubItemTreeAdded;
     event.u.media_subitemtree_added.item = p_md;
 
@@ -305,13 +310,15 @@ static void send_parsed_changed( libvlc_media_t *p_md,
 /**************************************************************************
  * input_item_preparse_ended (Private) (vlc event Callback)
  **************************************************************************/
-static void input_item_preparse_ended( const vlc_event_t * p_event,
-                                       void * user_data )
+static void input_item_preparse_ended(input_item_t *item,
+                                      enum input_item_preparse_status status,
+                                      void *user_data)
 {
+    VLC_UNUSED(item);
     libvlc_media_t * p_md = user_data;
     libvlc_media_parsed_status_t new_status;
 
-    switch( p_event->u.input_item_preparse_ended.new_status )
+    switch( status )
     {
         case ITEM_PREPARSE_SKIPPED:
             new_status = libvlc_media_parsed_status_skipped;
@@ -344,14 +351,6 @@ static void install_input_item_observer( libvlc_media_t *p_md )
                       vlc_InputItemDurationChanged,
                       input_item_duration_changed,
                       p_md );
-    vlc_event_attach( &p_md->p_input_item->event_manager,
-                      vlc_InputItemSubItemTreeAdded,
-                      input_item_subitemtree_added,
-                      p_md );
-    vlc_event_attach( &p_md->p_input_item->event_manager,
-                      vlc_InputItemPreparseEnded,
-                      input_item_preparse_ended,
-                      p_md );
 }
 
 /**************************************************************************
@@ -367,14 +366,6 @@ static void uninstall_input_item_observer( libvlc_media_t *p_md )
                       vlc_InputItemDurationChanged,
                       input_item_duration_changed,
                       p_md );
-    vlc_event_detach( &p_md->p_input_item->event_manager,
-                      vlc_InputItemSubItemTreeAdded,
-                      input_item_subitemtree_added,
-                      p_md );
-    vlc_event_detach( &p_md->p_input_item->event_manager,
-                      vlc_InputItemPreparseEnded,
-                      input_item_preparse_ended,
-                      p_md );
 }
 
 /**************************************************************************
@@ -778,6 +769,11 @@ libvlc_media_get_duration( libvlc_media_t * p_md )
     return from_mtime(input_item_GetDuration( p_md->p_input_item ));
 }
 
+static const input_preparser_callbacks_t input_preparser_callbacks = {
+    .on_preparse_ended = input_item_preparse_ended,
+    .on_subtree_added = input_item_subtree_added,
+};
+
 static int media_parse(libvlc_media_t *media, bool b_async,
                        libvlc_media_parse_flag_t parse_flag, int timeout)
 {
@@ -812,7 +808,7 @@ static int media_parse(libvlc_media_t *media, bool b_async,
             parse_scope |= META_REQUEST_OPTION_SCOPE_NETWORK;
         if (parse_flag & libvlc_media_do_interact)
             parse_scope |= META_REQUEST_OPTION_DO_INTERACT;
-        ret = libvlc_MetadataRequest(libvlc, item, parse_scope, NULL, NULL, timeout, media);
+        ret = libvlc_MetadataRequest(libvlc, item, parse_scope, &input_preparser_callbacks, media, timeout, media);
         if (ret != VLC_SUCCESS)
             return ret;
     }
diff --git a/lib/media_internal.h b/lib/media_internal.h
index 5a67e9ff60..0b5c18d712 100644
--- a/lib/media_internal.h
+++ b/lib/media_internal.h
@@ -55,5 +55,6 @@ libvlc_media_t * libvlc_media_new_from_input_item(
         libvlc_instance_t *, input_item_t * );
 
 void libvlc_media_set_state( libvlc_media_t *, libvlc_state_t );
+void libvlc_media_add_subtree(libvlc_media_t *, input_item_node_t *);
 
 #endif
diff --git a/lib/media_player.c b/lib/media_player.c
index 30374d4ee9..e413a004e8 100644
--- a/lib/media_player.c
+++ b/lib/media_player.c
@@ -952,6 +952,23 @@ static void del_es_callbacks( input_thread_t *p_input_thread, libvlc_media_playe
     var_DelListCallback( p_input_thread, "spu-es", input_es_changed, p_mi );
 }
 
+static void on_input_event(input_thread_t *input, void *userdata,
+                           const struct vlc_input_event *event)
+{
+    if (event->type == INPUT_EVENT_PARSING)
+    {
+        if (event->parsing.action == VLC_INPUT_PARSING_SUBTREE_ADDED)
+        {
+            libvlc_media_player_t *media_player = userdata;
+            libvlc_media_t *media = media_player->p_md;
+            libvlc_media_add_subtree(media, event->parsing.root);
+        }
+        return;
+    }
+
+    input_LegacyEvents(input, userdata, event);
+}
+
 /**************************************************************************
  * Tell media player to start playing.
  **************************************************************************/
@@ -984,7 +1001,7 @@ int libvlc_media_player_play( libvlc_media_player_t *p_mi )
 
     media_attach_preparsed_event( p_mi->p_md );
 
-    p_input_thread = input_Create( p_mi, input_LegacyEvents, NULL,
+    p_input_thread = input_Create( p_mi, on_input_event, p_mi,
                                    p_mi->p_md->p_input_item, NULL,
                                    p_mi->input.p_resource,
                                    p_mi->input.p_renderer );
diff --git a/test/libvlc/media.c b/test/libvlc/media.c
index 933ca41f70..5e20177a6a 100644
--- a/test/libvlc/media.c
+++ b/test/libvlc/media.c
@@ -127,12 +127,14 @@ static void test_media_preparsed(libvlc_instance_t *vlc, const char *path,
     libvlc_media_release (media);
 }
 
-static void input_item_preparse_timeout( const vlc_event_t *p_event,
+static void input_item_preparse_timeout( input_item_t *item,
+                                         enum input_item_preparse_status status,
                                          void *user_data )
 {
+    VLC_UNUSED(item);
     vlc_sem_t *p_sem = user_data;
 
-    assert( p_event->u.input_item_preparse_ended.new_status == ITEM_PREPARSE_TIMEOUT );
+    assert( status == ITEM_PREPARSE_TIMEOUT );
     vlc_sem_post(p_sem);
 }
 
@@ -154,12 +156,12 @@ static void test_input_metadata_timeout(libvlc_instance_t *vlc, int timeout,
 
     vlc_sem_t sem;
     vlc_sem_init (&sem, 0);
-    i_ret = vlc_event_attach(&p_item->event_manager, vlc_InputItemPreparseEnded,
-                             input_item_preparse_timeout, &sem);
-    assert(i_ret == 0);
+    const struct input_preparser_callbacks_t cbs = {
+        .on_preparse_ended = input_item_preparse_timeout,
+    };
     i_ret = libvlc_MetadataRequest(vlc->p_libvlc_int, p_item,
                                    META_REQUEST_OPTION_SCOPE_LOCAL,
-                                   NULL, NULL, timeout, vlc);
+                                   &cbs, &sem, timeout, vlc);
     assert(i_ret == 0);
 
     if (wait_and_cancel > 0)
-- 
2.18.0



More information about the vlc-devel mailing list