[vlc-devel] [RFC 1/2] player info

Romain Vimont rom1v at videolabs.io
Wed Jun 26 11:15:53 CEST 2019


---
 include/vlc_player.h       |   3 +
 include/vlc_player_info.h  |  78 +++++++++
 src/Makefile.am            |   3 +
 src/input/demux.c          |   6 +
 src/input/demux.h          |   2 +
 src/input/event.h          |  12 +-
 src/input/input.c          |  17 ++
 src/input/input_internal.h |   9 +-
 src/input/player.c         |  20 +++
 src/input/player_info.c    | 337 +++++++++++++++++++++++++++++++++++++
 src/input/player_info.h    |  77 +++++++++
 src/libvlccore.sym         |  11 ++
 12 files changed, 573 insertions(+), 2 deletions(-)
 create mode 100644 include/vlc_player_info.h
 create mode 100644 src/input/player_info.c
 create mode 100644 src/input/player_info.h

diff --git a/include/vlc_player.h b/include/vlc_player.h
index 2fe226ab70..090fde7ced 100644
--- a/include/vlc_player.h
+++ b/include/vlc_player.h
@@ -23,6 +23,7 @@
 
 #include <vlc_input.h>
 #include <vlc_aout.h>
+#include <vlc_player_info.h>
 
 /**
  * @defgroup player Player
@@ -2869,6 +2870,8 @@ vlc_player_vout_Snapshot(vlc_player_t *player);
 VLC_API void
 vlc_player_vout_OSDMessage(vlc_player_t *player, const char *fmt, ...);
 
+VLC_API struct vlc_pi_input *
+vlc_player_GetInputInfo(vlc_player_t *player);
 
 /** @} */
 #endif
diff --git a/include/vlc_player_info.h b/include/vlc_player_info.h
new file mode 100644
index 0000000000..2a56c50664
--- /dev/null
+++ b/include/vlc_player_info.h
@@ -0,0 +1,78 @@
+#ifndef VLC_PLAYER_INFO_H
+#define VLC_PLAYER_INFO_H
+
+#include <vlc_common.h>
+#include <vlc_vector.h>
+
+typedef struct input_source input_source_t;
+
+// "pi" stands for "player info" to avoid excessively long names
+
+// everything must be called with player locked
+
+struct vlc_pi_input;
+struct vlc_pi_source;
+struct vlc_pi_stream;
+
+struct vlc_pi_track;
+struct vlc_pi_decoder;
+struct vlc_pi_decoder_device;
+struct vlc_pi_aout;
+struct vlc_pi_vout;
+
+typedef struct vlc_pi_input_listener_id vlc_pi_input_listener_id;
+
+struct vlc_pi_input_callbacks {
+    void
+    (*on_reset)(struct vlc_pi_input *pi_input, void *userdata);
+
+    void
+    (*on_source_added)(struct vlc_pi_input *pi_input, size_t source_index,
+                       struct vlc_pi_source *pi_source, void *userdata);
+
+    void
+    (*on_source_demux_updated)(struct vlc_pi_input *pi_input,
+                               size_t source_index,
+                               struct vlc_pi_source *pi_source, void *userdata);
+};
+
+VLC_API
+vlc_pi_input_listener_id *
+vlc_pi_input_AddListener(struct vlc_pi_input *pi_input,
+                         const struct vlc_pi_input_callbacks *cbs,
+                         void *userdata);
+
+VLC_API
+void
+vlc_pi_input_RemoveListener(struct vlc_pi_input *pi_input,
+                            vlc_pi_input_listener_id *listener);
+
+VLC_API
+size_t
+vlc_pi_input_GetSourcesCount(const struct vlc_pi_input *pi_input);
+
+VLC_API
+const struct vlc_pi_source *
+vlc_pi_input_GetSource(const struct vlc_pi_input *pi_input, size_t index);
+
+VLC_API
+size_t
+vlc_pi_source_GetStreamsCount(const struct vlc_pi_source *pi_source);
+
+VLC_API
+const struct vlc_pi_stream *
+vlc_pi_source_GetStream(const struct vlc_pi_source *pi_source, size_t index);
+
+VLC_API
+const char *
+vlc_pi_stream_GetModuleShortName(const struct vlc_pi_stream *pi_stream);
+
+VLC_API
+const char *
+vlc_pi_stream_GetModuleLongName(const struct vlc_pi_stream *pi_stream);
+
+VLC_API
+const char *
+vlc_pi_stream_GetUrl(const struct vlc_pi_stream *pi_stream);
+
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 3f73999fdb..a2948ab272 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -79,6 +79,7 @@ pluginsinclude_HEADERS = \
 	../include/vlc_picture_fifo.h \
 	../include/vlc_picture_pool.h \
 	../include/vlc_player.h \
