From d7b285e051ee864c07484609affd346790629b1e Mon Sep 17 00:00:00 2001 From: Abhay Rana Date: Mon, 9 Jun 2014 21:56:35 +0530 Subject: [PATCH] Downgrading the version of vlcsub due to compatibility issues. --- .../share/vlc/lua/extensions/VLSub.luac | Bin 0 -> 89159 bytes .../.local/share/vlc/lua/extensions/vlsub.lua | 2042 ----------------- 2 files changed, 2042 deletions(-) create mode 100644 files/vlc/.local/share/vlc/lua/extensions/VLSub.luac delete mode 100644 files/vlc/.local/share/vlc/lua/extensions/vlsub.lua diff --git a/files/vlc/.local/share/vlc/lua/extensions/VLSub.luac b/files/vlc/.local/share/vlc/lua/extensions/VLSub.luac new file mode 100644 index 0000000000000000000000000000000000000000..3e8c2493c8fc02225d3b7345f339163d7ddbc236 GIT binary patch literal 89159 zcmc${31A$@btYWha{werNp>8OHbr|Rlcr8mlx0h%uI?FNKny`rA}LumO~C_TNWcUz z@XUY|6=&H!AOV@Ad`IyST8YD~b03>*Hpx11_kaW>QnH;**86W9{+mPjH-F+J&L&Qr zIJW=qRn_b6Y0LnS?0U#C+)vKecH}p>x_X#7}nd}s=|M=R~Z&)q(XT1IK zgb-bpDOOvSv)Z%V)s|fcOs^J=>D5l-)M_zzdY5O4f|Hvmh>NoY=i<`^ap{8v=hB&i zm_J)^=Fb(x!ZQVD;X?)S{D%w9^B-AlIWxPw4pFfBK34GhK3=d2pD1{RA1he9o-KI0 ze!O7yf3o29f2v^Z{&d0H{h5Nb=O+r@p7RB3?`I3%-scL|!#`Q@9{#C<^~mQ6-XlL< zu=ZUjc>8{)VD10+1#kc73)X?3EqDihu3$a-^9AqGUnp3Q{bIp;?3W7GJAb+0z4KQJ z*5kig@E-rQg7vQd;CinYzIcN$>^BJ8c!O}=HwYh3qXEAOzqvv9*$u)-z(2h~xO4Es zZ6t3HcJ~d!J#~ZdFWw-G6v9&*g^Q=(vr#vG0@5q-6*2q^1-pKD4tkM5c@J9cjV7>1T!PAfK65_hELKwbtEB@RnE?C02 z0>5G0CT#mQ@iP2f2CC}bCS3nEvB?(3F8EzPg*vCjF#KoX_l?_yk-c49fd2~oM*VhS zH*Oa%!{22hzIlgmvv-J1S;U9mt=}R1#vNi9{R_) zyAp_>*e2ZEHnAy(`0%^a+k`*2O$@_-7Jh#Yf09XY0sbp+8r?}@pGu0C;qOW!e)3M? zcHb#Bbt69fZZaYKQwcE)|5^C`Q+EpE(w*W0{8!*NQrm^yvt7Ile^(0ePj46QrR`!< z58}h`UP=l-b(a{1|1A7|&t1Zpxl3Gt{|fxZ{9VFMzg4^pe^(mu^KTXI%v;5#JmSOe z=E1+2lo*EpEd2ibTZPeax3~cR75I(byM;Y_w|E);t`5XsxLdd#Zxfq(5g&fH_ie(T zeVZ7D|1A9e!rO$=`F3#u{wwesJKrwsr{6AKhQF&5@t=RYa69i2n|2~T{O-KMtg?;Wp@iP2fYY@LbE!=Zyv8f;N;dftrQ21*e62tJHh2QUgNEpvN zBrd>z1%BhDhlIV>5--C)Y>C&)K4PIWxK`Ll{51N1N7zSvOSpy|_7S^7_-;qoM{IP4 zx*hhBMhEmoXV^y?Hgrce>?7H%@ax&Ik2KI361lLC^5ZG`;r}MW@$~R?$p23W zCqJHIH~jyMa6COc9rAw*;pE3t?1BGZ5RRvZr$hdKML7BK6no+SHp21r@N~%kZwMzp zp5kHnzk_f*Jv<%qe;48OoJaU0z{79hX?+jj&a zYPS!!uieJupigLexNYrr;dZs#huha~<6WRnYI?YB?RMdIwcCf=*KXt8pigOfxNYrr z;dZs#ha2OfPYeh6deAyH_UDc5{LTm-FjXPh&2nI}p;= z5tbDxmB)a%Y>1>`zE|w3qm8rgMLO@*>A;QrDSb(67R9b?0yIT2$NAQaVY-co+Z+t> zP34T>>k)S&;x>oExY>xi9&tA!ZgV)Gm*vb3i(Mx1YB(sr+laW$Qi#unZW*^;5~Xa1 z=0DtZ?KTgi?npCxSX=?0jOoLoG>5QkB5lmUo#>Qq)h7Z)ySV<&1BXN74tO@jc zp2Jm2fPJtH+TJx7+^XXpSgXrjDYGxpI#ltrSNmPzI4)vzWzUDrl8~BGsB}Vv~ncq0r${ zbqERH$}H7#m8nh*)<$b%rE2DIr97V5J6W38�~C3fgw9jzXzGHcG_`H5AM2z5vq| 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 literal 0 HcmV?d00001 diff --git a/files/vlc/.local/share/vlc/lua/extensions/vlsub.lua b/files/vlc/.local/share/vlc/lua/extensions/vlsub.lua deleted file mode 100644 index 0ee26ff..0000000 --- a/files/vlc/.local/share/vlc/lua/extensions/vlsub.lua +++ /dev/null @@ -1,2042 +0,0 @@ ---[[ - VLSub Extension for VLC media player 1.1 and 2.0 - Copyright 2013 Guillaume Le Maout - - Authors: Guillaume Le Maout - Contact: http://addons.videolan.org/messages/?action=newmessage&username=exebetche - Bug report: http://addons.videolan.org/content/show.php/?content=148752 - - 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. ---]] - - - --[[ Global var ]]-- - --- You can set here your default language by replacing nil with your language code (see below) --- Example: --- language = "fre", --- language = "ger", --- language = "eng", --- ... - -local options = { - language = nil, - downloadBehaviour = 'save', - langExt = false, - removeTag = false, - showMediaInformation = true, - progressBarSize = 80, - intLang = 'eng', - translations_avail = { - eng = 'English', - cze = 'Czech', - dan = 'Danish', - dut = 'Nederlands', - fre = 'Français', - ell = 'Greek', - baq = 'Basque', - pob = 'Brazilian Portuguese', - por = 'Portuguese (Portugal)', - rum = 'Romanian', - slo = 'Slovak', - spa = 'Spanish', - swe = 'Swedish', - ukr = 'Ukrainian', - hun = 'Hungarian' - }, - translation = { - int_all = 'All', - int_descr = 'Download subtitles from OpenSubtitles.org', - int_research = 'Research', - int_config = 'Config', - int_configuration = 'Configuration', - int_help = 'Help', - int_search_hash = 'Search by hash', - int_search_name = 'Search by name', - int_title = 'Title', - int_season = 'Season (series)', - int_episode = 'Episode (series)', - int_show_help = 'Show help', - int_show_conf = 'Show config', - int_dowload_sel = 'Download selection', - int_close = 'Close', - int_ok = 'Ok', - int_save = 'Save', - int_cancel = 'Cancel', - int_bool_true = 'Yes', - int_bool_false = 'No', - int_search_transl = 'Search translations', - int_searching_transl = 'Searching translations ...', - int_int_lang = 'Interface language', - int_default_lang = 'Subtitles language', - int_dowload_behav = 'What to do with subtitles', - int_dowload_save = 'Load and save', - int_dowload_load = 'Load only', - int_dowload_manual = 'Manual download', - int_display_code = 'Display language code in file name', - int_remove_tag = 'Remove tags', - int_vlsub_work_dir = 'VLSub working directory', - int_os_username = 'Username', - int_os_password = 'Password', - int_help_mess = " Download subtitles from opensubtitles.org and display them while watching a video.
".. - "
".. - " Usage:
".. - "
".. - " VLSub is meant to be used while you are watching the video, so start it first (if nothing is playing you will get a link to download the subtitles in your browser).
".. - "
".. - " Choose the language for your subtitles and click on the button corresponding to one of the two research methods provided by VLSub:
".. - "
".. - " Method 1: Search by hash
".. - " It is recommended to try this method first, because it performs a research based on the video file print, so you can find subtitles synchronized with your video.
".. - "
".. - " Method 2: Search by name
".. - " If you have no luck with the first method, just check the title is correct before clicking. If you search subtitles for a series, you can also provide a season and episode number.
".. - "
".. - " Downloading Subtitles
".. - " Select one subtitle in the list and click on 'Download'.
".. - " It will be put in the same directory that your video, with the same name (different extension)".. - " so VLC will load them automatically the next time you'll start the video.
".. - "
".. - " /!\\ Beware : Existing subtitles are overwritten without asking confirmation, so put them elsewhere if they're important.
".. - "
".. - " Find more VLC extensions at addons.videolan.org.", - int_no_support_mess = [[ - VLSub is not working with Vlc 2.1.x on any platform - because the lua "net" module needed to interact with opensubtitles has been - removed in this release for the extensions. -
- Works with Vlc 2.2 on mac and linux. -
- On windows you have to install an older version of Vlc (2.0.8 for example) - to use Vlsub: -
- http://download.videola...pub/videolan/vlc/2.0.8/ -
- ]], - - action_login = 'Logging in', - action_logout = 'Logging out', - action_noop = 'Checking session', - action_search = 'Searching subtitles', - action_hash = 'Calculating movie hash', - - mess_success = 'Success', - mess_error = 'Error', - mess_no_response = 'Server not responding', - mess_unauthorized = 'Request unauthorized', - mess_expired = 'Session expired, retrying', - mess_overloaded = 'Server overloaded, please retry later', - mess_no_input = 'Please use this method during playing', - mess_not_local = 'This method works with local file only (for now)', - mess_not_found = 'File not found', - mess_not_found2 = 'File not found (illegal character?)', - mess_no_selection = 'No subtitles selected', - mess_save_fail = 'Unable to save subtitles', - mess_click_link = 'Click here to open the file', - mess_complete = 'Research complete', - mess_no_res = 'No result', - mess_res = 'result(s)', - mess_loaded = 'Subtitles loaded', - mess_not_load = 'Unable to load subtitles', - mess_downloading = 'Downloading subtitle', - mess_dowload_link = 'Download link', - mess_err_conf_access ='Can\'t find a suitable path to save config, please set it manually', - mess_err_wrong_path ='the path contains illegal character, please correct it' - } -} - -local languages = { - {'alb', 'Albanian'}, - {'ara', 'Arabic'}, - {'arm', 'Armenian'}, - {'baq', 'Basque'}, - {'ben', 'Bengali'}, - {'bos', 'Bosnian'}, - {'bre', 'Breton'}, - {'bul', 'Bulgarian'}, - {'bur', 'Burmese'}, - {'cat', 'Catalan'}, - {'chi', 'Chinese'}, - {'hrv', 'Croatian'}, - {'cze', 'Czech'}, - {'dan', 'Danish'}, - {'dut', 'Dutch'}, - {'eng', 'English'}, - {'epo', 'Esperanto'}, - {'est', 'Estonian'}, - {'fin', 'Finnish'}, - {'fre', 'French'}, - {'glg', 'Galician'}, - {'geo', 'Georgian'}, - {'ger', 'German'}, - {'ell', 'Greek'}, - {'heb', 'Hebrew'}, - {'hin', 'Hindi'}, - {'hun', 'Hungarian'}, - {'ice', 'Icelandic'}, - {'ind', 'Indonesian'}, - {'ita', 'Italian'}, - {'jpn', 'Japanese'}, - {'kaz', 'Kazakh'}, - {'khm', 'Khmer'}, - {'kor', 'Korean'}, - {'lav', 'Latvian'}, - {'lit', 'Lithuanian'}, - {'ltz', 'Luxembourgish'}, - {'mac', 'Macedonian'}, - {'may', 'Malay'}, - {'mal', 'Malayalam'}, - {'mon', 'Mongolian'}, - {'nor', 'Norwegian'}, - {'oci', 'Occitan'}, - {'per', 'Persian'}, - {'pol', 'Polish'}, - {'por', 'Portuguese'}, - {'pob', 'Brazilian Portuguese'}, - {'rum', 'Romanian'}, - {'rus', 'Russian'}, - {'scc', 'Serbian'}, - {'sin', 'Sinhalese'}, - {'slo', 'Slovak'}, - {'slv', 'Slovenian'}, - {'spa', 'Spanish'}, - {'swa', 'Swahili'}, - {'swe', 'Swedish'}, - {'syr', 'Syriac'}, - {'tgl', 'Tagalog'}, - {'tel', 'Telugu'}, - {'tha', 'Thai'}, - {'tur', 'Turkish'}, - {'ukr', 'Ukrainian'}, - {'urd', 'Urdu'}, - {'vie', 'Vietnamese'} -} - --- Languages code conversion table: iso-639-1 to iso-639-3 --- See https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes -local lang_os_to_iso = { - sq = "alb", - ar = "ara", - hy = "arm", - eu = "baq", - bn = "ben", - bs = "bos", - br = "bre", - bg = "bul", - my = "bur", - ca = "cat", - zh = "chi", - hr = "hrv", - cs = "cze", - da = "dan", - nl = "dut", - en = "eng", - eo = "epo", - et = "est", - fi = "fin", - fr = "fre", - gl = "glg", - ka = "geo", - de = "ger", - el = "ell", - he = "heb", - hi = "hin", - hu = "hun", - is = "ice", - id = "ind", - it = "ita", - ja = "jpn", - kk = "kaz", - km = "khm", - ko = "kor", - lv = "lav", - lt = "lit", - lb = "ltz", - mk = "mac", - ms = "may", - ml = "mal", - mn = "mon", - no = "nor", - oc = "oci", - fa = "per", - pl = "pol", - pt = "por", - po = "pob", - ro = "rum", - ru = "rus", - sr = "scc", - si = "sin", - sk = "slo", - sl = "slv", - es = "spa", - sw = "swa", - sv = "swe", - tl = "tgl", - te = "tel", - th = "tha", - tr = "tur", - uk = "ukr", - ur = "urd", - vi = "vie" -} - -local dlg = nil -local input_table = {} -- General widget id reference -local select_conf = {} -- Drop down widget / option table association - - --[[ VLC extension stuff ]]-- - -function descriptor() - return { - title = "VLsub 0.9.11", - version = "0.9.11", - author = "exebetche", - url = 'http://www.opensubtitles.org/', - shortdesc = "VLsub"; - description = options.translation.int_descr, - capabilities = {"menu", "input-listener" } - } -end - -function activate() - vlc.msg.dbg("[VLsub] Welcome") - - if not check_config() then - vlc.msg.err("[VLsub] Unsupported VLC version") - return false - end - - if vlc.input.item() then - openSub.getFileInfo() - openSub.getMovieInfo() - end - - show_main() -end - -function close() - deactivate() -end - -function deactivate() - vlc.msg.dbg("[VLsub] Bye bye!") - if dlg then - dlg:hide() - end - - if openSub.session.token and openSub.session.token ~= "" then - openSub.request("LogOut") - end - vlc.deactivate() -end - -function menu() - return { - lang.int_research, - lang.int_config, - lang.int_help - } -end - -function meta_changed() - return false -end - -function input_changed() - collectgarbage() - set_interface_main() - collectgarbage() -end - - --[[ Interface data ]]-- - -function interface_main() - dlg:add_label(lang["int_default_lang"]..':', 1, 1, 1, 1) - input_table['language'] = dlg:add_dropdown(2, 1, 2, 1) - dlg:add_button(lang["int_search_hash"], searchHash, 4, 1, 1, 1) - - dlg:add_label(lang["int_title"]..':', 1, 2, 1, 1) - input_table['title'] = dlg:add_text_input(openSub.movie.title or "", 2, 2, 2, 1) - dlg:add_button(lang["int_search_name"], searchIMBD, 4, 2, 1, 1) - dlg:add_label(lang["int_season"]..':', 1, 3, 1, 1) - input_table['seasonNumber'] = dlg:add_text_input(openSub.movie.seasonNumber or "", 2, 3, 2, 1) - dlg:add_label(lang["int_episode"]..':', 1, 4, 1, 1) - input_table['episodeNumber'] = dlg:add_text_input(openSub.movie.episodeNumber or "", 2, 4, 2, 1) - input_table['mainlist'] = dlg:add_list(1, 5, 4, 1) - input_table['message'] = nil - input_table['message'] = dlg:add_label(' ', 1, 6, 4, 1) - dlg:add_button(lang["int_show_help"], show_help, 1, 7, 1, 1) - dlg:add_button(' '..lang["int_show_conf"]..' ', show_conf, 2, 7, 1, 1) - dlg:add_button(lang["int_dowload_sel"], download_subtitles, 3, 7, 1, 1) - dlg:add_button(lang["int_close"], deactivate, 4, 7, 1, 1) - - assoc_select_conf('language', 'language', openSub.conf.languages, 2, lang["int_all"]) - display_subtitles() -end - -function set_interface_main() - -- Update movie title and co. if video input change - if not type(input_table['title']) == 'userdata' then return false end - - openSub.getFileInfo() - openSub.getMovieInfo() - - input_table['title']:set_text(openSub.movie.title or "") - input_table['episodeNumber']:set_text(openSub.movie.episodeNumber or "") - input_table['seasonNumber']:set_text(openSub.movie.seasonNumber or "") -end - -function interface_config() - input_table['intLangLab'] = dlg:add_label(lang["int_int_lang"]..':', 1, 1, 1, 1) - input_table['intLangBut'] = dlg:add_button(lang["int_search_transl"], get_available_translations, 2, 1, 1, 1) - input_table['intLang'] = dlg:add_dropdown(3, 1, 1, 1) - dlg:add_label(lang["int_default_lang"]..':', 1, 2, 2, 1) - input_table['default_language'] = dlg:add_dropdown(3, 2, 1, 1) - dlg:add_label(lang["int_dowload_behav"]..':', 1, 3, 2, 1) - input_table['downloadBehaviour'] = dlg:add_dropdown(3, 3, 1, 1) - - dlg:add_label(lang["int_display_code"]..':', 1, 4, 0, 1) - input_table['langExt'] = dlg:add_dropdown(3, 4, 1, 1) - dlg:add_label(lang["int_remove_tag"]..':', 1, 5, 0, 1) - input_table['removeTag'] = dlg:add_dropdown(3, 5, 1, 1) - - if openSub.conf.dirPath then - if openSub.conf.os == "win" then - dlg :add_label(""..lang["int_vlsub_work_dir"].."", 1, 6, 2, 1) - else - dlg :add_label(""..lang["int_vlsub_work_dir"].."", 1, 6, 2, 1) - end - else - dlg :add_label(lang["int_vlsub_work_dir"], 1, 6, 2, 1) - end - - input_table['dir_path'] = dlg:add_text_input(openSub.conf.dirPath, 2, 6, 2, 1) - - dlg:add_label(lang["int_os_username"]..':', 1, 7, 0, 1) - input_table['os_username'] = dlg:add_text_input(type(openSub.option.os_username) == "string" and openSub.option.os_username or "", 2, 7, 2, 1) - dlg:add_label(lang["int_os_password"]..':', 1, 8, 0, 1) - input_table['os_password'] = dlg:add_text_input(type(openSub.option.os_password) == "string" and openSub.option.os_password or "", 2, 8, 2, 1) - - input_table['message'] = nil - input_table['message'] = dlg:add_label(' ', 1, 9, 3, 1) - - dlg:add_button(lang["int_cancel"], show_main, 2, 10, 1, 1) - dlg:add_button(lang["int_save"], apply_config, 3, 10, 1, 1) - - input_table['langExt']:add_value(lang["int_bool_"..tostring(openSub.option.langExt)], 1) - input_table['langExt']:add_value(lang["int_bool_"..tostring(not openSub.option.langExt)], 2) - input_table['removeTag']:add_value(lang["int_bool_"..tostring(openSub.option.removeTag)], 1) - input_table['removeTag']:add_value(lang["int_bool_"..tostring(not openSub.option.removeTag)], 2) - - assoc_select_conf('intLang', 'intLang', openSub.conf.translations_avail, 2) - assoc_select_conf('default_language', 'language', openSub.conf.languages, 2, lang["int_all"]) - assoc_select_conf('downloadBehaviour', 'downloadBehaviour', openSub.conf.downloadBehaviours, 1) -end - -function interface_help() - local help_html = lang["int_help_mess"] - - input_table['help'] = dlg:add_html(help_html, 1, 1, 4, 1) - dlg:add_label(string.rep (" ", 100), 1, 2, 3, 1) - dlg:add_button(lang["int_ok"], show_main, 4, 2, 1, 1) -end - -function interface_no_support() - local no_support_html = lang["int_no_support_mess"] - - input_table['no_support'] = dlg:add_html(no_support_html, 1, 1, 4, 1) - dlg:add_label(string.rep (" ", 100), 1, 2, 3, 1) -end - -function trigger_menu(dlg_id) - if dlg_id == 1 then - close_dlg() - dlg = vlc.dialog(openSub.conf.useragent) - interface_main() - elseif dlg_id == 2 then - close_dlg() - dlg = vlc.dialog(openSub.conf.useragent..': '..lang["int_configuration"]) - interface_config() - elseif dlg_id == 3 then - close_dlg() - dlg = vlc.dialog(openSub.conf.useragent..': '..lang["int_help"]) - interface_help() - end - collectgarbage() --~ !important -end - -function show_main() - trigger_menu(1) -end - -function show_conf() - trigger_menu(2) -end - -function show_help() - trigger_menu(3) -end - -function close_dlg() - vlc.msg.dbg("[VLSub] Closing dialog") - - if dlg ~= nil then - --~ dlg:delete() -- Throw an error - dlg:hide() - end - - dlg = nil - input_table = nil - input_table = {} - collectgarbage() --~ !important -end - - --[[ Drop down / config association]]-- - -function assoc_select_conf(select_id, option, conf, ind, default) --- Helper for i/o interaction between drop down and option list (lang...) - select_conf[select_id] = {cf = conf, opt = option, dflt = default, ind = ind} - set_default_option(select_id) - display_select(select_id) -end - -function set_default_option(select_id) --- Put the selected option of a list in first place of the associated table - local opt = select_conf[select_id].opt - local cfg = select_conf[select_id].cf - local ind = select_conf[select_id].ind - if openSub.option[opt] then - table.sort(cfg, function(a, b) - if a[1] == openSub.option[opt] then - return true - elseif b[1] == openSub.option[opt] then - return false - else - return a[ind] < b[ind] - end - end) - end -end - -function display_select(select_id) --- Display the drop down values with an optional default value at the top - local conf = select_conf[select_id].cf - local opt = select_conf[select_id].opt - local option = openSub.option[opt] - local default = select_conf[select_id].dflt - local default_isset = false - - if not default then - default_isset = true - end - - for k, l in ipairs(conf) do - if default_isset then - input_table[select_id]:add_value(l[2], k) - else - if option then - input_table[select_id]:add_value(l[2], k) - input_table[select_id]:add_value(default, 0) - else - input_table[select_id]:add_value(default, 0) - input_table[select_id]:add_value(l[2], k) - end - default_isset = true - end - end -end - - --[[ Config & interface localization]]-- - -function check_config() - -- Make a copy of english translation to use it as default - -- in case some element aren't translated in other translations - eng_translation = {} - for k, v in pairs(openSub.option.translation) do - eng_translation[k] = v - end - - -- Get available translation full name from code - trsl_names = {} - for i, lg in ipairs(languages) do - trsl_names[lg[1]] = lg[2] - end - - if is_window_path(vlc.config.datadir()) then - openSub.conf.os = "win" - slash = "\\" - else - openSub.conf.os = "lin" - slash = "/" - end - - local path_generic = {"lua", "extensions", "userdata", "vlsub"} - local dirPath = slash..table.concat(path_generic, slash) - local filePath = slash.."vlsub_conf.xml" - local config_saved = false - sub_dir = slash.."vlsub_subtitles" - - -- Check if config file path is stored in vlc config - local other_dirs = {} - - for path in vlc.config.get("sub-autodetect-path"):gmatch("[^,]+") do - if path:match(".*"..sub_dir.."$") then - openSub.conf.dirPath = path:gsub("%s*(.*)"..sub_dir.."%s*$", "%1") - config_saved = true - end - table.insert(other_dirs, path) - end - - -- if not stored in vlc config - -- try to find a suitable config file path - - if openSub.conf.dirPath then - if not is_dir(openSub.conf.dirPath) and - (openSub.conf.os == "lin" or - is_win_safe(openSub.conf.dirPath)) then - mkdir_p(openSub.conf.dirPath) - end - else - local userdatadir = vlc.config.userdatadir() - local datadir = vlc.config.datadir() - - -- check if the config already exist - if file_exist(userdatadir..dirPath..filePath) then - -- in vlc.config.userdatadir() - openSub.conf.dirPath = userdatadir..dirPath - config_saved = true - elseif file_exist(datadir..dirPath..filePath) then - -- in vlc.config.datadir() - openSub.conf.dirPath = datadir..dirPath - config_saved = true - else - -- if not found determine an accessible path - local extension_path = slash..path_generic[1] - ..slash..path_generic[2] - - -- use the same folder as the extension if accessible - if is_dir(userdatadir..extension_path) - and file_touch(userdatadir..dirPath..filePath) then - openSub.conf.dirPath = userdatadir..dirPath - elseif file_touch(datadir..dirPath..filePath) then - openSub.conf.dirPath = datadir..dirPath - end - - -- try to create working dir in user folder - if not openSub.conf.dirPath - and is_dir(userdatadir) then - if not is_dir(userdatadir..dirPath) then - mkdir_p(userdatadir..dirPath) - end - if is_dir(userdatadir..dirPath) and - file_touch(userdatadir..dirPath..filePath) then - openSub.conf.dirPath = userdatadir..dirPath - end - end - - -- try to create working dir in vlc folder - if not openSub.conf.dirPath and - is_dir(datadir) then - if not is_dir(datadir..dirPath) then - mkdir_p(datadir..dirPath) - end - if file_touch(datadir..dirPath..filePath) then - openSub.conf.dirPath = datadir..dirPath - end - end - end - end - - if openSub.conf.dirPath then - vlc.msg.dbg("[VLSub] Working directory: " .. - (openSub.conf.dirPath or "not found")) - - openSub.conf.filePath = openSub.conf.dirPath..filePath - openSub.conf.localePath = openSub.conf.dirPath..slash.."locale" - - if config_saved - and file_exist(openSub.conf.filePath) then - vlc.msg.dbg("[VLSub] Loading config file: "..openSub.conf.filePath) - load_config() - else - vlc.msg.dbg("[VLSub] No config file") - getenv_lang() - config_saved = save_config() - if not config_saved then - vlc.msg.dbg("[VLSub] Unable to save config") - end - end - - -- Check presence of a translation file in "%vlsub_directory%/locale" - -- Add translation files to available translation list - local file_list = list_dir(openSub.conf.localePath) - local translations_avail = openSub.conf.translations_avail - - if file_list then - for i, file_name in ipairs(file_list) do - local lg = string.gsub(file_name, "^(%w%w%w).xml$", "%1") - if lg and not openSub.option.translations_avail[lg] then - table.insert(translations_avail, {lg, trsl_names[lg]}) - end - end - end - - -- Load selected translation from file - if openSub.option.intLang ~= "eng" - and not openSub.conf.translated - then - local transl_file_path = openSub.conf.localePath..slash..openSub.option.intLang..".xml" - if file_exist(transl_file_path) then - vlc.msg.dbg("[VLSub] Loading translation from file: " .. transl_file_path) - load_transl(transl_file_path) - end - end - else - vlc.msg.dbg("[VLSub] Unable to find a suitable path to save config, please set it manually") - end - - lang = nil - lang = options.translation -- just a short cut - - if not(vlc.net or vlc.net.poll) then - dlg = vlc.dialog(openSub.conf.useragent..': '..lang["mess_error"]) - interface_no_support() - dlg:show() - return false - end - - SetDownloadBehaviours() - if not openSub.conf.dirPath then - setError(lang["mess_err_conf_access"]) - end - - -- Set table list of available translations from assoc. array - -- so it is sortable - - for k, l in pairs(openSub.option.translations_avail) do - if k == openSub.option.int_research then - table.insert(openSub.conf.translations_avail, 1, {k, l}) - else - table.insert(openSub.conf.translations_avail, {k, l}) - end - end - collectgarbage() - return true -end - -function load_config() --- Overwrite default conf with loaded conf - local tmpFile = io.open(openSub.conf.filePath, "rb") - if not tmpFile then return false end - local resp = tmpFile:read("*all") - tmpFile:flush() - tmpFile:close() - local option = parse_xml(resp) - - for key, value in pairs(option) do - if type(value) == "table" then - if key == "translation" then - openSub.conf.translated = true - for k, v in pairs(value) do - openSub.option.translation[k] = v - end - else - openSub.option[key] = value - end - else - if value == "true" then - openSub.option[key] = true - elseif value == "false" then - openSub.option[key] = false - else - openSub.option[key] = value - end - end - end - collectgarbage() -end - -function load_transl(path) --- Overwrite default conf with loaded conf - local tmpFile = assert(io.open(path, "rb")) - local resp = tmpFile:read("*all") - tmpFile:flush() - tmpFile:close() - openSub.option.translation = nil - - openSub.option.translation = parse_xml(resp) - collectgarbage() -end - -function apply_translation() --- Overwrite default conf with loaded conf - for k, v in pairs(eng_translation) do - if not openSub.option.translation[k] then - openSub.option.translation[k] = eng_translation[k] - end - end -end - -function getenv_lang() --- Retrieve the user OS language - local os_lang = os.getenv("LANG") - - if os_lang then -- unix, mac - os_lang = string.sub(os_lang, 0, 2) - if type(lang_os_to_iso[os_lang]) then - openSub.option.language = lang_os_to_iso[os_lang] - end - else -- Windows - local lang_w = string.match(os.setlocale("", "collate"), "^[^_]+") - for i, v in ipairs(openSub.conf.languages) do - if v[2] == lang_w then - openSub.option.language = v[1] - end - end - end -end - -function apply_config() --- Apply user config selection to local config - local lg_sel = input_table['intLang']:get_value() - local sel_val - local opt - - if lg_sel and lg_sel ~= 1 - and openSub.conf.translations_avail[lg_sel] then - local lg = openSub.conf.translations_avail[lg_sel][1] - set_translation(lg) - SetDownloadBehaviours() - end - - for select_id, v in pairs(select_conf) do - if input_table[select_id] and select_conf[select_id] then - sel_val = input_table[select_id]:get_value() - opt = select_conf[select_id].opt - - if sel_val == 0 then - openSub.option[opt] = nil - else - openSub.option[opt] = select_conf[select_id].cf[sel_val][1] - end - - set_default_option(select_id) - end - end - - - openSub.option.os_username = input_table['os_username']:get_text() - openSub.option.os_password = input_table['os_password']:get_text() - - if input_table["langExt"]:get_value() == 2 then - openSub.option.langExt = not openSub.option.langExt - end - - if input_table["removeTag"]:get_value() == 2 then - openSub.option.removeTag = not openSub.option.removeTag - end - - -- Set a custom working directory - local dir_path = input_table['dir_path']:get_text() - local dir_path_err = false - if trim(dir_path) == "" then dir_path = nil end - - if dir_path ~= openSub.conf.dirPath then - if openSub.conf.os == "lin" - or is_win_safe(dir_path) - or not dir_path then - local other_dirs = {} - - for path in vlc.config.get("sub-autodetect-path"):gmatch("[^,]+") do - path = trim(path) - if path ~= (openSub.conf.dirPath or "")..sub_dir then - table.insert(other_dirs, path) - end - end - openSub.conf.dirPath = dir_path - if dir_path then - table.insert(other_dirs, - string.gsub(dir_path, "^(.-)[\\/]?$", "%1")..sub_dir) - - if not is_dir(dir_path) then - mkdir_p(dir_path) - end - - openSub.conf.filePath = openSub.conf.dirPath..slash.."vlsub_conf.xml" - openSub.conf.localePath = openSub.conf.dirPath..slash.."locale" - else - openSub.conf.filePath = nil - openSub.conf.localePath = nil - end - vlc.config.set("sub-autodetect-path", table.concat(other_dirs, ", ")) - else - dir_path_err = true - setError(lang["mess_err_wrong_path"].."
"..string.gsub(dir_path, "[^%:%w%p%s§¤]+", "%1").."") - end - end - - if openSub.conf.dirPath and - not dir_path_err then - local config_saved = save_config() - trigger_menu(1) - if not config_saved then - setError(lang["mess_err_conf_access"]) - end - else - setError(lang["mess_err_conf_access"]) - end -end - -function save_config() --- Dump local config into config file - if openSub.conf.dirPath - and openSub.conf.filePath then - vlc.msg.dbg("[VLSub] Saving config file: " .. openSub.conf.filePath) - - if file_touch(openSub.conf.filePath) then - local tmpFile = assert(io.open(openSub.conf.filePath, "wb")) - local resp = dump_xml(openSub.option) - tmpFile:write(resp) - tmpFile:flush() - tmpFile:close() - tmpFile = nil - else - return false - end - collectgarbage() - return true - else - vlc.msg.dbg("[VLSub] Unable fount a suitable path to save config, please set it manually") - setError(lang["mess_err_conf_access"]) - return false - end -end - -function SetDownloadBehaviours() - openSub.conf.downloadBehaviours = nil - openSub.conf.downloadBehaviours = { - {'save', lang["int_dowload_save"]}, - {'load', lang["int_dowload_load"]}, - {'manual', lang["int_dowload_manual"]} - } -end - -function get_available_translations() --- Get all available translation files from the internet --- (drop previous direct download from github repo because of problem with github https CA certficate on OS X an XP) --- https://github.com/exebetche/vlsub/tree/master/locale - - local translations_url = "http://addons.videolan.org/CONTENT/content-files/148752-vlsub_translations.xml" - - if input_table['intLangBut']:get_text() == lang["int_search_transl"] then - openSub.actionLabel = lang["int_searching_transl"] - - local translations_content, lol = get(translations_url) - - all_trsl = parse_xml(translations_content) - local lg, trsl - - for lg, trsl in pairs(all_trsl) do - if lg ~= options.intLang[1] and not openSub.option.translations_avail[lg] then - openSub.option.translations_avail[lg] = trsl_names[lg] or "" - table.insert(openSub.conf.translations_avail, {lg, trsl_names[lg]}) - input_table['intLang']:add_value(trsl_names[lg], #openSub.conf.translations_avail) - end - end - - setMessage(success_tag(lang["mess_complete"])) - collectgarbage() - end -end - -function set_translation(lg) - openSub.option.translation = nil - openSub.option.translation = {} - - if lg == 'eng' then - for k, v in pairs(eng_translation) do - openSub.option.translation[k] = v - end - else - -- If translation file exists in /locale directory load it - if openSub.conf.localePath - and file_exist(openSub.conf.localePath..slash..lg..".xml") then - local transl_file_path = openSub.conf.localePath..slash..lg..".xml" - vlc.msg.dbg("[VLSub] Loading translation from file: " .. transl_file_path) - load_transl(transl_file_path) - apply_translation() - else - -- Load translation file from internet - if not all_trsl then - get_available_translations() - end - - if not all_trsl or not all_trsl[lg] then - vlc.msg.dbg("[VLSub] Error, translation not found") - return false - end - openSub.option.translation = all_trsl[lg] - apply_translation() - all_trsl = nil - end - end - - lang = nil - lang = openSub.option.translation - collectgarbage() -end - - --[[ Core ]]-- - -openSub = { - itemStore = nil, - actionLabel = "", - conf = { - url = "http://api.opensubtitles.org/xml-rpc", - path = nil, - userAgentHTTP = "VLSub", - useragent = "VLSub 0.9", - translations_avail = {}, - downloadBehaviours = nil, - languages = languages - }, - option = options, - session = { - loginTime = 0, - token = "" - }, - file = { - hasInput = false, - uri = nil, - ext = nil, - name = nil, - path = nil, - protocol = nil, - cleanName = nil, - dir = nil, - hash = nil, - bytesize = nil, - fps = nil, - timems = nil, - frames = nil - }, - movie = { - title = "", - seasonNumber = "", - episodeNumber = "", - sublanguageid = "" - }, - request = function(methodName) - local params = openSub.methods[methodName].params() - local reqTable = openSub.getMethodBase(methodName, params) - local request = ""..dump_xml(reqTable) - local host, path = parse_url(openSub.conf.url) - local header = { - "POST "..path.." HTTP/1.1", - "Host: "..host, - "User-Agent: "..openSub.conf.userAgentHTTP, - "Content-Type: text/xml", - "Content-Length: "..string.len(request), - "", - "" - } - request = table.concat(header, "\r\n")..request - - local response - local status, responseStr = http_req(host, 80, request) - - if status == 200 then - response = parse_xmlrpc(responseStr) - if response then - if response.status == "200 OK" then - return openSub.methods[methodName].callback(response) - elseif response.status == "406 No session" then - openSub.request("LogIn") - elseif response then - setError("code '"..response.status.."' ("..status..")") - return false - end - else - setError("Server not responding") - return false - end - elseif status == 401 then - setError("Request unauthorized") - - response = parse_xmlrpc(responseStr) - if openSub.session.token ~= response.token then - setMessage("Session expired, retrying") - openSub.session.token = response.token - openSub.request(methodName) - end - return false - elseif status == 503 then - setError("Server overloaded, please retry later") - return false - end - - end, - getMethodBase = function(methodName, param) - if openSub.methods[methodName].methodName then - methodName = openSub.methods[methodName].methodName - end - - local request = { - methodCall={ - methodName=methodName, - params={ param=param }}} - - return request - end, - methods = { - LogIn = { - params = function() - openSub.actionLabel = lang["action_login"] - return { - { value={ string=openSub.option.os_username } }, - { value={ string=openSub.option.os_password } }, - { value={ string=openSub.movie.sublanguageid } }, - { value={ string=openSub.conf.useragent } } - } - end, - callback = function(resp) - openSub.session.token = resp.token - openSub.session.loginTime = os.time() - return true - end - }, - LogOut = { - params = function() - openSub.actionLabel = lang["action_logout"] - return { - { value={ string=openSub.session.token } } - } - end, - callback = function() - return true - end - }, - NoOperation = { - params = function() - openSub.actionLabel = lang["action_noop"] - return { - { value={ string=openSub.session.token } } - } - end, - callback = function(resp) - return true - end - }, - SearchSubtitlesByHash = { - methodName = "SearchSubtitles", - params = function() - openSub.actionLabel = lang["action_search"] - setMessage(openSub.actionLabel..": "..progressBarContent(0)) - - return { - { value={ string=openSub.session.token } }, - { value={ - array={ - data={ - value={ - struct={ - member={ - { name="sublanguageid", value={ - string=openSub.movie.sublanguageid } }, - { name="moviehash", value={ - string=openSub.file.hash } }, - { name="moviebytesize", value={ - double=openSub.file.bytesize } } }}}}}}} - } - end, - callback = function(resp) - openSub.itemStore = resp.data - end - }, - SearchSubtitles = { - methodName = "SearchSubtitles", - params = function() - openSub.actionLabel = lang["action_search"] - setMessage(openSub.actionLabel..": "..progressBarContent(0)) - - local member = { - { name="sublanguageid", value={ - string=openSub.movie.sublanguageid } }, - { name="query", value={ - string=openSub.movie.title } } } - - - if openSub.movie.seasonNumber ~= nil then - table.insert(member, { name="season", value={ - string=openSub.movie.seasonNumber } }) - end - - if openSub.movie.episodeNumber ~= nil then - table.insert(member, { name="episode", value={ - string=openSub.movie.episodeNumber } }) - end - - return { - { value={ string=openSub.session.token } }, - { value={ - array={ - data={ - value={ - struct={ - member=member - }}}}}} - } - end, - callback = function(resp) - openSub.itemStore = resp.data - end - } - }, - getInputItem = function() - return vlc.item or vlc.input.item() - end, - getFileInfo = function() - -- Get video file path, name, extension from input uri - local item = openSub.getInputItem() - local file = openSub.file - if not item then - file.hasInput = false; - file.cleanName = nil; - file.protocol = nil; - file.path = nil; - file.ext = nil; - file.uri = nil; - else - vlc.msg.dbg("[VLSub] Video URI: "..item:uri()) - local parsed_uri = vlc.net.url_parse(item:uri()) - file.uri = item:uri() - file.protocol = parsed_uri["protocol"] - file.path = parsed_uri["path"] - - -- Corrections - - -- For windows - file.path = string.match(file.path, "^/(%a:/.+)$") or file.path - - -- For file in archive - local archive_path, name_in_archive = string.match(file.path, '^([^!]+)!/([^!/]*)$') - if archive_path and archive_path ~= "" then - file.path = string.gsub(archive_path, '\063', '%%') - file.path = vlc.strings.decode_uri(file.path) - file.completeName = string.gsub(name_in_archive, '\063', '%%') - file.completeName = vlc.strings.decode_uri(file.completeName) - file.is_archive = true - else -- "classic" input - file.path = vlc.strings.decode_uri(file.path) - file.dir, file.completeName = string.match(file.path, '^(.+/)([^/]*)$') - - local file_stat = vlc.net.stat(file.path) - if file_stat - then - file.stat = file_stat - end - - file.is_archive = false - end - - file.name, file.ext = string.match(file.completeName, '^([^/]-)%.?([^%.]*)$') - - if file.ext == "part" then - file.name, file.ext = string.match(file.name, '^([^/]+)%.([^%.]+)$') - end - - file.hasInput = true; - file.cleanName = string.gsub(file.name, "[%._]", " ") - vlc.msg.dbg("[VLSub] file info "..(dump_xml(file))) - end - collectgarbage() - end, - getMovieInfo = function() - -- Clean video file name and check for season/episode pattern in title - if not openSub.file.name then - openSub.movie.title = "" - openSub.movie.seasonNumber = "" - openSub.movie.episodeNumber = "" - return false - end - - local showName, seasonNumber, episodeNumber = string.match(openSub.file.cleanName, "(.+)[sS](%d%d)[eE](%d%d).*") - - if not showName then - showName, seasonNumber, episodeNumber = string.match(openSub.file.cleanName, "(.+)(%d)[xX](%d%d).*") - end - - if showName then - openSub.movie.title = showName - openSub.movie.seasonNumber = seasonNumber - openSub.movie.episodeNumber = episodeNumber - else - openSub.movie.title = openSub.file.cleanName - openSub.movie.seasonNumber = "" - openSub.movie.episodeNumber = "" - end - collectgarbage() - end, - getMovieHash = function() - -- Calculate movie hash - openSub.actionLabel = lang["action_hash"] - setMessage(openSub.actionLabel..": "..progressBarContent(0)) - - local item = openSub.getInputItem() - - if not item then - setError(lang["mess_no_input"]) - return false - end - - openSub.getFileInfo() - - if not openSub.file.path then - setError(lang["mess_not_found"]) - return false - end - - local data_start = "" - local data_end = "" - local size - local chunk_size = 65536 - - -- Get data for hash calculation - if openSub.file.is_archive then - vlc.msg.dbg("[VLSub] Read hash data from stream") - - local file = vlc.stream(openSub.file.uri) - local dataTmp1 = "" - local dataTmp2 = "" - size = chunk_size - - data_start = file:read(chunk_size) - - while data_end do - size = size + string.len(data_end) - dataTmp1 = dataTmp2 - dataTmp2 = data_end - data_end = file:read(chunk_size) - collectgarbage() - end - data_end = string.sub((dataTmp1..dataTmp2), -chunk_size) - elseif not file_exist(openSub.file.path) - and openSub.file.stat then - vlc.msg.dbg("[VLSub] Read hash data from stream") - - local file = vlc.stream(openSub.file.uri) - - if not file then - vlc.msg.dbg("[VLSub] No stream") - return false - end - - size = openSub.file.stat.size - local decal = size%chunk_size - - data_start = file:read(chunk_size) - - -- "Seek" to the end - file:read(decal) - - for i = 1, math.floor(((size-decal)/chunk_size))-2 do - file:read(chunk_size) - end - - data_end = file:read(chunk_size) - - file = nil - else - vlc.msg.dbg("[VLSub] Read hash data from file") - local file = io.open( openSub.file.path, "rb") - if not file then - vlc.msg.dbg("[VLSub] No stream") - return false - end - - data_start = file:read(chunk_size) - size = file:seek("end", -chunk_size) + chunk_size - data_end = file:read(chunk_size) - file = nil - end - - -- Hash calculation - local lo = size - local hi = 0 - local o,a,b,c,d,e,f,g,h - local hash_data = data_start..data_end - local max_size = 4294967296 - local overflow - - for i = 1, #hash_data, 8 do - a,b,c,d,e,f,g,h = hash_data:byte(i,i+7) - lo = lo + a + b*256 + c*65536 + d*16777216 - hi = hi + e + f*256 + g*65536 + h*16777216 - - if lo > max_size then - overflow = math.floor(lo/max_size) - lo = lo-(overflow*max_size) - hi = hi+overflow - end - - if hi > max_size then - overflow = math.floor(hi/max_size) - hi = hi-(overflow*max_size) - end - end - - openSub.file.bytesize = size - openSub.file.hash = string.format("%08x%08x", hi,lo) - vlc.msg.dbg("[VLSub] Video hash: "..openSub.file.hash) - vlc.msg.dbg("[VLSub] Video bytesize: "..size) - collectgarbage() - return true - end, - checkSession = function() - - if openSub.session.token == "" then - openSub.request("LogIn") - else - openSub.request("NoOperation") - end - end -} - -function searchHash() - local sel = input_table["language"]:get_value() - if sel == 0 then - openSub.movie.sublanguageid = 'all' - else - openSub.movie.sublanguageid = openSub.conf.languages[sel][1] - end - - openSub.getMovieHash() - - if openSub.file.hash then - openSub.checkSession() - openSub.request("SearchSubtitlesByHash") - display_subtitles() - end -end - -function searchIMBD() - openSub.movie.title = trim(input_table["title"]:get_text()) - openSub.movie.seasonNumber = tonumber(input_table["seasonNumber"]:get_text()) - openSub.movie.episodeNumber = tonumber(input_table["episodeNumber"]:get_text()) - - local sel = input_table["language"]:get_value() - if sel == 0 then - openSub.movie.sublanguageid = 'all' - else - openSub.movie.sublanguageid = openSub.conf.languages[sel][1] - end - - if openSub.movie.title ~= "" then - openSub.checkSession() - openSub.request("SearchSubtitles") - display_subtitles() - end -end - -function display_subtitles() - local mainlist = input_table["mainlist"] - mainlist:clear() - - if openSub.itemStore == "0" then - mainlist:add_value(lang["mess_no_res"], 1) - setMessage(""..lang["mess_complete"]..": "..lang["mess_no_res"]) - elseif openSub.itemStore then - for i, item in ipairs(openSub.itemStore) do - mainlist:add_value( - item.SubFileName.. - " ["..item.SubLanguageID.."]".. - " ("..item.SubSumCD.." CD)", i) - end - setMessage(""..lang["mess_complete"]..": "..#(openSub.itemStore).." "..lang["mess_res"]) - end -end - -function get_first_sel(list) - local selection = list:get_selection() - for index, name in pairs(selection) do - return index - end - return 0 -end - -function download_subtitles() - local index = get_first_sel(input_table["mainlist"]) - - if index == 0 then - setMessage(lang["mess_no_selection"]) - return false - end - - openSub.actionLabel = lang["mess_downloading"] - - display_subtitles() -- reset selection - - local item = openSub.itemStore[index] - - if openSub.option.downloadBehaviour == 'manual' then - - local link = "" - link = link..""..lang["mess_dowload_link"]..":" - link = link.."  " - link = link.."  " - link = link..item.MovieReleaseName.."" - - setMessage(link) - return false - elseif openSub.option.downloadBehaviour == 'load' then - if add_sub("zip://"..item.ZipDownloadLink.."!/"..item.SubFileName) then - setMessage(success_tag(lang["mess_loaded"])) - else - message = error_tag(lang["mess_not_load"]) .. message - end - return false - end - - local message = "" - local subfileName = openSub.file.name - - if openSub.option.langExt then - subfileName = subfileName.."."..item.SubLanguageID - end - - subfileName = subfileName.."."..item.SubFormat - local tmp_dir - local file_target_access = true - - if is_dir(openSub.file.dir) then - tmp_dir = openSub.file.dir - elseif openSub.conf.dirPath then - tmp_dir = openSub.conf.dirPath - - message = "
"..error_tag(lang["mess_save_fail"].."  ".. - "".. - lang["mess_click_link"].."") - else - setError(lang["mess_save_fail"].."  ".. - "".. - lang["mess_click_link"].."") - return false - end - - local tmpFileURI, tmpFileName = dump_zip( - item.ZipDownloadLink, - tmp_dir, - item.SubFileName) - - vlc.msg.dbg("[VLsub] tmpFileName: "..tmpFileName) - - -- Determine if the path to the video file is accessible for writing - - local target = openSub.file.dir..subfileName - - if not file_touch(target) then - if openSub.conf.dirPath then - target = openSub.conf.dirPath..slash..subfileName - message = "
"..error_tag(lang["mess_save_fail"].."  ".. - "".. - lang["mess_click_link"].."") - else - setError(lang["mess_save_fail"].."  ".. - "".. - lang["mess_click_link"].."") - return false - end - end - - vlc.msg.dbg("[VLsub] Subtitles files: "..target) - - -- Unzipped data into file target - - local stream = vlc.stream(tmpFileURI) - local data = "" - local subfile = io.open(target, "wb") - - while data do - subfile:write(data) - data = stream:read(65536) - end - - subfile:flush() - subfile:close() - - stream = nil - collectgarbage() - - if not os.remove(tmpFileName) then - vlc.msg.err("[VLsub] Unable to remove temp: "..tmpFileName) - end - - subfileURI = vlc.strings.make_uri(target) - - if not subfileURI then - subfileURI = make_uri(target) - end - - -- load subtitles - if add_sub(subfileURI) then - message = success_tag(lang["mess_loaded"]) .. message - else - message = error_tag(lang["mess_not_load"]) .. message - end - - setMessage(message) -end - -function dump_zip(url, dir, subfileName) - -- Dump zipped data in a temporary file - setMessage(openSub.actionLabel..": "..progressBarContent(0)) - local resp = get(url) - - if not resp then - setError(lang["mess_no_response"]) - return false - end - - local tmpFileName = dir..subfileName..".gz" - if not file_touch(tmpFileName) then - return false - end - local tmpFile = assert(io.open(tmpFileName, "wb")) - - tmpFile:write(resp) - tmpFile:flush() - tmpFile:close() - tmpFile = nil - collectgarbage() - return "zip://"..make_uri(tmpFileName).."!/"..subfileName, tmpFileName -end - -function add_sub(subfileURI) - if vlc.item or vlc.input.item() then - vlc.msg.dbg("[VLsub] Adding subtitle :" .. subfileURI) - return vlc.input.add_subtitle(subfileURI) - end - return false -end - - --[[ Interface helpers]]-- - -function progressBarContent(pct) - local accomplished = math.ceil(openSub.option.progressBarSize*pct/100) - local left = openSub.option.progressBarSize - accomplished - local content = "".. - string.rep ("-", accomplished).."".. - "".. - string.rep ("-", left).. - "" - return content -end - -function setMessage(str) - if input_table["message"] then - input_table["message"]:set_text(str) - dlg:update() - end -end - -function setError(mess) - setMessage(error_tag(mess)) -end - -function success_tag(str) - return "".. - lang["mess_success"]..": "..str.."" -end - -function error_tag(str) - return "".. - lang["mess_error"]..": "..str.."" -end - - --[[ Network utils]]-- - -function get(url) - local host, path = parse_url(url) - local header = { - "GET "..path.." HTTP/1.1", - "Host: "..host, - "User-Agent: "..openSub.conf.userAgentHTTP, - "", - "" - } - local request = table.concat(header, "\r\n") - - local response - local status, response = http_req(host, 80, request) - - if status == 200 then - return response - else - return false, status, response - end -end - -function http_req(host, port, request) - local fd = vlc.net.connect_tcp(host, port) - if not fd then return false end - local pollfds = {} - - pollfds[fd] = vlc.net.POLLIN - vlc.net.send(fd, request) - vlc.net.poll(pollfds) - - local response = vlc.net.recv(fd, 2048) - local headerStr, body = string.match(response, "(.-\r?\n)\r?\n(.*)") - local header = parse_header(headerStr) - local contentLength = tonumber(header["Content-Length"]) - local TransferEncoding = header["Transfer-Encoding"] - local status = tonumber(header["statuscode"]) - local bodyLenght = string.len(body) - local pct = 0 - - --~ if status ~= 200 then return status end - - while contentLength and bodyLenght < contentLength do - vlc.net.poll(pollfds) - response = vlc.net.recv(fd, 1024) - - if response then - body = body..response - else - vlc.net.close(fd) - return false - end - bodyLenght = string.len(body) - pct = bodyLenght / contentLength * 100 - setMessage(openSub.actionLabel..": "..progressBarContent(pct)) - end - vlc.net.close(fd) - - return status, body -end - -function parse_header(data) - local header = {} - - for name, s, val in string.gmatch(data, "([^%s:]+)(:?)%s([^\n]+)\r?\n") do - if s == "" then header['statuscode'] = tonumber(string.sub (val, 1 , 3)) - else header[name] = val end - end - return header -end - -function parse_url(url) - local url_parsed = vlc.net.url_parse(url) - return url_parsed["host"], url_parsed["path"], url_parsed["option"] -end - - --[[ XML utils]]-- - -function parse_xml(data) - local tree = {} - local stack = {} - local tmp = {} - local level = 0 - local op, tag, p, empty, val - table.insert(stack, tree) - - for op, tag, p, empty, val in string.gmatch( - data, - "[%s\r\n\t]*<(%/?)([%w:_]+)(.-)(%/?)>[%s\r\n\t]*([^<]*)[%s\r\n\t]*" - ) do - if op=="/" then - if level>0 then - level = level - 1 - table.remove(stack) - end - else - level = level + 1 - if val == "" then - if 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 - else - if type(stack[level][tag]) == "nil" then - stack[level][tag] = {} - end - stack[level][tag] = vlc.strings.resolve_xml_special_chars(val) - table.insert(stack, {}) - end - if empty ~= "" then - stack[level][tag] = "" - level = level - 1 - table.remove(stack) - end - end - end - - collectgarbage() - return tree -end - -function parse_xmlrpc(data) - local tree = {} - local stack = {} - local tmp = {} - local tmpTag = "" - local level = 0 - local op, tag, p, empty, val - table.insert(stack, tree) - - for op, tag, p, empty, val in string.gmatch( - data, - "<(%/?)([%w:]+)(.-)(%/?)>[%s\r\n\t]*([^<]*)" - ) do - if op=="/" then - if tag == "member" or tag == "array" then - if level>0 then - level = level - 1 - table.remove(stack) - end - end - elseif tag == "name" then - level = level + 1 - if val~= "" then tmpTag = vlc.strings.resolve_xml_special_chars(val) end - - if type(stack[level][tmpTag]) == "nil" then - stack[level][tmpTag] = {} - table.insert(stack, stack[level][tmpTag]) - else - tmp = nil - tmp = {} - table.insert(stack[level-1], tmp) - - stack[level] = nil - stack[level] = tmp - table.insert(stack, tmp) - end - if empty ~= "" then - level = level - 1 - stack[level][tmpTag] = "" - table.remove(stack) - end - elseif tag == "array" then - level = level + 1 - tmp = nil - tmp = {} - table.insert(stack[level], tmp) - table.insert(stack, tmp) - elseif val ~= "" then - stack[level][tmpTag] = vlc.strings.resolve_xml_special_chars(val) - end - end - collectgarbage() - return tree -end - -function dump_xml(data) - local level = 0 - local stack = {} - local dump = "" - - local function parse(data, stack) - local data_index = {} - local k - local v - local i - local tb - - for k,v in pairs(data) do - table.insert(data_index, {k, v}) - table.sort(data_index, function(a, b) - return a[1] < b[1] - end) - end - - for i,tb in pairs(data_index) do - k = tb[1] - v = tb[2] - if type(k)=="string" then - dump = dump.."\r\n"..string.rep (" ", level).."<"..k..">" - table.insert(stack, k) - level = level + 1 - elseif type(k)=="number" and k ~= 1 then - dump = dump.."\r\n"..string.rep (" ", level-1).."<"..stack[level]..">" - end - - if type(v)=="table" then - parse(v, stack) - elseif type(v)=="string" then - dump = dump..(vlc.strings.convert_xml_special_chars(v) or v) - elseif type(v)=="number" then - dump = dump..v - else - dump = dump..tostring(v) - end - - if type(k)=="string" then - if type(v)=="table" then - dump = dump.."\r\n"..string.rep (" ", level-1).."" - else - dump = dump.."" - end - table.remove(stack) - level = level - 1 - - elseif type(k)=="number" and k ~= #data then - if type(v)=="table" then - dump = dump.."\r\n"..string.rep (" ", level-1).."" - else - dump = dump.."" - end - end - end - end - parse(data, stack) - collectgarbage() - return dump -end - - --[[ Misc utils]]-- - -function make_uri(str) - str = str:gsub("\\", "/") - local windowdrive = string.match(str, "^(%a:).+$") - - local encodedPath = "" - for w in string.gmatch(str, "/([^/]+)") do - encodedPath = encodedPath.."/"..vlc.strings.encode_uri_component(w) - end - - if windowdrive then - return "file:///"..windowdrive..encodedPath - else - return "file://"..encodedPath - end -end - -function file_touch(name) -- test write ability - if not name or trim(name) == "" - then return false end - - local f=io.open(name ,"w") - if f~=nil then - io.close(f) - return true - else - return false - end -end - -function file_exist(name) -- test readability - if not name or trim(name) == "" - then return false end - local f=io.open(name ,"r") - if f~=nil then - io.close(f) - return true - else - return false - end -end - -function is_dir(path) - if not path or trim(path) == "" - then return false end - -- Remove slash at the end or it won't work on Windows - path = string.gsub(path, "^(.-)[\\/]?$", "%1") - local f, _, code = io.open(path, "rb") - - if f then - _, _, code = f:read("*a") - f:close() - if code == 21 then - return true - end - elseif code == 13 then - return true - end - - return false -end - -function list_dir(path) - if not path or trim(path) == "" - then return false end - local dir_list_cmd - local list = {} - if not is_dir(path) then return false end - - if openSub.conf.os == "win" then - dir_list_cmd = io.popen('dir /b "'..path..'"') - elseif openSub.conf.os == "lin" then - dir_list_cmd = io.popen('ls -1 "'..path..'"') - end - - if dir_list_cmd then - for filename in dir_list_cmd:lines() do - if string.match(filename, "^[^%s]+.+$") then - table.insert(list, filename) - end - end - return list - else - return false - end -end - -function mkdir_p(path) - if not path or trim(path) == "" - then return false end - if openSub.conf.os == "win" then - os.execute('mkdir "' .. path..'"') - elseif openSub.conf.os == "lin" then - os.execute("mkdir -p '" .. path.."'") - end -end - -function is_window_path(path) - return string.match(path, "^(%a:.+)$") -end - -function is_win_safe(path) - if not path or trim(path) == "" - or not is_window_path(path) - then return false end - return string.match(path, "^%a?%:?[\\%w%p%s§¤]+$") -end - -function trim(str) - if not str then return "" end - return string.gsub(str, "^[\r\n%s]*(.-)[\r\n%s]*$", "%1") -end - -function remove_tag(str) - return string.gsub(str, "{[^}]+}", "") -end - -function sleep(sec) - local t = vlc.misc.mdate() - vlc.misc.mwait(t + sec*1000*1000) -end -