[vlc-devel] [PATCH 1/4] stream_filter/icy: Add ICY metadata stream filter

Rémi Denis-Courmont remi at remlab.net
Wed Nov 1 13:20:54 CET 2017


Le 1 novembre 2017 06:16:33 GMT+02:00, Marvin Scholz <epirat07 at gmail.com> a écrit :
>---
> modules/stream_filter/Makefile.am |   3 +
>modules/stream_filter/icy.c       | 254
>++++++++++++++++++++++++++++++++++++++
> 2 files changed, 257 insertions(+)
> create mode 100644 modules/stream_filter/icy.c
>
>diff --git a/modules/stream_filter/Makefile.am
>b/modules/stream_filter/Makefile.am
>index 50d99faac9..d125556452 100644
>--- a/modules/stream_filter/Makefile.am
>+++ b/modules/stream_filter/Makefile.am
>@@ -22,6 +22,9 @@ if HAVE_ZLIB
> stream_filter_LTLIBRARIES += libinflate_plugin.la
> endif
> 
>+libicy_plugin_la_SOURCES = stream_filter/icy.c
>+stream_filter_LTLIBRARIES += libicy_plugin.la
>+
> libprefetch_plugin_la_SOURCES = stream_filter/prefetch.c
> libprefetch_plugin_la_LIBADD = $(LIBPTHREAD)
> if !HAVE_WINSTORE
>diff --git a/modules/stream_filter/icy.c b/modules/stream_filter/icy.c
>new file mode 100644
>index 0000000000..22e586128c
>--- /dev/null
>+++ b/modules/stream_filter/icy.c
>@@ -0,0 +1,254 @@
>+/*****************************************************************************
>+ * icy.c: ICY metadata extraction module for VLC
>+
>*****************************************************************************
>+ * Copyright (C) 2017 VLC authors and VideoLAN
>+ *
>+ * Authors: Marvin Scholz <epirat07 at gmail dot com>
>+ * 
>+ * This file reuses code from the old http access module,
>+ * Authors: Laurent Aimar <fenrir at via.ecp.fr>
>+ *          Christophe Massiot <massiot at via.ecp.fr>
>+ *          Rémi Denis-Courmont <rem # videolan.org>
>+ *          Antoine Cellerier <dionoea at videolan dot org>
>+ *
>+ * This program is free software; you can redistribute it and/or
>modify it
>+ * under the terms of the GNU Lesser General Public License as
>published by
>+ * the Free Software Foundation; either version 2.1 of the License, or
>+ * (at your option) any later version.
>+ *
>+ * This program is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>+ * GNU Lesser General Public License for more details.
>+ *
>+ * You should have received a copy of the GNU Lesser General Public
>License
>+ * along with this program; if not, write to the Free Software
>Foundation,
>+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
>+
>*****************************************************************************/
>+
>+#ifdef HAVE_CONFIG_H
>+# include "config.h"
>+#endif
>+
>+#include <stdlib.h>
>+#include <string.h>
>+
>+#include <vlc_common.h>
>+#include <vlc_plugin.h>
>+#include <vlc_stream.h>
>+#include <vlc_input.h>
>+#include <vlc_charset.h>
>+
>+struct stream_sys_t
>+{
>+    int      icy_metaint;
>+    char     *icy_title;
>+
>+    uint64_t offset;
>+};
>+
>+static void ParseICYData(stream_t *stream, char *data)
>+{
>+    stream_sys_t *sys = stream->p_sys;
>+    char *start = strcasestr(data, "StreamTitle=");
>+
>+    if (!start)
>+        return;
>+
>+    start += strlen("StreamTitle=");
>+    if (*start == '\'' || *start == '"')
>+    {
>+        char closing[] = { start[0], ';', '\0' };
>+        char *end = strstr(&start[1], closing);
>+        if (!end)
>+            end = strchr(&start[1], ';');
>+
>+        if (end)
>+            *end = '\0';
>+    }
>+    else
>+    {
>+        char *end = strchr( &start[1], ';' );
>+        if (end)
>+            *end = '\0';
>+    }
>+
>+    if (!sys->icy_title || strcmp(sys->icy_title, &start[1]))
>+    {
>+        free(sys->icy_title);
>+        char *tmp = strdup(&start[1]);
>+        sys->icy_title = EnsureUTF8(tmp);
>+        if (!sys->icy_title)
>+            free(tmp);
>+
>+        msg_Dbg(stream, "New Icy-Title=%s", sys->icy_title);
>+        input_thread_t *input = stream->p_input;
>+        if (input)
>+        {
>+            input_item_t *input_item = input_GetItem(input);
>+            if (input_item)
>+                input_item_SetMeta( input_item, vlc_meta_NowPlaying,
>sys->icy_title );
>+        }
>+    }
>+}
>+
>+static int ReadICYMeta( stream_t *stream )
>+{
>+    uint8_t buffer;
>+    size_t data_read;
>+    char *icy_data;
>+
>+    /* Read meta data length */
>+    if (vlc_stream_Read(stream->p_source, &buffer, 1) != 1)
>+        return VLC_EGENERIC;
>+
>+    const uint8_t icy_size = buffer << 4;
>+
>+    if (icy_size == 0)
>+        return VLC_SUCCESS;
>+
>+    icy_data = malloc(icy_size + 1);
>+    for (data_read = 0; data_read < icy_size;)
>+    {
>+        size_t tmp_read;
>+
>+        tmp_read = vlc_stream_Read(stream->p_source,
>&icy_data[data_read], icy_size - data_read);
>+
>+        if (tmp_read <= 0)
>+        {
>+            free(icy_data);
>+            return VLC_EGENERIC;
>+        }
>+        data_read += tmp_read;
>+    }
>+    icy_data[data_read] = '\0'; /* Just in case */
>+
>+    /* Now parse the meta */
>+    ParseICYData(stream, icy_data);
>+
>+    free(icy_data);
>+
>+    return VLC_SUCCESS;
>+}
>+
>+static ssize_t Read(stream_t *stream, void *buf, size_t buflen)
>+{
>+    stream_sys_t *p_sys = stream->p_sys;
>+    int i_read = 0;
>+
>+    if (p_sys->icy_metaint > 0 && p_sys->offset > 0)
>+    {
>+        int i_next = p_sys->icy_metaint - (p_sys->offset %
>p_sys->icy_metaint);
>+
>+        if (i_next == p_sys->icy_metaint)
>+        {
>+            p_sys->offset = 0;
>+            if (ReadICYMeta(stream))
>+                return 0;
>+        }
>+        if (buflen > (size_t)i_next)
>+            buflen = i_next;
>+    }
>+
>+    i_read = vlc_stream_Read(stream->p_source, buf, buflen);
>+
>+    if (i_read < 0)
>+        return -1;
>+
>+    p_sys->offset += i_read;
>+    return i_read;
>+}
>+
>+static int ReadDir(stream_t *stream, input_item_node_t *node)
>+{
>+    (void) stream; (void) node;
>+    return VLC_EGENERIC;
>+}
>+
>+static int Seek(stream_t *stream, uint64_t offset)
>+{
>+    (void) stream; (void) offset;
>+    return -1;
>+}
>+
>+static int Control(stream_t *stream, int query, va_list args)
>+{
>+    switch (query)
>+    {
>+        case STREAM_CAN_SEEK:
>+        case STREAM_CAN_FASTSEEK:
>+            *va_arg(args, bool *) = false;
>+            break;
>+        case STREAM_CAN_PAUSE:
>+        case STREAM_CAN_CONTROL_PACE:
>+        case STREAM_GET_PTS_DELAY:
>+        case STREAM_GET_META:
>+        case STREAM_GET_CONTENT_TYPE:
>+        case STREAM_GET_SIGNAL:
>+        case STREAM_SET_PAUSE_STATE:
>+            return vlc_stream_vaControl(stream->p_source, query,
>args);
>+        case STREAM_IS_DIRECTORY:
>+        case STREAM_GET_SIZE:
>+        case STREAM_GET_TITLE_INFO:
>+        case STREAM_GET_TITLE:
>+        case STREAM_GET_SEEKPOINT:
>+        case STREAM_SET_TITLE:
>+        case STREAM_SET_SEEKPOINT:
>+        case STREAM_SET_PRIVATE_ID_STATE:
>+        case STREAM_SET_PRIVATE_ID_CA:
>+        case STREAM_GET_PRIVATE_ID_STATE:
>+            return VLC_EGENERIC;
>+        default:
>+            msg_Err(stream, "unimplemented query (%d) in control",
>query);
>+            return VLC_EGENERIC;
>+    }
>+    return VLC_SUCCESS;
>+}
>+
>+static int Open(vlc_object_t *obj)
>+{
>+    stream_t *stream = (stream_t *)obj;
>+
>+    int metaint = var_InheritInteger(stream, "icy-metaint");
>+    if (metaint < 0)
>+        return VLC_EGENERIC;
>+
>+    config_PutInt(stream, "icy-metaint", -1);
>+
>+    stream_sys_t *sys = malloc(sizeof (*sys));
>+    if (unlikely(sys == NULL))
>+        return VLC_ENOMEM;
>+
>+    sys->offset = 0;
>+    sys->icy_metaint = metaint;
>+    sys->icy_title = NULL;
>+
>+    stream->p_sys = sys;
>+    stream->pf_read = Read;
>+    stream->pf_readdir = ReadDir;
>+    stream->pf_seek = Seek;
>+    stream->pf_control = Control;
>+
>+    return VLC_SUCCESS;
>+}
>+
>+static void Close (vlc_object_t *obj)
>+{
>+    stream_t *stream = (stream_t *)obj;
>+    stream_sys_t *sys = stream->p_sys;
>+    free(sys->icy_title);
>+    free(sys);
>+}
>+
>+vlc_module_begin()
>+    set_category(CAT_INPUT)
>+    set_subcategory(SUBCAT_INPUT_STREAM_FILTER)
>+    set_capability("stream_filter", 30)
>+
>+    set_description(N_("ICY metadata filter"))
>+
>+    add_integer("icy-metaint", -1, "ICY metaint", NULL, true)
>+    change_volatile()
>+
>+    set_callbacks(Open, Close)
>+vlc_module_end()
>-- 
>2.13.5 (Apple Git-94)
>
>_______________________________________________
>vlc-devel mailing list
>To unsubscribe or modify your subscription options:
>https://mailman.videolan.org/listinfo/vlc-devel

Unless the interval is decided by the client, I don't see how that will work.
-- 
Envoyé de mon appareil Android avec Courriel K-9 Mail. Veuillez excuser ma brièveté.


More information about the vlc-devel mailing list