2
* Totem Arte Plugin allows you to watch streams from arte.tv
3
* Copyright (C) 2009, 2010, 2011 Simon Wenner <simon@wenner.ch>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
* The Totem Arte Plugin project hereby grants permission for non-GPL compatible
20
* GStreamer plugins to be used and distributed together with GStreamer, Totem
21
* and Totem Arte Plugin. This permission is above and beyond the permissions
22
* granted by the GPL license by which Totem Arte Plugin is covered.
23
* If you modify this code, you may extend this exception to your version of the
24
* code, but you are not obligated to do so. If you do not wish to do so,
25
* delete this exception statement from your version.
32
public abstract class ArteParser : GLib.Object
34
public bool has_data { get; protected set; default = false; }
35
protected string xml_fr;
36
protected string xml_de;
37
protected GLib.SList<Video> videos;
39
private const MarkupParser parser = {
47
public ArteParser () {}
48
public virtual void reset () {}
49
public virtual bool has_duplicates () { return false; }
50
public virtual bool has_image_urls () { return true; }
51
public virtual uint get_error_threshold () { return 0; }
53
public virtual bool advance ()
58
public unowned GLib.SList<Video> parse (Language lang) throws MarkupError, IOError
60
videos = new GLib.SList<Video> ();
67
if (lang == Language.GERMAN) {
68
msg = new Soup.Message ("GET", xml_de);
70
msg = new Soup.Message ("GET", xml_fr);
73
Soup.SessionAsync session = create_session ();
75
session.send_message (msg);
77
if (msg.status_code != Soup.KnownStatusCode.OK) {
78
throw new IOError.HOST_NOT_FOUND ("plus7.arte.tv could not be accessed.");
81
var context = new MarkupParseContext (parser,
82
MarkupParseFlags.TREAT_CDATA_AS_TEXT, this, null);
83
context.parse ((string) msg.response_body.flatten ().data,
84
(ssize_t) msg.response_body.length);
90
protected virtual void open_tag (MarkupParseContext ctx,
92
string[] attribute_names,
93
string[] attribute_values) throws MarkupError {}
95
protected virtual void close_tag (MarkupParseContext ctx,
96
string elem) throws MarkupError {}
98
protected virtual void process_text (MarkupParseContext ctx,
100
size_t text_len) throws MarkupError {}
102
protected string sanitise_markup(string str)
104
return str.replace("&", "&");
108
public class ArteRSSParser : ArteParser
110
private Video current_video = null;
111
private string current_data = null;
112
/* official RSS feeds by topic, contains duplicats, no image urls and offline dates */
113
private const string[] feeds_fr = {
114
"http://videos.arte.tv/fr/do_delegate/videos/toutes_les_videos/actualites/index-3188636,view,rss.xml",
115
"http://videos.arte.tv/fr/do_delegate/videos/toutes_les_videos/documentaire/index-3188646,view,rss.xml",
116
"http://videos.arte.tv/fr/do_delegate/videos/decouverte/index-3188644,view,rss.xml",
117
"http://videos.arte.tv/fr/do_delegate/videos/toutes_les_videos/europe/index-3188648,view,rss.xml",
118
"http://videos.arte.tv/fr/do_delegate/videos/toutes_les_videos/geopolitique_histoire/index-3188654,view,rss.xml",
119
"http://videos.arte.tv/fr/do_delegate/videos/toutes_les_videos/societe/index-3188652,view,rss.xml",
120
"http://videos.arte.tv/fr/do_delegate/videos/toutes_les_videos/junior/index-3188656,view,rss.xml",
121
"http://videos.arte.tv/fr/do_delegate/videos/toutes_les_videos/cinema_fiction/index-3188642,view,rss.xml",
122
"http://videos.arte.tv/fr/do_delegate/videos/toutes_les_videos/arts_cultures_spectacles/index-3188640,view,rss.xml",
123
"http://videos.arte.tv/fr/do_delegate/videos/toutes_les_videos/culture_pop_alternative/index-3188638,view,rss.xml",
124
"http://videos.arte.tv/fr/do_delegate/videos/toutes_les_videos/environnement_science/index-3188650,view,rss.xml"
126
private const string[] feeds_de = {
127
"http://videos.arte.tv/de/do_delegate/videos/alle_videos/aktuelles/index-3188636,view,rss.xml",
128
"http://videos.arte.tv/de/do_delegate/videos/alle_videos/dokus/index-3188646,view,rss.xml",
129
"http://videos.arte.tv/de/do_delegate/videos/entdeckung/index-3188644,view,rss.xml",
130
"http://videos.arte.tv/de/do_delegate/videos/alle_videos/europa/index-3188648,view,rss.xml",
131
"http://videos.arte.tv/de/do_delegate/videos/alle_videos/geopolitik_geschichte/index-3188654,view,rss.xml",
132
"http://videos.arte.tv/de/do_delegate/videos/alle_videos/gesellschaft/index-3188652,view,rss.xml",
133
"http://videos.arte.tv/de/do_delegate/videos/alle_videos/junior/index-3188656,view,rss.xml",
134
"http://videos.arte.tv/de/do_delegate/videos/alle_videos/kino_serien/index-3188642,view,rss.xml",
135
"http://videos.arte.tv/de/do_delegate/videos/alle_videos/kunst_kultur/index-3188640,view,rss.xml",
136
"http://videos.arte.tv/de/do_delegate/videos/alle_videos/popkultur_musik/index-3188638,view,rss.xml",
137
"http://videos.arte.tv/de/do_delegate/videos/alle_videos/umwelt_wissenschaft/index-3188650,view,rss.xml"
139
private const uint feed_count = 11;
140
private uint feed_idx = 0;
142
public ArteRSSParser ()
144
xml_fr = feeds_fr[0];
145
xml_de = feeds_de[0];
150
public override void reset ()
156
public override bool has_duplicates () { return true; }
157
public override bool has_image_urls () { return false; }
158
public override uint get_error_threshold ()
160
return (uint)(feed_count * 0.5);
163
public override bool advance ()
166
has_data = feed_idx < feed_count;
173
private void set_feed (uint idx)
175
xml_de = feeds_de[idx];
176
xml_fr = feeds_fr[idx];
180
protected override void open_tag (MarkupParseContext ctx,
182
string[] attribute_names,
183
string[] attribute_values) throws MarkupError
187
current_video = new Video();
195
protected override void close_tag (MarkupParseContext ctx,
196
string elem) throws MarkupError
200
if (current_video != null) {
201
videos.append (current_video);
202
current_video = null;
211
protected override void process_text (MarkupParseContext ctx,
213
size_t text_len) throws MarkupError
215
if (current_video != null) {
216
switch (current_data) {
218
current_video.title = text;
221
current_video.page_url = text;
224
current_video.desc = sanitise_markup(text);
227
current_video.publication_date.from_iso8601 (text);
234
public class ArteXMLParser : ArteParser
236
private Video current_video = null;
237
private string current_data = null;
238
private uint page = 1;
239
/* number of video feed pages available */
240
private uint page_limit = 14;
241
/* Parses the XML feed of the Flash video wall */
242
private const string xml_tmpl =
243
"http://videos.arte.tv/%s/do_delegate/videos/index-3188698,view,asXml.xml?hash=%s////%u/10/";
245
public ArteXMLParser ()
250
public override void reset ()
256
public override uint get_error_threshold ()
258
return (uint)(page_limit * 0.5);
261
public override bool advance ()
264
has_data = page <= page_limit;
271
private void set_page (uint page)
274
xml_fr = xml_tmpl.printf ("fr", "fr", page);
275
xml_de = xml_tmpl.printf ("de", "de", page);
278
protected override void open_tag (MarkupParseContext ctx,
280
string[] attribute_names,
281
string[] attribute_values) throws MarkupError
285
current_video = new Video();
288
for (int i = 0; i < attribute_names.length ; i++) {
289
if (attribute_names[i] == "pageMax") {
290
page_limit = (uint) long.parse (attribute_values[i]);
300
protected override void close_tag (MarkupParseContext ctx,
301
string elem) throws MarkupError
305
if (current_video != null) {
306
videos.prepend (current_video);
307
current_video = null;
316
protected override void process_text (MarkupParseContext ctx,
318
size_t text_len) throws MarkupError
320
if (current_video != null) {
321
switch (current_data) {
323
current_video.title = text;
326
current_video.page_url = "http://videos.arte.tv" + text;
329
current_video.image_url = "http://videos.arte.tv" + text;
332
current_video.desc = sanitise_markup(text);
335
current_video.publication_date.from_iso8601 (text);
338
current_video.offline_date.from_iso8601 (text);