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 ?

6
  • 2
    Perhaps you can mute it in Sound Settings, Applications tab. Jun 12, 2016 at 11:53
  • The WM_CLASS is bftag@KubuntuMSW:~$ xprop WM_CLASS WM_CLASS(STRING) = "UDKGame-Linux", "UDKGame-Linux"
    – gambrelle
    Jun 12, 2016 at 12:07
  • @mikewhatever has the right idea - system settings -> sounds seems to use pactl to mute specific app, which is what i used in my script Jun 12, 2016 at 19:24
  • This not a problem my friend, it is a feature request I think.
    – userDepth
    Jun 13, 2016 at 16:01
  • Thank you all for your support, I am gonna try the script in few days,when I'll can use my computer.
    – gambrelle
    Jun 15, 2016 at 7:01

3 Answers 3

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.

7
  • 1
    Jacob, it would really be great if you would put a few more comment lines in your scripts then newcomers to python can learn as well from them without needing the script in the solution itself :)
    – Videonauth
    Jun 12, 2016 at 19:24
  • 1
    @Videonauth excellent suggestion, I will edit! Jun 12, 2016 at 19:40
  • 1
    yeah I'm one of the python new-bes who scour the site for input how certain things are done ;)
    – Videonauth
    Jun 12, 2016 at 19:42
  • @Videonauth that is a pleasure! will edit tonight, have to get a deadline though at the moment, kind of stressy :) Jun 12, 2016 at 19:51
  • @JacobVlijm Thank you so much I'll try it at home.
    – gambrelle
    Jun 15, 2016 at 6:51
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
14
  • Hi Serg, you really need to look into the system load, it adds too much for a continuesly running process. Jun 12, 2016 at 20:10
  • @JacobVlijm how much ? Jun 12, 2016 at 20:10
  • I get +6 to 7%, but the rule should be imo, if you notice, it's too much. Jun 12, 2016 at 20:11
  • @JacobVlijm htop reports around 2% for me Jun 12, 2016 at 20:13
  • Yeah, that's possible, not sure why and how, but it probably triggers other processes to consume more. We've had this before, I will look it up... Jun 12, 2016 at 20:14
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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .