summaryrefslogtreecommitdiff
path: root/mac/.config/mpv/scripts/history.lua
blob: 974f42bcc39ae72511e3edfe9a04cc13a7796c06 (plain)
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)