Skip to content

Instantly share code, notes, and snippets.

@pmenke-de
Last active May 1, 2026 14:36
Show Gist options
  • Select an option

  • Save pmenke-de/70b90f6363cfcd70dd32ce126e3b6eac to your computer and use it in GitHub Desktop.

Select an option

Save pmenke-de/70b90f6363cfcd70dd32ce126e3b6eac to your computer and use it in GitHub Desktop.
Plexamp NUC LED status display
#!/usr/bin/env python3
"""
Uses [intel-nuc-led](https://github.com/pmenke-de/intel-nuc-led) to control the LED ring light
on a NUC, to reflect the current status of a runnung Plexamp instance as well as shairport-sync.
-> For use with a NUC as headless Plexamp-player, controlled via another Plexamp instance on a smartphone.
"""
import nuc_wmi
from nuc_wmi.set_led import set_led
import xml.etree.ElementTree as ET
import requests
import time
import dbus
SHAIRPORT_BUS_NAME = "org.gnome.ShairportSync"
SHAIRPORT_OBJECT_PATH = "/org/gnome/ShairportSync"
SHAIRPORT_INTERFACE = "org.gnome.ShairportSync"
DBUS_PROPERTIES_IFACE = "org.freedesktop.DBus.Properties"
def is_airplay_active() -> bool:
"""
Equivalent to:
dbus-send --print-reply --system --dest=org.gnome.ShairportSync \
/org/gnome/ShairportSync org.freedesktop.DBus.Properties.Get \
string:org.gnome.ShairportSync string:Active
"""
try:
bus = dbus.SystemBus()
proxy = bus.get_object(SHAIRPORT_BUS_NAME, SHAIRPORT_OBJECT_PATH)
props = dbus.Interface(proxy, DBUS_PROPERTIES_IFACE)
active = props.Get(SHAIRPORT_INTERFACE, "Active")
return bool(active)
except Exception:
# If ShairportSync isn't running / D-Bus not available, treat as inactive
return False
def main():
last_change = time.time()
last_state = "unknown"
while True:
loop_start = time.time()
# Default: error/unknown
color = "Red"
freq = "0.25Hz fade"
brightness = 20
# AirPlay overrides everything else
if is_airplay_active():
state = "airplay"
color = "Blue"
freq = "Always on"
else:
url = "http://localhost:32500/player/timeline/poll?wait=1&includeMetadata=0&commandID=1"
state = "unknown"
try:
res = requests.get(url)
if res.ok:
root = ET.fromstring(res.content)
for type_tag in root.findall('Timeline'):
item_type = type_tag.get('itemType')
if item_type == "music":
state = type_tag.get('state')
match state:
case "playing":
color = "Green"
freq = "Always on"
case "paused":
color = "Yellow"
freq = "0.25Hz fade"
case "stopped":
color = "Yellow"
freq = "Always on"
case _:
print("bad state: " + state)
color = "Red"
break
else:
state = "error"
print("bad response: " + str(res.content))
except Exception as e:
state = "error"
print(e)
pass # color is red
if last_state != state:
last_change = time.time()
last_state = state
elif time.time() - last_change > 30:
# dim after 30s (including for AirPlay)
brightness = 1
freq = "Always on"
set_led(
nuc_wmi.LED_TYPE["legacy"].index("S0 Ring LED"),
brightness,
nuc_wmi.LED_BLINK_FREQUENCY["legacy"].index(freq),
nuc_wmi.LED_COLOR['legacy'][nuc_wmi.LED_COLOR_TYPE['legacy']["S0 Ring LED"]].index(color)
)
if time.time() - loop_start < .5:
time.sleep(0.5)
if __name__ == "__main__":
while True:
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment