Fix: auto-enable service on install, fix service startup, add config hot-reload; bump to v0.3.3

main
Sean Doran 2026-02-27 13:54:57 -05:00
parent 642a1212c7
commit 25da5b46ad
No known key found for this signature in database
GPG Key ID: A9D7D25CD95E8579
7 changed files with 72 additions and 27 deletions

View File

@ -1,6 +1,6 @@
pkgbase = turn-up-arch
pkgdesc = USB serial knob/button mixer daemon for PipeWire/PulseAudio on Linux
pkgver = 0.3.2
pkgver = 0.3.3
pkgrel = 1
url = https://github.com/sean351/turn-up-arch
arch = any
@ -15,7 +15,8 @@ pkgbase = turn-up-arch
depends = pipewire-pulse
optdepends = playerctl: media key support via button commands
optdepends = pulseaudio: alternative to pipewire-pulse
source = turn-up-arch-0.3.2.tar.gz::https://github.com/sean351/turn-up-arch/archive/refs/tags/v0.3.2.tar.gz
install = turnupd.install
source = turn-up-arch-0.3.3.tar.gz::https://github.com/sean351/turn-up-arch/archive/refs/tags/v0.3.3.tar.gz
sha256sums = SKIP
pkgname = turn-up-arch

View File

@ -1,7 +1,7 @@
# Maintainer: Sean Doran <sdoran35@gmail.com>
# AUR updates are automated via GitHub Actions on version tag push
pkgname=turn-up-arch
pkgver=0.3.2
pkgver=0.3.3
pkgrel=1
pkgdesc="USB serial knob/button mixer daemon for PipeWire/PulseAudio on Linux"
arch=('any')
@ -23,6 +23,7 @@ optdepends=(
'playerctl: media key support via button commands'
'pulseaudio: alternative to pipewire-pulse'
)
install=turnupd.install
source=("$pkgname-$pkgver.tar.gz::https://github.com/sean351/turn-up-arch/archive/refs/tags/v$pkgver.tar.gz")
sha256sums=('SKIP')

View File

@ -1,16 +1,14 @@
[Unit]
Description=Turn Up mixer daemon
Documentation=https://github.com/sean351/turn-up-arch
After=pipewire-pulse.service pulseaudio.service
Wants=pipewire-pulse.service
After=pipewire-pulse.socket pulseaudio.socket
Wants=pipewire-pulse.socket
[Service]
Type=simple
ExecStart=/usr/bin/turnupd
Restart=on-failure
Restart=always
RestartSec=5
# Give the audio server a moment to start before connecting
ExecStartPre=/bin/sleep 2
# Logging
StandardOutput=journal

View File

@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "turnup"
version = "0.3.2"
version = "0.3.3"
description = "USB serial knob/button mixer daemon for PipeWire/PulseAudio on Linux"
readme = "README.md"
license = { text = "MIT" }

View File

@ -1,3 +1,3 @@
"""Turn Up — USB serial mixer daemon for PipeWire/PulseAudio."""
__version__ = "0.3.2"
__version__ = "0.3.3"

View File

@ -13,6 +13,7 @@ even when no knob is being moved.
"""
import logging
import os
import signal
import subprocess
import sys
@ -21,7 +22,7 @@ import time
import pulsectl
import serial
from turnup.config import get_knob_led_cfg, get_led_color, load_config
from turnup.config import DEFAULT_CONFIG_PATH, get_knob_led_cfg, get_led_color, load_config
logging.basicConfig(
level=logging.INFO,
@ -359,6 +360,13 @@ def main() -> None:
knob_norms = init_knob_norms(config, pulse)
buf = bytearray()
# Track config file mtime so we can restart when it changes.
try:
config_mtime: float | None = os.stat(DEFAULT_CONFIG_PATH).st_mtime
except OSError:
config_mtime = None
last_config_check = time.monotonic()
def _shutdown(sig: int, _frame: object) -> None:
log.info("Received signal %d — shutting down", sig)
pulse.close()
@ -376,8 +384,7 @@ def main() -> None:
while True:
data = ser.read(64)
if not data:
continue
if data:
buf.extend(data)
messages, buf = parse_messages(buf)
for msg in messages:
@ -393,6 +400,19 @@ def main() -> None:
elif msg["type"] == "heartbeat":
send_leds(ser, all_led_colors(config, knob_norms))
# Check for config changes every 2 s (serial read timeout = 0.1 s).
now = time.monotonic()
if now - last_config_check >= 2.0:
last_config_check = now
try:
new_mtime = os.stat(DEFAULT_CONFIG_PATH).st_mtime
if config_mtime is not None and new_mtime != config_mtime:
log.info("Config changed — restarting daemon")
pulse.close()
os.execv(sys.executable, [sys.executable] + sys.argv)
except OSError:
pass
except serial.SerialException as exc:
log.warning("Serial error: %s — retrying in 3 s", exc)
time.sleep(3)

25
turnupd.install Normal file
View File

@ -0,0 +1,25 @@
post_install() {
systemctl --global enable turnupd.service
echo "turnupd: service enabled for all users — it will start on next login."
echo "To start it now: systemctl --user start turnupd.service"
}
post_upgrade() {
systemctl --global reenable turnupd.service
# Restart for all currently logged-in users
while read -r uid _; do
systemctl -M "${uid}@.host" --user restart turnupd.service 2>/dev/null || true
done < <(loginctl list-users --no-legend 2>/dev/null)
}
pre_remove() {
# Stop and disable for all currently logged-in users
while read -r uid _; do
systemctl -M "${uid}@.host" --user stop turnupd.service 2>/dev/null || true
systemctl -M "${uid}@.host" --user disable turnupd.service 2>/dev/null || true
done < <(loginctl list-users --no-legend 2>/dev/null)
# Remove the global enable symlink
# (/etc/systemd/user/default.target.wants/turnupd.service)
systemctl --global disable turnupd.service 2>/dev/null || true
}