From 5f1df7751fe26c1714328e879001a384fce73d38 Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Tue, 30 Jun 2026 09:51:14 -0700 Subject: [PATCH 1/2] Parameterize and fix race condition for i2samp --- i2samp.py | 50 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/i2samp.py b/i2samp.py index 5969a61..2fda081 100644 --- a/i2samp.py +++ b/i2samp.py @@ -17,6 +17,8 @@ PRODUCT_NAME = "I2S Amplifier" OVERLAY = "googlevoicehat-soundcard" CARD_NAME_FALLBACK = "sndrpigooglevoi" +I2SAMP_INIT_SERVICE = "adafruit-i2samp-init.service" +APLAY_SERVICE = "aplay.service" def get_card_name(overlay): """Load overlay at runtime and discover the ALSA card id from aplay -l.""" @@ -48,10 +50,13 @@ def uninstall(): if config is None: shell.bail("No Device Tree Detected, not supported") - print("\nStopping and removing aplay systemd unit...") - shell.run_command("sudo systemctl stop aplay", suppress_message=True) - shell.run_command("sudo systemctl disable aplay", suppress_message=True) - shell.remove("/etc/systemd/system/aplay.service") + print("\nStopping and removing systemd units...") + shell.run_command(f"sudo systemctl stop {APLAY_SERVICE}", suppress_message=True) + shell.run_command(f"sudo systemctl disable {APLAY_SERVICE}", suppress_message=True) + shell.run_command(f"sudo systemctl stop {I2SAMP_INIT_SERVICE}", suppress_message=True) + shell.run_command(f"sudo systemctl disable {I2SAMP_INIT_SERVICE}", suppress_message=True) + shell.remove(f"/etc/systemd/system/{APLAY_SERVICE}") + shell.remove(f"/etc/systemd/system/{I2SAMP_INIT_SERVICE}") shell.run_command("sudo systemctl daemon-reload") print(f"Removing Device Tree overlay from {config}") @@ -192,12 +197,38 @@ def install(): shell.run_command(f"amixer -D 'plug:softvol' sset PCM 100% > /dev/null 2>&1") shell.run_command("sudo alsactl store") + print("Installing I2S amplifier initialization systemd unit") + shell.write_text_file(f"/etc/systemd/system/{I2SAMP_INIT_SERVICE}", f""" +[Unit] +Description=Initialize Adafruit I2S amplifier softvol control. +After=local-fs.target +Wants=sound.target +Before={APLAY_SERVICE} +StartLimitBurst=5 +StartLimitIntervalSec=60 + +[Service] +Type=oneshot +RemainAfterExit=yes +Restart=on-failure +RestartSec=5s + +ExecStartPre=/bin/sh -c 'i=0; while [ "$i" -lt 30 ]; do \\ + aplay -l | grep -qi "{card_name}" && exit 0; \\ + i=$((i+1)); sleep 1; \\ + done; exit 1' +ExecStart=/usr/bin/amixer -D plug:softvol sset PCM 100% +ExecStart=/usr/sbin/alsactl store + +[Install] +WantedBy=multi-user.target""", append=False) + print("Installing aplay systemd unit") - shell.write_text_file("/etc/systemd/system/aplay.service", """ + shell.write_text_file(f"/etc/systemd/system/{APLAY_SERVICE}", f""" [Unit] Description=Invoke aplay from /dev/zero at system start. -After=sound.target -Wants=sound.target +Requires={I2SAMP_INIT_SERVICE} +After={I2SAMP_INIT_SERVICE} StartLimitBurst=5 StartLimitIntervalSec=60 @@ -211,12 +242,13 @@ def install(): WantedBy=multi-user.target""", append=False) shell.run_command("sudo systemctl daemon-reload") - shell.run_command("sudo systemctl disable aplay") + shell.run_command(f"sudo systemctl enable {I2SAMP_INIT_SERVICE}") + shell.run_command(f"sudo systemctl disable {APLAY_SERVICE}") print("\nYou can optionally activate '/dev/zero' playback in\n" "the background at boot. This will remove all\n" "popping/clicking but does use some processor time.\n\n") if shell.prompt("Activate '/dev/zero' playback in background? [RECOMMENDED]\n", default="y"): - shell.run_command("sudo systemctl enable aplay") + shell.run_command(f"sudo systemctl enable {APLAY_SERVICE}") reboot = True if driver_loaded("max98357a"): From 959091e0a4c9137bca50e350d046a017bdb720c5 Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Tue, 30 Jun 2026 10:12:06 -0700 Subject: [PATCH 2/2] Address review suggestions --- i2samp.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/i2samp.py b/i2samp.py index 2fda081..f268b20 100644 --- a/i2samp.py +++ b/i2samp.py @@ -201,7 +201,7 @@ def install(): shell.write_text_file(f"/etc/systemd/system/{I2SAMP_INIT_SERVICE}", f""" [Unit] Description=Initialize Adafruit I2S amplifier softvol control. -After=local-fs.target +After=local-fs.target sound.target Wants=sound.target Before={APLAY_SERVICE} StartLimitBurst=5 @@ -214,11 +214,13 @@ def install(): RestartSec=5s ExecStartPre=/bin/sh -c 'i=0; while [ "$i" -lt 30 ]; do \\ - aplay -l | grep -qi "{card_name}" && exit 0; \\ - i=$((i+1)); sleep 1; \\ + /usr/bin/aplay -l | /bin/grep -qi "{card_name}" && exit 0; \\ + i=$((i+1)); /bin/sleep 1; \\ done; exit 1' -ExecStart=/usr/bin/amixer -D plug:softvol sset PCM 100% -ExecStart=/usr/sbin/alsactl store +ExecStart=/bin/sh -c '/usr/bin/amixer -c "{card_name}" controls | \\ + /bin/grep -qi "name=.*PCM" || \\ + /usr/bin/amixer -D plug:softvol sset PCM 100%' +ExecStart=-/usr/sbin/alsactl restore [Install] WantedBy=multi-user.target""", append=False)