+	../include/vlc_player_info.h \
 	../include/vlc_playlist.h \
 	../include/vlc_playlist_export.h \
 	../include/vlc_plugin.h \
@@ -262,6 +263,8 @@ libvlccore_la_SOURCES = \
 	input/input.c \
 	input/player.c \
 	input/player.h \
+	input/player_info.c \
+	input/player_info.h \
 	input/info.h \
 	input/meta.c \
 	clock/input_clock.h \
diff --git a/src/input/demux.c b/src/input/demux.c
index 22952ae800..f49664848e 100644
--- a/src/input/demux.c
+++ b/src/input/demux.c
@@ -150,6 +150,12 @@ struct vlc_demux_private
     module_t *module;
 };
 
+const char *demux_GetModuleName(demux_t *demux, bool longname)
+{
+    struct vlc_demux_private *priv = vlc_stream_Private(demux);
+    return module_get_name(priv->module, longname);
+}
+
 static void demux_DestroyDemux(demux_t *demux)
 {
     struct vlc_demux_private *priv = vlc_stream_Private(demux);
diff --git a/src/input/demux.h b/src/input/demux.h
index f729018105..7d347d44c3 100644
--- a/src/input/demux.h
+++ b/src/input/demux.h
@@ -62,4 +62,6 @@ demux_t *demux_FilterChainNew( demux_t *source, const char *list ) VLC_USED;
 bool demux_FilterEnable( demux_t *p_demux_chain, const char* psz_demux );
 bool demux_FilterDisable( demux_t *p_demux_chain, const char* psz_demux );
 
+const char *demux_GetModuleName(demux_t *demux, bool longname);
+
 #endif
diff --git a/src/input/event.h b/src/input/event.h
index 01163c479a..2d846e0850 100644
--- a/src/input/event.h
+++ b/src/input/event.h
@@ -25,7 +25,7 @@
 
 #include <vlc_common.h>
 #include <vlc_input.h>
-#include "input_internal.h"
+#include "player_info.h"
 
 static inline void input_SendEvent(input_thread_t *p_input,
                                    const struct vlc_input_event *event)
@@ -269,6 +269,16 @@ static inline void input_SendEventVbiTransparency(input_thread_t *p_input,
     });
 }
 
+static inline void
+input_SendEventInfo(input_thread_t *input, struct vlc_input_event_info *info)
+{
+    input_SendEvent(input, &(struct vlc_input_event) {
+        .type = INPUT_EVENT_INFO,
+        .info = info,
+    });
+}
+
+
 /*****************************************************************************
  * Event for resource.c
  *****************************************************************************/
diff --git a/src/input/input.c b/src/input/input.c
index 6ab5233653..cc0c32276e 100644
--- a/src/input/input.c
+++ b/src/input/input.c
@@ -1278,6 +1278,11 @@ static int Init( input_thread_t * p_input )
         goto error;
     priv->master = master;
 
+    struct vlc_input_event_info info;
+    info.type = VLC_INPUT_EVENT_INFO_INPUT_SOURCE_ADDED;
+    info.source = master;
+    input_SendEventInfo(p_input, &info);
+
     InitTitle( p_input, false );
 
     /* Load master infos */
