local M = {} local mkutils = require "mkutils" local task_template = [[ ${lang} ${file_desc} ${file_id} ${prefix}${html_file} ${text_type} ${prefix}${audio_file} ${id_sort} ${id_regex} ${sub_file} ${sub_format} ${html_file} ${audio_file} ]] -- get html files local function get_html_files(config) local config = config or {} local files = {} local filematch = config.file_match or "html$" -- this is a trick to get list of files from the LG file for _, file in ipairs(Make.lgfile.files) do if file:match(filematch) then table.insert(files, file) end end return files end -- prepare filename for the audio local function get_audio_file(filename, config) local extension = config.audio_extension or "mp3" local base = mkutils.remove_extension(filename) return base .. "." .. extension end local function get_sub_file(filename, config) local extension = config.sub_format or "smil" local base = mkutils.remove_extension(filename) return base .. "." .. extension end -- create task record for each HTML file local function prepare_tasks(files, configuration) local tasks = {} -- the map can contain info for particular files, otherwise we will interfere default values local map = configuration.map or {} -- task_template should be configurable local task_template = configuration.task_template or task_template for i, filename in ipairs(files) do local filemap = map[filename] if filemap ~= false then filemap = filemap or {} local taskconfig = configuration taskconfig.html_file = filename taskconfig.prefix = filemap.prefix or configuration.prefix taskconfig.file_desc = filemap.description or configuration.description .. " " .. i taskconfig.file_id = filemap.id or filename:gsub("[%/%.]", "_") taskconfig.text_type = filemap.text_type or configuration.text_type taskconfig.audio_file = filemap.audio_file or get_audio_file(filename, configuration) taskconfig.sub_file = filemap.sub_file or get_sub_file(filename, configuration) taskconfig.id_sort= filemap.id_sort or configuration.id_sort taskconfig.id_prefix = filemap.id_regex or configuration.id_regex taskconfig.sub_format = filemap.sub_format or configuration.sub_format tasks[#tasks+1] = task_template % taskconfig Make:add_file(taskconfig.audio_file) Make:add_file(taskconfig.sub_file) end end return tasks --table.concat(tasks, "\n") end -- from https://www.readbeyond.it/aeneas/docs/clitutorial.html#xml-config-file-config-xml local config_template = [[ ${lang} ${description} ${tasks} output_example4 zip flat ${prefix} ]] -- check if the config file exists local function is_config(filename) return mkutils.file_exists(filename) end -- prepare Aeneas configuration local function prepare_configuration(parameters) local config = parameters or {} config.lang = parameters.lang config.tasks = table.concat(prepare_tasks(parameters.files, config), "\n") return config end -- write Aeneeas configuration file in the XML format local function write_config(filename, configuration) local cfg = config_template % configuration print(cfg) local f = io.open(filename, "w") f:write(cfg) f:close() end local function make_default_options(options) local configuration = {} local par = get_filter_settings "aeneas-config" configuration.lang = options.lang or par.lang or "en" configuration.description = options.description or par.description or "Aeneas job" configuration.map = options.map or par.map or {} configuration.text_type = options.text_type or par.text_type or "unparsed" configuration.id_sort = options.id_sort or par.id_sort or "numeric" configuration.id_regex = options.id_regex or par.id_regex or par.id_prefix .. "[0-9]+" configuration.sub_format = options.sub_format or par.sub_format or "smil" configuration.prefix = options.prefix or par.prefix or "./" configuration.config_name = options.config_name or par.config_name or "config.xml" configuration.keep_config = options.keep_config or par.keep_config return configuration end local function configure_job(options) local configuration = make_default_options(options) local config_name = configuration.config_name -- prepare the configuration in every case configuration.files = get_html_files() local configuration = prepare_configuration(configuration) -- write the configuration only if the config file doesn't exist -- and keep_config option is set to true if is_config(config_name) and configuration.keep_config==true then else write_config(config_name, configuration) end end local function execute_job(options) local par = get_filter_settings "aeneas-config" local configuration = make_default_options(options) configuration.files = get_html_files() -- we need to configure prepare_tasks to return calls to aeneas task convertor configuration.python = options.python or par.python or "python3" configuration.module = options.module or par.module or "aeneas.tools.execute_task" configuration.task_template = '${python} -m "${module}" "${audio_file}" "${html_file}" "is_text_type=${text_type}|os_task_file_smil_audio_ref=${audio_file}|os_task_file_smil_page_ref=${html_file}|task_language=${lang}|is_text_unparsed_id_sort=${id_sort}|is_text_unparsed_id_regex=${id_regex}|os_task_file_format=${sub_format}" "${sub_file}"' local tasks = prepare_tasks(configuration.files, configuration) -- execute the tasks for _, v in ipairs(tasks) do print("task", v) local proc = io.popen(v, "r") local result = proc:read("*all") proc:close() print(result) end end -- the aeneas configuration must be executed at last processed file, after all filters -- have been executed local function get_last_lg_file() local t = Make.lgfile.files for i = #t, 1, -1 do -- find last html file or the tmp file local x = t[i] if x:match "html$" or x:match "tmp$" then return x end end return t[#t] end -- write Aeneas job configuration file -- it doesn't execute Aeneas function M.write_job(par) -- configuration table for Aeneas job Make:match("tmp$", function() configure_job(par) end) end -- execute Aeneas directly function M.execute(par) Make:match("tmp$", function(current_name) -- there may be html files after the .tmp file -- the aeneas must be executed after the Aeneas filter inserts the id -- attributes, so it is necessary to execute this code as very last one local last = get_last_lg_file() -- execute the job if there are no HTML files after the tmp file if current_name == last then execute_job(par) end Make:match(last, function() execute_job(par) end) end) end -- only register the audio and smil files as processed files function M.process_files(par) Make:match("tmp$", function() local configuration = make_default_options(par) local files = get_html_files() prepare_tasks(files, configuration) end) end return M