"
.. "Get information about movies from the Internet "
.. "Movie Database (IMDb). This Extension will show "
.. "you the cast, a short plot summary and a link to "
.. "the web page on imdb.org." ;
capabilities = { "input-listener" } }
end
-- Remove trailing & leading spaces
function trim(str)
if not str then return "" end
return string.gsub(str, "^%s*(.*)+%s$", "%1")
end
-- Update title text field. Removes file extensions.
function update_title()
local item = vlc.input.item()
local name = item and item:name()
if name ~= nil then
name = string.gsub(name, "(.*)(%.%w+)$", "%1")
end
if name ~= nil then
txt:set_text(trim(name))
end
end
-- Function called when the input (media being read) changes
function input_changed()
update_title()
end
-- First function to be called when the extension is activated
function activate()
create_dialog()
end
-- This function is called when the extension is disabled
function deactivate()
end
-- Create the main dialog with a simple search bar
function create_dialog()
dlg = vlc.dialog("IMDb")
dlg:add_label("Movie Title:", 1, 1, 1, 1)
local item = vlc.input.item()
txt = dlg:add_text_input(item and item:name() or "", 2, 1, 1, 1)
dlg:add_button("Search", click_okay, 3, 1, 1, 1)
-- Show, if not already visible
dlg:show()
end
-- Dialog closed
function close()
-- Deactivate this extension
vlc.deactivate()
end
-- Called when the user presses the "Search" button
function click_okay()
vlc.msg.dbg("[IMDb] Searching for " .. txt:get_text())
-- Search IMDb: build URL
title = string.gsub(string.gsub(txt:get_text(), "[%p%s%c]", "+"), "%++", " ")
url = "http://www.imdb.com/find?s=all&q=" .. string.gsub(title, " ", "+")
-- Recreate dialog structure: delete useless widgets
if html then
dlg:del_widget(html)
html = nil
end
if list then
dlg:del_widget(list)
dlg:del_widget(button_open)
list = nil
button_open = nil
end
-- Ask the user to wait some time...
local waitmsg = 'Searching for ' .. title .. " on IMDb..."
if not waitlbl then
waitlbl = dlg:add_label(waitmsg, 1, 2, 3, 1)
else
waitlbl:set_text(waitmsg)
end
dlg:update()
-- Download the data
local s, msg = vlc.stream(url)
if not s then
vlc.msg.warn("[IMDb] " .. msg)
waitlbl:set_text('Sorry, an error occured while searching for ' .. title .. ". Please try again later.")
return
end
-- Fetch HTML data
local data = s:read(65000)
if not data then
vlc.msg.warn("[IMDb] Not data received!")
waitlbl:set_text('Sorry, an error occured while searching for ' .. title .. ". Please try again later.")
return
end
-- Probe result & parse it
if string.find(data, "
Overview
") then
-- We found a direct match
parse_moviepage(data)
else
-- We have a list of results to parse
parse_resultspage(data)
end
end
-- Called when clicked on the "Open" button
function click_open()
-- Get user selection
selection = list:get_selection()
if not selection then return end
local sel = nil
for idx, selectedItem in pairs(selection) do
sel = idx
break
end
if not sel then return end
local imdbID = titles[sel].id
-- Update information message
url = "http://www.imdb.org/title/" .. imdbID .. "/"
title = titles[sel].title
dlg:del_widget(list)
dlg:del_widget(button_open)
list = nil
button_open = nil
waitlbl:set_text("Loading IMDb page for " .. title .. ".")
dlg:update()
local s, msg = vlc.stream(url)
if not s then
waitlbl:set_text('Sorry, an error occured while looking for ' .. title .. ".")
vlc.msg.warn("[IMDb] " .. msg)
return
end
data = s:read(65000)
if data and string.find(data, "
Overview
") then
parse_moviepage(data)
else
waitlbl:set_text('Sorry, no results found for ' .. title .. ".")
end
end
-- Parse the results page and find titles, years & URL's
function parse_resultspage(data)
vlc.msg.dbg("[IMDb] Analysing results page")
-- Find titles
titles = {}
local count = 0
local idxEnd = 1
while idxEnd ~= nil do
-- Find title types
local titleType = nil
_, idxEnd, titleType = string.find(data, "([^<]*Titles[^<]*)", idxEnd)
local _, _, nextTitle = string.find(data, "([^<]*Titles[^<]*)", idxEnd)
if not titleType then
break
else
-- Find current scope
local table = nil
if not nextTitle then
_, _, table = string.find(data, "
.*"..nextTitle, idxEnd)
end
if not table then break end
local pos = 0
local thistitle = nil
-- Find all titles in this scope
while pos ~= nil do
local _, _, link = string.find(table, "]*>([^<]+)", pos)
if not thistitle then break end -- this would not be normal behavior...
local _, _, year = string.find(table, "\((%d+)\)", pos)
-- Add this title to the list
count = count + 1
local _, _, imdbID = string.find(link, "/([^/]+)/$")
thistitle = replace_html_chars(thistitle)
titles[count] = { id = imdbID ; title = thistitle ; year = year ; link = link }
end
end
end
-- Did we find anything at all?
if not count or count == 0 then
waitlbl:set_text('Sorry, no results found for ' .. title .. ".")
return
end
-- Sounds good, we found some results, let's display them
waitlbl:set_text(count .. " results found for " .. title .. ".")
list = dlg:add_list(1, 3, 3, 1)
button_open = dlg:add_button("Open", click_open, 3, 4, 1, 1)
for idx, title in ipairs(titles) do
--list:add_value("[" .. title.id .. "] " .. title.title .. " (" .. title.year .. ")", idx)
list:add_value(title.title .. " (" .. title.year .. ")", idx)
end
end
-- Parse a movie description page
function parse_moviepage(data)
-- Title & year
title = string.gsub(data, "^.*(.*).*$", "%1")
local text = "
" .. title .. "
"
text = text .. "
Overview
"
-- Real URL
url = string.gsub(data, "^.*]+>([%w%s]+)", nextIdx)
end
if not director then
director = "(Unknown)"
end
text = text .. "
Director
" .. director .. "
"
-- Main genres
local genres = "
Genres
"
local first = true
for genre, _ in string.gmatch(data, "/Sections/Genres/(%w+)/\">") do
if first then
genres = genres .. "
" .. genre .. "
"
else
genres = genres .. "
" .. genre .. "
"
end
first = false
end
text = text .. genres
-- List main actors
local actors = "
Cast
"
local first = true
for nm, char in string.gmatch(data, "
")
if list then
dlg:del_widget(list)
dlg:del_widget(button_open)
end
html = dlg:add_html(text .. " Loading summary...", 1, 3, 3, 1)
dlg:update()
text = text .. "
Plot Summary
"
local s, msg = vlc.stream(url .. "plotsummary")
if not s then
vlc.msg.warn("[IMDb] " .. msg)
return
end
local data = s:read(65000)
-- We read only the first summary
_, _, summary = string.find(data, "
([^<]+)")
if not summary then
summary = "(Unknown)"
end
text = text .. "
" .. summary .. "
"
text = text .. "
Source IMDb
" .. url .. ""
html:set_text(text)
end
-- Convert some HTML characters into UTF8
function replace_html_chars(txt)
if not txt then return nil end
-- return vlc.strings.resolve_xml_special_chars(txt)
for num in string.gmatch(txt, "(%x+);") do
-- Convert to decimal (any better way?)
dec = 0
for c in string.gmatch(num, "%x") do
cc = string.byte(c) - string.byte("0")
if (cc >= 10 or cc < 0) then
cc = string.byte(string.lower(c)) - string.byte("a") + 10
end
dec = dec * 16 + cc
end
txt = string.gsub(txt, "" .. num .. ";", string.char(dec))
end
return txt
end