Thank you for your donation!


Cloudsmith graciously provides open-source package management and distribution for our project.


Idea: Keep Last Selected Audio Output Device After Reboot
#13
Information 
This is the my solution I'm trying, but I'm not sure if it's stable.

1. Device Detection
> script:
sudo nano /usr/local/bin/detect_alsa_device.sh
Code:
#!/bin/bash

LAST_DEVICE_FILE="/var/local/last-alsa-device"

echo "Starting ALSA device detector..."
# Check if the stored device file exists
if [ ! -f "$LAST_DEVICE_FILE" ]; then
   echo "No last ALSA device record found. Skipping..."
   exit 0
fi
# Read the last stored ALSA device information from the file
LAST_FILE_ROW1=$(head -n 1 "$LAST_DEVICE_FILE")
LAST_FILE_ROW2=$(head -n 2 "$LAST_DEVICE_FILE" | tail -n 1)
LAST_FILE_ROW3=$(head -n 3 "$LAST_DEVICE_FILE" | tail -n 1)
LAST_FILE_ROW4=$(head -n 4 "$LAST_DEVICE_FILE" | tail -n 1)
# Extract stored values
LAST_CARD=$(echo "$LAST_FILE_ROW1" | awk '{gsub(":", "", $2); print $2}')
LAST_DEVICE=$(echo "$LAST_FILE_ROW1" | cut -d' ' -f3-)
LAST_OUTPUT_MODE="$LAST_FILE_ROW2"
LAST_VOLUME_MAX="$LAST_FILE_ROW3"
LAST_MIXER_TYPE="$LAST_FILE_ROW4"
# Pooling
while true; do
   # Detect the current ALSA device
   CURRENT_CARD=$(aplay -l | grep "$LAST_DEVICE" | awk -F'[: ]+' '{print $2}')
   # If the device is not found, continue the loop
   if [[ -z "$CURRENT_CARD" ]]; then
       echo "Last ALSA device ($LAST_DEVICE) not found in aplay -l. Skipping..."
       sleep 3
       continue
   fi

   CURRENT_DEVICE="$LAST_DEVICE"
   echo "Last ALSA: card $LAST_CARD ($LAST_DEVICE)"
   echo "Current ALSA: card $CURRENT_CARD ($CURRENT_DEVICE)"
   # Get the currently stored ALSA device in Moode
   CFG_MPD_CARD=$(moodeutl -q "SELECT value FROM cfg_mpd WHERE param='device';" | awk -F'|' '{print $1}')
   if [ "$CFG_MPD_CARD" != "$LAST_CARD" ]; then
       echo "Updating Moode to use last known ALSA device ($LAST_CARD : $LAST_DEVICE) | $LAST_OUTPUT_MODE | $LAST_VOLUME_MAX | $LAST_MIXER_TYPE ..."
       sleep 1
       moodeutl -q "UPDATE cfg_mpd SET value='$LAST_CARD' WHERE param='device'; \
       UPDATE cfg_system SET value='$LAST_DEVICE' WHERE param='adevname'; \
       UPDATE cfg_system SET value='$LAST_CARD' WHERE param='cardnum'; \
       UPDATE cfg_system SET value='$LAST_OUTPUT_MODE' WHERE param='alsa_output_mode'; \
       UPDATE cfg_system SET value='$LAST_VOLUME_MAX' WHERE param='alsavolume_max'; \
       UPDATE cfg_mpd SET value='$LAST_MIXER_TYPE' WHERE param='mixer_type';"

        echo "Cleaning \$_SESSION variables..."
        moodeutl -D cardnum
        moodeutl -D adevname
        moodeutl -D alsa_output_mode
        moodeutl -D alsavolume_max
        moodeutl -D amixname
       break
   fi
   sleep 5
done

sleep 1
# Restart Moode services as the www-data user
if ! pgrep -f "moodeutl -r" > /dev/null; then
   echo "Restarting Moode servers..."
   /bin/su -s /bin/bash -c "moodeutl -r" www-data
else
   echo "Moode server is already being restarted. Skipping..."
fi
> systemd Service:
sudo nano /etc/systemd/system/detect_alsa_device.service
Code:
[Unit]
Description=Detect ALSA device and restore last known output
After=sound.target network.target
Requires=sound.target

[Service]
ExecStart=/usr/local/bin/detect_alsa_device.sh
Restart=on-failure
RestartSec=5
User=root
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

[Install]
WantedBy=multi-user.target

2. Device Monitoring
> script:
sudo nano /usr/local/bin/monitor_alsa_device.sh
Code:
#!/bin/bash

WATCH_DIR="/etc/alsa/conf.d/"
LAST_DEVICE_FILE="/var/local/last-alsa-device"

echo "Starting ALSA device monitor..." | systemd-cat -t monitor_alsa_device

inotifywait -m -e moved_to,delete_self,modify "$WATCH_DIR" | while read path action file; do
    if [ "$file" == "_audioout.conf" ]; then
        echo "Detected change in _audioout.conf ($action)"

        CURRENT_CARD=$(moodeutl --hwparams | grep "card" | awk -F'[: ]+' '{print $2}')
        CURRENT_DEVICE=$(moodeutl --hwparams | grep "card" | cut -d' ' -f3-)

        if [[ "$CURRENT_CARD" == "empty" ]]; then
            echo "ALSA device not initialized yet. Skipping update."
            continue
        fi
        echo "Temporarily stopping detect_alsa_device.service"
        systemctl stop detect_alsa_device.service
        sleep 1
        FORMATTED_ENTRY="card $CURRENT_CARD: $CURRENT_DEVICE"

        echo "Recording last ALSA device: $FORMATTED_ENTRY"
        echo "$FORMATTED_ENTRY" > "$LAST_DEVICE_FILE"
        moodeutl -q "SELECT value FROM cfg_system WHERE param='alsa_output_mode'" >> "$LAST_DEVICE_FILE"
        moodeutl -q "SELECT value FROM cfg_system WHERE param='alsavolume_max'" >> "$LAST_DEVICE_FILE"
        moodeutl -q "SELECT value FROM cfg_mpd WHERE param='mixer_type'" >> "$LAST_DEVICE_FILE"
    fi
done
> systemd Service:
sudo nano /etc/systemd/system/monitor_alsa_device.service
Code:
[Unit]
Description=Monitor ALSA device changes for Moode
After=sound.target network.target
Requires=sound.target

[Service]
ExecStart=/usr/local/bin/monitor_alsa_device.sh
Restart=on-failure
RestartSec=5s
User=root

[Install]
WantedBy=multi-user.target

Any insights or suggestions would be greatly appreciated.

Thanks!
Reply


Messages In This Thread
RE: Keep Last Selected Audio Output Device After Reboot - by storaid - 03-15-2025, 11:03 AM

Forum Jump: