Skip to content

Commit

Permalink
select.lua: select from the watch history with g-h
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
guidocella committed Jan 7, 2025
1 parent 827ebf0 commit a9b847a
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 1 deletion.
3 changes: 3 additions & 0 deletions DOCS/man/mpv.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 7 additions & 1 deletion DOCS/man/options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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::

Expand All @@ -1163,6 +1164,11 @@ Watch History
The path in which to store the watch history. Default:
``~~state/watch_history.jsonl`` (see `PATHS`_).

This file contains one JSON array per line. The first field is the UNIX
timestamp when the file was opened, the second field is its normalized path,
and the third file is its title, or missing if no title was present. Any new
fields will be appended after the last one.

Video
-----

Expand Down
1 change: 1 addition & 0 deletions etc/input.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
100 changes: 100 additions & 0 deletions player/lua/select.lua
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,106 @@ 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

local time, path, title = unpack(entry)

if not path then
mp.msg.warn(error_message)
return
end

if seen[path] then
return
end

seen[path] = true

local status, date = pcall(os.date, "(%Y-%m-%d %H:%M) ", time)

if not status then
mp.msg.warn(error_message)
return
end

return {
date = date,
path = path,
title = title,
}
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.date .. 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")

Expand Down

0 comments on commit a9b847a

Please sign in to comment.