How can I write a plugin for VLC that responds to play, pause and stop events?
lua, vlc
Solution
I'm using VLC 2.2.1 on Windows.
Here's a simple Lua plugin that recognizes play/pause/stop events:
function descriptor()
return {
title = "VLC Dummy Extension",
capabilities = { "playing-listener" }
}
end
function activate()
end
function deactivate()
end
function meta_changed()
end
function playing_changed()
vlc.msg.dbg("[Dummy] Status: " .. vlc.playlist.status())
end
Notes:
- VLC will call `activate()`, `deactivate()`, `meta_changed()` at some point in the plugin life cycle. You're not required to include them, but VLC will fill up your debug log with useless "function not found" messages.
- If the plugin's capabilities contain `playing-listener`, VLC will expect the `playing_changed()` hook and call it when appropriate (even though the code comment says the hook name is "status_changed").
- `vlc.playlist.status()` returns "stopped", "playing", "paused" or "unknown".
Run:
- Save the plugin in a .lua file, then drop it in VLC's extensions folder: `%APPDATA%\vlc\lua\extensions\` (Windows) or `~/.local/share/vlc/lua/extensions/` (Linux).
- Load it by Tools > Plugins and extensions, Reload extensions (restarting VLC is unnecessary).
- Activate it (there's an option under View, named after title in the plugin descriptor); `activate()` will be called.
- To view all logs (`vlc.msg` calls), open Tools > Messages (Ctrl+M), set the level to debug and filter by "lua".
To do something whenever a new item plays:
- Add `input-listener` to the plugin's capabilities.
- Add the corresponding hook `input_changed()`.
- Use `vlc.input.item()` to get the current item (name, URI, metadata, etc).
- You can post what's playing to an HTTP server. VLC offers `vlc.net`, which means you have to program for sockets. Fortunately, the extension vlsub, shipped with VLC by default, has utility methods for sending GET requests. We can steal those.
In this example, I'm just sending a threadbare GET:
http://127.0.0.1:5000/?name=MMFR.2015.720p.mp4
If I don't care about redirects or reading responses, `get()` is a lot simpler than the vlsub's version:
function descriptor()
return {
title = "VLC Dummy Extension",
capabilities = { "input-listener" }
}
end
function activate()
end
function deactivate()
end
function meta_changed()
end
function input_changed()
if vlc.input.is_playing() and vlc.playlist.status() == "playing" then
local item = vlc.input.item()
if item then
vlc.msg.dbg("[Dummy] Now playing: " .. item:name())
get("http://127.0.0.1:5000/?name=" .. item:name())
end
end
end
function get(url)
local u = vlc.net.url_parse(url)
local host, port, path = u["host"], u["port"], u["path"]
local header = {
"GET "..path.." HTTP/1.1",
"Host: "..host,
"",
""
}
local request = table.concat(header, "\r\n")
http_req(host, port, request)
end
function http_req(host, port, request)
local fd = vlc.net.connect_tcp(host, port)
if not fd then return false end
local pollfds = {}
pollfds[fd] = vlc.net.POLLIN
vlc.net.send(fd, request)
vlc.net.poll(pollfds)
local chunk = vlc.net.recv(fd, 2048)
while chunk do
vlc.net.poll(pollfds)
chunk = vlc.net.recv(fd, 1024)
end
vlc.net.close(fd)
end
Problem
I'd like to write a very simple plugin for VLC that makes web requests when a media is played, paused, or stopped. It is a very similar to a scrobbling plugin . I saw that VLC supports plugin and extensions (which are very simple Lua scripts) but I haven't been able to find any information on how to do this. I guess I'd need to write a plugin that registers some callbacks -- am I right? Any idea on how I could accomplish this? It seems to be quite an uphill battle figuring this out. Can I do this using Python?