diff -Nru totem-plugin-arte-3.2.1/debian/changelog totem-plugin-arte-3.2.1/debian/changelog --- totem-plugin-arte-3.2.1/debian/changelog 2014-02-14 21:19:44.000000000 +0100 +++ totem-plugin-arte-3.2.1/debian/changelog 2014-11-22 11:44:54.000000000 +0100 @@ -1,3 +1,15 @@ +totem-plugin-arte (3.2.1-2ubuntu1+14.10) utopic-proposed; urgency=medium + + * Add patches to restore video playback and harden the plugin + - Fixes video URL extraction (LP: #1368596) + - Uses http streams by default (they are seekable and more reliable) + - Fix RTMP playback (needed for low quality and as fallback if something + happens to http streams) + - Repair and use the RSS parser as the main video-listing fallback in case + the JSON parser break in the future + + -- Nicolas Delvaux Sat, 22 Nov 2014 10:24:37 +0100 + totem-plugin-arte (3.2.1-2) unstable; urgency=low * Do not build depends on a specific valac, closes: #739001 diff -Nru totem-plugin-arte-3.2.1/debian/patches/fix-json-uri-extraction.patch totem-plugin-arte-3.2.1/debian/patches/fix-json-uri-extraction.patch --- totem-plugin-arte-3.2.1/debian/patches/fix-json-uri-extraction.patch 1970-01-01 01:00:00.000000000 +0100 +++ totem-plugin-arte-3.2.1/debian/patches/fix-json-uri-extraction.patch 2014-11-22 11:44:54.000000000 +0100 @@ -0,0 +1,20 @@ +Description: Fix the Json URI extraction + Adapt to a change made on the Arte website that prevents the extraction of + a JSON resource that is required for playing videos. +Author: Nicolas Delvaux +--- +Origin: upstream, https://gitorious.org/totem-plugin-arte/mainline/commit/31bd0d57e11e7633b13fa9721de20539d5ef2e12 +Bug-Ubuntu: https://launchpad.net/bugs/1368596 +Last-Update: 2014-11-19 + +--- totem-plugin-arte-3.2.1.orig/url-extractor.vala ++++ totem-plugin-arte-3.2.1/url-extractor.vala +@@ -87,7 +87,7 @@ public class RTMPStreamUrlExtractor : In + debug ("Initial Page URL:\t\t'%s'", page_url); + + /* JSON uri */ +- regexp = "arte_vp_url=\"(https?://.*.json)\">"; ++ regexp = "arte_vp_url=['\"](https?://.*.json)['\"].*>"; + var json_uri = extract_string_from_page (page_url, regexp); + debug ("Extract JSON URI:\t'%s'", json_uri); + if (json_uri == null) diff -Nru totem-plugin-arte-3.2.1/debian/patches/fix-rtmp-playback.patch totem-plugin-arte-3.2.1/debian/patches/fix-rtmp-playback.patch --- totem-plugin-arte-3.2.1/debian/patches/fix-rtmp-playback.patch 1970-01-01 01:00:00.000000000 +0100 +++ totem-plugin-arte-3.2.1/debian/patches/fix-rtmp-playback.patch 2014-11-22 11:44:54.000000000 +0100 @@ -0,0 +1,19 @@ +Description: Fix the RTMP URI construction + This fixes RTMP streaming and most notably low quality playback. +Author: Nicolas Delvaux +--- +Origin: vendor +Forwarded: https://gitorious.org/totem-plugin-arte/mainline/commit/0801169427ad0836fe0f2f82808af25927ba15ee +Last-Update: 2014-11-22 + +--- totem-plugin-arte-3.2.1.orig/url-extractor.vala ++++ totem-plugin-arte-3.2.1/url-extractor.vala +@@ -147,7 +147,7 @@ public class RTMPStreamUrlExtractor : In + debug ("Streamer base:\t'%s'", streamer); + debug ("Streamer path:\t'%s'", url); + +- uri = streamer + "mp4:" + url; ++ uri = streamer + url; + + } catch (Error e) { + throw new ExtractionError.EXTRACTION_FAILED ("Video URL Extraction Error"); diff -Nru totem-plugin-arte-3.2.1/debian/patches/repair-and-use-rss-parser-as-main-fallback.patch totem-plugin-arte-3.2.1/debian/patches/repair-and-use-rss-parser-as-main-fallback.patch --- totem-plugin-arte-3.2.1/debian/patches/repair-and-use-rss-parser-as-main-fallback.patch 1970-01-01 01:00:00.000000000 +0100 +++ totem-plugin-arte-3.2.1/debian/patches/repair-and-use-rss-parser-as-main-fallback.patch 2014-11-22 11:44:54.000000000 +0100 @@ -0,0 +1,231 @@ +Description: Make the RSS parser functional again and use it as a fallback + Now we at least have one woking fallback in case the JSON parser break. + Hopefully this will give us more time before needing to patch the package + once again. +Author: Nicolas Delvaux +--- +Origin: vendor +Forwarded: https://gitorious.org/totem-plugin-arte/mainline/commit/99e73deb7e9bd230064bceb1155fa737fd70f202 +Last-Update: 2014-11-22 + +--- totem-plugin-arte-3.2.1.orig/arteparser.vala ++++ totem-plugin-arte-3.2.1/arteparser.vala +@@ -197,38 +197,14 @@ public class ArteRSSParser : ArteParser + { + private Video current_video = null; + private string current_data = null; +- /* official RSS feeds by topic, contains duplicats, no image urls and offline dates */ ++ /* official RSS feeds */ + private const string[] feeds_fr = { +- "http://videos.arte.tv/fr/do_delegate/videos/index-3188626,view,rss.xml", +- "http://videos.arte.tv/fr/do_delegate/videos/chaines/arts_cultures_spectacles/index-3188640,view,rss.xml", +- "http://videos.arte.tv/fr/do_delegate/videos/chaines/culture_pop_alternative/index-3188638,view,rss.xml", +- "http://videos.arte.tv/fr/do_delegate/videos/chaines/documentaire/index-3188646,view,rss.xml", +- "http://videos.arte.tv/fr/do_delegate/videos/chaines/europe/index-3188648,view,rss.xml", +- "http://videos.arte.tv/fr/do_delegate/videos/chaines/junior/index-3188656,view,rss.xml", +- "http://videos.arte.tv/fr/do_delegate/videos/index--3188626,view,rss.xml", +- "http://videos.arte.tv/fr/do_delegate/videos/chaines/actualites/index-3188636,view,rss.xml", +- "http://videos.arte.tv/fr/do_delegate/videos/chaines/cinema_fiction/index-3188642,view,rss.xml", +- "http://videos.arte.tv/fr/do_delegate/videos/decouverte/index-3188644,view,rss.xml", +- "http://videos.arte.tv/fr/do_delegate/videos/chaines/environnement_science/index-3188650,view,rss.xml", +- "http://videos.arte.tv/fr/do_delegate/videos/chaines/geopolitique_histoire/index-3188654,view,rss.xml", +- "http://videos.arte.tv/fr/do_delegate/videos/chaines/societe/index-3188652,view,rss.xml" ++ "http://www.arte.tv/papi/tvguide-flow/feeds/videos/fr.xml?type=ARTE_PLUS_SEVEN" + }; + private const string[] feeds_de = { +- "http://videos.arte.tv/de/do_delegate/videos/index-3188626,view,rss.xml", +- "http://videos.arte.tv/de/do_delegate/videos/themen/aktuelles/index-3188636,view,rss.xml", +- "http://videos.arte.tv/de/do_delegate/videos/entdeckung/index-3188644,view,rss.xml", +- "http://videos.arte.tv/de/do_delegate/videos/themen/geopolitik_geschichte/index-3188654,view,rss.xml", +- "http://videos.arte.tv/de/do_delegate/videos/themen/junior/index-3188656,view,rss.xml", +- "http://videos.arte.tv/de/do_delegate/videos/themen/kunst_kultur/index-3188640,view,rss.xml", +- "http://videos.arte.tv/de/do_delegate/videos/themen/umwelt_wissenschaft/index-3188650,view,rss.xml", +- "http://videos.arte.tv/de/do_delegate/videos/index--3188626,view,rss.xml", +- "http://videos.arte.tv/de/do_delegate/videos/themen/dokus/index-3188646,view,rss.xml", +- "http://videos.arte.tv/de/do_delegate/videos/themen/europe/index-3188648,view,rss.xml", +- "http://videos.arte.tv/de/do_delegate/videos/themen/gesellschaft/index-3188652,view,rss.xml", +- "http://videos.arte.tv/de/do_delegate/videos/themen/kino_serien/index-3188642,view,rss.xml", +- "http://videos.arte.tv/de/do_delegate/videos/themen/popkultur_musik/index-3188638,view,rss.xml" ++ "http://www.arte.tv/papi/tvguide-flow/feeds/videos/de.xml?type=ARTE_PLUS_SEVEN" + }; +- private const uint feed_count = 11; ++ private const uint feed_count = feeds_fr.length; + private uint feed_idx = 0; + + public ArteRSSParser () +@@ -245,8 +221,8 @@ public class ArteRSSParser : ArteParser + feed_idx = 0; + } + +- public override bool has_duplicates () { return true; } +- public override bool has_image_urls () { return false; } ++ public override bool has_duplicates () { return false; } ++ public override bool has_image_urls () { return true; } + public override uint get_error_threshold () + { + return (uint)(feed_count * 0.5); +@@ -278,6 +254,16 @@ public class ArteRSSParser : ArteParser + case "item": + current_video = new Video(); + break; ++ case "media:thumbnail": ++ if (current_video != null) { ++ for (int i = 0; i < attribute_names.length; i++) { ++ if (attribute_names[i] == "url") { ++ current_video.image_url = attribute_values[i]; ++ break; ++ } ++ } ++ } ++ break; + default: + current_data = elem; + break; +@@ -304,105 +290,47 @@ public class ArteRSSParser : ArteParser + string text, + size_t text_len) throws MarkupError + { +- if (current_video != null) { ++ if (current_video != null && text_len > 0) { ++ var my_text = text; ++ if (text.has_suffix("]]>")) { ++ // FIXME Why is the end of the CDATA tag kept? ++ // We do use MarkupParseFlags.TREAT_CDATA_AS_TEXT... ++ my_text = text.slice(0, -3); ++ } + switch (current_data) { + case "title": +- current_video.title = text; ++ current_video.title = my_text; + break; + case "link": +- current_video.page_url = text; ++ current_video.page_url = my_text; + break; + case "description": +- current_video.desc = sanitise_markup(text); ++ current_video.desc = sanitise_markup(my_text); + break; +- case "pubDate": +- // date is present, but it does not conform to ISO 8601 +- // example fr: +- // Sun, 22 Apr 2012 11:46:27 +0200 +- // example de: +- // Sun, 22 Apr 2012 09:07:19 +0200 +- string iso_date = rss_date_to_iso8601 (text); +- +- if (!current_video.publication_date.from_iso8601 (iso_date)) { +- GLib.warning ("Publication date '%s' parsing failed.", text); ++ case "dcterms:valid": ++ MatchInfo match; ++ // example value: ++ // start=2014-11-13T06:44+00:00;end=2014-11-20T06:44+00:00;scheme=W3C-DTF ++ try { ++ var regex = new Regex ("start=([0-9T\\-:+]+);end=([0-9T\\-:+]+);"); ++ regex.match(my_text, 0, out match); ++ } catch (GLib.RegexError e) { ++ GLib.warning ("Date parsing failed."); ++ break; ++ } ++ // Results are already in the ISO8601 format, but GLib requires seconds... ++ var pub_date = match.fetch(1).replace("+00:00", ":00+00:00");; ++ var off_date = match.fetch(2).replace("+00:00", ":00+00:00"); ++ if (!current_video.publication_date.from_iso8601(pub_date)) { ++ GLib.warning ("Publication date '%s' parsing failed.", pub_date); ++ } ++ if (!current_video.offline_date.from_iso8601(off_date)) { ++ GLib.warning ("Offline date '%s' parsing failed.", off_date); + } + break; + } + } + } +- +- private static string rss_date_to_iso8601 (string date) +- { +- // in: Sun, 22 Apr 2012 11:46:27 +0200 +- // out: 2008-02-01T09:00:22+05:00 +- string[] s = date.split(" "); +- +- if (s.length != 6) { +- GLib.warning ("Conversion to ISO8601 failed."); +- return ""; +- } +- +- string month; +- switch (s[2]) +- { +- case "Jan": +- month = "01"; +- break; +- case "Feb": +- month = "02"; +- break; +- case "Mar": +- month = "03"; +- break; +- case "Apr": +- month = "04"; +- break; +- case "May": +- month = "05"; +- break; +- case "Jun": +- month = "06"; +- break; +- case "Jul": +- month = "07"; +- break; +- case "Aug": +- month = "08"; +- break; +- case "Sep": +- month = "09"; +- break; +- case "Oct": +- month = "10"; +- break; +- case "Nov": +- month = "11"; +- break; +- case "Dec": +- month = "12"; +- break; +- default: +- GLib.warning("Conversion to ISO8601 failed. Unknown month: '%s'.", s[2]); +- return ""; +- } +- +- string day = s[1]; +- if (day.length < 2) { +- day = "0" + day; +- } +- +- var builder = new StringBuilder (); +- builder.append (s[3]); +- builder.append ("-"); +- builder.append (month); +- builder.append ("-"); +- builder.append (day); +- builder.append ("T"); +- builder.append (s[4]); +- builder.append ("+0%c:00".printf(s[5][2])); +- +- return builder.str; +- } + } + + public class ArteXMLParser : ArteParser +--- totem-plugin-arte-3.2.1.orig/arteplus7.vala ++++ totem-plugin-arte-3.2.1/arteplus7.vala +@@ -157,8 +157,8 @@ class ArtePlugin : Peas.Activatable, Pea + cache = new Cache (Environment.get_user_cache_dir () + + CACHE_PATH_SUFFIX); + parsers[0] = new ArteJSONParser (); +- parsers[1] = new ArteXMLParser (); +- parsers[2] = new ArteRSSParser (); ++ parsers[1] = new ArteRSSParser (); ++ parsers[2] = new ArteXMLParser (); + tree_view = new VideoListView (cache); + + tree_view.video_selected.connect (callback_video_selected); diff -Nru totem-plugin-arte-3.2.1/debian/patches/series totem-plugin-arte-3.2.1/debian/patches/series --- totem-plugin-arte-3.2.1/debian/patches/series 1970-01-01 01:00:00.000000000 +0100 +++ totem-plugin-arte-3.2.1/debian/patches/series 2014-11-22 11:44:54.000000000 +0100 @@ -0,0 +1,4 @@ +fix-json-uri-extraction.patch +use-http-streams.patch +fix-rtmp-playback.patch +repair-and-use-rss-parser-as-main-fallback.patch diff -Nru totem-plugin-arte-3.2.1/debian/patches/use-http-streams.patch totem-plugin-arte-3.2.1/debian/patches/use-http-streams.patch --- totem-plugin-arte-3.2.1/debian/patches/use-http-streams.patch 1970-01-01 01:00:00.000000000 +0100 +++ totem-plugin-arte-3.2.1/debian/patches/use-http-streams.patch 2014-11-22 11:44:54.000000000 +0100 @@ -0,0 +1,76 @@ +Description: Retrieve HTTP video links if possible + Totem can actually seek much more reliably with them. + If they are not available, fallback to good-old RTMP links. +Author: Nicolas Delvaux +--- +Origin: upstream, https://gitorious.org/totem-plugin-arte/mainline/commit/ea439b17b73b85f1fa11649de8a86f0595ba0b9e +Last-Update: 2014-11-22 + +--- totem-plugin-arte-3.2.1.orig/url-extractor.vala ++++ totem-plugin-arte-3.2.1/url-extractor.vala +@@ -98,7 +98,7 @@ public class RTMPStreamUrlExtractor : In + var message = new Soup.Message ("GET", json_uri); + this.session.send_message (message); + +- string rtmp_uri = null; ++ string uri = null; + + // TODO detect if a video is only availabe after 23:00 + +@@ -111,24 +111,43 @@ public class RTMPStreamUrlExtractor : In + var streams_object = player_object.get_object_member ("VSR"); + Json.Object video_object; + ++ var is_rtmp = false; ++ + switch (q) { + case VideoQuality.LOW: ++ // As of 09/2014, LQ was only available with RTMP + video_object = streams_object.get_object_member ("RTMP_LQ_1"); ++ is_rtmp = true; + break; + case VideoQuality.HIGH: +- video_object = streams_object.get_object_member ("RTMP_SQ_1"); ++ video_object = streams_object.get_object_member ("HTTP_MP4_SQ_1"); ++ if (video_object == null) { ++ video_object = streams_object.get_object_member ("RTMP_SQ_1"); ++ is_rtmp = true; ++ } + break; + default: // MEDIUM is the default +- video_object = streams_object.get_object_member ("RTMP_MQ_1"); // or "RTMP_EQ_1" ? ++ video_object = streams_object.get_object_member ("HTTP_MP4_MQ_1"); // or "EQ_1"? ++ if (video_object == null) { ++ video_object = streams_object.get_object_member ("RTMP_MQ_1"); ++ is_rtmp = true; ++ } + break; + } + +- string streamer = video_object.get_string_member ("streamer"); ++ if (!is_rtmp) { ++ uri = video_object.get_string_member ("url"); ++ debug ("Extracted video uri:\t'%s'", uri); ++ return uri; ++ } ++ + string url = video_object.get_string_member ("url"); ++ string streamer = video_object.get_string_member ("streamer"); ++ + debug ("Streamer base:\t'%s'", streamer); + debug ("Streamer path:\t'%s'", url); + +- rtmp_uri = streamer + "mp4:" + url; ++ uri = streamer + "mp4:" + url; + + } catch (Error e) { + throw new ExtractionError.EXTRACTION_FAILED ("Video URL Extraction Error"); +@@ -153,7 +172,7 @@ public class RTMPStreamUrlExtractor : In + } + + +- string stream_uri = rtmp_uri + " swfVfy=1 swfUrl=" + player_uri; ++ string stream_uri = uri + " swfVfy=1 swfUrl=" + player_uri; + debug ("Build stream URI:\t\t'%s'", stream_uri); + + return stream_uri;