Моя цель состоит в том, чтобы смочь отключить звук приложения Spotify, не всей системы. Используя команду: ps -C spotify -o pid=
Я могу найти идентификатор процесса Spotify, в этом случае идентификатор "22981"
. С тем идентификатором процесса я хотел бы искать из этого списка: pacmd list-sink-inputs
. Та команда возвращает список как это:
eric@eric-desktop:~$ pacmd list-sink-inputs
Welcome to PulseAudio! Use "help" for usage information.
>>> 1 sink input(s) available.
index: 0
driver: <protocol-native.c>
flags: START_CORKED
state: RUNNING
sink: 1 <alsa_output.pci-0000_00_1b.0.analog-stereo>
volume: 0: 100% 1: 100%
0: -0.00 dB 1: -0.00 dB
balance 0.00
muted: no
current latency: 1019.80 ms
requested latency: 371.52 ms
sample spec: s16le 2ch 44100Hz
channel map: front-left,front-right
Stereo
resample method: (null)
module: 8
client: 10 <Spotify>
properties:
media.role = "music"
media.name = "Spotify"
application.name = "Spotify"
native-protocol.peer = "UNIX socket client"
native-protocol.version = "26"
application.process.id = "22981"
application.process.user = "eric"
application.process.host = "eric-desktop"
application.process.binary = "spotify"
window.x11.display = ":0"
application.language = "en_US.UTF-8"
application.process.machine_id = "058c89ad77c15e1ce0dd5a7800000012"
application.process.session_id = "058c89ad77c15e1ce0dd5a7800000012-1345692739.486413-85297109"
application.icon_name = "spotify-linux-512x512"
module-stream-restore.id = "sink-input-by-media-role:music"
Теперь я хотел бы коррелировать application.process.id = "22981"
к входному индексу приемника, который в этом случае является index: 0
. Теперь с тем индексом я затем должен был выполнить эту команду: pacmd set-sink-input-mute 0 1
отключать звук Spotify и pacmd set-sink-input-mute 0 0
не отключать звук Spotify. Для тех команд первое число должно было бы быть заменено индексом, найденным ранее, и следующее число является булевской переменной для включения или выключения бесшумного режима. Как я могу поместить это в целом в сценарий, таким образом, я могу заставить команду отключать звук/не отключать звук приложения Spotify?
Править: Оба из сценариев ниже работы как ожидалось, может кто-то добавлять переключатель, который проверил бы muted: yes
или muted: no
и затем бесшумный режим или небесшумный режим соответственно?
Править: Я смог изменить сценарий glenn jackman для добавления переключателя:
#!/bin/bash
main() {
local action=toggle
while getopts :mu option; do
case "$option" in
m) action=mute ;;
u) action=unmute ;;
?) usage 1 "invalid option: -$OPTARG" ;;
esac
done
shift $((OPTIND - 1))
local pid=$(pidof "$1")
if [[ -z "$pid" ]]; then
echo "error: no running processes for: $1" >&2
elif [[ "$1" ]]; then
$action "$1"
else
usage 1 "specify an application name"
fi
}
usage() {
[[ "$2" ]] && echo "error: $2"
echo "Usage: $0 [-m | -u] appname"
echo "Default: toggle mute"
echo "Arguments:"
echo "-m = mute application"
echo "-u = unmute application"
exit $1
}
toggle() {
local status=$(get_status "$1")
if [[ "$status" == "yes" ]]; then
unmute "$1"
elif [[ "$status" == "no" ]]; then
mute "$1"
fi
}
mute() { adjust_muteness "$1" 1; }
unmute() { adjust_muteness "$1" 0; }
adjust_muteness() {
local index=$(get_index "$1")
local status=$(get_status "$1")
[[ "$index" ]] && pacmd set-sink-input-mute "$index" $2 >/dev/null
}
get_index() {
local pid=$(pidof "$1")
pacmd list-sink-inputs |
awk -v pid=$pid '
$1 == "index:" {idx = $2}
$1 == "application.process.id" && $3 == "\"" pid "\"" {print idx; exit}
'
}
get_status() {
local pid=$(pidof "$1")
pacmd list-sink-inputs |
awk -v pid=$pid '
$1 == "muted:" {idx = $2}
$1 == "application.process.id" && $3 == "\"" pid "\"" {print idx; exit}
'
}
main "$@"
Вот мой взгляд на ваш интересный вызов:
#!/bin/bash
main() {
local action=mute
while getopts :hu option; do
case "$option" in
h) usage 0 ;;
u) action=unmute ;;
?) usage 1 "invalid option: -$OPTARG" ;;
esac
done
shift $((OPTIND - 1))
if [[ "$1" ]]; then
$action "$1"
else
usage 1 "specify an application name"
fi
}
usage() {
[[ "$2" ]] && echo "error: $2"
echo "usage: $0 [-h] [-u] appname"
echo "where: -u = ummute application (default action is to mute)"
exit $1
}
mute() { adjust_muteness "$1" 1; }
unmute() { adjust_muteness "$1" 0; }
adjust_muteness() {
local index=$(get_index "$1")
[[ "$index" ]] && pacmd set-sink-input-mute "$index" $2 >/dev/null
}
get_index() {
local pid=$(pidof "$1")
if [[ -z "$pid" ]]; then
echo "error: no running processes for: $1" >&2
else
pacmd list-sink-inputs |
awk -v pid=$pid '
$1 == "index:" {idx = $2}
$1 == "application.process.id" && $3 == "\"" pid "\"" {print idx; exit}
'
fi
}
main "$@"
Несмотря на то, что вопрос касается сценария, я хотел оставить его здесь.
Я написали приложение C, которое делает это на Ubuntu. Более того, он находится на панели индикаторов (используя libappindicator
) и проверяет, что играет Spotify, через короткие промежутки времени. Если он воспроизводит рекламу (сверяется с черным списком), он отключает звук Spotify. Если воспроизводится новая реклама, вы просто нажимаете «Отключить» в меню индикатора, и она добавляется в черный список.
Что он делает, так это ищет окно X, для которого XFetchName
возвращает Spotify - Linux Preview
. Затем он вызывает XGetWindowProperty
, чтобы запросить свойство _NET_WM_ICON_NAME
этого окна, которое возвращает строку в формате «Spotify -
. При воспроизведении рекламы он возвращает что-то вроде этого:
"Spotify – Spotify – Premium Free Trial Cancel Any Time"
Он поддерживает троичное дерево поиска списка объявлений, чтобы эффективно проверять, присутствует ли текущий заголовок в списке.
Он также использует Асинхронный API PulseAudio для запроса входов-приемников
и установить отключение звука
:
pa_context_get_sink_input_info_list()
pa_context_set_sink_input_mute()
Поскольку это простой код C, он легковесен. Ознакомьтесь с исходным кодом и пакетом Ubuntu .deb
по адресу: indicator-muteads . Вероятно, он бы превзошел сценарий оболочки на 2-3 порядка.
Прежде всего, "более правильный" способ найти PID приложения, как испортить, это использовать:
pidof spotify
Я создал скрипт, который делает эту работу, я не знаю, если это лучший способ сделать это, но он работает отлично:
#!/bin/bash
# Script to mute an application using PulseAudio, depending solely on
# process name, constructed as answer on askubuntu.com:
# http://askubuntu.com/questions/180612/script-to-mute-an-application
#It works as: mute_application.sh vlc mute OR mute_application.sh vlc unmute
if [ -z "$1" ]; then
echo "Please provide me with an application name"
exit 1
fi
if [ -z "$2" ]; then
echo "Please provide me with an action mute/unmute after the application name"
exit 1
fi
if ! [[ "$2" == "mute" || "$2" == "unmute" ]]; then
echo "The 2nd argument must be mute/unmute"
exit 1
fi
process_id=$(pidof "$1")
if [ $? -ne 0 ]; then
echo "There is no such process as "$1""
exit 1
fi
temp=$(mktemp)
pacmd list-sink-inputs > $temp
inputs_found=0;
current_index=-1;
while read line; do
if [ $inputs_found -eq 0 ]; then
inputs=$(echo -ne "$line" | awk '{print $2}')
if [[ "$inputs" == "to" ]]; then
continue
fi
inputs_found=1
else
if [[ "${line:0:6}" == "index:" ]]; then
current_index="${line:7}"
elif [[ "${line:0:25}" == "application.process.id = " ]]; then
if [[ "${line:25}" == "\"$process_id\"" ]]; then
#index found...
break;
fi
fi
fi
done < $temp
rm -f $temp
if [ $current_index -eq -1 ]; then
echo "Could not find "$1" in the processes that output sound."
exit 1
fi
#muting...
if [[ "$2" == "mute" ]]; then
pacmd set-sink-input-mute "$current_index" 1 > /dev/null 2>&1
else
pacmd set-sink-input-mute "$current_index" 0 > /dev/null 2>&1
fi
exit 0
Вы можете работать с как:
./mute_application.sh spotify mute
или
./mute_application.sh spotify unmute
Проверено с Audacious и Vlc запустить и отключить/отключить только один из них.
спасибо за решение! Мне удалось использовать предоставленные здесь сценарии, чтобы решить мою проблему. Поскольку мне пришлось немного их изменить, здесь я присоединяюсь к улучшенной версии.
Причина, по которой исходные сценарии у меня не работали, заключается в том, что некоторые приложения могут иметь несколько экземпляров, то есть несколько PID, но, возможно, только один из них является воспроизводящий звук, и поэтому фактически подключен к Pulseaudio. Поскольку в сценарии используется только первый найденный PID, он обычно / не / отключает / отключает / отключение звука желаемого приложения.
Итак, вот версия, в которой аргументом является имя приложения, зарегистрированное в PulseAudio. Вы можете найти это имя, выполнив команду pacmd list-opt-inputs
и найдите поле application.name
.
Альтернативным решением может быть отключение / включение всех PID, которые иметь такое же имя приложения.
#!/bin/bash
# Adapter from glenn jackman on http://askubuntu.com/questions/180612/script-to-mute-an-application
# to depend directly on the name of the PulseAudio client
# rather than the application name (several instances of one application could
# run while only one is connected to PulseAudio)
# Possible further improvement: it could be useful to also mute all clients having
# the specified name. Here, only the first one is muted.
#!/bin/bash
main() {
local action=mute
while getopts :hu option; do
case "$option" in
h) usage 0 ;;
u) action=unmute ;;
?) usage 1 "invalid option: -$OPTARG" ;;
esac
done
shift $((OPTIND - 1))
if [[ "$1" ]]; then
$action "$1"
else
usage 1 "specify the name of a PulseAudio client"
fi
}
usage() {
[[ "$2" ]] && echo "error: $2"
echo "usage: $0 [-h] [-u] appname"
echo "where: -u = ummute application (default action is to mute)"
exit $1
}
mute() { adjust_muteness "$1" 1; }
unmute() { adjust_muteness "$1" 0; }
adjust_muteness() {
local index=$(get_index "$1")
if [[ -z "$index" ]]; then
echo "error: no PulseAudio sink named $1 was found" >&2
else
[[ "$index" ]] && pacmd set-sink-input-mute "$index" $2 >/dev/null
fi
}
get_index() {
# local pid=$(pidof "$1")
# if [[ -z "$pid" ]]; then
# echo "error: no running processes for: $1" >&2
# else
pacmd list-sink-inputs |
awk -v name=$1 '
$1 == "index:" {idx = $2}
$1 == "application.name" && $3 == "\"" name "\"" {print idx; exit}
'
# fi
}
main "$@"
Я действительно не могу создать скрипт, но я изменил скрипт hakermania, чтобы создать еще один.
Этот скрипт увеличит или уменьшит громкость конкретного приложения с шагом 5%:
edit : на самом деле, он работает при постоянном изменении последнего открытого приложения. Идеи?
#!/bin/bash
# Script to increase or decrease an individual application's volume using PulseAudio, depending solely on
# process name, based on another script by hakermania, constructed as answer on askubuntu.com:
# http://askubuntu.com/questions/180612/script-to-mute-an-application
# It works as: change_app_volume.sh vlc increase OR change_app_volume.sh vlc decrease
# Set desired increments in lines #66 and #68
if [ -z "$1" ]; then
echo "Please provide me with an application name"
exit 1
fi
if [ -z "$2" ]; then
echo "Please provide me with an action increase/decrease after the application name"
exit 1
fi
if ! [[ "$2" == "increase" || "$2" == "decrease" ]]; then
echo "The 2nd argument must be increase/decrease"
exit 1
fi
process_id=$(pidof "$1")
if [ $? -ne 0 ]; then
echo "There is no such process as "$1""
exit 1
fi
temp=$(mktemp)
pacmd list-sink-inputs > $temp
inputs_found=0;
current_index=-1;
while read line; do
if [ $inputs_found -eq 0 ]; then
inputs=$(echo -ne "$line" | awk '{print $2}')
if [[ "$inputs" == "to" ]]; then
continue
fi
inputs_found=1
else
if [[ "${line:0:6}" == "index:" ]]; then
current_index="${line:7}"
elif [[ "${line:0:25}" == "application.process.id = " ]]; then
if [[ "${line:25}" == "\"$process_id\"" ]]; then
#index found...
break;
fi
fi
fi
done < $temp
rm -f $temp
if [ $current_index -eq -1 ]; then
echo "Could not find "$1" in the processes that output sound."
exit 1
fi
#increase/decrease...
if [[ "$2" == "increase" ]]; then
pactl set-sink-input-volume "$current_index" +5% > /dev/null 2>&1
else
pactl set-sink-input-volume "$current_index" -5% > /dev/null 2>&1
fi
exit 0
Отредактированный скрипт для отключения всех входных данных приложения (нескольких процессов) и по умолчанию переключено:
#!/bin/bash
main() {
local action=toggle
while getopts :hum option; do
case "$option" in
h) usage 0 ;;
m) action=mute ;;
u) action=unmute ;;
?) usage 1 "invalid option: -$OPTARG" ;;
esac
done
shift $((OPTIND - 1))
if [[ "$1" ]]; then
$action "$1"
else
usage 1 "specify an application name"
fi
}
usage() {
[[ "$2" ]] && echo "error: $2"
echo "usage: $0 [-h] [-u | -m] appname"
echo "where: -u = ummute , -m = mute (default action is to toggle)"
echo "Usage examples:"
echo " toggle mute: $0 appname"
echo " to mute an app: $0 -m appname"
echo " to unmute an app: $0 -u appname"
exit $1
}
mute() { adjust_muteness "$1" 1; }
unmute() { adjust_muteness "$1" 0; }
toggle() { adjust_muteness "$1" toggle; }
adjust_muteness() {
clients=$(pactl list clients short | awk '/[0-9]+.*'$1'.*/{print $1}')
inputs=$(pactl list sink-inputs short)
for c in $clients; do
for i in $(printf '%s' "$inputs" | awk '/[0-9]+\s[0-9]+\s'$c'/{print $1}'); do
pactl set-sink-input-mute $i $2 &
done
done
}
main "$@"
Я изменил скрипт Джага, чтобы включить отключение звука. Я назначил это сочетанию клавиш для включения / выключения звука Chromium. pidof
очевидно не работает с Chromium. Таким образом, здесь используется клиент Pulseaudio.
#!/bin/bash
# Adapter from glenn Jag on http://askubuntu.com/questions/180612/script-to-mute-an-application
# Toggles muting of all audio streams of an app
main() {
if [[ "$1" ]]; then
prev=""; prev2="";
while read line; do
if [[ $line = "end" ]]; then
adjust_muteness $1 $(echo "$prev2 $prev" | tr -d '\n')
prev=""; prev2="";
else
if [[ $prev2 = "" ]]; then prev2=$line; else prev=$line; fi
fi
done < <(get_info "$1")
else
usage 1 "specify the name of a PulseAudio client"
fi
}
usage() {
[[ "$2" ]] && echo "error: $2"
echo "usage: $0 [-h] [-u] appname"
exit $1
}
adjust_muteness() {
# muted or not
muted=$2
# process ID
index=$3
# muteness value
if [[ $muted = "yes" ]]; then
mute=0 # unmute
else
mute=1 # mute
fi
echo $muted
if [[ -z "$index" ]]; then
echo "error: no PulseAudio sink named $1 was found" >&2
else
[[ "$index" ]] && pacmd set-sink-input-mute "$index" $mute >/dev/null
fi
}
get_info() {
pacmd list-sink-inputs |
awk -v name=$1 '
$1 == "index:" {idx = $2}
$1 == "muted:" {idm = $2}
$1 == "application.name" && $3 == "\"" name "\"" {print idm; print idx; print "end";}
'
}
main "$@"
Использование:
./mute-app.sh Chromium
Вы можете получить имена приложений с помощью pacmd list-receiver-inputs