-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpdf_hook.lua
145 lines (122 loc) · 4.58 KB
/
pdf_hook.lua
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
139
140
141
142
143
144
145
-- pdf_hook.lua
--
-- view PDFs in mpv by using ImageMagick to convert PDF pages to images
--
-- Dependancies:
-- * Linux / Unix / OSX (windows support should be possible, but I can't test it.)
-- * ImageMagick (`convert` must be in the PATH)
-- * pdfinfo
--
-- Notes: jpegs are generated for each page and are placed in /tmp/mpv-pdf/.
-- If your OS doesn't periodically clean /tmp/, this could get large...
--
-- Use of an mpv-image-viewer is recommended for panning/zooming.
--
-- Is this userscript a weird joke? To be honest I'm not really sure anymore.
local utils = require 'mp.utils'
local msg = require 'mp.msg'
local opts = {
--TODO use pandoc to support more file formats?
density=150,
quality=50,
supported_extensions=[[
["pdf"]
]]
}
(require 'mp.options').read_options(opts)
opts.supported_extensions = utils.parse_json(opts.supported_extensions)
local function exec(args)
local ret = utils.subprocess({args = args})
return ret.status, ret.stdout, ret, ret.killed_by_us
end
local function findl(str, patterns)
for i,p in pairs(patterns) do
if str:find("%."..p.."$") then
return true
end
end
return false
end
generators = {}
mp.register_script_message("pdf-page-generator-broadcast", function(generator_name)
for _, g in ipairs(generators) do
if generator_name == g then return end
end
generators[#generators + 1] = generator_name
end)
mp.register_script_message("pdf-page-generator-return", function(failed, from, to)
if failed == "true" then
msg.error("generator was killed..: "..from .. " to: " .. to)
outstanding_tasks[from] = nil
return
end
completed_tasks[from] = to;
outstanding_tasks[from] = nil
if mp.get_property("playlist/"..mp.get_property("playlist-pos").."/filename") == from then
-- append new jpg to playlist, reorder it, then delete the current playlist entry
mp.commandv("loadfile", to, "append")
mp.commandv("playlist-move", mp.get_property("playlist-count")-1, mp.get_property("playlist-pos")+1)
mp.commandv("playlist-remove", mp.get_property("playlist-pos"))
end
end)
placeholder=nil
next_generator=1
outstanding_tasks={}
completed_tasks={}
local function request_page(url)
if completed_tasks[url] then return completed_tasks[url] end
if outstanding_tasks[url] then return placeholder end
mp.commandv("script-message-to", generators[next_generator], "generate-pdf-page", url, tostring(opts.density), tostring(opts.quality))
outstanding_tasks[url] = generators[next_generator]
next_generator = next_generator + 1
if next_generator > #generators then next_generator = 1 end
return placeholder
end
local function prefetch_pages()
local urls = {}
for i=mp.get_property("playlist-pos"), mp.get_property("playlist-count")-1,1 do
url = mp.get_property("playlist/"..i.."/filename")
if url:find("pdf://") == 1 then
urls[#urls+1] = url
end
end
for i=1,math.min(#generators,#urls),1 do
request_page(urls[i])
end
end
mp.add_hook("on_load", 10, function ()
local url = mp.get_property("stream-open-filename", "")
msg.debug("stream-open-filename: "..url)
if (url:find("pdf://") == 1) then
mp.set_property("stream-open-filename", request_page(url)) --swap in jpg (or placeholder)
prefetch_pages()
return
end
if (findl(url, opts.supported_extensions) == false) then
msg.debug("did not find a supported file")
return
end
-- get pagecount
local pdfinfo = "pdfinfo"
local stat,out = exec({pdfinfo, url})
local num_pages = string.match(out, "Pages:%s+(%d+)")
local page_size_x = string.match(out, "Page size:%s+(%d+.*%d*) x %d+.*%d*%s+pts") / 72 * opts.density
local page_size_y = string.match(out, "Page size:%s+%d+.*%d* x (%d+.*%d*)%s+pts") / 72 * opts.density
local size_str = tostring(page_size_x).."x"..tostring(page_size_y)
placeholder="/tmp/mpv-pdf/placeholder-"..size_str..".jpg"
exec({"convert",
"-size", size_str,
"canvas:white",
placeholder})
--build pdf:// playlist
local playlist = {"#EXTM3U"}
for i=0,num_pages-1,1 do
table.insert(playlist, "#EXTINF:0,Page "..i) --TODO use 'real' page numbers e.g. 'ix', 'Cover', etc
table.insert(playlist, "pdf://"..url.."["..i.."]") --playlist entry has the page number on it, used by `convert`
end
--load playlist
if #playlist > 0 then
mp.set_property("stream-open-filename", "memory://" .. table.concat(playlist, "\n"))
end
return
end)