-- Display some stats.
--
-- Please consult the readme for information about usage and configuration:
-- https://github.com/Argon-/mpv-stats
--
-- Please note: not every property is always available and therefore not always
-- visible.
local mp = require 'mp'
local options = require 'mp.options'
local utils = require 'mp.utils'
-- Options
local o = {
-- Default key bindings
key_page_1 = "1",
key_page_2 = "2",
key_page_3 = "3",
key_page_4 = "4",
key_page_0 = "0",
-- For pages which support scrolling
key_scroll_up = "UP",
key_scroll_down = "DOWN",
scroll_lines = 1,
duration = 4,
redraw_delay = 1, -- acts as duration in the toggling case
ass_formatting = true,
persistent_overlay = false, -- whether the stats can be overwritten by other output
print_perfdata_passes = false, -- when true, print the full information about all passes
filter_params_max_length = 100, -- a filter list longer than this many characters will be shown one filter per line instead
<<<<<<< HEAD
show_frame_info = false, -- whether to show the current frame info
=======
term_width_limit = -1, -- overwrites the terminal width
term_height_limit = -1, -- overwrites the terminal height
>>>>>>> 89493c38fb (stats.lua: truncate long lines for the terminal)
debug = false,
-- Graph options and style
plot_perfdata = true,
plot_vsync_ratio = true,
plot_vsync_jitter = true,
plot_tonemapping_lut = false,
skip_frames = 5,
global_max = true,
flush_graph_data = true, -- clear data buffers when toggling
plot_bg_border_color = "0000FF",
plot_bg_color = "262626",
plot_color = "FFFFFF",
-- Text style
font = "sans-serif",
font_mono = "monospace", -- monospaced digits are sufficient
font_size = 8,
font_color = "FFFFFF",
border_size = 0.8,
border_color = "262626",
shadow_x_offset = 0.0,
shadow_y_offset = 0.0,
shadow_color = "000000",
alpha = "11",
-- Custom header for ASS tags to style the text output.
-- Specifying this will ignore the text style values above and just
-- use this string instead.
custom_header = "",
-- Text formatting
-- With ASS
ass_nl = "\\N",
ass_indent = "\\h\\h\\h\\h\\h",
ass_prefix_sep = "\\h\\h",
ass_b1 = "{\\b1}",
ass_b0 = "{\\b0}",
ass_it1 = "{\\i1}",
ass_it0 = "{\\i0}",
-- Without ASS
no_ass_nl = "\n",
no_ass_indent = "\t",
no_ass_prefix_sep = " ",
no_ass_b1 = "\027[1m",
no_ass_b0 = "\027[0m",
no_ass_it1 = "\027[3m",
no_ass_it0 = "\027[0m",
bindlist = "no", -- print page 4 to the terminal on startup and quit mpv
}
options.read_options(o)
o.term_width_limit = tonumber(o.term_width_limit) or -1
o.term_height_limit = tonumber(o.term_height_limit) or -1
if o.term_width_limit < 0 then
o.term_width_limit = nil
end
if o.term_height_limit < 0 then
o.term_height_limit = nil
end
local format = string.format
local max = math.max
local min = math.min
-- Function used to record performance data
local recorder = nil
-- Timer used for redrawing (toggling) and clearing the screen (oneshot)
local display_timer = nil
-- Timer used to update cache stats.
local cache_recorder_timer = nil
-- Current page and <page key>:<page function> mappings
local curr_page = o.key_page_1
local pages = {}
local scroll_bound = false
local tm_viz_prev = nil
-- Save these sequences locally as we'll need them a lot
local ass_start = mp.get_property_osd("osd-ass-cc/0")
local ass_stop = mp.get_property_osd("osd-ass-cc/1")
-- Ring buffers for the values used to construct a graph.
-- .pos denotes the current position, .len the buffer length
-- .max is the max value in the corresponding buffer
local vsratio_buf, vsjitter_buf
local function init_buffers()
vsratio_buf = {0, pos = 1, len = 50, max = 0}
vsjitter_buf = {0, pos = 1, len = 50, max = 0}
end
local cache_ahead_buf, cache_speed_buf
local perf_buffers = {}
local function graph_add_value(graph, value)
graph.pos = (graph.pos % graph.len) + 1
graph[graph.pos] = value
graph.max = max(graph.max, value)
end
-- "\\<U+2060>" in UTF-8 (U+2060 is WORD-JOINER)
local ESC_BACKSLASH = "\\" .. string.char(0xE2, 0x81, 0xA0)
local function no_ASS(t)
if not o.use_ass then
return t
elseif not o.persistent_overlay then
-- mp.osd_message supports ass-escape using osd-ass-cc/{0|1}
return ass_stop .. t .. ass_start
else
-- mp.set_osd_ass doesn't support ass-escape. roll our own.
-- similar to mpv's sub/osd_libass.c:mangle_ass(...), excluding
-- space after newlines because no_ASS is not used with multi-line.
-- space at the beginning is replaced with "\\h" because it matters
-- at the beginning of a line, and we can't know where our output
-- ends up. no issue if it ends up at the middle of a line.
return tostring(t)
:gsub("\\", ESC_BACKSLASH)
:gsub("{", "\\{")
:gsub("^ ", "\\h")
end
end
local function b(t)
return o.b1 .. t .. o.b0
end
local function it(t)
return o.it1 .. t .. o.it0
end
local function text_style()
if not o.use_ass then
return ""
end
if o.custom_header and o.custom_header ~= "" then
return o.custom_header
else
local has_shadow = mp.get_property('osd-back-color'):sub(2, 3) == '00'
return format("{\\r\\an7\\fs%d\\fn%s\\bord%f\\3c&H%s&" ..
"\\1c&H%s&\\1a&H%s&\\3a&H%s&" ..
(has_shadow and "\\4a&H%s&\\xshad%f\\yshad%f\\4c&H%s&}" or "}"),
o.font_size, o.font, o.border_size,
o.border_color, o.font_color, o.alpha, o.alpha, o.alpha,
o.shadow_x_offset, o.shadow_y_offset, o.shadow_color)
end
end
local function has_vo_window()
return mp.get_property_native("vo-configured") and mp.get_property_native("video-osd")
end
-- Generate a graph from the given values.
-- Returns an ASS formatted vector drawing as string.
--
-- values: Array/table of numbers representing the data. Used like a ring buffer
-- it will get iterated backwards `len` times starting at position `i`.
-- i : Index of the latest data value in `values`.
-- len : The length/amount of numbers in `values`.
-- v_max : The maximum number in `values`. It is used to scale all data
-- values to a range of 0 to `v_max`.
-- v_avg : The average number in `values`. It is used to try and center graphs
-- if possible. May be left as nil
-- scale : A value that will be multiplied with all data values.
-- x_tics: Horizontal width multiplier for the steps
local function generate_graph(values, i, len, v_max, v_avg, scale, x_tics)
-- Check if at least one value exists
if not values[i] then
return ""
end
local x_max = (len - 1) * x_tics
local y_offset = o.border_size
local y_max = o.font_size * 0.66
local x = 0
if v_max > 0 then
-- try and center the graph if possible, but avoid going above `scale`
if v_avg and v_avg > 0 then
scale = min(scale, v_max / (2 * v_avg))
end
scale = scale * y_max / v_max
end -- else if v_max==0 then all values are 0 and scale doesn't matter
local s = {format("m 0 0 n %f %f l ", x, y_max - scale * values[i])}
i = ((i - 2) % len) + 1
for p = 1, len - 1 do
if values[i] then
x = x - x_tics
s[#s+1] = format("%f %f ", x, y_max - scale * values[i])
end
i = ((i - 2) % len) + 1
end
s[#s+1] = format("%f %f %f %f", x, y_max, 0, y_max)
local bg_box = format("{\\bord0.5}{\\3c&H%s&}{\\1c&H%s&}m 0 %f l %f %f %f 0 0 0",
o.plot_bg_border_color, o.plot_bg_color, y_max, x_max, y_max, x_max)
return format("%s{\\r}{\\rDefault}{\\pbo%f}{\\shad0}{\\alpha&H00}{\\p1}%s{\\p0}{\\bord0}{\\1c&H%s}{\\p1}%s{\\p0}%s",
o.prefix_sep, y_offset, bg_box, o.plot_color, table.concat(s), text_style())
end
local function append(s, str, attr)
|