|
Lines 1-22
Link Here
|
| 1 |
--[[ |
1 |
--[[ |
| 2 |
VLSub Extension for VLC media player 1.1 and 2.0 |
2 |
VLSub Extension for VLC media player 1.1 and 2.0 |
| 3 |
Copyright 2013 Guillaume Le Maout |
3 |
Copyright 2013 Guillaume Le Maout |
| 4 |
|
|
|
| 5 |
Authors: Guillaume Le Maout |
4 |
Authors: Guillaume Le Maout |
| 6 |
Contact: |
5 |
Contact: |
| 7 |
http://addons.videolan.org/messages/?action=newmessage&username=exebetche |
6 |
http://addons.videolan.org/messages/?action=newmessage&username=exebetche |
| 8 |
Bug report: http://addons.videolan.org/content/show.php/?content=148752 |
7 |
Bug report: http://addons.videolan.org/content/show.php/?content=148752 |
| 9 |
|
|
|
| 10 |
This program is free software; you can redistribute it and/or modify |
8 |
This program is free software; you can redistribute it and/or modify |
| 11 |
it under the terms of the GNU General Public License as published by |
9 |
it under the terms of the GNU General Public License as published by |
| 12 |
the Free Software Foundation; either version 2 of the License, or |
10 |
the Free Software Foundation; either version 2 of the License, or |
| 13 |
(at your option) any later version. |
11 |
(at your option) any later version. |
| 14 |
|
|
|
| 15 |
This program is distributed in the hope that it will be useful, |
12 |
This program is distributed in the hope that it will be useful, |
| 16 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 |
GNU General Public License for more details. |
15 |
GNU General Public License for more details. |
| 19 |
|
|
|
| 20 |
You should have received a copy of the GNU General Public License |
16 |
You should have received a copy of the GNU General Public License |
| 21 |
along with this program; if not, write to the Free Software |
17 |
along with this program; if not, write to the Free Software |
| 22 |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
18 |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
|
Lines 45-50
local options = {
Link Here
|
| 45 |
cze = 'Czech', |
41 |
cze = 'Czech', |
| 46 |
dan = 'Danish', |
42 |
dan = 'Danish', |
| 47 |
dut = 'Nederlands', |
43 |
dut = 'Nederlands', |
|
|
44 |
fin = 'Finnish', |
| 48 |
fre = 'Français', |
45 |
fre = 'Français', |
| 49 |
ell = 'Greek', |
46 |
ell = 'Greek', |
| 50 |
baq = 'Basque', |
47 |
baq = 'Basque', |
|
Lines 55-61
local options = {
Link Here
|
| 55 |
spa = 'Spanish', |
52 |
spa = 'Spanish', |
| 56 |
swe = 'Swedish', |
53 |
swe = 'Swedish', |
| 57 |
ukr = 'Ukrainian', |
54 |
ukr = 'Ukrainian', |
| 58 |
hun = 'Hungarian' |
55 |
hun = 'Hungarian', |
|
|
56 |
scc = 'Serbian' |
| 59 |
}, |
57 |
}, |
| 60 |
translation = { |
58 |
translation = { |
| 61 |
int_all = 'All', |
59 |
int_all = 'All', |
|
Lines 179-185
local options = {
Link Here
|
| 179 |
mess_err_conf_access ='Can\'t find a suitable path to save'.. |
177 |
mess_err_conf_access ='Can\'t find a suitable path to save'.. |
| 180 |
'config, please set it manually', |
178 |
'config, please set it manually', |
| 181 |
mess_err_wrong_path ='the path contains illegal character, '.. |
179 |
mess_err_wrong_path ='the path contains illegal character, '.. |
| 182 |
'please correct it' |
180 |
'please correct it', |
|
|
181 |
mess_err_cant_download_interface_translation='could not download interface translation' |
| 183 |
} |
182 |
} |
| 184 |
} |
183 |
} |
| 185 |
|
184 |
|
|
Lines 322-336
local dlg = nil
Link Here
|
| 322 |
local input_table = {} -- General widget id reference |
321 |
local input_table = {} -- General widget id reference |
| 323 |
local select_conf = {} -- Drop down widget / option table association |
322 |
local select_conf = {} -- Drop down widget / option table association |
| 324 |
|
323 |
|
|
|
324 |
local app_name = "VLsub"; |
| 325 |
local app_version = "0.10.2"; |
| 326 |
local app_useragent = app_name.." "..app_version; |
| 327 |
|
| 325 |
--[[ VLC extension stuff ]]-- |
328 |
--[[ VLC extension stuff ]]-- |
| 326 |
|
329 |
|
| 327 |
function descriptor() |
330 |
function descriptor() |
| 328 |
return { |
331 |
return { |
| 329 |
title = "VLsub 0.9.13", |
332 |
title = app_useragent, |
| 330 |
version = "0.9.13", |
333 |
version = app_version, |
| 331 |
author = "exebetche", |
334 |
author = "exebetche", |
| 332 |
url = 'http://www.opensubtitles.org/', |
335 |
url = 'http://www.opensubtitles.org/', |
| 333 |
shortdesc = "Download Subtitles"; |
336 |
shortdesc = "Download Subtitles"; |
| 334 |
description = options.translation.int_descr, |
337 |
description = options.translation.int_descr, |
| 335 |
capabilities = {"menu", "input-listener" } |
338 |
capabilities = {"menu", "input-listener" } |
| 336 |
} |
339 |
} |
|
Lines 414-420
function interface_main()
Link Here
|
| 414 |
dlg:add_button( |
417 |
dlg:add_button( |
| 415 |
lang["int_dowload_sel"], download_subtitles, 3, 7, 1, 1) |
418 |
lang["int_dowload_sel"], download_subtitles, 3, 7, 1, 1) |
| 416 |
dlg:add_button( |
419 |
dlg:add_button( |
| 417 |
lang["int_close"], deactivate, 4, 7, 1, 1) |
420 |
lang["int_close"], close, 4, 7, 1, 1) |
| 418 |
|
421 |
|
| 419 |
assoc_select_conf( |
422 |
assoc_select_conf( |
| 420 |
'language', |
423 |
'language', |
|
Lines 931-937
function apply_config()
Link Here
|
| 931 |
if lg_sel and lg_sel ~= 1 |
934 |
if lg_sel and lg_sel ~= 1 |
| 932 |
and openSub.conf.translations_avail[lg_sel] then |
935 |
and openSub.conf.translations_avail[lg_sel] then |
| 933 |
local lg = openSub.conf.translations_avail[lg_sel][1] |
936 |
local lg = openSub.conf.translations_avail[lg_sel][1] |
| 934 |
set_translation(lg) |
937 |
if not set_translation(lg) then |
|
|
938 |
vlc.msg.err("[VLSub] Couldn't not set translation") |
| 939 |
return false |
| 940 |
end |
| 935 |
SetDownloadBehaviours() |
941 |
SetDownloadBehaviours() |
| 936 |
end |
942 |
end |
| 937 |
|
943 |
|
|
Lines 1071-1077
function get_available_translations()
Link Here
|
| 1071 |
-- (drop previous direct download from github repo |
1077 |
-- (drop previous direct download from github repo |
| 1072 |
-- causing error with github https CA certficate on OS X an XP) |
1078 |
-- causing error with github https CA certficate on OS X an XP) |
| 1073 |
-- https://github.com/exebetche/vlsub/tree/master/locale |
1079 |
-- https://github.com/exebetche/vlsub/tree/master/locale |
| 1074 |
|
1080 |
|
| 1075 |
local translations_url = "http://addons.videolan.org/CONTENT/".. |
1081 |
local translations_url = "http://addons.videolan.org/CONTENT/".. |
| 1076 |
"content-files/148752-vlsub_translations.xml" |
1082 |
"content-files/148752-vlsub_translations.xml" |
| 1077 |
|
1083 |
|
|
Lines 1079-1085
function get_available_translations()
Link Here
|
| 1079 |
then |
1085 |
then |
| 1080 |
openSub.actionLabel = lang["int_searching_transl"] |
1086 |
openSub.actionLabel = lang["int_searching_transl"] |
| 1081 |
|
1087 |
|
| 1082 |
local translations_content, lol = get(translations_url) |
1088 |
local translations_content = get(translations_url) |
|
|
1089 |
if not translations_content then |
| 1090 |
collectgarbage() |
| 1091 |
return false |
| 1092 |
end |
| 1083 |
local translations_avail = openSub.option.translations_avail |
1093 |
local translations_avail = openSub.option.translations_avail |
| 1084 |
all_trsl = parse_xml(translations_content) |
1094 |
all_trsl = parse_xml(translations_content) |
| 1085 |
local lg, trsl |
1095 |
local lg, trsl |
|
Lines 1101-1106
function get_available_translations()
Link Here
|
| 1101 |
setMessage(success_tag(lang["mess_complete"])) |
1111 |
setMessage(success_tag(lang["mess_complete"])) |
| 1102 |
collectgarbage() |
1112 |
collectgarbage() |
| 1103 |
end |
1113 |
end |
|
|
1114 |
return true |
| 1104 |
end |
1115 |
end |
| 1105 |
|
1116 |
|
| 1106 |
function set_translation(lg) |
1117 |
function set_translation(lg) |
|
Lines 1123-1131
function set_translation(lg)
Link Here
|
| 1123 |
load_transl(transl_file_path) |
1134 |
load_transl(transl_file_path) |
| 1124 |
apply_translation() |
1135 |
apply_translation() |
| 1125 |
else |
1136 |
else |
| 1126 |
-- Load translation file from internet |
1137 |
-- Load translation file from internet |
| 1127 |
if not all_trsl then |
1138 |
if not all_trsl and not get_available_translations() then |
| 1128 |
get_available_translations() |
1139 |
setMessage(error_tag(lang["mess_err_cant_download_interface_translation"])) |
|
|
1140 |
return false |
| 1129 |
end |
1141 |
end |
| 1130 |
|
1142 |
|
| 1131 |
if not all_trsl or not all_trsl[lg] then |
1143 |
if not all_trsl or not all_trsl[lg] then |
|
Lines 1141-1146
function set_translation(lg)
Link Here
|
| 1141 |
lang = nil |
1153 |
lang = nil |
| 1142 |
lang = openSub.option.translation |
1154 |
lang = openSub.option.translation |
| 1143 |
collectgarbage() |
1155 |
collectgarbage() |
|
|
1156 |
return true |
| 1144 |
end |
1157 |
end |
| 1145 |
|
1158 |
|
| 1146 |
--[[ Core ]]-- |
1159 |
--[[ Core ]]-- |
|
Lines 1151-1158
openSub = {
Link Here
|
| 1151 |
conf = { |
1164 |
conf = { |
| 1152 |
url = "http://api.opensubtitles.org/xml-rpc", |
1165 |
url = "http://api.opensubtitles.org/xml-rpc", |
| 1153 |
path = nil, |
1166 |
path = nil, |
| 1154 |
userAgentHTTP = "VLSub", |
1167 |
HTTPVersion = "1.1", |
| 1155 |
useragent = "VLSub 0.9", |
1168 |
userAgentHTTP = app_useragent, |
|
|
1169 |
useragent = app_useragent, |
| 1156 |
translations_avail = {}, |
1170 |
translations_avail = {}, |
| 1157 |
downloadBehaviours = nil, |
1171 |
downloadBehaviours = nil, |
| 1158 |
languages = languages |
1172 |
languages = languages |
|
Lines 1189-1195
openSub = {
Link Here
|
| 1189 |
local request = "<?xml version='1.0'?>"..dump_xml(reqTable) |
1203 |
local request = "<?xml version='1.0'?>"..dump_xml(reqTable) |
| 1190 |
local host, path = parse_url(openSub.conf.url) |
1204 |
local host, path = parse_url(openSub.conf.url) |
| 1191 |
local header = { |
1205 |
local header = { |
| 1192 |
"POST "..path.." HTTP/1.1", |
1206 |
"POST "..path.." HTTP/"..openSub.conf.HTTPVersion, |
| 1193 |
"Host: "..host, |
1207 |
"Host: "..host, |
| 1194 |
"User-Agent: "..openSub.conf.userAgentHTTP, |
1208 |
"User-Agent: "..openSub.conf.userAgentHTTP, |
| 1195 |
"Content-Type: text/xml", |
1209 |
"Content-Type: text/xml", |
|
Lines 1204-1209
openSub = {
Link Here
|
| 1204 |
|
1218 |
|
| 1205 |
if status == 200 then |
1219 |
if status == 200 then |
| 1206 |
response = parse_xmlrpc(responseStr) |
1220 |
response = parse_xmlrpc(responseStr) |
|
|
1221 |
|
| 1207 |
if response then |
1222 |
if response then |
| 1208 |
if response.status == "200 OK" then |
1223 |
if response.status == "200 OK" then |
| 1209 |
return openSub.methods[methodName] |
1224 |
return openSub.methods[methodName] |
|
Lines 1222-1228
openSub = {
Link Here
|
| 1222 |
end |
1237 |
end |
| 1223 |
elseif status == 401 then |
1238 |
elseif status == 401 then |
| 1224 |
setError("Request unauthorized") |
1239 |
setError("Request unauthorized") |
| 1225 |
|
|
|
| 1226 |
response = parse_xmlrpc(responseStr) |
1240 |
response = parse_xmlrpc(responseStr) |
| 1227 |
if openSub.session.token ~= response.token then |
1241 |
if openSub.session.token ~= response.token then |
| 1228 |
setMessage("Session expired, retrying") |
1242 |
setMessage("Session expired, retrying") |
|
Lines 1354-1359
openSub = {
Link Here
|
| 1354 |
callback = function(resp) |
1368 |
callback = function(resp) |
| 1355 |
openSub.itemStore = resp.data |
1369 |
openSub.itemStore = resp.data |
| 1356 |
end |
1370 |
end |
|
|
1371 |
}, |
| 1372 |
SearchSubtitles2 = { |
| 1373 |
methodName = "SearchSubtitles", |
| 1374 |
params = function() |
| 1375 |
openSub.actionLabel = lang["action_search"] |
| 1376 |
setMessage(openSub.actionLabel..": ".. |
| 1377 |
progressBarContent(0)) |
| 1378 |
|
| 1379 |
local member = { |
| 1380 |
{ name="sublanguageid", value={ |
| 1381 |
string=openSub.movie.sublanguageid } }, |
| 1382 |
{ name="tag", value={ |
| 1383 |
string=openSub.file.completeName } } } |
| 1384 |
|
| 1385 |
return { |
| 1386 |
{ value={ string=openSub.session.token } }, |
| 1387 |
{ value={ |
| 1388 |
array={ |
| 1389 |
data={ |
| 1390 |
value={ |
| 1391 |
struct={ |
| 1392 |
member=member |
| 1393 |
}}}}}} |
| 1394 |
} |
| 1395 |
end, |
| 1396 |
callback = function(resp) |
| 1397 |
openSub.itemStore = resp.data |
| 1398 |
end |
| 1357 |
} |
1399 |
} |
| 1358 |
}, |
1400 |
}, |
| 1359 |
getInputItem = function() |
1401 |
getInputItem = function() |
|
Lines 1402-1408
openSub = {
Link Here
|
| 1402 |
file.path = vlc.strings.decode_uri(file.path) |
1444 |
file.path = vlc.strings.decode_uri(file.path) |
| 1403 |
file.dir, file.completeName = string.match( |
1445 |
file.dir, file.completeName = string.match( |
| 1404 |
file.path, |
1446 |
file.path, |
| 1405 |
'^(.*/)([^/]*)$') |
1447 |
'^(.+/)([^/]*)$') |
|
|
1448 |
if file.dir == nil then |
| 1449 |
-- happens on http://example.org/?x=y |
| 1450 |
file.dir = openSub.conf.dirPath..slash |
| 1451 |
end |
| 1406 |
|
1452 |
|
| 1407 |
local file_stat = vlc.net.stat(file.path) |
1453 |
local file_stat = vlc.net.stat(file.path) |
| 1408 |
if file_stat |
1454 |
if file_stat |
|
Lines 1413-1418
openSub = {
Link Here
|
| 1413 |
file.is_archive = false |
1459 |
file.is_archive = false |
| 1414 |
end |
1460 |
end |
| 1415 |
|
1461 |
|
|
|
1462 |
if file.completeName == nil then |
| 1463 |
file.completeName = '' |
| 1464 |
end |
| 1416 |
file.name, file.ext = string.match( |
1465 |
file.name, file.ext = string.match( |
| 1417 |
file.completeName, |
1466 |
file.completeName, |
| 1418 |
'^([^/]-)%.?([^%.]*)$') |
1467 |
'^([^/]-)%.?([^%.]*)$') |
|
Lines 1440-1453
openSub = {
Link Here
|
| 1440 |
return false |
1489 |
return false |
| 1441 |
end |
1490 |
end |
| 1442 |
|
1491 |
|
|
|
1492 |
local infoString = openSub.file.cleanName |
| 1493 |
if infoString == nil then |
| 1494 |
infoString = '' |
| 1495 |
end |
| 1496 |
|
| 1497 |
if infoString == '' then |
| 1498 |
-- read from meta-title |
| 1499 |
local meta = vlc.var.get(vlc.object.input(), 'meta-title') |
| 1500 |
if meta ~= nil then |
| 1501 |
infoString = meta |
| 1502 |
end |
| 1503 |
end |
| 1504 |
|
| 1505 |
if infoString == '' then |
| 1506 |
-- read from metadata |
| 1507 |
local metas = vlc.input.item():metas() |
| 1508 |
if metas['title'] ~= nil then |
| 1509 |
infoString = metas['title'] |
| 1510 |
end |
| 1511 |
end |
| 1512 |
|
| 1443 |
local showName, seasonNumber, episodeNumber = string.match( |
1513 |
local showName, seasonNumber, episodeNumber = string.match( |
| 1444 |
openSub.file.cleanName, |
1514 |
infoString, |
| 1445 |
"(.+)[sS](%d%d)[eE](%d%d).*") |
1515 |
"(.+)[sS](%d?%d)[eE](%d%d).*") |
| 1446 |
|
1516 |
|
| 1447 |
if not showName then |
1517 |
if not showName then |
| 1448 |
showName, seasonNumber, episodeNumber = string.match( |
1518 |
showName, seasonNumber, episodeNumber = string.match( |
| 1449 |
openSub.file.cleanName, |
1519 |
infoString, |
| 1450 |
"(.+)(%d)[xX](%d%d).*") |
1520 |
"(.-)(%d?%d)[xX](%d%d).*") |
| 1451 |
end |
1521 |
end |
| 1452 |
|
1522 |
|
| 1453 |
if showName then |
1523 |
if showName then |
|
Lines 1455-1461
openSub = {
Link Here
|
| 1455 |
openSub.movie.seasonNumber = seasonNumber |
1525 |
openSub.movie.seasonNumber = seasonNumber |
| 1456 |
openSub.movie.episodeNumber = episodeNumber |
1526 |
openSub.movie.episodeNumber = episodeNumber |
| 1457 |
else |
1527 |
else |
| 1458 |
openSub.movie.title = openSub.file.cleanName |
1528 |
openSub.movie.title = infoString |
| 1459 |
openSub.movie.seasonNumber = "" |
1529 |
openSub.movie.seasonNumber = "" |
| 1460 |
openSub.movie.episodeNumber = "" |
1530 |
openSub.movie.episodeNumber = "" |
| 1461 |
end |
1531 |
end |
|
Lines 1636-1644
function display_subtitles()
Link Here
|
| 1636 |
elseif openSub.itemStore then |
1706 |
elseif openSub.itemStore then |
| 1637 |
for i, item in ipairs(openSub.itemStore) do |
1707 |
for i, item in ipairs(openSub.itemStore) do |
| 1638 |
mainlist:add_value( |
1708 |
mainlist:add_value( |
| 1639 |
item.SubFileName.. |
1709 |
(item.SubFileName or "???").. |
| 1640 |
" ["..item.SubLanguageID.."]".. |
1710 |
" ["..(item.SubLanguageID or "?").."]".. |
| 1641 |
" ("..item.SubSumCD.." CD)", i) |
1711 |
" ("..(item.SubSumCD or "?").." CD)", i) |
| 1642 |
end |
1712 |
end |
| 1643 |
setMessage("<b>"..lang["mess_complete"]..":</b> ".. |
1713 |
setMessage("<b>"..lang["mess_complete"]..":</b> ".. |
| 1644 |
#(openSub.itemStore).." "..lang["mess_res"]) |
1714 |
#(openSub.itemStore).." "..lang["mess_res"]) |
|
Lines 1663-1670
function download_subtitles()
Link Here
|
| 1663 |
|
1733 |
|
| 1664 |
openSub.actionLabel = lang["mess_downloading"] |
1734 |
openSub.actionLabel = lang["mess_downloading"] |
| 1665 |
|
1735 |
|
| 1666 |
display_subtitles() -- reset selection |
|
|
| 1667 |
|
| 1668 |
local item = openSub.itemStore[index] |
1736 |
local item = openSub.itemStore[index] |
| 1669 |
|
1737 |
|
| 1670 |
if openSub.option.downloadBehaviour == 'manual' |
1738 |
if openSub.option.downloadBehaviour == 'manual' |
|
Lines 1681-1687
function download_subtitles()
Link Here
|
| 1681 |
end |
1749 |
end |
| 1682 |
|
1750 |
|
| 1683 |
local message = "" |
1751 |
local message = "" |
| 1684 |
local subfileName = openSub.file.name or "" |
1752 |
local subfileName = "subtitle" |
|
|
1753 |
if openSub.file.name == nil or openSub.file.name == '' then |
| 1754 |
-- happens on http://example.org/?x=y |
| 1755 |
local uriName = nil |
| 1756 |
if item.SubFileName then |
| 1757 |
uriName = string.sub( |
| 1758 |
item.SubFileName, 1, #item.SubFileName - 4) |
| 1759 |
else |
| 1760 |
uriName = openSub.getInputItem():uri() |
| 1761 |
end |
| 1762 |
uriName = vlc.strings.encode_uri_component(uriName) |
| 1763 |
if uriName then |
| 1764 |
subfileName = string.sub(uriName, -64, -1) |
| 1765 |
end |
| 1766 |
else |
| 1767 |
subfileName = openSub.file.name |
| 1768 |
end |
| 1685 |
|
1769 |
|
| 1686 |
if openSub.option.langExt then |
1770 |
if openSub.option.langExt then |
| 1687 |
subfileName = subfileName.."."..item.SubLanguageID |
1771 |
subfileName = subfileName.."."..item.SubLanguageID |
|
Lines 1776-1784
function dump_zip(url, dir, subfileName)
Link Here
|
| 1776 |
return false |
1860 |
return false |
| 1777 |
end |
1861 |
end |
| 1778 |
|
1862 |
|
| 1779 |
local tmpFileName = dir..subfileName..".gz" |
1863 |
local tmpFileName = dir..slash..subfileName..".gz" |
| 1780 |
if not file_touch(tmpFileName) then |
1864 |
if not file_touch(tmpFileName) then |
| 1781 |
return false |
1865 |
vlc.msg.dbg("[VLsub] Cant touch:"..tmpFileName) |
|
|
1866 |
if openSub.conf.os == "win" then |
| 1867 |
-- todo for windows |
| 1868 |
return false |
| 1869 |
else |
| 1870 |
-- using tmp dir to download |
| 1871 |
tmpFileName = "/tmp/"..subfileName..".gz" |
| 1872 |
vlc.msg.dbg("[VLsub] Fixing to:"..tmpFileName) |
| 1873 |
end |
| 1782 |
end |
1874 |
end |
| 1783 |
local tmpFile = assert(io.open(tmpFileName, "wb")) |
1875 |
local tmpFile = assert(io.open(tmpFileName, "wb")) |
| 1784 |
|
1876 |
|
|
Lines 1795-1800
function add_sub(subPath)
Link Here
|
| 1795 |
if vlc.item or vlc.input.item() then |
1887 |
if vlc.item or vlc.input.item() then |
| 1796 |
subPath = decode_uri(subPath) |
1888 |
subPath = decode_uri(subPath) |
| 1797 |
vlc.msg.dbg("[VLsub] Adding subtitle :" .. subPath) |
1889 |
vlc.msg.dbg("[VLsub] Adding subtitle :" .. subPath) |
|
|
1890 |
vlc.var.set(vlc.object.input(), 'sub-file', subPath) |
| 1798 |
return vlc.input.add_subtitle(subPath) |
1891 |
return vlc.input.add_subtitle(subPath) |
| 1799 |
end |
1892 |
end |
| 1800 |
return false |
1893 |
return false |
|
Lines 1840-1916
end
Link Here
|
| 1840 |
function get(url) |
1933 |
function get(url) |
| 1841 |
local host, path = parse_url(url) |
1934 |
local host, path = parse_url(url) |
| 1842 |
local header = { |
1935 |
local header = { |
| 1843 |
"GET "..path.." HTTP/1.1", |
1936 |
"GET "..path.." HTTP/"..openSub.conf.HTTPVersion, |
| 1844 |
"Host: "..host, |
1937 |
"Host: "..host, |
| 1845 |
"User-Agent: "..openSub.conf.userAgentHTTP, |
1938 |
"User-Agent: "..openSub.conf.userAgentHTTP, |
| 1846 |
"", |
1939 |
"", |
| 1847 |
"" |
1940 |
"" |
| 1848 |
} |
1941 |
} |
| 1849 |
local request = table.concat(header, "\r\n") |
1942 |
local request = table.concat(header, "\r\n") |
| 1850 |
|
1943 |
|
| 1851 |
local response |
|
|
| 1852 |
local status, response = http_req(host, 80, request) |
1944 |
local status, response = http_req(host, 80, request) |
| 1853 |
|
1945 |
|
| 1854 |
if status == 200 then |
1946 |
if status == 200 then |
| 1855 |
return response |
1947 |
return response |
| 1856 |
else |
1948 |
else |
| 1857 |
return false, status, response |
1949 |
vlc.msg.err("[VLSub] HTTP "..tostring(status).." : "..response) |
|
|
1950 |
return false |
| 1858 |
end |
1951 |
end |
| 1859 |
end |
1952 |
end |
| 1860 |
|
1953 |
|
| 1861 |
function http_req(host, port, request) |
1954 |
function http_req(host, port, request) |
| 1862 |
local fd = vlc.net.connect_tcp(host, port) |
1955 |
local fd = vlc.net.connect_tcp(host, port) |
| 1863 |
if not fd then return false end |
1956 |
if not fd then |
| 1864 |
local pollfds = {} |
1957 |
setError("Unable to connect to server") |
| 1865 |
|
1958 |
return nil, "" |
| 1866 |
pollfds[fd] = vlc.net.POLLIN |
1959 |
end |
| 1867 |
vlc.net.send(fd, request) |
1960 |
local pollfds = {} |
| 1868 |
vlc.net.poll(pollfds) |
1961 |
|
| 1869 |
|
1962 |
pollfds[fd] = vlc.net.POLLIN |
| 1870 |
local chunk = vlc.net.recv(fd, 2048) |
1963 |
vlc.net.send(fd, request) |
| 1871 |
local response = "" |
1964 |
vlc.net.poll(pollfds) |
| 1872 |
local headerStr, header, body |
1965 |
|
| 1873 |
local contentLength, status |
1966 |
local response = vlc.net.recv(fd, 2048) |
| 1874 |
local pct = 0 |
1967 |
local buf = "" |
| 1875 |
|
1968 |
local headerStr, header, body |
| 1876 |
while chunk do |
1969 |
local contentLength, status, TransferEncoding, chunked |
| 1877 |
response = response..chunk |
1970 |
local pct = 0 |
| 1878 |
if not header then |
1971 |
|
| 1879 |
headerStr, body = response:match("(.-\r?\n)\r?\n(.*)") |
1972 |
while response and #response>0 do |
| 1880 |
if headerStr then |
1973 |
buf = buf..response |
| 1881 |
response = body |
1974 |
|
| 1882 |
header = parse_header(headerStr) |
1975 |
if not header then |
| 1883 |
contentLength = tonumber(header["Content-Length"]) |
1976 |
headerStr, body = buf:match("(.-\r?\n)\r?\n(.*)") |
| 1884 |
status = tonumber(header["statuscode"]) |
1977 |
|
| 1885 |
end |
1978 |
if headerStr then |
| 1886 |
end |
1979 |
header = parse_header(headerStr); |
| 1887 |
|
1980 |
status = tonumber(header["statuscode"]); |
| 1888 |
if contentLength then |
1981 |
contentLength = tonumber(header["Content-Length"]); |
| 1889 |
bodyLenght = #response |
1982 |
if not contentLength then |
| 1890 |
pct = bodyLenght / contentLength * 100 |
1983 |
contentLength = tonumber(header["X-Uncompressed-Content-Length"]) |
| 1891 |
setMessage(openSub.actionLabel..": "..progressBarContent(pct)) |
1984 |
end |
| 1892 |
if bodyLenght >= contentLength then |
1985 |
|
| 1893 |
break |
1986 |
TransferEncoding = trim(header["Transfer-Encoding"]); |
|
|
1987 |
chunked = (TransferEncoding=="chunked"); |
| 1988 |
|
| 1989 |
buf = body; |
| 1990 |
body = ""; |
| 1991 |
end |
| 1992 |
end |
| 1993 |
|
| 1994 |
if chunked then |
| 1995 |
chunk_size_hex, chunk_content = buf:match("(%x+)\r?\n(.*)") |
| 1996 |
chunk_size = tonumber(chunk_size_hex,16) |
| 1997 |
chunk_content_len = chunk_content:len() |
| 1998 |
chunk_remaining = chunk_size-chunk_content_len |
| 1999 |
|
| 2000 |
while chunk_content_len > chunk_size do |
| 2001 |
body = body..chunk_content:sub(0, chunk_size) |
| 2002 |
buf = chunk_content:sub(chunk_size+2) |
| 2003 |
|
| 2004 |
chunk_size_hex, chunk_content = buf:match("(%x+)\r?\n(.*)") |
| 2005 |
|
| 2006 |
if not chunk_size_hex |
| 2007 |
or chunk_size_hex == "0" then |
| 2008 |
chunk_size = 0 |
| 2009 |
break |
| 2010 |
end |
| 2011 |
|
| 2012 |
chunk_size = tonumber(chunk_size_hex,16) |
| 2013 |
chunk_content_len = chunk_content:len() |
| 2014 |
chunk_remaining = chunk_size-chunk_content_len |
| 2015 |
end |
| 2016 |
|
| 2017 |
if chunk_size == 0 then |
| 2018 |
break |
| 2019 |
end |
| 2020 |
end |
| 2021 |
|
| 2022 |
if contentLength then |
| 2023 |
if #body == 0 then |
| 2024 |
bodyLength = #buf |
| 2025 |
else |
| 2026 |
bodyLength = #body |
| 1894 |
end |
2027 |
end |
| 1895 |
end |
2028 |
|
| 1896 |
|
2029 |
pct = bodyLength / contentLength * 100 |
| 1897 |
vlc.net.poll(pollfds) |
2030 |
setMessage(openSub.actionLabel..": "..progressBarContent(pct)) |
| 1898 |
chunk = vlc.net.recv(fd, 1024) |
2031 |
if bodyLength >= contentLength then |
| 1899 |
end |
2032 |
break |
|
|
2033 |
end |
| 2034 |
end |
| 2035 |
|
| 2036 |
vlc.net.poll(pollfds) |
| 2037 |
response = vlc.net.recv(fd, 1024) |
| 2038 |
end |
| 2039 |
|
| 2040 |
if not chunked then |
| 2041 |
body = buf |
| 2042 |
end |
| 2043 |
|
| 2044 |
if status == 301 |
| 2045 |
and header["Location"] then |
| 2046 |
local host, path = parse_url(trim(header["Location"])) |
| 2047 |
request = request |
| 2048 |
:gsub("^([^%s]+ )([^%s]+)", "%1"..path) |
| 2049 |
:gsub("(Host: )([^\n]*)", "%1"..host) |
| 1900 |
|
2050 |
|
| 1901 |
vlc.net.close(fd) |
2051 |
return http_req(host, port, request) |
| 1902 |
|
2052 |
end |
| 1903 |
if status == 301 |
|
|
| 1904 |
and header["Location"] then |
| 1905 |
local host, path = parse_url(trim(header["Location"])) |
| 1906 |
request = request |
| 1907 |
:gsub("^([^%s]+ )([^%s]+)", "%1"..path) |
| 1908 |
:gsub("(Host: )([^\n]*)", "%1"..host) |
| 1909 |
|
| 1910 |
return http_req(host, port, request) |
| 1911 |
end |
| 1912 |
|
2053 |
|
| 1913 |
return status, response |
2054 |
return status, body |
| 1914 |
end |
2055 |
end |
| 1915 |
|
2056 |
|
| 1916 |
function parse_header(data) |
2057 |
function parse_header(data) |
|
Lines 1995-2054
function parse_xml(data)
Link Here
|
| 1995 |
return tree |
2136 |
return tree |
| 1996 |
end |
2137 |
end |
| 1997 |
|
2138 |
|
| 1998 |
function parse_xmlrpc(data) |
2139 |
function parse_xmlrpc(xmlText) |
| 1999 |
local tree = {} |
2140 |
local stack = {} |
| 2000 |
local stack = {} |
2141 |
local tree = {} |
| 2001 |
local tmp = {} |
2142 |
local tmp, name = nil, nil |
| 2002 |
local tmpTag = "" |
2143 |
table.insert(stack, tree) |
| 2003 |
local level = 0 |
2144 |
local FromXmlString = vlc.strings.resolve_xml_special_chars |
| 2004 |
local op, tag, p, empty, val |
2145 |
|
| 2005 |
local resolve_xml = vlc.strings.resolve_xml_special_chars |
2146 |
local data_handle = { |
| 2006 |
table.insert(stack, tree) |
2147 |
int = function(v) return tonumber(v) end, |
| 2007 |
|
2148 |
i4 = function(v) return tonumber(v) end, |
| 2008 |
for op, tag, p, empty, val in string.gmatch( |
2149 |
double = function(v) return tonumber(v) end, |
| 2009 |
data, |
2150 |
boolean = function(v) return tostring(v) end, |
| 2010 |
"<(%/?)([%w:]+)(.-)(%/?)>[%s\r\n\t]*([^<]*)" |
2151 |
base64 = function(v) return tostring(v) end, -- FIXME |
| 2011 |
) do |
2152 |
["string"] = function(v) return FromXmlString(v) end |
| 2012 |
if op=="/" then |
2153 |
} |
| 2013 |
if tag == "member" or tag == "array" then |
2154 |
|
| 2014 |
if level>0 then |
2155 |
for c, label, empty, value |
| 2015 |
level = level - 1 |
2156 |
in xmlText:gmatch("<(%/?)([%w_:]+)(%/?)>([^<]*)") do |
| 2016 |
table.remove(stack) |
2157 |
|
| 2017 |
end |
2158 |
if c == "" |
| 2018 |
end |
2159 |
then -- start tag |
| 2019 |
elseif tag == "name" then |
2160 |
if label == "struct" |
| 2020 |
level = level + 1 |
2161 |
or label == "array" then |
| 2021 |
if val~= "" then tmpTag = resolve_xml(val) end |
2162 |
tmp = nil |
| 2022 |
|
2163 |
tmp = {} |
| 2023 |
if type(stack[level][tmpTag]) == "nil" then |
2164 |
if name then |
| 2024 |
stack[level][tmpTag] = {} |
2165 |
stack[#stack][name] = tmp |
| 2025 |
table.insert(stack, stack[level][tmpTag]) |
2166 |
else |
| 2026 |
else |
2167 |
table.insert(stack[#stack], tmp) |
| 2027 |
tmp = nil |
2168 |
end |
| 2028 |
tmp = {} |
2169 |
table.insert(stack, tmp) |
| 2029 |
table.insert(stack[level-1], tmp) |
2170 |
name = nil |
| 2030 |
|
2171 |
elseif label == "name" then |
| 2031 |
stack[level] = nil |
2172 |
name = value |
| 2032 |
stack[level] = tmp |
2173 |
elseif data_handle[label] then |
| 2033 |
table.insert(stack, tmp) |
2174 |
if name then |
| 2034 |
end |
2175 |
stack[#stack][name] = data_handle[label](value) |
| 2035 |
if empty ~= "" then |
2176 |
else |
| 2036 |
level = level - 1 |
2177 |
table.insert(stack[#stack], |
| 2037 |
stack[level][tmpTag] = "" |
2178 |
data_handle[label](value)) |
| 2038 |
table.remove(stack) |
2179 |
end |
| 2039 |
end |
2180 |
name = nil |
| 2040 |
elseif tag == "array" then |
2181 |
end |
| 2041 |
level = level + 1 |
2182 |
if empty == "/" -- empty tag |
| 2042 |
tmp = nil |
2183 |
and #stack>0 |
| 2043 |
tmp = {} |
2184 |
and (label == "struct" |
| 2044 |
table.insert(stack[level], tmp) |
2185 |
or label == "array") |
| 2045 |
table.insert(stack, tmp) |
2186 |
then |
| 2046 |
elseif val ~= "" then |
2187 |
table.remove(stack) |
| 2047 |
stack[level][tmpTag] = resolve_xml(val) |
2188 |
end |
| 2048 |
end |
2189 |
else -- end tag |
| 2049 |
end |
2190 |
if #stack>0 |
| 2050 |
collectgarbage() |
2191 |
and (label == "struct" |
| 2051 |
return tree |
2192 |
or label == "array")then |
|
|
2193 |
table.remove(stack) |
| 2194 |
end |
| 2195 |
end |
| 2196 |
end |
| 2197 |
|
| 2198 |
return tree[1] |
| 2052 |
end |
2199 |
end |
| 2053 |
|
2200 |
|
| 2054 |
function dump_xml(data) |
2201 |
function dump_xml(data) |
|
Lines 2226-2232
function mkdir_p(path)
Link Here
|
| 2226 |
end |
2373 |
end |
| 2227 |
|
2374 |
|
| 2228 |
function decode_uri(str) |
2375 |
function decode_uri(str) |
| 2229 |
vlc.msg.err(slash) |
|
|
| 2230 |
return str:gsub("/", slash) |
2376 |
return str:gsub("/", slash) |
| 2231 |
end |
2377 |
end |
| 2232 |
|
2378 |
|