--[[ Youtube playlist importer for VLC media player 1.1 and 2.0 Copyright 2012 Guillaume Le Maout Authors: Guillaume Le Maout Contact: http://addons.videolan.org/messages/?action=newmessage&username=exebetche This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU 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. --]] -- Helper function to get a parameter's value in a URL function get_url_param( url, name ) local _, _, res = string.find( url, "[&?]"..name.."=([^&]*)" ) return res end -- Probe function. function probe() if vlc.access ~= "http" and vlc.access ~= "https" then return false end return string.match(vlc.path:match("([^/]+)"),"%w+.youtube.com") and (string.match(vlc.path, "list=") or string.match(vlc.path, "/watch%?") or string.match(vlc.path, "/watch%?") or string.match(vlc.path, "/player2.swf")) end -- Parse function. function parse() if string.match( vlc.path, "list=" ) then local p = {} local playlistID = get_url_param( vlc.path, "list" ) local videoID = get_url_param( vlc.path, "v" ) local playlistURL = "http://www.youtube.com/list_ajax?action_get_list=1&style=xml&list="..playlistID local s = vlc.stream(playlistURL) local playlistData = "" local line = "" while line do playlistData = playlistData..line line = s:readline() end local playlist_parsed = parse_xml(playlistData).root.video for i, video in ipairs(playlist_parsed) do local item = {} item.path = "http://www.youtube.com/watch?v="..video.encrypted_id.CDATA item.title = video.title.CDATA item.artist = video.author.CDATA item.arturl = video.thumbnail.CDATA --~ item.description = video.description --~ item.rating = video.rating table.insert (p, item) end return p elseif string.match( vlc.path, "/watch%?" ) then while true do line = vlc.readline() if not line then break end path = string.match( line, 'yt%.preload%.start%("([^"]+generate_204[^"]+)"%);' ) if path then break end end if not path then vlc.msg.err( "Couldn't extract youtube video URL, please check for updates to this script/report this bug here:\nhttp://addons.videolan.org/content/show.php?content=149909" ) return { } end path = path:gsub("generate_204", "videoplayback") path = path:gsub("\\/", "/") path = path:gsub("\\u0026", "&") local video_id = get_url_param( vlc.path, "v" ) local video_info_url = "http://gdata.youtube.com/feeds/api/videos/"..video_id local s = vlc.stream(video_info_url) local video_data = "" local line = "" while line do video_data = video_data..line line = s:readline() end local video_info_parsed = parse_xml(video_data) local arturl = video_info_parsed.entry['media:group']['media:thumbnail'][1].ATTR.url local title = video_info_parsed.entry['media:group']['media:title'].CDATA local description = video_info_parsed.entry['media:group']['media:description'].CDATA return { { path = path; title = title; description = description; arturl = arturl } } elseif string.match( vlc.path, "/v/" ) then -- This is the flash player's URL video_id = get_url_param( vlc.path, "video_id" ) if not video_id then _,_,video_id = string.find( vlc.path, "/v/([^?]*)" ) end if not video_id then vlc.msg.err( "Couldn't extract youtube video URL" ) return { } end fmt = get_url_param( vlc.path, "fmt" ) if fmt then format = "&fmt=" .. fmt else format = "" end return { { path = "http://www.youtube.com/watch?v="..video_id..format } } end end function parse_xml(data) local tree = {} local stack = {} local tmp = {} local tmpTag = "" local level = 0 table.insert(stack, tree) for op, tag, attr, empty, val in string.gmatch(data, "<(%p?)([^%s>/]+)([^>]-)(%/?)>[%s\r\n\t]*([^<]*)[%s\r\n\t]*") do if op=="?" then --~ DOCTYPE elseif op=="/" then if level>0 then level = level - 1 table.remove(stack) end else level = level + 1 if op=="!" then stack[level]['CDATA'] = vlc.strings.resolve_xml_special_chars(string.gsub(tag..attr, "%[CDATA%[(.+)%]%]", "%1")) attr = "" level = level - 1 elseif type(stack[level][tag]) == "nil" then stack[level][tag] = {} table.insert(stack, stack[level][tag]) else if type(stack[level][tag][1]) == "nil" then tmp = nil tmp = stack[level][tag] stack[level][tag] = nil stack[level][tag] = {} table.insert(stack[level][tag], tmp) end tmp = nil tmp = {} table.insert(stack[level][tag], tmp) table.insert(stack, tmp) end if val~="" then stack[level][tag]['CDATA'] = {} stack[level][tag]['CDATA'] = vlc.strings.resolve_xml_special_chars(val) end if attr ~= "" then stack[level][tag]['ATTR'] = {} string.gsub(attr, "(%w+)=[\"'](.-)[\"']", function (name, value) stack[level][tag]['ATTR'][name] = value end) end if empty ~= "" then level = level - 1 table.remove(stack) end end end return tree end