Guest User

chapter_frame

a guest
Apr 13th, 2024
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 22.51 KB | Source Code | 0 0
  1. --[[
  2.   * chapter-make-read.lua v.2024-03-24
  3.   *
  4.   * AUTHORS: dyphire
  5.   * License: MIT
  6.   * link: https://github.com/dyphire/mpv-scripts
  7. --]]
  8.  
  9. --[[
  10. Copyright (c) 2023 dyphire <[email protected]>
  11.  
  12. Permission is hereby granted, free of charge, to any person obtaining a copy
  13. of this software and associated documentation files (the "Software"), to deal
  14. in the Software without restriction, including without limitation the rights
  15. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  16. copies of the Software, and to permit persons to whom the Software is
  17. furnished to do so, subject to the following conditions:
  18.  
  19. The above copyright notice and this permission notice shall be included in all
  20. copies or substantial portions of the Software.
  21.  
  22. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  23. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  24. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  25. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  26. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  27. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  28. SOFTWARE.
  29. --]]
  30.  
  31. -- Implementation read and automatically load the namesake external chapter file.
  32. -- The external chapter files should conform to the following formats.
  33. -- Note: The Timestamps should use the 12-bit format of 'hh:mm:ss.sss'.
  34. -- Note: The file encoding should be UTF-8 and the linebreak should be Unix(LF).
  35. -- Note: The script also supports reading OGM format and MediaInfo format in addition to the following formats.
  36. --[[
  37. 00:00:00.000 A part
  38. 00:00:40.312 OP
  39. 00:02:00.873 B part
  40. 00:10:44.269 C part
  41. 00:22:40.146 ED
  42. --]]
  43.  
  44. -- This script also supports manually load/refresh,marks,edits,remove and creates external chapter files, usage:
  45. -- Note: It can also be used to export the existing chapter information of the playback file.
  46. -- add bindings to input.conf:
  47. -- key script-message-to chapter_make_read load_chapter
  48. -- key script-message-to chapter_make_read create_chapter
  49. -- key script-message-to chapter_make_read edit_chapter
  50. -- key script-message-to chapter_make_read remove_chapter
  51. -- key script-message-to chapter_make_read write_chapter chp
  52. -- key script-message-to chapter_make_read write_chapter ogm
  53.  
  54. local msg = require 'mp.msg'
  55. local utils = require 'mp.utils'
  56. local options = require "mp.options"
  57.  
  58. local o = {
  59.     autoload = true,
  60.     autosave = false,
  61.     force_overwrite = false,
  62.     -- Specifies the extension of the external chapter file.
  63.     chapter_file_ext = ".chp",
  64.     -- Select whether the external chapter file needs to match the extension of the source file.
  65.     basename_with_ext = true,
  66.     -- Specifies the subpath of the same directory as the playback file as the external chapter file path.
  67.     -- Note: The external chapter file is read from the subdirectory first.
  68.     -- If the file does not exist, it will next be read from the same directory as the playback file.
  69.     external_chapter_subpath = "chapters",
  70.     -- save all chapter files in a single global directory
  71.     global_chapters = false,
  72.     global_chapters_dir = "~~/chapters",
  73.     -- hash works only in global_chapters_dir
  74.     hash = false,
  75.     -- ask for title or leave it empty
  76.     ask_for_title = true,
  77.     -- placeholder when asking for title of a new chapter
  78.     placeholder_title = "Chapter ",
  79.     -- pause the playback when asking for chapter title
  80.     pause_on_input = true,
  81. }
  82.  
  83. options.read_options(o)
  84.  
  85. local success, input = pcall(require, 'mp.input')
  86. if not success then
  87.     -- Requires: https://github.com/CogentRedTester/mpv-user-input
  88.     package.path = mp.command_native({"expand-path", "~~/script-modules/?.lua;"}) .. package.path
  89.     user_input_module, input = pcall(require, "user-input-module")
  90. end
  91.  
  92. local curr = nil
  93. local path = nil
  94. local dir = nil
  95. local fpath = nil
  96. local fname = nil
  97. local subpath = nil
  98. local all_chapters = {}
  99. local chapter_count = 0
  100. local insert_chapters = ""
  101. local chapters_modified = false
  102. local paused = false
  103. local protocol = false
  104.  
  105. local function is_protocol(path)
  106.     return type(path) == 'string' and (path:find('^%a[%w.+-]-://') ~= nil or path:find('^%a[%w.+-]-:%?') ~= nil)
  107. end
  108.  
  109. function str_decode(str)
  110.     local function hex_to_char(x)
  111.         return string.char(tonumber(x, 16))
  112.     end
  113.  
  114.     if str ~= nil then
  115.         str = str:gsub('^%a[%a%d-_]+://', '')
  116.         str = str:gsub('^%a[%a%d-_]+:\\?', '')
  117.         str = str:gsub('%%(%x%x)', hex_to_char)
  118.         if str:find('://localhost:?') then
  119.             str = str:gsub('^.*/', '')
  120.         end
  121.         str = str:gsub('[\\/:%?]*', '')
  122.         return str
  123.     else
  124.         return
  125.     end
  126. end
  127.  
  128. --create global_chapters_dir if it doesn't exist
  129. global_chapters_dir = mp.command_native({ "expand-path", o.global_chapters_dir })
  130. if global_chapters_dir and global_chapters_dir ~= '' then
  131.     local meta, meta_error = utils.file_info(global_chapters_dir)
  132.     if not meta or not meta.is_dir then
  133.         local is_windows = package.config:sub(1, 1) == "\\"
  134.         local windows_args = { 'powershell', '-NoProfile', '-Command', 'mkdir', string.format("\"%s\"", global_chapters_dir) }
  135.         local unix_args = { 'mkdir', '-p', global_chapters_dir }
  136.         local args = is_windows and windows_args or unix_args
  137.         local res = mp.command_native({ name = "subprocess", capture_stdout = true, playback_only = false, args = args })
  138.         if res.status ~= 0 then
  139.             msg.error("Failed to create global_chapters_dir save directory " .. global_chapters_dir ..
  140.             ". Error: " .. (res.error or "unknown"))
  141.             return
  142.         end
  143.     end
  144. end
  145.  
  146. local function read_chapter(func)
  147.     local meta, meta_error = utils.file_info(chapter_fullpath)
  148.     if not meta or not meta.is_file then return end
  149.     local f = io.open(chapter_fullpath, "r")
  150.     if not f then return end
  151.     local contents = {}
  152.     for line in f:lines() do
  153.         table.insert(contents, (func(line)))
  154.     end
  155.     f:close()
  156.     return contents
  157. end
  158.  
  159. local function read_chapter_table()
  160.     local line_pos = 0
  161.     return read_chapter(function(line)
  162.         local h, m, s, t, n, l
  163.         if line:match("^%d+:%d+:%d+") ~= nil then
  164.             h, m, s = line:match("^(%d+):(%d+):(%d+[,%.]?%d+)")
  165.             s = s:gsub(',', '.')
  166.             t = h * 3600 + m * 60 + s
  167.             if line:match("^%d+:%d+:%d+[,%.]?%d+[,%s].*") ~= nil then
  168.                 n = line:match("^%d+:%d+:%d+[,%.]?%d+[,%s](.*)")
  169.                 n = n:gsub(":%s%a?%a?:", "")
  170.                     :gsub("^%s*(.-)%s*$", "%1")
  171.             end
  172.             l = line
  173.             line_pos = line_pos + 1
  174.         elseif line:match("^CHAPTER%d+=%d+:%d+:%d+") ~= nil then
  175.             h, m, s = line:match("^CHAPTER%d+=(%d+):(%d+):(%d+[,%.]?%d+)")
  176.             s = s:gsub(',', '.')
  177.             t = h * 3600 + m * 60 + s
  178.             l = line
  179.             line_pos = line_pos + 1
  180.         elseif line:match("^CHAPTER%d+NAME=.*") ~= nil then
  181.             n = line:gsub("^CHAPTER%d+NAME=", "")
  182.             n = n:gsub("^%s*(.-)%s*$", "%1")
  183.             l = line
  184.             line_pos = line_pos + 1
  185.         else return end
  186.         return { found_title = n, found_time = t, found_line = l }
  187.     end)
  188. end
  189.  
  190. local function refresh_globals()
  191.     path = mp.get_property("path")
  192.     if path then
  193.         dir, name_ext = utils.split_path(path)
  194.         protocol = is_protocol(path)
  195.     end
  196.     if o.basename_with_ext then
  197.         fname = str_decode(mp.get_property("filename"))
  198.     else
  199.         fname = str_decode(mp.get_property("filename/no-ext"))
  200.     end
  201.     all_chapters = mp.get_property_native("chapter-list")
  202.     chapter_count = mp.get_property_number("chapter-list/count")
  203. end
  204.  
  205. local function format_time(seconds)
  206.     local result = ""
  207.     if seconds <= 0 then
  208.         return "00:00:00.000";
  209.     else
  210.         hours = string.format("%02.f", math.floor(seconds / 3600))
  211.         mins = string.format("%02.f", math.floor(seconds / 60 - (hours * 60)))
  212.         secs = string.format("%02.f", math.floor(seconds - hours * 60 * 60 - mins * 60))
  213.         msecs = string.format("%03.f", seconds * 1000 - hours * 60 * 60 * 1000 - mins * 60 * 1000 - secs * 1000)
  214.         result = hours .. ":" .. mins .. ":" .. secs .. "." .. msecs
  215.     end
  216.     return result
  217. end
  218.  
  219. -- for unix use only
  220. -- returns a table of command path and varargs, or nil if command was not found
  221. local function command_exists(command, ...)
  222.     msg.debug("looking for command:", command)
  223.     -- msg.debug("args:", )
  224.     local process = mp.command_native({
  225.         name = "subprocess",
  226.         capture_stdout = true,
  227.         capture_stderr = true,
  228.         playback_only = false,
  229.         args = {"sh", "-c", "command -v -- " .. command}
  230.     })
  231.  
  232.     if process.status == 0 then
  233.         local command_path = process.stdout:gsub("\n", "")
  234.         msg.debug("command found:", command_path)
  235.         return {command_path, ...}
  236.     else
  237.         msg.debug("command not found:", command)
  238.         return nil
  239.     end
  240. end
  241.  
  242. -- returns md5 hash of the full path of the current media file
  243. local function hash(path)
  244.     if path == nil then
  245.         msg.debug("something is wrong with the path, can't get full_path, can't hash it")
  246.         return
  247.     end
  248.  
  249.     msg.debug("hashing:", path)
  250.  
  251.     local cmd = {
  252.         name = 'subprocess',
  253.         capture_stdout = true,
  254.         playback_only = false,
  255.     }
  256.     local args = nil
  257.  
  258.     local is_unix = package.config:sub(1,1) == "/"
  259.     if is_unix then
  260.         local md5 = command_exists("md5sum") or command_exists("md5") or command_exists("openssl", "md5 | cut -d ' ' -f 2")
  261.         if md5 == nil then
  262.             msg.warn("no md5 command found, can't generate hash")
  263.             return
  264.         end
  265.         md5 = table.concat(md5, " ")
  266.         cmd["stdin_data"] = path
  267.         args = {"sh", "-c", md5 .. " | cut -d ' ' -f 1 | tr '[:lower:]' '[:upper:]'" }
  268.     else --windows
  269.         -- https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-filehash?view=powershell-7.3
  270.         local hash_command ="$s = [System.IO.MemoryStream]::new(); $w = [System.IO.StreamWriter]::new($s); $w.write(\"" .. path .. "\"); $w.Flush(); $s.Position = 0; Get-FileHash -Algorithm MD5 -InputStream $s | Select-Object -ExpandProperty Hash"
  271.         args = {"powershell", "-NoProfile", "-Command", hash_command}
  272.     end
  273.     cmd["args"] = args
  274.     msg.debug("hash cmd:", utils.to_string(cmd))
  275.     local process = mp.command_native(cmd)
  276.  
  277.     if process.status == 0 then
  278.         local hash = process.stdout:gsub("%s+", "")
  279.         msg.debug("hash:", hash)
  280.         return hash
  281.     else
  282.         msg.warn("hash function failed")
  283.         return
  284.     end
  285. end
  286.  
  287. local function get_chapter_filename(path)
  288.     name = hash(path)
  289.     if name == nil then
  290.         msg.warn("hash function failed, fallback to filename")
  291.         name = fname
  292.     end
  293.     return name
  294. end
  295.  
  296. local function mark_chapter(force_overwrite)
  297.     refresh_globals()
  298.     if not path then return end
  299.  
  300.     local chapter_index = 0
  301.     local chapters_time = {}
  302.     local chapters_title = {}
  303.     local fpath = dir
  304.     if protocol then
  305.         fpath = global_chapters_dir
  306.         fname = str_decode(mp.get_property("media-title"))
  307.         if o.hash then fname = get_chapter_filename(path) end
  308.     elseif o.external_chapter_subpath ~= '' then
  309.         fpath = utils.join_path(dir, o.external_chapter_subpath)
  310.         local meta, meta_error = utils.file_info(fpath)
  311.         if not meta or not meta.is_dir then
  312.             fpath = dir
  313.         end
  314.     end
  315.  
  316.     if o.global_chapters and global_chapters_dir and global_chapters_dir ~= '' and not protocol then
  317.         fpath = global_chapters_dir
  318.         local meta, meta_error = utils.file_info(fpath)
  319.         if meta and meta.is_dir then
  320.             if o.hash then
  321.                 fname = get_chapter_filename(path)
  322.             end
  323.         end
  324.     end
  325.  
  326.     local chapter_filename = fname .. o.chapter_file_ext
  327.     chapter_fullpath = utils.join_path(fpath, chapter_filename)
  328.     local fmeta, fmeta_error = utils.file_info(chapter_fullpath)
  329.     if (not fmeta or not fmeta.is_file) and fpath ~= dir and not protocol then
  330.         if o.basename_with_ext then
  331.             fname = str_decode(mp.get_property("filename"))
  332.         else
  333.             fname = str_decode(mp.get_property("filename/no-ext"))
  334.         end
  335.         chapter_filename = fname .. o.chapter_file_ext
  336.         chapter_fullpath = utils.join_path(dir, chapter_filename)
  337.     end
  338.     list_contents = read_chapter_table()
  339.  
  340.     if not list_contents then return end
  341.     for i = 1, #list_contents do
  342.         local chapter_time = tonumber(list_contents[i].found_time)
  343.         if chapter_time ~= nil and chapter_time >= 0 then
  344.             table.insert(chapters_time, chapter_time)
  345.         end
  346.         if list_contents[i].found_title ~= nil then
  347.             table.insert(chapters_title, list_contents[i].found_title)
  348.         end
  349.     end
  350.     if not chapters_time[1] then return end
  351.  
  352.     table.sort(chapters_time, function(a, b) return a < b end)
  353.  
  354.     if force_overwrite then all_chapters = {} end
  355.     for i = 1, #chapters_time do
  356.         chapter_index = chapter_index + 1
  357.         all_chapters[chapter_index] = {
  358.             title = chapters_title[i] or ("Chapter " .. string.format("%02.f", chapter_index)),
  359.             time = chapters_time[i]
  360.         }
  361.     end
  362.  
  363.     table.sort(all_chapters, function(a, b) return a['time'] < b['time'] end)
  364.  
  365.     mp.set_property_native("chapter-list", all_chapters)
  366.     msg.info("load external chapter file successful: " .. chapter_filename)
  367. end
  368.  
  369. local function change_title_callback(user_input, err, chapter_index)
  370.     if user_input == nil or err ~= nil then
  371.         if paused then return elseif o.pause_on_input then mp.set_property_native("pause", false) end
  372.         msg.warn("no chapter title provided:", err)
  373.         return
  374.     end
  375.  
  376.     local chapter_list = mp.get_property_native("chapter-list")
  377.  
  378.     if chapter_index > mp.get_property_number("chapter-list/count") then
  379.         msg.warn("can't set chapter title")
  380.         return
  381.     end
  382.  
  383.     chapter_list[chapter_index].title = user_input
  384.  
  385.     mp.set_property_native("chapter-list", chapter_list)
  386.     if paused then return elseif o.pause_on_input then mp.set_property_native("pause", false) end
  387.     chapters_modified = true
  388. end
  389.  
  390. local function input_title(default_input, cursor_pos, chapter_index)
  391.     input.get({
  392.         prompt = 'Chapter title:',
  393.         default_text = default_input,
  394.         cursor_position = cursor_pos,
  395.         submit = function(text)
  396.             local chapter_list = mp.get_property_native("chapter-list")
  397.  
  398.             if chapter_index > mp.get_property_number("chapter-list/count") then
  399.                 msg.warn("can't set chapter title")
  400.                 return
  401.             end
  402.  
  403.             chapter_list[chapter_index].title = text
  404.             mp.set_property_native("chapter-list", chapter_list)
  405.             input.terminate()
  406.         end,
  407.         closed = function()
  408.             if paused then return elseif o.pause_on_input then mp.set_property_native("pause", false) end
  409.         end
  410.     })
  411. end
  412.  
  413. local function input_choice(title, chapter_index)
  414.     if not input and not user_input_module then
  415.         msg.error("no mpv-user-input, can't get user input, install: https://github.com/CogentRedTester/mpv-user-input")
  416.         return
  417.     end
  418.  
  419.     if user_input_module then
  420.         -- ask user for chapter title
  421.         -- (+1 because mpv indexes from 0, lua from 1)
  422.         input.get_user_input(change_title_callback, {
  423.             request_text = "Chapter title:",
  424.             default_input = title,
  425.             cursor_pos = #title + 1,
  426.         }, chapter_index)
  427.     elseif input then
  428.         input_title(title, #title + 1, chapter_index)
  429.     end
  430. end
  431.  
  432. local function create_chapter()
  433.     refresh_globals()
  434.     if not path then return end
  435.  
  436.     local time_pos = mp.get_property_number("time-pos")
  437.     local frame_pos = mp.get_property_number("estimated-frame-number")
  438.     local frame_pos_osd = mp.get_property_osd("estimated-frame-number")
  439.     local curr_chapter = mp.get_property_number("chapter")
  440.     mp.osd_message(frame_pos_osd, 1)
  441.  
  442.     if chapter_count == 0 then
  443.         all_chapters[1] = {
  444.             title = frame_pos .. " " .. o.placeholder_title .. "01",
  445.             time = time_pos
  446.         }
  447.         -- We just set it to zero here so when we add 1 later it ends up as 1
  448.         -- otherwise it's probably "nil"
  449.         curr_chapter = 0
  450.         -- note that mpv will treat the beginning of the file as all_chapters[0] when using pageup/pagedown
  451.         -- so we don't actually have to worry if the file doesn't start with a chapter
  452.     else
  453.         -- to insert a chapter we have to increase the index on all subsequent chapters
  454.         -- otherwise we'll end up with duplicate chapter IDs which will confuse mpv
  455.         -- +2 looks weird, but remember mpv indexes at 0 and lua indexes at 1
  456.         -- adding two will turn "current chapter" from mpv notation into "next chapter" from lua's notation
  457.         -- count down because these areas of memory overlap
  458.         for i = chapter_count, curr_chapter + 2, -1 do
  459.             all_chapters[i + 1] = all_chapters[i]
  460.         end
  461.         all_chapters[curr_chapter + 2] = {
  462.             title = frame_pos .. " " .. o.placeholder_title .. string.format("%02.f", curr_chapter + 2),
  463.             time = time_pos
  464.         }
  465.     end
  466.     mp.set_property_native("chapter-list", all_chapters)
  467.     mp.set_property_number("chapter", curr_chapter + 1)
  468.     chapters_modified = true
  469.    
  470.     if o.ask_for_title then
  471.         local chapter_index = mp.get_property_number("chapter") + 1
  472.         local title = frame_pos .. " " .. o.placeholder_title .. string.format("%02.f", chapter_index)
  473.  
  474.         input_choice(title, chapter_index)
  475.  
  476.         if o.pause_on_input then
  477.             paused = mp.get_property_native("pause")
  478.             mp.set_property_bool("pause", true)
  479.             -- FIXME: for whatever reason osd gets hidden when we pause the
  480.             -- playback like that, workaround to make input prompt appear
  481.             -- right away without requiring mouse or keyboard action
  482.             mp.osd_message(" ", 0.1)
  483.         end
  484.     end
  485. end
  486.  
  487. local function edit_chapter()
  488.     local chapter_index = mp.get_property_number("chapter") + 1
  489.     local chapter_list = mp.get_property_native("chapter-list")
  490.     local title = chapter_list[chapter_index].title
  491.     if chapter_index == nil or chapter_index == -1 then
  492.         msg.verbose("no chapter selected, nothing to edit")
  493.         return
  494.     end
  495.  
  496.     input_choice(title, chapter_index)
  497.  
  498.     if o.pause_on_input then
  499.         paused = mp.get_property_native("pause")
  500.         mp.set_property_bool("pause", true)
  501.         -- FIXME: for whatever reason osd gets hidden when we pause the
  502.         -- playback like that, workaround to make input prompt appear
  503.         -- right away without requiring mouse or keyboard action
  504.         mp.osd_message(" ", 0.1)
  505.     end
  506. end
  507.  
  508. local function remove_chapter()
  509.     local chapter_count = mp.get_property_number("chapter-list/count")
  510.  
  511.     if chapter_count < 1 then
  512.         msg.verbose("no chapters to remove")
  513.         return
  514.     end
  515.  
  516.     local chapter_list = mp.get_property_native("chapter-list")
  517.     -- +1 because mpv indexes from 0, lua from 1
  518.     local current_chapter = mp.get_property_number("chapter") + 1
  519.  
  520.     table.remove(chapter_list, current_chapter)
  521.     msg.debug("removing chapter", current_chapter)
  522.  
  523.     mp.set_property_native("chapter-list", chapter_list)
  524.     chapters_modified = true
  525. end
  526.  
  527. local function write_chapter(format, force_write)
  528.     refresh_globals()
  529.     if not force_write and (chapter_count == 0 or not chapters_modified) or not path then
  530.         msg.debug("nothing to write")
  531.         return
  532.     end
  533.  
  534.     if o.global_chapters then dir = global_chapters_dir end
  535.     if o.hash and o.global_chapters then fname = get_chapter_filename(path) end
  536.     local out_path = utils.join_path(dir, fname .. o.chapter_file_ext)
  537.     local next_chapter = nil
  538.     for i = 1, chapter_count, 1 do
  539.         curr = all_chapters[i]
  540.         local time_pos = format_time(curr.time)
  541.         if format == "ogm" then
  542.             next_chapter = "CHAPTER" .. string.format("%02.f", i) .. "=" .. string.sub(curr.title, 1, string.find(curr.title, " ") - 1) .. "\n" ..
  543.                            "CHAPTER" .. string.format("%02.f", i) .. "NAME=" .. string.sub(curr.title, string.find(curr.title, " ") + 1) .. "\n"
  544.         elseif format == "chp" then
  545.             next_chapter = curr.title .. "\n"
  546.         else
  547.             msg.warn("please specify the correct chapter format: chp/ogm.")
  548.             return
  549.         end
  550.         if i == 1 and (o.global_chapters or protocol) then
  551.             insert_chapters = "# " .. path .. "\n\n" .. next_chapter
  552.         else
  553.             insert_chapters = insert_chapters .. next_chapter
  554.         end
  555.     end
  556.  
  557.     local chapters = insert_chapters
  558.  
  559.     local file = io.open(out_path, "w")
  560.     if file == nil then
  561.         dir = global_chapters_dir
  562.         fname = str_decode(mp.get_property("media-title"))
  563.         if o.hash then fname = get_chapter_filename(path) end
  564.         out_path = utils.join_path(dir, fname .. o.chapter_file_ext)
  565.         file = io.open(out_path, "w")
  566.     end
  567.     if file == nil then
  568.         mp.error("Could not open chapter file for writing.")
  569.         return
  570.     end
  571.     file:write(chapters)
  572.     file:close()
  573.     if not force_write then
  574.         mp.osd_message("Export chapter file to: " .. out_path, 3)
  575.         msg.info("Export chapter file to: " .. out_path)
  576.     else
  577.         msg.info("Auto save chapter file to: " .. out_path)
  578.     end
  579. end
  580.  
  581. -- HOOKS -----------------------------------------------------------------------
  582.  
  583. if o.autoload then
  584.     mp.add_hook("on_preloaded", 50, function()
  585.         if o.force_overwrite then
  586.             mark_chapter(true)
  587.         else
  588.             mark_chapter(false)
  589.         end
  590.     end)
  591. end
  592.  
  593. if o.autosave then
  594.     mp.add_hook("on_unload", 50, function() write_chapter("chp", true) end)
  595. end
  596.  
  597. if user_input_module then
  598.     mp.add_hook("on_unload", 50, function() input.cancel_user_input() end)
  599. end
  600.  
  601. mp.register_script_message("load_chapter", function() mark_chapter(true) end)
  602. mp.register_script_message("create_chapter", create_chapter, { repeatable = true })
  603. mp.register_script_message("remove_chapter", remove_chapter)
  604. mp.register_script_message("edit_chapter", edit_chapter)
  605. mp.register_script_message("write_chapter", function(value, value2)
  606.     write_chapter(value, value2)
  607. end)
  608.  
Advertisement
Add Comment
Please, Sign In to add comment