Skip to content

Instantly share code, notes, and snippets.

@DBX12
Created June 29, 2023 11:06
Show Gist options
  • Save DBX12/8fb430c988bfad6872ae064e158bd5fe to your computer and use it in GitHub Desktop.
Save DBX12/8fb430c988bfad6872ae064e158bd5fe to your computer and use it in GitHub Desktop.
VLC player command runner extension, see https://dbx-12.de/?linux/vlc-command-runner for instructions
# comma-separated list of commands to run when playback is started
on_play_commands=
# comma-separated list of commands to run when playback is paused
on_pause_commands=
# comma-separated list of commands to run when playback is stopped
on_stop_commands=
local cfgPath = ""
local options = {
on_play_commands = {},
on_pause_commands = {},
on_stop_commands = {},
}
local last_called = {
playing = 0,
paused = 0,
stopped = 0
}
--region methods called by vlc
---descriptor Describes the extension for VLC
function descriptor()
return {
title = "Command runner",
version = "1.0",
author = "dbx12",
url = "http://dbx-12.de/?linux/vlc-command-runner",
shortdesc = "Command runner",
description = "This extension triggers commands on your machine when playback is started, paused or stopped.",
capabilities = {
"playing-listener",
"menu"
}
}
end
---activate called when the extension is activated
function activate()
cfgPath = vlc.config.configdir() .. "/command-runner.conf"
if file_exists(cfgPath) == false then
write_config_file(cfgPath)
log_info("Config file is missing, empty config file generated at "..cfgPath)
log_info("After editing this file, you should reload the extension config with View > Command Runner > Reload config")
else
load_config(cfgPath)
end
end
---deactivate called when the extension is deactivated
function deactivate()
end
---meta_changed called when meta information changes
function meta_changed()
end
---playing_changed called when the playback status changes
function playing_changed()
local status = vlc.playlist.status()
if debounce(status) then
return
end
if status == "playing" then
run_commands(options.on_play_commands)
elseif status == "paused" then
run_commands(options.on_pause_commands)
elseif status == "stopped" then
run_commands(options.on_stop_commands)
end
end
---menu contains the entries in the menu
function menu()
return {"Reload config"}
end
---trigger_menu is called when a menu entry is clicked
---@param action_id number 1-based id of the entry that was clicked
function trigger_menu(action_id)
if action_id == 1 then
load_config()
end
end
--endregion
---debounce prevents calling the commands too fast in case VLC calls `playing_changed()` more than once per state change
---@param action string
function debounce(action)
local now = os.time()
if last_called[action] == now then
log_dbg(action.." was called too fast after the last call. Ignoring this one.")
return true
end
last_called[action] = now
return false
end
---run_commands runs specified commands with os.execute
---@param commands table list of commands to execute
function run_commands(commands)
for _, command in pairs(commands) do
log_dbg("Running command: "..command)
os.execute(command)
end
end
--region log functions
function log_dbg(message)
vlc.msg.dbg("[command runner] "..message)
end
function log_info(message)
vlc.msg.info("[command runner] "..message)
end
--endregion
--region Config file handling
function load_config()
log_dbg("Loading config from: " .. cfgPath)
local lines = lines_from(cfgPath)
for _, line in pairs(lines) do
-- only process line if it does not start with a #
if string.match(line, "^%s*#") == nil then
parsed = parse_line(line)
if string.match(parsed.key, "_commands") then
options[parsed.key] = parse_list(parsed.value)
else
options[parsed.key] = parsed.value
end
end
end
end
function parse_line(line)
local key, value
for k, v in string.gmatch(line, "([a-z_]+)=(.*)") do
key = k
value = v
end
return { key = key, value = value }
end
function parse_list(value)
local values = {}
for v in string.gmatch(value, "([^,]+)") do
table.insert(values, v)
end
return values
end
-- source: https://github.com/michaelbull/vlc-credit-skipper/blob/84211bc6e08596d2626be6f58bf8a3beec6db728/credit-skipper.lua#L206
function lines_from(cfgFile)
local lines = {}
for line in io.lines(cfgFile) do
lines[#lines + 1] = line
end
return lines
end
-- source: https://github.com/michaelbull/vlc-credit-skipper/blob/84211bc6e08596d2626be6f58bf8a3beec6db728/credit-skipper.lua#L200
function file_exists(file)
local f = io.open(file, "rb")
if f then
f:close()
end
return f ~= nil
end
---write_config_file writes the default config (no commands at all) to `cfgPath`
function write_config_file()
content=[=[
# comma-separated list of commands to run when playback is started
on_play_commands=
# comma-separated list of commands to run when playback is paused
on_pause_commands=
# comma-separated list of commands to run when playback is stopped
on_stop_commands=
]=]
local fd = io.open(cfgPath, "wb")
fd:write(content)
fd:close()
end
--endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment