Skip to content

Instantly share code, notes, and snippets.

@ferdiebergado
Last active December 8, 2023 05:11
Show Gist options
  • Save ferdiebergado/191f0c9c22865f5486a77a94f1293c8f to your computer and use it in GitHub Desktop.
Save ferdiebergado/191f0c9c22865f5486a77a94f1293c8f to your computer and use it in GitHub Desktop.
mpv script for sending notifications on track change
local mp = require("mp")
local utils = require("mp.utils")
local msg = require("mp.msg")
local home = os.getenv("HOME")
-- local mpv_cache = home .. "/.cache/mpv"
local mpv_cache = "/tmp"
local title = ""
local origin = ""
local thumbnail = home .. "/Pictures/icons/Guyman-Helmet-Music-512.png"
table.unpack = table.unpack or unpack -- 5.1 compatibility
local function shell_escape(inputString)
if inputString == nil then
return "Station ID"
end
-- Characters to escape: $ ` "
local escapedString = string.gsub(inputString, '([$`"])', "\\%1")
-- Preserve newline characters
escapedString = string.gsub(escapedString, "\\n", "\n")
return escapedString
end
local function notify(summary, body, options)
local option_args = {}
for key, value in pairs(options or {}) do
-- local info = key .. " = " .. value
-- msg.log("info", "DEBUG: " .. info)
table.insert(option_args, string.format("--%s=%s", key, value))
end
msg.log("info", "summary:", summary)
msg.log("info", "body:", body)
return pcall(mp.command_native, {
"run",
"notify-send",
table.unpack(option_args),
shell_escape(summary),
shell_escape(body),
})
end
local function notify_media()
return notify(title, origin, {
-- For some inscrutable reason, GNOME 3.24.2
-- nondeterministically fails to pick up the notification icon
-- if either of these two parameters are present.
--
-- urgency = "low",
-- ["app-name"] = "mpv",
-- ...and this one makes notifications nondeterministically
-- fail to appear altogether.
--
-- hint = "string:desktop-entry:mpv",
icon = thumbnail,
--["replaces-process"] = "mpv-notification",
--["replace-file"] = mpv_cache .. "/mpv_notification",
})
end
local function set_data(metadata)
local function tag(name)
return metadata[string.upper(name)] or metadata[name]
end
local function parse_data(data)
local t = {}
-- TODO: Address multiple hyphen
for s in string.gmatch(data, "[^-]+") do
table.insert(t, s)
end
if t[2] ~= nil then
t[2] = t[2]:gsub("^%s+", "")
end
return t
end
local function update_origin(meta)
return string.format("%s\\n%s", origin, meta)
end
local ice = tag("icy-title")
if ice then
local data = parse_data(ice)
origin = data[1]
title = data[2]
local icy_name = tag("icy-name")
origin = update_origin(icy_name)
else
title = tag("title") or title
origin = tag("artist_credit") or tag("artist") or origin
local album = tag("album")
if album then
origin = update_origin(album)
end
local year = tag("original_year") or tag("year")
if year then
origin = update_origin(year)
else
local date = tag("date")
if date then
origin = update_origin(date)
end
end
end
return title, origin
end
local function initialize_data_from_filename()
local path = mp.get_property_native("path")
local dir, file = utils.split_path(path)
-- TODO: handle embedded covers and videos?
-- potential options: mpv's take_screenshot, ffprobe/ffmpeg, ...
-- hooking off existing desktop thumbnails would be good too
-- local thumbnail = find_cover(dir)
title = file
origin = dir
end
local function dump_cover()
if mp.get_property("track-list/1/albumart") == "yes" then
msg.log("info", "Cover art found. Dumping cover art...")
local path = mp.get_property_native("path")
local cover = mpv_cache .. "/mpv.jpg"
mp.command_native({
"run",
"ffmpeg",
"-loglevel",
"quiet",
"-y",
"-i",
path,
"-map",
"0:v",
"-map",
"-0:V",
"-c",
"copy",
cover,
})
msg.log("info", "Command finished. Cover art dumped to " .. cover)
thumbnail = cover
end
end
local function update_data()
initialize_data_from_filename()
dump_cover()
end
local function notify_metadata_updated(_, metadata)
if metadata then
-- for name,val in pairs(metadata) do
-- msg.log("info", name, ": ", val)
-- end
title, origin = set_data(metadata)
end
if title ~= "" then
msg.log("info", "Sending notification...")
-- return notify_media(title, origin, thumbnail)
return notify_media()
end
end
mp.add_hook("on_preloaded", 50, update_data)
mp.observe_property("metadata", "native", notify_metadata_updated)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment