arch-setup/files/scripts/music-notify
2026-03-16 13:58:03 +01:00

72 lines
2.4 KiB
Python
Executable file

#!/usr/bin/env python3
import subprocess, threading, urllib.request
import dbus, dbus.service, dbus.mainloop.glib
from gi.repository import GLib
class MusicNotifier:
def __init__(self):
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SessionBus()
obj = bus.get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
self.iface = dbus.Interface(obj, "org.freedesktop.Notifications")
self.notif_id = dbus.UInt32(0)
bus.add_signal_receiver(
self.on_action,
dbus_interface="org.freedesktop.Notifications",
signal_name="ActionInvoked"
)
def get_art(self, url):
if not url:
return ""
try:
if url.startswith("file://"):
return url[7:]
path = "/tmp/music_art.jpg"
urllib.request.urlretrieve(url, path)
return path
except:
return ""
def notify(self, artist, title, art_url, status):
art = self.get_art(art_url)
play_label = "⏸ Pause" if status == "Playing" else "▶ Play"
actions = ["prev", "⏮ Zurück", "toggle", play_label, "next", "⏭ Weiter"]
hints = {"image-path": dbus.String(art)} if art else {}
self.notif_id = self.iface.Notify(
"music", self.notif_id, art,
title, artist,
actions, hints, 0
)
def on_action(self, notif_id, action):
if notif_id != self.notif_id:
return
cmds = {"prev": "previous", "toggle": "play-pause", "next": "next"}
if action in cmds:
subprocess.run(["playerctl", cmds[action]])
def monitor(self):
proc = subprocess.Popen(
["playerctl", "--follow", "metadata", "--format",
"{{artist}}||{{title}}||{{mpris:artUrl}}||{{status}}"],
stdout=subprocess.PIPE, text=True
)
prev = ""
for line in proc.stdout:
parts = line.strip().split("||")
if len(parts) != 4:
continue
artist, title, art_url, status = parts
if title != prev:
prev = title
self.notify(artist, title, art_url, status)
def run(self):
threading.Thread(target=self.monitor, daemon=True).start()
GLib.MainLoop().run()
if __name__ == "__main__":
MusicNotifier().run()