From c653be6ce9cc5e9975ec2255d13dbfcaf762b038 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Thu, 9 Jan 2025 12:01:25 +0100 Subject: [PATCH] select.lua: select from the watch history with g-h Implement selection of the entries in the watch history. --osd-playlist-entry determines whether titles and/or filenames are shown. But unlike in show-text ${playlist} and select-playlist, "file" and "both" print full paths because history is much more likely to have files from completely different directories, so showing the directory conveys where files are located. This is particularly helpful for filenames like 1.jpg. The last entry in the selector deletes the history file, as requested by Samillion. --- DOCS/man/mpv.rst | 3 ++ DOCS/man/options.rst | 3 +- etc/input.conf | 1 + player/lua/select.lua | 104 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 1 deletion(-) diff --git a/DOCS/man/mpv.rst b/DOCS/man/mpv.rst index 7c67cf0d96d18..ecb54f42abec9 100644 --- a/DOCS/man/mpv.rst +++ b/DOCS/man/mpv.rst @@ -328,6 +328,9 @@ g-l g-d Select an audio device. +g-h + Select a file from the watch history. Requires ``--save-watch-history``. + 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/DOCS/man/options.rst b/DOCS/man/options.rst index 1a172495d50ab..79f4376df559c 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -1152,7 +1152,8 @@ Watch History ------------- ``--save-watch-history`` - Whether to save which files are played. + Whether to save which files are played. These can be then selected with the + default ``g-h`` key binding. .. warning:: diff --git a/etc/input.conf b/etc/input.conf index 2faa88c233b28..adbb824a0d838 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-watch-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..3ca3853a96309 100644 --- a/player/lua/select.lua +++ b/player/lua/select.lua @@ -18,6 +18,12 @@ License along with mpv. If not, see . local utils = require "mp.utils" local input = require "mp.input" +local options = { + history_date_format = "%Y-%m-%d %H:%M:%S", +} + +require "mp.options".read_options(options, nil, function () end) + local function show_warning(message) mp.msg.warn(message) if mp.get_property_native("vo-configured") then @@ -353,6 +359,104 @@ mp.add_key_binding(nil, "select-audio-device", function () }) end) +local function get_history_entry(line, seen, error_message) + local entry = utils.parse_json(line) + + if not entry then + mp.msg.warn(error_message) + return + end + + if not entry.path then + mp.msg.warn(error_message) + return + end + + if seen[entry.path] then + return + end + + seen[entry.path] = true + + local status + status, entry.time = pcall(os.date, options.history_date_format, entry.time) + + if not status then + -- Lua 5.1 and LuaJIT return invalid formats as is, but Lua 5.2+ errors, + -- so also print the returned error message for that case. + mp.msg.warn(error_message .. " - " .. entry.time) + return + end + + return entry +end + + +local function format_history_entry(entry, osd_playlist_entry) + if entry.title and osd_playlist_entry == "title" then + return entry.title + end + + if entry.title and osd_playlist_entry == "both" then + return entry.title .. " (" .. entry.path .. ")" + end + + return entry.path +end + +mp.add_key_binding(nil, "select-watch-history", function () + local history_file_path = mp.command_native({"expand-path", + mp.get_property("watch-history-path")}) + local history_file, error_message = io.open(history_file_path) + if not history_file then + show_warning(mp.get_property_native("save-watch-history") + and error_message + or "Enable --save-watch-history") + return + end + + local lines = {} + for line in history_file:lines() do + table.insert(lines, line) + end + history_file:close() + + local entries = {} + local seen = {} + local items = {} + local osd_playlist_entry = mp.get_property("osd-playlist-entry") + + for i = #lines, 1, -1 do + error_message = history_file_path .. ": Parse error at line " .. i + local entry = get_history_entry(lines[i], seen, error_message) + if entry then + entries[#entries + 1] = entry + items[#items + 1] = "(" .. entry.time .. ") " .. + format_history_entry(entry, osd_playlist_entry) + end + end + + items[#items+1] = "Clear history" + + input.select({ + prompt = "Select a file:", + items = items, + submit = function (i) + if entries[i] then + mp.commandv("loadfile", entries[i].path) + 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")