@@ -1780,7 +1785,14 @@ static void ControlInsertDemuxFilter( input_thread_t* p_input, const char* psz_d
     input_source_t *p_inputSource = input_priv(p_input)->master;
     demux_t *p_filtered_demux = demux_FilterChainNew( p_inputSource->p_demux, psz_demux_chain );
     if ( p_filtered_demux != NULL )
+    {
         p_inputSource->p_demux = p_filtered_demux;
+
+        struct vlc_input_event_info info;
+        info.type = VLC_INPUT_EVENT_INFO_INPUT_SOURCE_DEMUX_UPDATED;
+        info.source = p_inputSource;
+        input_SendEventInfo(p_input, &info);
+    }
     else if ( psz_demux_chain != NULL )
         msg_Dbg(p_input, "Failed to create demux filter %s", psz_demux_chain);
 }
@@ -3249,6 +3261,11 @@ static int input_SlaveSourceAdd( input_thread_t *p_input,
     es_out_Control( priv->p_es_out_display, ES_OUT_SET_ES_BY_ID,
                     priv->i_last_es_id, false );
 
+    struct vlc_input_event_info info;
+    info.type = VLC_INPUT_EVENT_INFO_INPUT_SOURCE_ADDED;
+    info.source = p_source;
+    input_SendEventInfo(p_input, &info);
+
     return VLC_SUCCESS;
 }
 
diff --git a/src/input/input_internal.h b/src/input/input_internal.h
index 96357200be..043d21b5f6 100644
--- a/src/input/input_internal.h
+++ b/src/input/input_internal.h
@@ -34,6 +34,8 @@
 #include "input_interface.h"
 #include "misc/interrupt.h"
 
+typedef struct input_source input_source_t;
+
 struct input_stats;
 
 /*****************************************************************************
@@ -182,6 +184,9 @@ typedef enum input_event_type_e
 
     /* Thumbnail generation */
     INPUT_EVENT_THUMBNAIL_READY,
+
+    /* Input info event */
+    INPUT_EVENT_INFO,
 } input_event_type_e;
 
 #define VLC_INPUT_CAPABILITIES_SEEKABLE (1<<0)
@@ -314,6 +319,8 @@ struct vlc_input_event
         float subs_fps;
         /* INPUT_EVENT_THUMBNAIL_READY */
         picture_t *thumbnail;
+        /* INPUT_EVENT_INFO */
+        struct vlc_input_event_info *info;
     };
 };
 
@@ -387,7 +394,7 @@ input_item_t* input_GetItem( input_thread_t * ) VLC_USED;
 #define INPUT_CONTROL_FIFO_SIZE    100
 
 /* input_source_t: gathers all information per input source */
