3

When I'm playing some games like chivalry Medieval Warfare and I switch to another software like Firefox or Desktop the sound of the game still plays.

So, How can I fix this problem ?

Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497

3 Answers3

5

(Automatically) mute sound of a specific application if its window is not in front

I tested the script below on Rhythmbox, doing the job without a single error.

Running the script below in the background will pause the targeted process if its window is not in front (within one second), muting sound if it comes with the application.
Whenever the window gets in front again, the process is resumed where it was, and sound works again.

If the targeted process/application does not run at all, the script switches to a longer period (mode), checking only once per five seconds if the targeted application runs or not. This way, the script is extremely low on juice if it has no job to fulfill.

The script

#!/usr/bin/env python3
import subprocess
import time

# ---set the proc to pause when not the active window
wclass = "rhythmbox"
# ---

def get(cmd):
    # just a helper function to not repeat verbose subprocess sections
    try:
        return subprocess.check_output(cmd).decode("utf-8").strip()
    except subprocess.CalledProcessError:
        pass

while True:
    # the longer period: application is not running (saving fuel)
    time.sleep(5)
    front1 = ""
    while True:
        # if the application runs, switch to a shorter response time
        time.sleep(1)
        # get the possible pid, get() returns "None" if not running,
        # script then switches back to 5 sec check
        pid = get(["pgrep", wclass])
        if pid:
            front2 = wclass in get([
                "xprop", "-id", get(["xdotool", "getactivewindow"])
                ])
            # run either kill -stop or kill -cont only if there is
            # a change in the situation
            if front2 != front1:
                if front2 == True:
                    cm = ["kill", "-cont", pid]
                    print("run") # just a test indicator, remove afterwards
                else:
                    cm = ["kill", "-stop", pid]
                    print("stop") # just a test indicator, remove afterwards
                subprocess.Popen(cm)
            front1 = front2
        else:
            break

How to use

  • The script needs xdotool to get information on the frontmost window:

    sudo apt-get install xdotool
    
  • Copy the script into an empty file, save it as pause_app.py
  • In the head section of the script, set the process name to pause (replace rhythmbox).
    Usually this is the same as the (first section of) the WM_CLASS, but in your case, I am having doubts if this should not be steam or something else. Run to make sure

    ps -u <yourname>
    

    to make an educated guess, and subsequently

    kill <pid> 
    (the process id)
    

    to check.

  • Run the script by the command:

    python3 /path/to/pause_app.py
    

    and check if all works as expected.

  • If all works fine, add to Startup Applications: Dash > Startup Applications > Add. Then add the command:

    python3 /path/to/pause_app.py
    

Note

The script can be easily edited to target multiple applications, but first please see if this is what you need.

Alternatively

If you'd prefer to mute the sound in general once the targeted window is not in front, replace the command to pause the application by the command to mute (/unmute) sound. The script then becomes:

#!/usr/bin/env python3
import subprocess
import time

# ---set the proc to pause when not the active window
wclass = "rhythmbox"
# ---

def get(cmd):
    # just a helper function to not repeat verbose subprocess sections
    try:
        return subprocess.check_output(cmd).decode("utf-8").strip()
    except subprocess.CalledProcessError:
        pass

while True:
    # the longer period: application is not running (saving fuel)
    time.sleep(5)
    front1 = ""
    while True:
        # if the application runs, switch to a shorter response time
        time.sleep(1)
        # get the possible pid, get() returns "None" if not running,
        # script then switches back to 5 sec check
        pid = get(["pgrep", wclass])
        if pid:
            front2 = wclass in get([
                "xprop", "-id", get(["xdotool", "getactivewindow"])
                ])
            # run either kill -stop or kill -cont only if there is
            # a change in the situation
            if front2 != front1:
                if front2 == True:
                    cm = ["amixer", "-q", "-D", "pulse", "sset", "Master", "on"]
                    print("sound") # just a test indicator, remove afterwards
                else:
                    cm = ["amixer", "-q", "-D", "pulse", "sset", "Master", "off"]
                    print("no sound") # just a test indicator, remove afterwards
                subprocess.Popen(cm)
            front1 = front2
        else:
            break

Usage is exactly similar to the first script.

Jacob Vlijm
  • 83,767
4

The script bellow relies on all native tools of Ubuntu, pactl and qdbus to determine active app, automatically mute and unmute as the app gains and focus from user.

The app name is set in APP_ICON_NAME variable. You can use pactl list sink-inputs | grep icon_name to determine the value you need it to be set. In my case, i tested it with chromium-browser .

The script will undergo minor improvements in style and perhaps additional features will be added , but as of right now it's 90% usable and performs it's task properly. It will eventually be posted to github

#!/bin/bash

list_sinks()
{
  pactl list sink-inputs | awk '/Sink Input #/{ sub(/#/," ");  printf $3" "} /application.icon_name/{ printf $0"\n" }'
}

get_active_app_icon_name()
{
  qdbus org.ayatana.bamf  /org/ayatana/bamf/matcher org.ayatana.bamf.matcher.ActiveApplication \
      | xargs -I {} qdbus org.ayatana.bamf {} org.ayatana.bamf.view.Icon
}



get_sinks_for_app()
{
  list_sinks | while read line ; do

    if grep -q "$APP_ICON_NAME" <<< "$line"
    then
       awk '{printf $1" "}' <<< "$line"
    fi
 done
}

mute_sinks()
{
   for sink_id in $( get_sinks_for_app  ) ; do
       pactl set-sink-input-mute "$sink_id" 1
   done
}

unmute_sinks()

{
   for sink_id in $( get_sinks_for_app  ) ; do
       pactl set-sink-input-mute "$sink_id" 0
   done
}
main()
{
  local APP_ICON_NAME="chromium-browser"

  while true 
  do

     if [ "$( get_active_app_icon_name )" != "$APP_ICON_NAME" ] ;
     then
          mute_sinks
     else 
         unmute_sinks
     fi

  sleep 0.25  
  done
}


main
Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497
3

If the game is using the normal sound system from ubuntu, a.k.a. pulse audio, then you go into:

system settings -> sound -> applications

You should see your song playing application there, you can change the volume and even mute it.