[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