diff --git a/locale/spa.xml b/locale/spa.xml index f261fbc..2152908 100644 --- a/locale/spa.xml +++ b/locale/spa.xml @@ -1,53 +1,71 @@ Calculando el hash del video -Entrar -Salir -Comprobando sesion -Buscando subtitulos +Iniciar sesión +Cerrar sesión +Comprobando sesión +Buscando subtítulos Todos +No + Cancelar Cerrar -Configuracion -Configuracion -Lenguaje de subtitulos -Descargando subtitulos de OpenSubtitles.org -Mostrar el codigo del lenguaje en nombre del fichero -Que hacer con los subtitulos -Solo cargar +Configurar +Configuración +Idioma de los subtítulos +Descargar subtítulos de OpenSubtitles.org +Incluir el código del idioma en el nombre del archivo +¿Qué hacer con los subtitulos? +Sólo cargar Descarga manual Cargar y guardar Descargar seleccionados -Capitulo (serie) +Capítulo (serie) Ayuda - Descargar subtitulos de <a href='http://www.opensubtitles.org/'>opensubtitles.org</a> y mostrarlos durante la reproduccion del video.<br> <br> <b><u>Uso:</u></b><br> <br> VLSub se va a usar durante la reproduccion de video, asi que inicialo primero (si nada no esta en reproduccion, obtenga el enlace para descargar los subtitulos con navegador).<br> <br> Selecciona el lenguaje de los subtitulos y haga click en el boton correspondiente en uno de los dos metodos de busqueda proporcionados por VLSub:<br> <br> <b>Metodo 1:Buscar por hash</b><br>Es recomendable probar por el primer metodo, porque la busqueda esta basada en el reconocimiendo por el fichero del video, asi que puede encontrar los subtitulos sincronizados con tu video.<br> <br> <b>Metodo 2: Buscar por el nombre</b><br> Si no ha tenido suerte con el primer metodo, comprueba si el titulo es correcto antes de dar click al boton, puede proporcionar el numero de la temporada y el numero del capitulo.<br> <br> <b>Descargando Subtitulos</b><br>Seleccione uno de los subtitulos en la lista y haga click en "Descargar".<br> Se descargara al mismo directorio donde esta el video, con el mismo nombre(diferente extension) asi que Vlc los cargara automaticamente cuando reproduzca el video de nuevo.<br> <br> <b>/!\ Cuidado :</b> Los subtitulos existentes seran sobreescribidos sin preguntar la confirmacion, asi que haz una copia si los necesitas.<br> <br> Encuentra mas extensiones para Vlc en la pagina <a href='http://addons.videolan.org'>addons.videolan.org</a>. -Lenguaje del interfaz + Descarga los subtítulos de <a href='http://www.opensubtitles.org/'>opensubtitles.org</a> y los añade automáticamente mientras reproduces un video.<br> <br> <b><u>Uso:</u></b><br> <br> VLSub está pensado para utilizarse mientras reproduces un video, así que comienza por reproducir tu video (si ningún video se encuentra en reproducción vas a obtener un enlace para descargar los subtítulos con tu navegador).<br> <br> Selecciona el idioma de los subtítulos y haz clic en el botón correspondiente a uno de los dos métodos de búsqueda proporcionados por VLSub:<br> <br> <b>Método 1: Buscar por hash</b><br> Se recomienda probar primero con este método porque la búsqueda se basa en información propia del archivo de video, así que encontrarás subtítulos especialmente sincronizados con tu video.<br> <br> <b> Método 2: Buscar por nombre</b><br> Si no tuviste suerte con el primer método puedes buscar por nombre. Asegurate de comprobar que el título sea el correcto antes de hacer clic para buscar. Si estás buscando subtítulos para una serie también puedes indicar la temporada y el número de capítulo.<br> <br> <b>Descargar subtítulos</b><br>Selecciona uno de los subtítulos en la lista y haz clic en "Descargar seleccionados". Se descargará en el mismo directorio donde se ubica tu video y con el mismo nombre (pero diferente extensión) para que VLC lo cargue automáticamente cuando reproduzcas el video de nuevo.<br> <br> <b>/!\ Cuidado :</b> Los subtítulos pre existentes serán sobrescritos sin solicitar confirmación alguna, así que guarda una copia en cualquier otro directorio si deseas conservarlos.<br> <br> Encuentra más extensiones para VLC en el sitio <a href='http://addons.videolan.org'>addons.videolan.org</a>. +Idioma de la interfaz +<strong>VLSub no está funcionando en VLC 2.1.x en ninguna plataforma</strong> + dado que el módulo lua "net" necesario para interactuar con opensubtitles ha sido removido para las extensiones en esta versión de VLC. + <br> + <strong>Funciona en VLC Vlc 2.2 para Mac y Linux.</strong> + <br> + <strong>En Windows tienes que instalar una versión más antigua de VLC (2.0.8 por ejemplo)</strong> + para poder usar VLSub: + <br> + <a target="_blank" rel="nofollow" + href="http://download.videolan.org/pub/videolan/vlc/2.0.8/"> + http://download.videolan.org/pub/videolan/vlc/2.0.8/</a><br> Ok -Quitar tag -Rebuscar +Contraseña +Nombre de usuario +Quitar etiquetas +Buscar Guardar Buscar por hash -Buscando traduccion... -Buscando por nombre -Buscando traduccion +Buscando traducciones... +Buscar por nombre +Buscar traducciones Temporada (serie) -Mostrar fichero de configuracion +Mostrar configuración Mostrar ayuda -Titulo -Haga click aqui para abrir -Rebusqueda acabada -Descargar enlace -Descargar subtitulos -Fallo -Sesion expirada, probando de nuevo -Subtitulos cargados -Por favor usa este metodo durante la reproduccion -Ningun resultado +Título +Directorio de trabajo de VLSub +Haga clic aquí para abrir el archivo +Búsqueda finalizada +Enlace de descarga +Descargando subtítulo +No se puede encontrar una ruta adecuada para guardar la configuración, por favor indicala manulmente +Error +la ruta contiene caracteres ilegales, por favor corrijela antes de continuar +Expiró la sesión, probando de nuevo +Subtítulos cargados +Por favor usa este método durante la reproducción +Sin resultados El servidor no responde -Subtitulos no elegidos -Fichero no encontrado -Fichero no encontrado (caracter ilegal?) -Este metodo funciona solo con el fichero local (de momento) -Servidor sobrecargado, por favor prueba mas tarde -Resultado(s) -Imposible guardar los subtitulos -Correcto -Peticion no autorizada +Ningún subtítulo fue seleccionado +Archivo no encontrado +Archivo no encontrado (¿caracter ilegal?) +Este método sólo funciona con un archivo local (por el momento) +Servidor sobrecargado, por favor prueba más tarde +resultado(s) +Falla al guardar los subtítulos +Éxito +Petición no autorizada diff --git a/vlsub.lua b/vlsub.lua index 8f7c411..e1cf21b 100644 --- a/vlsub.lua +++ b/vlsub.lua @@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. --]] - --[[ Global var ]]-- + --[[ Global var ]]-- -- You can set here your default language by replacing nil with -- your language code (see below).Example: @@ -32,65 +32,68 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. -- 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', + language = nil, + downloadBehaviour = 'save', + langExt = false, + isoLangExt = true, -- iso (ned, eng) file extensions instead of two letter (nl, en) extensions + 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', + fre = 'Français', + ell = 'Greek', + baq = 'Basque', + pob = 'Brazilian Portuguese', por = 'Portuguese (Portugal)', - rum = 'Romanian', - slo = 'Slovak', - spa = 'Spanish', - swe = 'Swedish', + 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', + }, + 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_display_iso_code = 'Use ISO 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 @@ -149,175 +152,177 @@ local options = { href="http://download.videolan.org/pub/videolan/vlc/2.0.8/"> http://download.videolan.org/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', + + 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_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'} + {'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" + 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 language_to_ext_map = {} + local dlg = nil local input_table = {} -- General widget id reference local select_conf = {} -- Drop down widget / option table association @@ -325,31 +330,35 @@ local select_conf = {} -- Drop down widget / option table association --[[ VLC extension stuff ]]-- function descriptor() - return { + return { title = "VLsub 0.9.13", version = "0.9.13", - author = "exebetche", - url = 'http://www.opensubtitles.org/', - shortdesc = "VLsub"; - description = options.translation.int_descr, - capabilities = {"menu", "input-listener" } - } + 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") - + vlc.msg.dbg("[VLsub] Welcome") + + for k,v in pairs (lang_os_to_iso) do + language_to_ext_map[v] = k + end + 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() + + if vlc.input.item() then + openSub.getFileInfo() + openSub.getMovieInfo() + end + + show_main() end function close() @@ -357,56 +366,56 @@ function close() 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.msg.dbg("[VLsub] Bye bye!") + if dlg then + dlg:hide() + end + + if openSub.session.token and openSub.session.token ~= "" then + openSub.request("LogOut") + end end function menu() - return { - lang.int_research, - lang.int_config, - lang.int_help - } + return { + lang.int_research, + lang.int_config, + lang.int_help + } end function meta_changed() - return false + return false end function input_changed() - collectgarbage() - set_interface_main() - collectgarbage() + collectgarbage() + set_interface_main() + collectgarbage() end - --[[ Interface data ]]-- + --[[ 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_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) + + 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) + 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) + 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) + 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( @@ -415,7 +424,7 @@ function interface_main() 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', @@ -423,16 +432,16 @@ function interface_main() 2, lang["int_all"]) - display_subtitles() + 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() - + -- 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( @@ -460,55 +469,65 @@ function interface_config() 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_display_iso_code"]..':', 1, 6, 0, 1) + input_table['isoLangExt'] = dlg:add_dropdown(3, 6, 1, 1) + + -- VLSub working dir + if openSub.conf.dirPath then + if openSub.conf.os == "win" then dlg:add_label( "".. - lang["int_vlsub_work_dir"].."", 1, 6, 2, 1) - else + lang["int_vlsub_work_dir"].."", 1, 7, 2, 1) + else dlg:add_label( "".. - lang["int_vlsub_work_dir"].."", 1, 6, 2, 1) - end - else + lang["int_vlsub_work_dir"].."", 1, 7, 2, 1) + end + else dlg :add_label( - lang["int_vlsub_work_dir"], 1, 6, 2, 1) - end - + lang["int_vlsub_work_dir"], 1, 7, 2, 1) + end + input_table['dir_path'] = dlg:add_text_input( - openSub.conf.dirPath, 2, 6, 2, 1) - + openSub.conf.dirPath, 2, 7, 2, 1) + dlg:add_label( - lang["int_os_username"]..':', 1, 7, 0, 1) + lang["int_os_username"]..':', 1, 8, 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) + and openSub.option.os_username or "", 2, 8, 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) + lang["int_os_password"]..':', 1, 9, 0, 1) - input_table['message'] = nil - input_table['message'] = dlg:add_label(' ', 1, 9, 3, 1) - + -- Password + dlg:add_label(lang["int_os_password"]..':', 1, 1, 0, 1) + input_table['os_password'] = dlg:add_text_input(type(openSub.option.os_password) == "string" and openSub.option.os_password or "", 2, 9, 2, 1) + + -- Message + input_table['message'] = nil + input_table['message'] = dlg:add_label(' ', 1, 10, 3, 1) + dlg:add_button( lang["int_cancel"], - show_main, 2, 10, 1, 1) + show_main, 2, 11, 1, 1) dlg:add_button( lang["int_save"], - apply_config, 3, 10, 1, 1) - + apply_config, 3, 11, 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) + + -- ... iso language extension + input_table['isoLangExt']:add_value(lang["int_bool_"..tostring(openSub.option.isoLangExt)], 1) + input_table['isoLangExt']:add_value(lang["int_bool_"..tostring(not openSub.option.isoLangExt)], 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', @@ -528,8 +547,8 @@ function interface_config() end function interface_help() - local help_html = lang["int_help_mess"] - + local help_html = lang["int_help_mess"] + input_table['help'] = dlg:add_html( help_html, 1, 1, 4, 1) dlg:add_label( @@ -548,52 +567,52 @@ function interface_no_support() end function trigger_menu(dlg_id) - if dlg_id == 1 then - close_dlg() + if dlg_id == 1 then + close_dlg() dlg = vlc.dialog( openSub.conf.useragent) - interface_main() - elseif dlg_id == 2 then - close_dlg() + 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() + interface_config() + elseif dlg_id == 3 then + close_dlg() dlg = vlc.dialog( openSub.conf.useragent..': '..lang["int_help"]) - interface_help() - end - collectgarbage() --~ !important + interface_help() + end + collectgarbage() --~ !important end function show_main() - trigger_menu(1) + trigger_menu(1) end function show_conf() - trigger_menu(2) + trigger_menu(2) end function show_help() - trigger_menu(3) + 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 + 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]]-- + --[[ 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 @@ -603,188 +622,188 @@ function assoc_select_conf(select_id, option, conf, ind, default) dflt = default, ind = ind } - set_default_option(select_id) - display_select(select_id) + 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 + 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 + 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]]-- + --[[ 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 = {} - + -- 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 + 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 + 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 + 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 + 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 + 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 - + 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 + -- 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 + if file_list then + for i, file_name in ipairs(file_list) do local lg = string.gsub( file_name, "^(%w%w%w).xml$", @@ -795,31 +814,31 @@ function check_config() lg, trsl_names[lg] }) - end - end - end - - -- Load selected translation from file - if openSub.option.intLang ~= "eng" - and not openSub.conf.translated - then + 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 + 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 + 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 + end + + lang = nil lang = options.translation -- just a short cut - + if not vlc.net or not vlc.net.poll then dlg = vlc.dialog( openSub.conf.useragent..': '..lang["mess_error"]) @@ -828,184 +847,188 @@ function check_config() return false end - SetDownloadBehaviours() - if not openSub.conf.dirPath then - setError(lang["mess_err_conf_access"]) - 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() + -- 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() + 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() + 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 + 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 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 + 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 + local lg_sel = input_table['intLang']:get_value() + local sel_val + local opt local sel_cf - - 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 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() + sel_val = input_table[select_id]:get_value() sel_cf = select_conf[select_id] opt = sel_cf.opt - - if sel_val == 0 then - openSub.option[opt] = nil - else + + if sel_val == 0 then + openSub.option[opt] = nil + else openSub.option[opt] = sel_cf.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 = {} - + 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["isoLangExt"]:get_value() == 2 then + openSub.option.isoLangExt = not openSub.option.isoLangExt + 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 - + 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 + 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 + else + dir_path_err = true setError(lang["mess_err_wrong_path"].. "
".. string.gsub( @@ -1014,56 +1037,56 @@ function apply_config() "%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 + 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 + 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 + + 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 + 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 + setError(lang["mess_err_conf_access"]) + return false + end end function SetDownloadBehaviours() - openSub.conf.downloadBehaviours = nil - openSub.conf.downloadBehaviours = { - {'save', lang["int_dowload_save"]}, - {'manual', lang["int_dowload_manual"]} - } + openSub.conf.downloadBehaviours = nil + openSub.conf.downloadBehaviours = { + {'save', lang["int_dowload_save"]}, + {'manual', lang["int_dowload_manual"]} + } end function get_available_translations() @@ -1071,20 +1094,20 @@ function get_available_translations() -- (drop previous direct download from github repo -- causing error 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) + openSub.actionLabel = lang["int_searching_transl"] + + local translations_content, lol = get(translations_url) local translations_avail = openSub.option.translations_avail - all_trsl = parse_xml(translations_content) - local lg, trsl - - for lg, trsl in pairs(all_trsl) do + all_trsl = parse_xml(translations_content) + local lg, trsl + + for lg, trsl in pairs(all_trsl) do if lg ~= options.intLang[1] and not translations_avail[lg] then translations_avail[lg] = trsl_names[lg] or "" @@ -1095,782 +1118,791 @@ function get_available_translations() input_table['intLang']:add_value( trsl_names[lg], #openSub.conf.translations_avail) - end - end - - setMessage(success_tag(lang["mess_complete"])) - collectgarbage() - end + 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 + 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() + 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 ]]-- + --[[ 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 + 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 + 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"] + 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={ + + 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={ + { 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"] + } + 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 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 + if archive_path and archive_path ~= "" then file.path = string.gsub( archive_path, '\063', '%%') - file.path = vlc.strings.decode_uri(file.path) + 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.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 - + + 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 + + if file.ext == "part" then file.name, file.ext = string.match( file.name, '^([^/]+)%.([^%.]+)$') - end - - file.hasInput = true; + 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 - + 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 + 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"] + 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) + + 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 - 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 + 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 + 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.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 + 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) + 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 + 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 end function get_first_sel(list) - local selection = list:get_selection() - for index, name in pairs(selection) do - return index - end - return 0 + 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"] - - local item = openSub.itemStore[index] - + 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"] + + local item = openSub.itemStore[index] + if openSub.option.downloadBehaviour == 'manual' or not openSub.file.hasInput then - local link = "" - link = link..""..lang["mess_dowload_link"]..":" - link = link.."  " + local link = "" + link = link..""..lang["mess_dowload_link"]..":" + link = link.."  " link = link.."  " - link = link..item.MovieReleaseName.."" - - setMessage(link) - return false - end - - local message = "" + link = link..item.MovieReleaseName.."" + + setMessage(link) + return false + end + + local message = "" local subfileName = openSub.file.name or "" - - 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 - + + if openSub.option.langExt then + if openSub.option.isoLangExt then + subfileName = subfileName.."."..item.SubLanguageID + else + local subLangId = item.SubLanguageID + if type(language_to_ext_map[subLangId]) then + subLangId = language_to_ext_map[subLangId] + end + + subfileName = subfileName.."."..subLangId + end + 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 + "".. + 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 - - -- load subtitles + 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 + + -- load subtitles if add_sub(target) then - message = success_tag(lang["mess_loaded"]) .. message + message = success_tag(lang["mess_loaded"]) .. message else message = error_tag(lang["mess_not_load"]) .. message - end - - setMessage(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 - + -- 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() + 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(subPath) - if vlc.item or vlc.input.item() then + if vlc.item or vlc.input.item() then subPath = decode_uri(subPath) vlc.msg.dbg("[VLsub] Adding subtitle :" .. subPath) return vlc.input.add_subtitle(subPath) - end - return false + end + return false end - --[[ Interface helpers]]-- + --[[ 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 + 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 + if input_table["message"] then + input_table["message"]:set_text(str) + dlg:update() + end end function setError(mess) - setMessage(error_tag(mess)) + setMessage(error_tag(mess)) end function success_tag(str) - return "".. - lang["mess_success"]..": "..str.."" + return "".. + lang["mess_success"]..": "..str.."" end function error_tag(str) - return "".. - lang["mess_error"]..": "..str.."" + return "".. + lang["mess_error"]..": "..str.."" end - --[[ Network utils]]-- + --[[ 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 + 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 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 chunk = vlc.net.recv(fd, 2048) local response = "" local headerStr, header, body local contentLength, status - local pct = 0 - + local pct = 0 + while chunk do response = response..chunk if not header then @@ -1885,19 +1917,19 @@ function http_req(host, port, request) if contentLength then bodyLenght = #response - pct = bodyLenght / contentLength * 100 - setMessage(openSub.actionLabel..": "..progressBarContent(pct)) + pct = bodyLenght / contentLength * 100 + setMessage(openSub.actionLabel..": "..progressBarContent(pct)) if bodyLenght >= contentLength then break - end + end end vlc.net.poll(pollfds) chunk = vlc.net.recv(fd, 1024) end - vlc.net.close(fd) - + vlc.net.close(fd) + if status == 301 and header["Location"] then local host, path = parse_url(trim(header["Location"])) @@ -1912,8 +1944,8 @@ function http_req(host, port, request) end function parse_header(data) - local header = {} - + local header = {} + for name, s, val in string.gmatch( data, "([^%s:]+)(:?)%s([^\n]+)\r?\n") @@ -1922,305 +1954,305 @@ function parse_header(data) header['statuscode'] = tonumber(string.sub(val, 1 , 3)) else header[name] = val - end + end end - return header + return header end function parse_url(url) - local url_parsed = vlc.net.url_parse(url) + local url_parsed = vlc.net.url_parse(url) return url_parsed["host"], url_parsed["path"], url_parsed["option"] end - --[[ XML utils]]-- + --[[ 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) + local tree = {} + local stack = {} + local tmp = {} + local level = 0 + local op, tag, p, empty, val + table.insert(stack, tree) local resolve_xml = vlc.strings.resolve_xml_special_chars - for op, tag, p, empty, val in string.gmatch( - data, + 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 + ) 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] = resolve_xml(val) - table.insert(stack, {}) - end - if empty ~= "" then - stack[level][tag] = "" - level = level - 1 - table.remove(stack) - end - end - end - - collectgarbage() - return tree + 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 + local tree = {} + local stack = {} + local tmp = {} + local tmpTag = "" + local level = 0 + local op, tag, p, empty, val local resolve_xml = vlc.strings.resolve_xml_special_chars - 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 + 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 = resolve_xml(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 + + 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] = resolve_xml(val) - end - end - collectgarbage() - return tree + end + end + collectgarbage() + return tree end function dump_xml(data) - local level = 0 - local stack = {} - local dump = "" + local level = 0 + local stack = {} + local dump = "" local convert_xml = vlc.strings.convert_xml_special_chars - - 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 + + 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 + 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 + end + + if type(v)=="table" then + parse(v, stack) + elseif type(v)=="string" then dump = dump..(convert_xml(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 + 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 + 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 + else + dump = dump.."" + end + end + end + end + parse(data, stack) + collectgarbage() + return dump end - --[[ Misc utils]]-- + --[[ Misc utils]]-- function make_uri(str) str = str:gsub("\\", "/") local windowdrive = string.match(str, "^(%a:).+$") local encode_uri = vlc.strings.encode_uri_component - local encodedPath = "" - for w in string.gmatch(str, "/([^/]+)") do + local encodedPath = "" + for w in string.gmatch(str, "/([^/]+)") do encodedPath = encodedPath.."/"..encode_uri(w) - end + end - if windowdrive then + if windowdrive then return "file:///"..windowdrive..encodedPath - else + else return "file://"..encodedPath - end + 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 + 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 + 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 + 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 + 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 + 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 + 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 decode_uri(str) @@ -2233,17 +2265,17 @@ function is_window_path(path) 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§¤]+$") + 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") + 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, "{[^}]+}", "") + return string.gsub(str, "{[^}]+}", "") end