From ddb0bbdbb015d7e70a9622a6dff46935b1a9251c Mon Sep 17 00:00:00 2001 From: Jens Georg Date: Thu, 27 Jan 2011 19:04:45 +0100 Subject: [PATCH] mediathek: Add option to chose between H.264 and WMV videos --- data/rygel-default.conf | 1 + data/rygel-maemo.conf | 1 + doc/man/rygel.conf.xml | 8 ++++ src/plugins/mediathek/Makefile.am | 2 + .../rygel-mediathek-asx-playlist-parser.vala | 31 ++++-------- .../rygel-mediathek-mov-playlist-parser.vala | 56 ++++++++++++++++++++++ .../mediathek/rygel-mediathek-playlist-parser.vala | 55 +++++++++++++++++++++ .../rygel-mediathek-video-item-factory.vala | 35 ++++++++++++-- 8 files changed, 163 insertions(+), 26 deletions(-) create mode 100644 src/plugins/mediathek/rygel-mediathek-mov-playlist-parser.vala create mode 100644 src/plugins/mediathek/rygel-mediathek-playlist-parser.vala diff --git a/data/rygel-default.conf b/data/rygel-default.conf index 5612008..d32c445 100644 --- a/data/rygel-default.conf +++ b/data/rygel-default.conf @@ -94,6 +94,7 @@ enabled=false # List of ids of broadcasts rss=508 update-interval=1800 +video-format=wmv [GstLaunch] enabled=false diff --git a/data/rygel-maemo.conf b/data/rygel-maemo.conf index 15326eb..2aca50a 100644 --- a/data/rygel-maemo.conf +++ b/data/rygel-maemo.conf @@ -94,6 +94,7 @@ enabled=false # List of ids of broadcasts rss=508 update-interval=1800 +video-format=wmv [GstLaunch] enabled=false diff --git a/doc/man/rygel.conf.xml b/doc/man/rygel.conf.xml index b92a9d2..a5c069e 100644 --- a/doc/man/rygel.conf.xml +++ b/doc/man/rygel.conf.xml @@ -278,6 +278,14 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/ Time in seconds after which the plugin checks for new content. Default is 1800s (30 minutes). The minimum timeout is 10 minutes. + + + + + + The mediathek usually offers the videos in two formats, WMV and H.264. Possible values here are wmv and mp4. The default video format is wmv. + + diff --git a/src/plugins/mediathek/Makefile.am b/src/plugins/mediathek/Makefile.am index 93a1478..782f151 100644 --- a/src/plugins/mediathek/Makefile.am +++ b/src/plugins/mediathek/Makefile.am @@ -19,7 +19,9 @@ AM_CFLAGS = $(LIBGUPNP_CFLAGS) \ -include config.h librygel_mediathek_la_SOURCES = rygel-mediathek-asx-playlist-parser.vala \ + rygel-mediathek-mov-playlist-parser.vala \ rygel-mediathek-plugin.vala \ + rygel-mediathek-playlist-parser.vala \ rygel-mediathek-video-item-factory.vala \ rygel-mediathek-root-container.vala \ rygel-mediathek-rss-container.vala \ diff --git a/src/plugins/mediathek/rygel-mediathek-asx-playlist-parser.vala b/src/plugins/mediathek/rygel-mediathek-asx-playlist-parser.vala index 95c047d..e7bd647 100644 --- a/src/plugins/mediathek/rygel-mediathek-asx-playlist-parser.vala +++ b/src/plugins/mediathek/rygel-mediathek-asx-playlist-parser.vala @@ -33,15 +33,16 @@ using Xml; * This parser is //only// intended to work with the simple * ASX files presented by the ZDF Mediathek streaming server */ -internal class Rygel.Mediathek.AsxPlaylistParser : Object { +internal class Rygel.Mediathek.AsxPlaylistParser : PlaylistParser { private Regex normalizer; - private Session session; public AsxPlaylistParser (Session session) { + Object (session : session, + playlist_suffix : ".asx", + mime_type : "video/x-ms-wmv"); try { this.normalizer = new Regex ("(<[/]?)([a-zA-Z:]+)"); } catch (RegexError error) {}; - this.session = session; } /** @@ -55,29 +56,17 @@ internal class Rygel.Mediathek.AsxPlaylistParser : Object { * @param uri network location of the ASX file * @return a list of uris found in this file */ - public async Gee.List? parse (string uri) throws VideoItemError { - var message = new Soup.Message ("GET", uri); + public override Gee.List? parse_playlist (string data, + int length) + throws VideoItemError { ArrayList uris = null; - // FIXME: Revert to SoupUtils once bgo#639702 is fixed - SourceFunc callback = parse.callback; - this.session.queue_message (message, () => { callback (); }); - yield; - - if (message.status_code != 200) { - throw new VideoItemError.NETWORK_ERROR - ("Playlist download failed: %u (%s)", - message.status_code, - Soup.status_get_phrase - (message.status_code)); - } - try { // lowercase all tags using regex and \L\E syntax var normalized_content = this.normalizer.replace - ((string) message.response_body.data, - (long) message.response_body.length, - 0, + (data, + length, + 0, "\\1\\L\\2\\E"); var doc = Parser.parse_memory (normalized_content, diff --git a/src/plugins/mediathek/rygel-mediathek-mov-playlist-parser.vala b/src/plugins/mediathek/rygel-mediathek-mov-playlist-parser.vala new file mode 100644 index 0000000..5e14bf6 --- /dev/null +++ b/src/plugins/mediathek/rygel-mediathek-mov-playlist-parser.vala @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2011 Jens Georg + * + * Author: Jens Georg + * + * This file is part of Rygel. + * + * Rygel 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 of the License, or + * (at your option) any later version. + * + * Rygel 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. + */ + +using Gee; +using Soup; + +internal class Rygel.Mediathek.MovPlaylistParser : PlaylistParser { + public MovPlaylistParser (Session session) { + Object (session : session, + playlist_suffix : ".mov", + mime_type : "video/mp4"); + } + + public override Gee.List? parse_playlist (string data, + int length) + throws VideoItemError { + var lines = data.split ("\n"); + if (lines.length < 2) { + throw new VideoItemError.XML_PARSE_ERROR + ("Not enough entries in playlist"); + } + + if (lines[0] != "RTSPtext") { + throw new VideoItemError.XML_PARSE_ERROR ("Invalid playlist format"); + } + + if (!lines[1].has_prefix ("rtsp")) { + throw new VideoItemError.XML_PARSE_ERROR + ("No rtsp url found in playlist"); + } + + var list = new ArrayList (); + list.add (lines[1]); + + return list; + } +} diff --git a/src/plugins/mediathek/rygel-mediathek-playlist-parser.vala b/src/plugins/mediathek/rygel-mediathek-playlist-parser.vala new file mode 100644 index 0000000..f9b0fec --- /dev/null +++ b/src/plugins/mediathek/rygel-mediathek-playlist-parser.vala @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2011 Jens Georg + * + * Author: Jens Georg + * + * This file is part of Rygel. + * + * Rygel 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 of the License, or + * (at your option) any later version. + * + * Rygel 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. + */ + +using Soup; +using Gee; + +internal abstract class Rygel.Mediathek.PlaylistParser : Object { + public Session session { get; construct; } + public string playlist_suffix { get; construct; } + public string mime_type { get; construct; } + + public async Gee.List? parse (string uri) throws VideoItemError { + var message = new Soup.Message ("GET", uri); + + // FIXME: Revert to SoupUtils once bgo#639702 is fixed + SourceFunc callback = parse.callback; + this.session.queue_message (message, () => { callback (); }); + yield; + + if (message.status_code != 200) { + throw new VideoItemError.NETWORK_ERROR + ("Playlist download failed: %u (%s)", + message.status_code, + Soup.status_get_phrase + (message.status_code)); + } + + return this.parse_playlist ((string) message.response_body.data, + (int) message.response_body.length); + } + + + public abstract Gee.List? parse_playlist (string data, + int length) + throws VideoItemError; +} diff --git a/src/plugins/mediathek/rygel-mediathek-video-item-factory.vala b/src/plugins/mediathek/rygel-mediathek-video-item-factory.vala index d5e4a73..62c9730 100644 --- a/src/plugins/mediathek/rygel-mediathek-video-item-factory.vala +++ b/src/plugins/mediathek/rygel-mediathek-video-item-factory.vala @@ -27,7 +27,9 @@ internal errordomain Rygel.Mediathek.VideoItemError { internal class Rygel.Mediathek.VideoItemFactory : Object { private static VideoItemFactory instance; - private AsxPlaylistParser playlist_parser; + private PlaylistParser playlist_parser; + private const string VIDEO_FORMAT_WMV = "wmv"; + private const string VIDEO_FORMAT_MP4 = "mp4"; public static VideoItemFactory get_default () { if (instance == null) { @@ -55,7 +57,7 @@ internal class Rygel.Mediathek.VideoItemFactory : Object { var id = Checksum.compute_for_string (ChecksumType.MD5, title); var item = new VideoItem (id, parent, title); - item.mime_type = "video/x-ms-wmv"; + item.mime_type = this.playlist_parser.mime_type; item.author = "ZDF - Second German TV Channel Streams"; foreach (var uri in resolved_uris) { @@ -66,8 +68,31 @@ internal class Rygel.Mediathek.VideoItemFactory : Object { } private VideoItemFactory () { - playlist_parser = new AsxPlaylistParser - (RootContainer.get_default_session ()); + var config = Rygel.MetaConfig.get_default (); + string video_format = VIDEO_FORMAT_WMV; + + try { + video_format = config.get_string ("ZDFMediathek", + "video-format").casefold (); + if (video_format != VIDEO_FORMAT_WMV && + video_format != VIDEO_FORMAT_MP4) { + video_format = VIDEO_FORMAT_WMV; + } + } catch (Error error) { } + + debug ("Exposing mediathek items in format: %s", video_format); + var session = RootContainer.get_default_session (); + + switch (video_format) { + case VIDEO_FORMAT_WMV: + this.playlist_parser = new AsxPlaylistParser (session); + break; + case VIDEO_FORMAT_MP4: + this.playlist_parser = new MovPlaylistParser (session); + break; + default: + assert_not_reached (); + } } private bool namespace_ok (Xml.Node* node) { @@ -105,7 +130,7 @@ internal class Rygel.Mediathek.VideoItemFactory : Object { if (url_attribute != null && namespace_ok (content)) { unowned string url = url_attribute->children->content; - if (url.has_suffix (".asx")) { + if (url.has_suffix (this.playlist_parser.playlist_suffix)) { playlist_url = url; break; -- 2.7.4