]> git.sesse.net Git - vlc/blob - share/lua/playlist/youtube.lua
youtube.lua: more clean-up
[vlc] / share / lua / playlist / youtube.lua
1 --[[
2  $Id$
3
4  Copyright © 2007-2011 the VideoLAN team
5
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 --]]
20
21 -- Helper function to get a parameter's value in a URL
22 function get_url_param( url, name )
23     local _, _, res = string.find( url, "[&?]"..name.."=([^&]*)" )
24     return res
25 end
26
27 function get_arturl()
28     -- FIXME: vlc.strings() is not a function, it should probably be
29     -- vlc.strings.decode_uri()
30     --if string.match( vlc.path, "iurl=" ) then
31     --    return vlc.strings( get_url_param( vlc.path, "iurl" ) )
32     --end
33     video_id = get_url_param( vlc.path, "v" )
34     if not video_id then
35         return nil
36     end
37     return "http://img.youtube.com/vi/"..video_id.."/default.jpg"
38 end
39
40 -- Probe function.
41 function probe()
42     if vlc.access ~= "http" and vlc.access ~= "https" then
43         return false
44     end
45     youtube_site = string.match( string.sub( vlc.path, 1, 8 ), "youtube" )
46     if not youtube_site then
47         -- FIXME we should be using a builtin list of known youtube websites
48         -- like "fr.youtube.com", "uk.youtube.com" etc..
49         youtube_site = string.find( vlc.path, ".youtube.com" )
50         if youtube_site == nil then
51             return false
52         end
53     end
54     return (  string.match( vlc.path, "watch%?v=" ) -- the html page
55             or string.match( vlc.path, "watch_fullscreen%?video_id=" ) -- the fullscreen page
56             or string.match( vlc.path, "p.swf" ) -- the (old?) player url
57             or string.match( vlc.path, "jp.swf" ) -- the (new?) player url (as of 24/08/2007)
58             or string.match( vlc.path, "player2.swf" ) ) -- another player url
59 end
60
61 -- Parse function.
62 function parse()
63     if string.match( vlc.path, "watch%?v=" )
64     then -- This is the HTML page's URL
65         -- fmt is the format of the video
66         -- (cf. http://en.wikipedia.org/wiki/YouTube#Quality_and_codecs)
67         fmt = get_url_param( vlc.path, "fmt" )
68         while true do
69             -- Try to find the video's title
70             line = vlc.readline()
71             if not line then break end
72             if string.match( line, "<meta name=\"title\"" ) then
73                 _,_,name = string.find( line, "content=\"(.-)\"" )
74                 name = vlc.strings.resolve_xml_special_chars( name )
75                 name = vlc.strings.resolve_xml_special_chars( name )
76             end
77             if string.match( line, "<meta name=\"description\"" ) then
78                -- Don't ask me why they double encode ...
79                 _,_,description = string.find( line, "content=\"(.-)\"" )
80                 description = vlc.strings.resolve_xml_special_chars( description )
81                 description = vlc.strings.resolve_xml_special_chars( description )
82             end
83             if string.match( line, "<meta property=\"og:image\"" ) then
84                 _,_,arturl = string.find( line, "content=\"(.-)\"" )
85             end
86             if string.match( line, " rel=\"author\"" ) then
87                 _,_,artist = string.find( line, "href=\"/user/([^\"]*)\"" )
88             end
89             -- JSON parameters, also formerly known as "swfConfig",
90             -- "SWF_ARGS", "swfArgs" ...
91             if string.match( line, "PLAYER_CONFIG" ) then
92                 url_map = string.match( line, "\"url_encoded_fmt_stream_map\": \"(.-)\"" )
93                 if url_map then
94                     -- FIXME: do this properly
95                     url_map = string.gsub( url_map, "\\u0026", "&" )
96                     for url,itag in string.gmatch( url_map, "url=([^&,]+).-&itag=(%d+)" ) do
97                         -- Apparently formats are listed in quality order,
98                         -- so we can afford to simply take the first one
99                         if not fmt or tonumber( itag ) == tonumber( fmt ) then
100                             url = vlc.strings.decode_uri( url )
101                             path = url
102                             break
103                         end
104                     end
105                 end
106             -- There is also another version of the parameters, encoded
107             -- differently, as an HTML attribute of an <object> or <embed>
108             -- tag; but we don't need it now
109             end
110         end
111
112         if not arturl then
113             arturl = get_arturl()
114         end
115
116         if not path then
117             vlc.msg.err( "Couldn't extract youtube video URL, please check for updates to this script" )
118             return { }
119         end
120         return { { path = path; name = name; description = description; artist = artist; arturl = arturl } }
121     else -- This is the flash player's URL
122         if string.match( vlc.path, "title=" ) then
123             name = vlc.strings.decode_uri(get_url_param( vlc.path, "title" ))
124         end
125         video_id = get_url_param( vlc.path, "video_id" )
126         arturl = get_arturl( vlc.path, video_id )
127         fmt = get_url_param( vlc.path, "fmt" )
128         if fmt then
129             format = "&fmt=" .. fmt
130         else
131             format = ""
132         end
133         if not string.match( vlc.path, "t=" ) then
134             -- This sucks, we're missing "t" which is now mandatory. Let's
135             -- try using another url
136             return { { path = "http://www.youtube.com/v/"..video_id; name = name; arturl = arturl } }
137         end
138         return { { path = "http://www.youtube.com/get_video.php?video_id="..video_id.."&t="..get_url_param( vlc.path, "t" )..format; name = name; arturl = arturl } }
139     end
140 end