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 0000000..3e8c249 Binary files /dev/null and b/files/vlc/.local/share/vlc/lua/extensions/VLSub.luac differ 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 -