diff --git a/DOCS/man/mpv.rst b/DOCS/man/mpv.rst index 7c67cf0d96d18..b4abf4e4519af 100644 --- a/DOCS/man/mpv.rst +++ b/DOCS/man/mpv.rst @@ -328,6 +328,12 @@ g-l g-d Select an audio device. +g-h + Select a file from the watch history. Requires + ``--script-opt=select-save_watch_history=yes``. The history path is + configured with ``--script-opt=select-watch_history_path=...``, and defaults + to ``~~state/watch_history.txt`` (see `PATHS`_). + g-w Select a file from watch later config files (see `RESUMING PLAYBACK`_) to resume playing. Requires ``--write-filename-in-watch-later-config``. This diff --git a/etc/input.conf b/etc/input.conf index 2faa88c233b28..8dbd42d53555f 100644 --- a/etc/input.conf +++ b/etc/input.conf @@ -187,6 +187,7 @@ #g-e script-binding select/select-edition #g-l script-binding select/select-subtitle-line #g-d script-binding select/select-audio-device +#g-h script-binding select/select-history #g-w script-binding select/select-watch-later #g-b script-binding select/select-binding #g-r script-binding select/show-properties diff --git a/player/lua/select.lua b/player/lua/select.lua index 7f20602aff098..2db92f6fb9645 100644 --- a/player/lua/select.lua +++ b/player/lua/select.lua @@ -18,6 +18,13 @@ License along with mpv. If not, see . local utils = require "mp.utils" local input = require "mp.input" +local options = { + save_watch_history = false, + watch_history_path = "~~state/watch_history.txt", +} + +require "mp.options".read_options(options) + local function show_warning(message) mp.msg.warn(message) if mp.get_property_native("vo-configured") then @@ -353,6 +360,92 @@ mp.add_key_binding(nil, "select-audio-device", function () }) end) +local history_file_path = mp.command_native({"expand-path", options.watch_history_path}) + +local function save_to_watch_history() + local history_file, error_message = io.open(history_file_path, "a") + if not history_file then + show_error("Failed to write the watch history: " .. error_message) + return + end + + local path = mp.command_native({"normalize-path", mp.get_property("path")}) + local title = mp.get_property("playlist/" .. mp.get_property("playlist-pos") .. "/title") + + history_file:write(utils.format_json({os.time(), path, title}) .. "\n") + history_file:close() +end + +if options.save_watch_history then + mp.register_event("file-loaded", save_to_watch_history) +end + +local function add_history_entry(line, items, paths, osd_playlist_entry) + local entry = utils.parse_json(line) + + if not entry then + mp.msg.warn(line .. " in " .. history_file_path .. " is not valid JSON.") + return + end + + local time, path, title = unpack(entry) + + local status, date = pcall(os.date, "(%Y-%m-%d %H:%M) ", time) + + if not status or not path then + mp.msg.warn(line .. " in " .. history_file_path .. " has invalid data.") + return + end + + local item = path + if title and osd_playlist_entry == "title" then + item = title + elseif title and osd_playlist_entry == "both" then + item = title .. " (" .. path .. ")" + end + + table.insert(items, 1, date .. item) + table.insert(paths, 1, path) +end + +mp.add_key_binding(nil, "select-history", function () + local history_file, error_message = io.open(history_file_path) + if not history_file then + show_warning(options.save_watch_history + and error_message + or "Enable --script-opt=select-save_watch_history=yes") + return + end + + local items = {} + local paths = {} + local osd_playlist_entry = mp.get_property("osd-playlist-entry") + + for line in history_file:lines() do + add_history_entry(line, items, paths, osd_playlist_entry) + end + + items[#items+1] = "Clear the history" + + input.select({ + prompt = "Select a file:", + items = items, + submit = function (i) + if paths[i] then + mp.commandv("loadfile", paths[i]) + return + end + + error_message = select(2, os.remove(history_file_path)) + if error_message then + show_error(error_message) + else + mp.osd_message("History cleared.") + end + end, + }) +end) + mp.add_key_binding(nil, "select-watch-later", function () local watch_later_dir = mp.get_property("current-watch-later-dir")