media/: Use socket.url
[libquvi-scripts.git] / share / media / arte.lua
blobf990e7ea697c176991178d30ff95b1bf7d088f81
1 -- libquvi-scripts
2 -- Copyright (C) 2012 Toni Gundogdu <legatvs@gmail.com>
3 -- Copyright (C) 2011 Raphaƫl Droz <raphael.droz+floss@gmail.com>
4 --
5 -- This file is part of libquvi-scripts <http://quvi.googlecode.com/>.
6 --
7 -- This library is free software; you can redistribute it and/or
8 -- modify it under the terms of the GNU Lesser General Public
9 -- License as published by the Free Software Foundation; either
10 -- version 2.1 of the License, or (at your option) any later version.
12 -- This library is distributed in the hope that it will be useful,
13 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
14 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 -- Lesser General Public License for more details.
17 -- You should have received a copy of the GNU Lesser General Public
18 -- License along with this library; if not, write to the Free Software
19 -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 -- 02110-1301 USA
22 -- NOTE: Most videos expire some (7?) days after their original broadcast
24 local Arte = {} -- Utility functions unique to to this script.
26 -- Identify the media script.
27 function ident(qargs)
28 return {
29 can_parse_url = Arte.can_parse_url(qargs),
30 domains = table.concat({'videos.arte.tv'}, ',')
32 end
34 -- Parse media properties.
35 function parse(qargs)
36 local L = require 'quvi/lxph'
37 local P = require 'lxp.lom'
39 -- Config data ('c') contains config data for each available language.
40 -- Each language consists of >0 media streams, e.g. 'hd', 'sd'.
42 local c,lang_code = Arte.get_config(qargs, L, P)
43 qargs.streams,S = Arte.iter_streams(c, L, P, lang_code)
45 -- Many of the optional properties depend on the language setting.
46 -- e.g. title, even the media ID. Have these parsed _after_ the
47 -- streams have been parsed.
49 Arte.opt_properties(qargs, lang_code);
51 return qargs
52 end
55 -- Utility functions
58 function Arte.can_parse_url(qargs)
59 local U = require 'socket.url'
60 local t = U.parse(qargs.input_url)
61 if t and t.scheme and t.scheme:lower():match('^http$')
62 and t.host and t.host:lower():match('^videos%.arte%.tv$')
63 and t.path and t.path:lower():match('^/%w+/videos/')
64 then
65 return true
66 else
67 return false
68 end
69 end
71 function Arte.get_config(qargs, L, P)
73 -- Collect all config data for all available (language) streams.
74 -- Return a list containing the config dictionaries, and the language
75 -- code which will be used to select the default and the best streams.
77 local p = quvi.fetch(qargs.input_url)
79 local u = p:match('videorefFileUrl = "(.-)"')
80 or error('no match: config URL')
82 local l = u:match('%.tv/(%w+)/') or error('no match: lang code')
84 local C = require 'quvi/const'
85 local o = { [C.qfo_type] = C.qft_config }
86 local c = quvi.fetch(u, o)
88 local x = lxp.lom.parse(c)
89 local v = L.find_first_tag(x, 'videos')
90 local r = {}
92 for i=1, #v do -- For each language in the config.
93 if v[i].tag == 'video' then
94 local d = quvi.fetch(v[i].attr['ref'], o)
95 local t = {
96 lang_code = v[i].attr['lang'],
97 lang_data = d
99 -- Make the stream the first in the list if the language codes
100 -- match, making it the new default stream.
101 table.insert(r, ((t.lang_code == l) and 1 or #t), t)
105 return r, l
108 function Arte.opt_properties(qargs, lang_code)
110 -- The first stream should now be the default stream. This should
111 -- apply to the 'best' stream also, they are both the first streams
112 -- in the stream list.
114 local r = qargs.streams[1]
115 qargs.thumb_url = r.nostd.thumb_url
116 qargs.title = r.nostd.title
117 qargs.id = r.nostd.id
120 function Arte.iter_streams(config, L, P, lang_code)
121 local S = require 'quvi/stream'
122 local U = require 'quvi/util'
123 local r = {}
125 for _,v in pairs(config) do -- For each language in the config.
126 local c = P.parse(v.lang_data)
128 local d = L.find_first_tag(c, 'dateExpiration')[1]
129 if Arte.has_expired(d, U) then
130 error('media no longer available (expired)')
133 local urls = L.find_first_tag(c, 'urls')
135 for i=1, #urls do
136 if urls[i].tag == 'url' then
137 local t = S.stream_new(urls[i][1])
139 -- Save the property values that may be used later, these depend
140 -- on the language setting. Many of these are the so called
141 -- "optional media properties". The 'nostd' dictionary is used
142 -- only by this script. libquvi ignores it completely.
144 t.nostd = {
145 thumb_url = L.find_first_tag(c, 'firstThumbnailUrl')[1],
146 title = L.find_first_tag(c, 'name')[1],
147 quality = urls[i].attr['quality'],
148 lang_code = c.attr['lang'],
149 id = c.attr['id'] or ''
151 t.id = Arte.to_id(t)
152 table.insert(r, t)
157 if #r >1 then
158 Arte.ch_best(S, r, lang_code)
161 return r,S
164 function Arte.has_expired(s, U)
165 return (U.to_timestamp(s) - os.time()) <0
168 function Arte.ch_best(S, t, lang_code)
169 local r = t[1] -- Make the first one the 'best' by default.
170 r.flags.best = true
171 for _,v in pairs(t) do -- Whatever matches 'hd' first.
172 if v.id:match('hd') and v.nostd.lang_code == lang_code then
173 r = S.swap_best(r, v)
178 -- Return an ID for a stream.
179 function Arte.to_id(t)
180 return string.format("%s_%s", t.nostd.quality, t.nostd.lang_code)
183 -- vim: set ts=2 sw=2 tw=72 expandtab: