web-dev-qa-db-ja.com

フォーカスがないときにアプリケーションを自動的にミュートするにはどうすればよいですか?

Chivalry Medieval Warfareのようなゲームをプレイしていて、FirefoxやDesktopのような別のソフトウェアに切り替えると、ゲームのサウンドが引き続き再生されます。

だから、どうすればこの問題を修正できますか?

3
Battlefield TAG

(自動)ウィンドウが前面にない場合、特定のアプリケーションのサウンドをミュートします

Rhythmboxで以下のスクリプトをテストし、1つのエラーなしでジョブを実行しました。

以下のスクリプトをバックグラウンドで実行すると、ウィンドウが前面にない場合(1秒以内)にターゲットプロセスが一時停止し、アプリケーションに付属している場合はサウンドがミュートされます。
ウィンドウが再び前面に表示されるたびに、プロセスが再開され、サウンドが再び機能します。

対象のプロセス/アプリケーションがまったく実行しないを実行する場合、スクリプトはより長い期間(モード)に切り替わり、5秒に1回のみ対象のアプリケーションが実行されるかどうかを確認します。このように、実行する仕事がない場合、スクリプトのジュースは非常に少なくなります。

スクリプト

#!/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

使い方

  • スクリプトは、最前面のウィンドウの情報を取得するためにxdotoolを必要とします:

    Sudo apt-get install xdotool
    
  • スクリプトを空のファイルにコピーし、pause_app.pyとして保存します
  • スクリプトのヘッドセクションで、プロセス名を一時停止に設定します(rhythmboxを置き換えます)。
    通常、これはWM_CLASS(の最初のセクション)と同じですが、あなたの場合、これがSteamまたは他の何かであってはならないかどうか疑問に思っています。実行して確認してください

    ps -u <yourname>
    

    経験に基づいた推測を行い、その後

    kill <pid> 
    (the process id)
    

    チェックする。

  • 次のコマンドでスクリプトを実行します。

    python3 /path/to/pause_app.py
    

    すべてが期待どおりに動作するかどうかを確認します。

  • すべてが正常に機能する場合は、スタートアップアプリケーションに追加します:[ダッシュ]> [スタートアップアプリケーション]> [追加]。次に、コマンドを追加します。

    python3 /path/to/pause_app.py
    

注意

このスクリプトは、複数のアプリケーションを対象とするように簡単に編集できますが、最初にこれが必要かどうかを確認してください。

代わりに

サウンドをミュートしたい場合一般ターゲットウィンドウが前面にない場合は、コマンドをアプリケーションを一時停止に置き換えて、コマンドをmute (/ミュート解除)音。スクリプトは次のようになります。

#!/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

使用方法は、最初のスクリプトとまったく同じです。

5
Jacob Vlijm

以下のスクリプトは、Ubuntuのすべてのネイティブツールpactlおよびqdbusに依存して、アクティブなアプリを決定し、アプリがユーザーから取得してフォーカスを取得すると自動的にミュートおよびミュート解除します。

アプリ名はAPP_ICON_NAME変数に設定されます。 pactl list sink-inputs | grep icon_nameを使用して、設定する必要がある値を決定できます。私の場合、chromium-browserでテストしました。

スクリプトはスタイルが少し改善され、おそらく追加機能が追加される予定ですが、現時点では90%が使用可能で、タスクを適切に実行します。最終的には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
4

ゲームがubuntuの通常のサウンドシステム、別名パルスオーディオを使用している場合、次のようになります:

システム設定->サウンド->アプリケーション

そこに曲再生アプリケーションが表示されるはずです。音量を変更したり、ミュートすることもできます。

3
E. Timotei