Simple Bash script to mute Spotify while playing ads on Linux.
Requires jq to function as expected.
| #!/usr/bin/env bash | |
| ############### FUNCTIONS ############### | |
| function getAppSinkIndex { | |
| local app_name="$1" | |
| # get sink index for app name, or 'null' on missing | |
| pactl -f json list sink-inputs | jq "map(select(.properties.\"application.name\" | test(\"^$app_name\$\"; \"i\")))[0]?.index" | |
| } | |
| function setAppSinkMute { | |
| local app_name="$1" | |
| local mute_state="$2" | |
| # try setting mute state until succeeds (sink index can be 'null' after app start, before any audio played) | |
| until `pactl set-sink-input-mute $(getAppSinkIndex $app_name) $mute_state 2> /dev/null`; do sleep 1; done | |
| } | |
| ############### PROGRAM ############### | |
| # busctl --user introspect org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 | |
| echo "Start listening..." | |
| # constants | |
| app_name="spotify" | |
| spotify_pattern='string ("/com/spotify/(ad|track)/.+")' | |
| # read lines from media player dbus | |
| dbus-monitor "interface='org.freedesktop.DBus.Properties',path='/org/mpris/MediaPlayer2',member='PropertiesChanged'" | while read -r line; do | |
| # check if message contains spotify entries to determine track types | |
| if [[ "$line" =~ $spotify_pattern ]]; then | |
| # extract variables | |
| spotify_track="${BASH_REMATCH[1]}" | |
| spotify_track_type="${BASH_REMATCH[2]}" | |
| # mute / unmute spotify | |
| if [[ "$spotify_track_type" == "ad" ]]; then | |
| echo "muting an ad: $spotify_track" | |
| setAppSinkMute "$app_name" 1 # mute | |
| else | |
| echo "playing audio: $spotify_track" | |
| setAppSinkMute "$app_name" 0 # unmute | |
| fi | |
| fi | |
| done |