(XFCE) Basic SH script to fade out/fade in volume using Playerctl (Winamp style)

Hello !
I use playerctl to control audio on FreeBSD from a keyboard shortcut, and I didn't really enjoy the fact that it instantly pauses the sound, so it "cuts" the sound. Same when I turn it back on, and as a very old Winamp user, I've always enjoyed the fade out/fade in applied. So I've written a very small sh script to mimic it.

Because it relies on playerctl (which is not necessary, you can remove reference to it and use it without); it is session wide and will work with anything that playerctl can control : Firefox stream, VLC, Audacious, etc etc.

Please be kind, I'm really *noob*, so the script can be heavily optimized, and can be pretty easy to break... I did it the way I could and it works for me. I did it for me but if it can be useful to someone else, that's nice :)

Intended for use with XFCE (just call the script by a keyboard shortcut) ; notifications are enabled. The script is provided as is, do anything you want with it, but I didn't add anything to protect the script from bugs !

The code needs to be saved into anything.sh and chmod +x. The concept is pretty simple :
- It checks the volume value.
- If the current volume value is <0, then a file called volume.txt is created next to the script with the current volume value stored in (I understood (?) that I can't store the value into a variable out of another terminal window, so I store it in a file, I don't like but nevermind !). The volume is then set to 0 using a loop (values you can change to affect the delay : step and delay. They are on top of the script to affect them easily). Then, playerctl is run to pause the audio.
- If the current volume value = 0, then it will look for volume.txt file (there's no security to check if the file exist or not), reads the value inside, start playerctl to play the audio and set the volume back with a fade in. The file volume.txt is deleted.

Code:
step=.1 # Increment step, value (ie 0.10). Percent do not work. The lower it is, smoother is the fade, but will make the fade longer. Adjust delay consequently !
delay=.333 #Delay in sec, or whatever you like. Don't put days. YOU DON'T WANT TO... RIGHT?

# Check volume value. If set to zero, suppose we need a fade-in. Also check if volume.txt exists.

CurrentVolume=$(mixer vol.volume | sed 's/.*s*\t*s* *s*://')

if [ $CurrentVolume = "0.00" ]
then
    echo Volume set to 0. Supposing a fade in is required.
    if [ -e volume.txt ]
    then
        echo FADING IN !
        PreviousVolume=$(cat volume.txt)
        rm volume.txt
    
        echo Previous volume value : $PreviousVolume

        playerctl play-pause
        notify-send -i /usr/local/share/icons/elementary-xfce/panel/24/audio-volume-high.png -t 10 'Play' "Vol : $PreviousVolume"

        for volume in $(seq 0 $step $PreviousVolume)
        do
            echo $(mixer -o vol.volume=$volume)
            sleep .05
        done
    fi
else
    echo FADING OUT !
    echo Current Volume set : $CurrentVolume
    printf '%s\n' "$CurrentVolume" >volume.txt

    notify-send -i /usr/local/share/icons/elementary-xfce/panel/24/audio-volume-muted.png -t 10 'Pause'

    for volume in $(seq $CurrentVolume -$step 0)
    do
        echo $(mixer -o vol.volume=$volume)
        sleep .05
    done
    echo $(mixer vol.volume=0) # Force value to 0, NEEDED because fade in switch expects a value of 0 to operate.
    
    playerctl play-pause
fi
 
[…] If the current volume value is <0, then a file called volume.txt is created next to the script with the current volume value stored in (I understood (?) that I can't store the value into a variable out of another terminal window, so I store it in a file, I don't like but nevermind !). […]
You can spare the volume.txt auxiliary file by using the vol.mute value as implicit storage. ?️​
  • vol.mute is 0 → fade‑out requested.​
    1. Save the current vol.volume value in a shell (script) variable.​
    2. Fade out, fade out, fade out, fade out.​
    3. Mute the main mixer.​
    4. playerctl pause
    5. Restore the original volume consulting the shell variable.​
  • vol.mute is 1 → fade‑in requested.​
    1. Save the current vol.volume value in a shell variable.​
    2. Mute the main mixer. Whoops, brain fart, it’s already muted.​
    3. Set vol.volume to 0.​
    4. Unmute the main mixer.​
    5. playerctl play
    6. Fade in, fade in, fade in, fade in.​
[…] Please be kind, I'm really *noob*, so the script can be heavily optimized […]
Don’t worry, it’s actually a pretty neat exercise. The task is not too complicated and there is still some opportunity to optimize, e. g. you can learn how to use shell functions (custom functions you define and use). ? And hey, you spotted you can use vol.volume as implicit storage. Total noobs might have created yet another auxiliary file fadein.txt/fadeout.txt just to convey that piece of information.​
 
That's a very interesting idea, everything works but I need to admit that using a file to store a variable is kind of Microsofty ?
I'll test this later, thanks a lot for this idea !!

EDIT : updated the code and using your method,works perfect ! It allows to get a cleaner code without any running txt file. I also cleaned several parts.
Nice one Kai Burghardt !!!

Code:
#!/bin/sh
# 15/10/2024

step=.1 # Increment step, either value (ie 0.10). Percent do not work. The lower it is, smoother is the fade, but will make the fade longer. Adjust delay consequently !
delay=.333 #Delay in sec, or whatever you like. Don't put days. YOU DON'T WANT TO... RIGHT?

# Stores current volume value, then check if vol.mute=on. If it is, suppose we need a fade-in.

CurrentVolume=$(mixer vol.volume | sed 's/.*s*\t*s* *s*://')

if [ $(mixer vol.mute | sed 's/vol.mute=//') = "on" ]
then    # FADE IN
    mixer vol.volume=0
    mixer -o vol.mute=off

    playerctl play-pause
    notify-send -i /usr/local/share/icons/elementary-xfce/panel/24/audio-volume-high.png -t 10 'PLAY IT LOUD' "Vol : $CurrentVolume"

    for volume in $(seq 0 $step $CurrentVolume)
    do
        mixer -o vol.volume=$volume
        sleep .05
    done
        
else    # FADE OUT
    notify-send -i /usr/local/share/icons/elementary-xfce/panel/24/audio-volume-muted.png -t 10 'PAUSE'

    for volume in $(seq $CurrentVolume -$step 0)
    do
        mixer -o vol.volume=$volume
        sleep .05
    done
    mixer vol.volume=0 # Force value to 0, because it's cleaner.

    playerctl play-pause

    mixer -o vol.mute=on
    mixer vol.volume=$CurrentVolume
fi
 
Last edited:
Back
Top