1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
-- public domain
-- http://git.smrk.net/mpv-scripts/file/history.lua.html
-- Corrections and productive feedback appreciated, publicly
-- (<public@smrk.net>, inbox.smrk.net) or in private.
local mpu = require("mp.utils")
local sqlite3 = require("lsqlite3")
local history_db_path = mpu.join_path(os.getenv("XDG_DATA_HOME"), "history/mpv.sqlite")
local db = nil
local last_insert_id = nil
local function opendb()
local d, errcode, errmsg = sqlite3.open(history_db_path)
if not d then
error(("Failed to open %s: %d (%s)"):format(history_db_path, errcode, errmsg))
end
db = d
local sql = [=[
CREATE TABLE IF NOT EXISTS loaded_items(
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
path TEXT NOT NULL,
filename TEXT NOT NULL,
title TEXT NOT NULL,
time_pos REAL,
date DATE NOT NULL
);
]=]
if db:exec(sql) ~= sqlite3.OK then
error(("sqlite: %d (%s)"):format(db:errcode(), db:errmsg()))
end
end
local function dbexec(sql, func, udata)
if not db then
opendb()
end
if db:exec(sql, func, udata) ~= sqlite3.OK then
error(("sqlite: %d (%s)"):format(db:errcode(), db:errmsg()))
end
end
local function abspath()
local path = mp.get_property("path")
if path:find("://") then
return path
else
return mpu.join_path(mp.get_property("working-directory"), path)
end
end
mp.register_event("file-loaded", function()
dbexec(
([=[
INSERT INTO loaded_items (path, filename, title, date)
VALUES(
"%s",
"%s",
"%s",
unixepoch()
);
SELECT LAST_INSERT_ROWID();
]=]):format(abspath(), mp.get_property("filename"), mp.get_property("media-title")),
function(_udata, _cols, values, _names)
last_insert_id = values[1]
return 0
end,
nil
)
end)
mp.add_hook("on_unload", 50, function(_hook)
local timepos = mp.get_property("audio-pts") or mp.get_property("time-pos")
if timepos then
dbexec(([=[
UPDATE loaded_items
SET time_pos = %g
WHERE id = %d;
]=]):format(timepos, last_insert_id))
end
end)
mp.register_event("shutdown", function()
if db then
db:close()
end
end)
mp.add_key_binding("ctrl+r", "history-resume", function()
dbexec(
([=[
SELECT time_pos FROM loaded_items
WHERE time_pos NOTNULL AND title = "%s"
ORDER BY date DESC
LIMIT 1;
]=]):format(mp.get_property("media-title")),
function(_udata, _cols, values, _names)
if values[1] then
mp.commandv("seek", values[1], "absolute", "exact")
end
return 0
end,
nil
)
end)
mp.add_key_binding("alt+r", "play-recent", function()
local items = {}
dbexec(
[=[
SELECT DISTINCT path, title FROM loaded_items
ORDER BY date DESC;
]=],
function(_udata, _cols, values, _names)
if values[1] then
items[#items + 1] = values[1] .. "\x1f" .. values[2]
end
return 0
end,
nil
)
if items[1] then
local dmenu = mp.command_native({
name = "subprocess",
args = { "dmenu", "-l", "20" },
capture_stdout = true,
playback_only = false,
stdin_data = table.concat(items, "\n"),
})
if dmenu.status == 0 then
mp.commandv("loadfile", dmenu.stdout:sub(1, dmenu.stdout:find("\x1f") - 1))
end
end
end)
|