[vlc-devel] commit: Extensions: an example Lua script: IMDb ( Jean-Philippe André )

git version control git at videolan.org
Sun Jan 24 16:39:59 CET 2010


vlc | branch: master | Jean-Philippe André <jpeg at videolan.org> | Sun Jan 24 16:26:15 2010 +0100| [92ea10da4e5694e98f4e5a92656d366c2e9e7f26] | committer: Jean-Philippe André 

Extensions: an example Lua script: IMDb

This Lua Extension will get some meta data on the current movie
(or any movie) from the Internet Movie Database and shows it in
a simple dialog box.

Please consider this script more as an example than as a final
version of the IMDb extension.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=92ea10da4e5694e98f4e5a92656d366c2e9e7f26
---

 share/lua/extensions/imdb.lua |  234 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 234 insertions(+), 0 deletions(-)

diff --git a/share/lua/extensions/imdb.lua b/share/lua/extensions/imdb.lua
new file mode 100644
index 0000000..7cfb623
--- /dev/null
+++ b/share/lua/extensions/imdb.lua
@@ -0,0 +1,234 @@
+--[[
+ Get information about a movie from IMDb
+
+ Copyright © 2009-2010 VideoLAN and AUTHORS
+
+ Authors:  Jean-Philippe André (jpeg at videolan.org)
+
+ 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.
+--]]
+
+dlg = nil
+txt = nil
+function descriptor()
+    return { title = "IMDb" ; capabilities = {} }
+end
+
+-- Update title text field. Removes file extensions.
+function update_title()
+    local title = vlc.input.get_title()
+    if (title ~= nil) then
+        title = string.gsub(title, "(.*)(%.%w+)$", "%1")
+    end
+    if (title ~= nil) then
+        txt:set_text(title)
+    end
+end
+
+function create_dialog()
+    dlg = vlc.dialog("IMDb Search")
+    dlg:add_label("The Internet Movie Database", 1, 1, 4, 1)
+    dlg:add_label("<b>Movie Title</b>", 1, 2, 1, 1)
+    txt = dlg:add_text_input(vlc.input.get_title(), 2, 2, 1, 1)
+    dlg:add_button("Okay", "click_okay", 3, 2, 1, 1)
+    dlg:add_button("*", "update_title", 4, 2, 1, 1)
+    dlg:show() -- Show, if not already visible
+end
+
+function activate()
+    create_dialog()
+end
+
+function deactivate()
+end
+
+-- Dialog closed
+function close()
+    -- Deactivate this extension
+    vlc.deactivate()
+end
+
+-- Some global variables: widgets
+list = nil
+button_open = nil
+titles = nil
+html = nil
+
+function click_okay()
+    vlc.msg.dbg("Searching for " .. txt:get_text() .. " on IMDb")
+
+    if html then
+        dlg:del_widget(html)
+        html = nil
+    end
+
+    if (not list) then
+        list = dlg:add_list(1, 3, 4, 1)
+        button_open = dlg:add_button("Open", "click_open", 1, 4, 4, 1)
+    end
+
+    -- Clear previous results
+    list:clear()
+
+    -- Search IMDb
+    local url = "http://www.imdb.com/find?s=all&q="
+    local title = string.gsub(txt:get_text(), " ", "+")
+    local s = vlc.stream(url .. title)
+
+    -- Fetch HTML data
+    local data = s:read(65000)
+
+    -- Find titles
+    titles = {}
+    local count = 0
+
+    idxEnd = 1
+    while idxEnd ~= nil do
+        -- Find title types
+        _, idxEnd, titleType = string.find(data, "<b>([^<]*Titles[^<]*)</b>", idxEnd)
+        _, _, nextTitle = string.find(data, "<b>([^<]*Titles[^<]*)</b>", idxEnd)
+        if (not titleType) then
+            break
+        else
+            -- Find current scope
+            if (not nextTitle) then
+                _, _, table = string.find(data, "<table>(.*)</table>", idxEnd)
+            else
+                nextTitle = string.gsub(nextTitle, "%(", "%%(")
+                nextTitle = string.gsub(nextTitle, "%)", "%%)")
+                _, _, table = string.find(data, "<table>(.*)</table>.*"..nextTitle, idxEnd)
+            end
+            -- Find all titles in this scope
+            if (not table) then break end
+            pos = 0
+            while (pos ~= nil) do
+                _, _, link = string.find(table, "<a href=\"([^\"]+)\"", pos)
+                if (not link) then break end -- this would not be normal behavior...
+                _, pos, title = string.find(table, "<a href=\"" .. link .. "\"[^>]*>([^<]+)</a>", pos)
+                if (not title) then break end -- this would not be normal behavior...
+                _, _, year = string.find(table, "\((%d+)\)", pos)
+                -- Add this title to the list
+                count = count + 1
+                _, _, imdbID = string.find(link, "/([^/]+)/$")
+                title = replace_html_chars(title)
+                titles[count] = { id = imdbID ; title = title ; year = year ; link = link }
+            end
+        end
+    end
+
+    for idx, title in ipairs(titles) do
+        list:add_value("[" .. title.id .. "] " .. title.title .. " (" .. title.year .. ")", idx)
+    end
+end
+
+function click_open()
+    selection = list:get_selection()
+    if (not selection) then return 1 end
+    if (not html) then
+        html = dlg:add_html("Loading IMDb page...", 1, 3, 4, 1)
+        -- userLink = dlg:add_label("", 1, 4, 5, 1)
+    end
+
+    dlg:del_widget(list)
+    dlg:del_widget(button_open)
+    list = nil
+    button_open = nil
+
+    local sel = nil
+    for idx, selectedItem in pairs(selection) do
+        sel = idx
+        break
+    end
+    imdbID = titles[sel].id
+    url = "http://www.imdb.org/title/" .. imdbID .. "/"
+
+    -- userLink:set_text("<a href=\"url\">" .. url .. "</a>")
+
+    local s = vlc.stream(url)
+    data = s:read(65000)
+
+    text = "<h1>" .. titles[sel].title .. " (" .. titles[sel].year .. ")</h1>"
+    text = text .. "<h2>Overview</h2><table>"
+
+    -- Director
+    local director = nil
+    _, nextIdx, _ = string.find(data, "<div id=\"director-info\"", 1, true)
+    if (nextIdx) then
+        _, _, director = string.find(data, "<a href[^>]+>([%w%s]+)</a>", nextIdx)
+    end
+    if (not director) then
+        director = "(Unknown)"
+    end
+    text = text .. "<tr><td><b>Director</b></td><td>" .. director .. "</td></tr>"
+
+    -- Main genres
+    local genres = "<tr><td><b>Genres</b></td>"
+    local first = true
+    for genre, _ in string.gmatch(data, "/Sections/Genres/(%w+)/\">") do
+        if (first) then
+            genres = genres .. "<td>" .. genre .. "</td></tr>"
+        else
+            genres = genres .. "<tr><td /><td>" .. genre .. "</td></tr>"
+        end
+        first = false
+    end
+    text = text .. genres
+
+    -- List main actors
+    local actors = "<tr><td><b>Cast</b></td>"
+    first = true
+    for nm, char in string.gmatch(data, "<td class=\"nm\"><a[^>]+>([%w%s]+)</a></td><td class=\"ddd\"> ... </td><td class=\"char\"><a[^>]+>([%w%s]+)</a>") do
+        if (not first) then
+            actors = actors .. "<tr><td />"
+        end
+        actors = actors .. "<td>" .. nm .. "</td><td><i>" .. char .. "</i></td></tr>"
+        first = false
+    end
+    text = text .. actors .. "</table>"
+
+    text = text .. "<h2>Plot Summary</h2>"
+    s = vlc.stream(url .. "plotsummary")
+    data = s:read(65000)
+
+    -- We read only the first summary
+    _, _, summary = string.find(data, "<p class=\"plotpar\">([^<]+)")
+    if (not summary) then
+        summary = "(Unknown)"
+    end
+    text = text .. "<p>" .. summary .. "</p>"
+    text = text .. "<p><h2>Source IMDb</h2><a href=\"url\">" .. url .. "</a></p>"
+
+    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(%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, "&#x" .. num .. ";", string.char(dec))
+    end
+    return txt
+end
+




More information about the vlc-devel mailing list