-typedef struct
+typedef struct input_source
 {
     demux_t  *p_demux; /**< Demux object (most downstream) */
 
diff --git a/src/input/player.c b/src/input/player.c
index a038ae67d6..340c4920a4 100644
--- a/src/input/player.c
+++ b/src/input/player.c
@@ -37,6 +37,7 @@
 #include "input_internal.h"
 #include "resource.h"
 #include "../audio_output/aout_internal.h"
+#include "player_info.h"
 
 #define RETRY_TIMEOUT_BASE VLC_TICK_FROM_MS(100)
 #define RETRY_TIMEOUT_MAX VLC_TICK_FROM_MS(3200)
@@ -167,6 +168,7 @@ struct vlc_player_t
 
     input_item_t *media;
     struct vlc_player_input *input;
+    struct vlc_pi_input info;
 
     bool releasing_media;
     bool next_media_requested;
@@ -1006,7 +1008,10 @@ vlc_player_input_HandleState(struct vlc_player_input *input,
         case VLC_PLAYER_STATE_STOPPING:
             input->started = false;
             if (input == player->input)
+            {
                 player->input = NULL;
+                vlc_pi_input_reset(&player->info);
+            }
 
             if (player->started)
             {
@@ -2108,6 +2113,9 @@ input_thread_Events(input_thread_t *input_thread,
             vlc_player_SendEvent(player, on_teletext_transparency_changed,
                                  input->teletext_transparent);
             break;
+        case INPUT_EVENT_INFO:
+            vlc_pi_input_handle_event(&player->info, event->info);
+            break;
         default:
             break;
     }
@@ -2194,6 +2202,7 @@ vlc_player_SetCurrentMedia(vlc_player_t *player, input_item_t *media)
     {
         vlc_player_destructor_AddInput(player, player->input);
         player->input = NULL;
+        vlc_pi_input_reset(&player->info);
     }
 
     assert(media == player->next_media);
@@ -2362,6 +2371,7 @@ vlc_player_Stop(vlc_player_t *player)
 
     vlc_player_destructor_AddInput(player, input);
     player->input = NULL;
+    vlc_pi_input_reset(&player->info);
 
 }
 
@@ -3446,6 +3456,8 @@ vlc_player_Delete(vlc_player_t *player)
 
     assert(vlc_list_is_empty(&player->listeners));
 
+    vlc_pi_input_destroy(&player->info);
+
     vlc_mutex_unlock(&player->lock);
 
     vlc_join(player->destructor.thread, NULL);
@@ -3508,6 +3520,8 @@ vlc_player_New(vlc_object_t *parent, enum vlc_player_lock_type lock_type,
     player->next_media_requested = false;
     player->next_media = NULL;
 
+    vlc_pi_input_init(&player->info);
+
 #define VAR_CREATE(var, flag) do { \
     if (var_Create(player, var, flag) != VLC_SUCCESS) \
         goto error; \
@@ -3595,3 +3609,9 @@ vlc_player_GetObject(vlc_player_t *player)
 {
     return VLC_OBJECT(player);
 }
+
+struct vlc_pi_input *
+vlc_player_GetInputInfo(vlc_player_t *player)
+{
+    return &player->info;
+}
diff --git a/src/input/player_info.c b/src/input/player_info.c
new file mode 100644
index 0000000000..c32bfe3f1a
--- /dev/null
+++ b/src/input/player_info.c
@@ -0,0 +1,337 @@
+#include "player_info.h"
+
+#include "demux.h"
+
+struct vlc_pi_input_listener_id
+{
+    const struct vlc_pi_input_callbacks *cbs;
+    void *userdata;
+    struct vlc_list node; /**< node of vlc_pi_input.listeners */
+};
+
+#define vlc_pi_input_listener_foreach(listener, pi_input) \
+    vlc_list_foreach(listener, &(pi_input)->listeners, node)
+
+#define vlc_pi_input_NotifyListener(pi_input, listener, event, ...) \
+do { \
+    if (listener->cbs->event) \
+        listener->cbs->event(pi_input, __VA_ARGS__, listener->userdata); \
+} while (0)
+
+#define vlc_pi_input_Notify(pi_input, event, ...) \
+do { \
+    vlc_pi_input_listener_id *listener; \
+    vlc_pi_input_listener_foreach(listener, pi_input) \
+        vlc_pi_input_NotifyListener(pi_input, listener, event, __VA_ARGS__); \
+} while(0)
+
+// ##__VA_ARGS__ is forbidden in VLC, so we need a specific macro for 0 varargs
+#define vlc_pi_input_NotifyListener0(pi_input, listener, event) \
+do { \
+    if (listener->cbs->event) \
+        listener->cbs->event(pi_input, listener->userdata); \
+} while (0)
+
+#define vlc_pi_input_Notify0(pi_input, event) \
+do { \
+    vlc_pi_input_listener_id *listener; \
+    vlc_pi_input_listener_foreach(listener, pi_input) \
+        vlc_pi_input_NotifyListener0(pi_input, listener, event); \
+} while(0)
+
+static struct vlc_pi_stream *
+vlc_pi_stream_new(const char *url, const char *module_shortname,
+                  const char *module_longname)
+{
+    struct vlc_pi_stream *pi_stream = malloc(sizeof(*pi_stream));
+    if (!pi_stream)
+        return NULL;
+
+    assert(url);
+    pi_stream->url = strdup(url);
+    if (!pi_stream->url)
+    {
+        free(pi_stream);
+        return NULL;
+    }
+
+    if (module_shortname) {
+        pi_stream->module_shortname = strdup(module_shortname);
+        if (!pi_stream->module_shortname)
+        {
+            free(pi_stream->url);
+            free(pi_stream);
+            return NULL;
+        }
+
+        // either no module names, either both short and long names
+        assert(module_longname);
+        pi_stream->module_longname = strdup(module_longname);
+        if (!pi_stream->module_longname)
+        {
+            free(pi_stream->module_shortname);
+            free(pi_stream->url);
+            free(pi_stream);
+            return NULL;
+        }
+    }
+    else
+    {
+        pi_stream->module_shortname = NULL;
+        pi_stream->module_longname = NULL;
+    }
+
+    return pi_stream;
+}
+
+static void
+vlc_pi_stream_delete(struct vlc_pi_stream *pi_stream)
+{
+    free(pi_stream->module_shortname);
+    free(pi_stream->module_longname);
+    free(pi_stream->url);
+    free(pi_stream);
+}
+
+static struct vlc_pi_source *
+vlc_pi_source_new(input_source_t *source)
+{
+    struct vlc_pi_source *pi_source = malloc(sizeof(*pi_source));
+    if (!pi_source)
+        return NULL;
+
+    vlc_vector_init(&pi_source->streams);
+    pi_source->source = source;
+    return pi_source;
+}
+
+static void
+vlc_pi_source_delete(struct vlc_pi_source *pi_source)
+{
+    for (size_t i = 0; i < pi_source->streams.size; ++i)
+        vlc_pi_stream_delete(pi_source->streams.data[i]);
+    vlc_vector_destroy(&pi_source->streams);
+
+    free(pi_source);
+}
+
+void
+vlc_pi_input_init(struct vlc_pi_input *pi_input)
+{
+    vlc_vector_init(&pi_input->sources);
+    vlc_list_init(&pi_input->listeners);
+}
+
+void
+vlc_pi_input_destroy(struct vlc_pi_input *pi_input)
+{
+    assert(vlc_list_is_empty(&pi_input->listeners));
+
+    for (size_t i = 0; i < pi_input->sources.size; ++i)
+        vlc_pi_source_delete(pi_input->sources.data[i]);
+    vlc_vector_destroy(&pi_input->sources);
+}
+
+void
+vlc_pi_input_reset(struct vlc_pi_input *pi_input)
+{
+    for (size_t i = 0; i < pi_input->sources.size; ++i)
+        vlc_pi_source_delete(pi_input->sources.data[i]);
+    vlc_vector_clear(&pi_input->sources);
+
+    vlc_pi_input_Notify0(pi_input, on_reset);
+}
+
+vlc_pi_input_listener_id *
+vlc_pi_input_AddListener(struct vlc_pi_input *pi_input,
+                         const struct vlc_pi_input_callbacks *cbs,
+                         void *userdata)
+{
+    vlc_pi_input_listener_id *listener = malloc(sizeof(*listener));
+    if (!listener)
+        return NULL;
+
+    listener->cbs = cbs;
+    listener->userdata = userdata;
+    vlc_list_append(&listener->node, &pi_input->listeners);
+
+    // notify initial state
+    vlc_pi_input_NotifyListener0(pi_input, listener, on_reset);
+
+    return listener;
+}
+
+void
+vlc_pi_input_RemoveListener(struct vlc_pi_input *pi_input,
+                            vlc_pi_input_listener_id *listener)
+{
+    (void) pi_input;
+    vlc_list_remove(&listener->node);
+    free(listener);
+}
+
+static void
+debug_print_pi_input(struct vlc_pi_input *pi_input)
+{
+    printf("[PI INPUT]\n");
+    for (size_t i = 0; i < pi_input->sources.size; ++i)
+    {
+        struct vlc_pi_source *pi_source = pi_input->sources.data[i];
+        printf("  [PI SOURCE %zd]\n", i);
+        for (size_t j = 0; j < pi_source->streams.size; ++j)
+        {
+            struct vlc_pi_stream *pi_stream = pi_source->streams.data[j];
+            printf("    [PI STREAM %zd]: %s (%s): %s\n", j,
+                   pi_stream->module_longname, pi_stream->module_shortname,
+                   pi_stream->url);
+        }
+    }
+}
+
+static ssize_t
+vlc_pi_source_find(struct vlc_pi_input *pi_input, input_source_t *source)
+{
+    for (size_t i = 0; i < pi_input->sources.size; ++i)
+    {
+        struct vlc_pi_source *pi_source = pi_input->sources.data[i];
+        if (pi_source->source == source)
+            return i;
+    }
+    return -1;
+}
+
+static bool
+vlc_pi_source_reset_streams(struct vlc_pi_source *pi_source,
+                                 demux_t *demux)
+{
+    vlc_vector_clear(&pi_source->streams);
+
+    assert(demux);
+    while (demux) {
+        const char *module_shortname;
+        const char *module_longname;
+        if (demux->p_next)
+        {
+            // demux filter
+            module_shortname = demux_GetModuleName(demux, false);
+            module_longname = demux_GetModuleName(demux, true);
+            assert(module_shortname);
+            assert(module_longname);
+        }
+        else
+        {
+            // access stream, no module
+            module_shortname = NULL;
+            module_longname = NULL;
+        }
+
+        struct vlc_pi_stream *pi_stream =
+            vlc_pi_stream_new(demux->psz_url, module_shortname, module_longname);
+        if (!pi_stream || !vlc_vector_push(&pi_source->streams, pi_stream))
+        {
+            vlc_vector_foreach(pi_stream, &pi_source->streams)
+                vlc_pi_stream_delete(pi_stream);
+            vlc_vector_clear(&pi_source->streams);
+            return false;
+        }
+
+        demux = demux->p_next;
+    }
+
+    return true;
+}
+
+static void
+handle_info_input_source_added(struct vlc_pi_input *pi_input,
+                               input_source_t *source)
+{
+    struct vlc_pi_source *pi_source = vlc_pi_source_new(source);
+    if (!pi_source)
+        return;
+
+    if (!vlc_pi_source_reset_streams(pi_source, source->p_demux))
+    {
+        vlc_pi_source_delete(pi_source);
+        return;
+    }
+
+    size_t index = pi_input->sources.size;
+    if (!vlc_vector_push(&pi_input->sources, pi_source))
+        return;
+
+    vlc_pi_input_Notify(pi_input, on_source_added, index, pi_source);
+}
+
+static void
+handle_info_input_source_demux_updated(struct vlc_pi_input *pi_input,
+                                       input_source_t *source)
+{
+    ssize_t source_index = vlc_pi_source_find(pi_input, source);
+    assert(source_index >= 0);
+    struct vlc_pi_source *pi_source = pi_input->sources.data[source_index];
+    if (!vlc_pi_source_reset_streams(pi_source, source->p_demux))
+        return;
+
+    vlc_pi_input_Notify(pi_input, on_source_demux_updated, source_index,
+                        pi_source);
+}
+
+void
+vlc_pi_input_handle_event(struct vlc_pi_input *input,
+                          struct vlc_input_event_info *info)
+{
+    switch (info->type) {
+        case VLC_INPUT_EVENT_INFO_INPUT_SOURCE_ADDED:
+            handle_info_input_source_added(input, info->source);
+            //debug_print_pi_input(input);
+            break;
+        case VLC_INPUT_EVENT_INFO_INPUT_SOURCE_DEMUX_UPDATED:
+            handle_info_input_source_demux_updated(input, info->source);
+            //debug_print_pi_input(input);
+        default:
+            // do nothing
+            break;
+    }
+}
+
+size_t
+vlc_pi_input_GetSourcesCount(const struct vlc_pi_input *pi_input)
+{
+    return pi_input->sources.size;
+}
+
+const struct vlc_pi_source *
+vlc_pi_input_GetSource(const struct vlc_pi_input *pi_input, size_t index)
+{
+    return pi_input->sources.data[index];
+}
+
+size_t
+vlc_pi_source_GetStreamsCount(const struct vlc_pi_source *pi_source)
+{
+    return pi_source->streams.size;
+}
+
+const struct vlc_pi_stream *
+vlc_pi_source_GetStream(const struct vlc_pi_source *pi_source, size_t index)
+{
+    return pi_source->streams.data[index];
+}
+
+const char *
+vlc_pi_stream_GetModuleShortName(const struct vlc_pi_stream *pi_stream)
+{
+    return pi_stream->module_shortname;
+}
+
+const char *
+vlc_pi_stream_GetModuleLongName(const struct vlc_pi_stream *pi_stream)
+{
+    return pi_stream->module_longname;
+}
+
+const char *
+vlc_pi_stream_GetUrl(const struct vlc_pi_stream *pi_stream)
+{
+    return pi_stream->url;
+}
diff --git a/src/input/player_info.h b/src/input/player_info.h
new file mode 100644
index 0000000000..a8bb35036c
--- /dev/null
+++ b/src/input/player_info.h
@@ -0,0 +1,77 @@
+#ifndef VLC_PLAYER_INFO_INTERNAL_H
+#define VLC_PLAYER_INFO_INTERNAL_H
+
+#include <vlc_common.h>
+#include <vlc_list.h>
+#include <vlc_player_info.h>
+#include "input_internal.h"
+
+typedef struct VLC_VECTOR(struct vlc_pi_source *) vlc_pi_source_vec_t;
+typedef struct VLC_VECTOR(struct vlc_pi_stream *) vlc_pi_stream_vec_t;
+
+struct vlc_pi_input {
+    vlc_pi_source_vec_t sources;
+    struct vlc_list listeners;
+};
+
+struct vlc_pi_source {
+    vlc_pi_stream_vec_t streams;
+    input_source_t *source;
+};
+
+struct vlc_pi_stream {
+    char *url;
+    char *module_shortname;
+    char *module_longname;
+};
+
+struct vlc_pi_track {
+    vlc_es_id_t *id;
+    struct vlc_pi_decoder *decoder;
+    struct vlc_pi_device *device;
+    struct vlc_pi_aout *aout;
+    struct vlc_pi_vout *vout;
+};
+
+struct vlc_pi_decoder {
+
+};
+
+struct vlc_pi_device {
+
+};
+
+struct vlc_pi_aout {
+
+};
+
+struct vlc_pi_vout {
+
+};
+
+enum vlc_input_event_info_type {
+    VLC_INPUT_EVENT_INFO_INPUT_SOURCE_ADDED,
+    VLC_INPUT_EVENT_INFO_INPUT_SOURCE_DEMUX_UPDATED,
+};
+
+struct vlc_input_event_info {
+    enum vlc_input_event_info_type type;
+    union {
+        input_source_t *source;
+    };
+};
+
+void
+vlc_pi_input_init(struct vlc_pi_input *input);
+
+void
+vlc_pi_input_destroy(struct vlc_pi_input *input);
+
+void
+vlc_pi_input_reset(struct vlc_pi_input *input);
+
+void
+vlc_pi_input_handle_event(struct vlc_pi_input *input,
+                          struct vlc_input_event_info *info);
+
+#endif
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 64a6c0123b..df513c4e1b 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -89,6 +89,7 @@ demux_PacketizerNew
 demux_New
 demux_vaControl
 demux_vaControlHelper
+demux_GetModuleName
 vlc_demux_chained_New
 vlc_demux_chained_Send
 vlc_demux_chained_ControlVa
@@ -790,6 +791,7 @@ vlc_player_GetCategoryLanguage
 vlc_player_GetCurrentMedia
 vlc_player_GetError
 vlc_player_GetEsIdFromVout
+vlc_player_GetInputInfo
 vlc_player_GetLength
 vlc_player_GetPosition
 vlc_player_GetProgram
@@ -939,3 +941,12 @@ vlc_media_tree_Unlock
 vlc_media_tree_Find
 vlc_media_tree_Preparse
 vlc_viewpoint_to_4x4
+vlc_pi_input_AddListener
+vlc_pi_input_RemoveListener
+vlc_pi_input_GetSourcesCount
+vlc_pi_input_GetSource
+vlc_pi_source_GetStreamsCount
+vlc_pi_source_GetStream
+vlc_pi_stream_GetModuleShortName
+vlc_pi_stream_GetModuleLongName
+vlc_pi_stream_GetUrl
-- 
2.20.1



More information about the vlc-devel mailing list