Mon objectif est de pouvoir désactiver l'application Spotify, pas le système entier. En utilisant la commande: ps -C spotify -o pid=
Je suis en mesure de trouver l'ID de processus de Spotify, dans ce cas l'ID est "22981"
. Avec cet ID de processus, j'aimerais effectuer une recherche dans cette liste: pacmd list-sink-inputs
. Cette commande retourne une liste comme celle-ci:
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"
Maintenant, j'aimerais corréler le application.process.id = "22981"
à l'index d'entrée du puits, qui dans ce cas est index: 0
. Maintenant, avec ce numéro d'index, il me faudrait alors exécuter cette commande: pacmd set-sink-input-mute 0 1
pour désactiver Spotify et pacmd set-sink-input-mute 0 0
pour réactiver Spotify. Pour ces commandes, le premier numéro devrait être remplacé par le numéro d'index trouvé précédemment et le prochain nombre est le booléen pour activer ou désactiver le mode muet. Comment puis-je l'intégrer complètement dans un script afin d'obtenir une commande pour désactiver/activer le son de l'application Spotify?
EDIT: Les deux scripts ci-dessous fonctionnent comme prévu. Quelqu'un peut-il ajouter une bascule permettant de vérifier muted: yes
ou muted: no
, puis d'activer ou de désactiver le son en conséquence?
EDIT: J'ai été capable de modifier le script de Glenn Jackman pour ajouter la bascule:
#!/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 "$@"
Voici mon point de vue sur votre défi intéressant:
#!/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 "$@"
merci pour la solution! J'ai réussi à utiliser les scripts fournis ici pour résoudre mon problème. Comme je devais les modifier un peu, je rejoins ici la version améliorée.
La raison pour laquelle les scripts originaux ne fonctionnaient pas pour moi est que certaines applications peuvent avoir plusieurs instances, c’est-à-dire plusieurs PID, mais peut-être qu’une d’entre elles produit du son et est donc réellement connectée à Pulseaudio. Etant donné que le script utilisait uniquement le premier PID trouvé, l'application souhaitée serait/ne serait pas/désactivée/désactivée.
Donc, voici une version où l'argument est le nom de l'application tel qu'il est enregistré dans PulseAudio. Vous pouvez trouver ce nom en exécutant la commande pacmd list-sink-inputs
et rechercher le champ application.name
.
Une autre solution consisterait à désactiver/réactiver le son de tous les PID portant le même nom d'application.
#!/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 "$@"
Même si la question demande un script, je voulais laisser cela ici.
J'ai écrit une application C qui le fait sur Ubuntu. Mieux encore, il se trouve sur le tableau des indicateurs (à l’aide de libappindicator
) et vérifie la lecture de Spotify à de courts intervalles. Si une annonce est diffusée (comparant avec une liste noire), le Spotify est mis en sourdine. Si une nouvelle annonce est en cours de lecture, il vous suffit de cliquer sur Muet dans le menu des indicateurs et l'ajoute à la liste noire.
Ce qu'il fait, c'est rechercher une fenêtre X pour laquelle XFetchName
renvoie Spotify - Linux Preview
. Ensuite, il appelle XGetWindowProperty
pour interroger la propriété _NET_WM_ICON_NAME
de cette fenêtre, qui renvoie une chaîne au format "Spotify – <Artist> – <Song>"
. Lors de la lecture des annonces, cela renvoie quelque chose comme ceci:
"Spotify – Spotify – Premium Free Trial Cancel Any Time"
Il gère un arbre de recherche ternaire de la liste des annonces, afin de vérifier efficacement si le titre en cours figure dans la liste.
Il utilise également le API PulseAudio asynchrone pour interroger le sink-inputs
et le set-mute
:
pa_context_get_sink_input_info_list()
pa_context_set_sink_input_mute()
Puisqu'il s'agit simplement de code C simple, il est léger. Vérifiez le code source et le paquet Ubuntu .deb
à l'adresse suivante: indicateur-muteads . Il serait probablement préférable à un script Shell de 2 à 3 ordres de grandeur.
Tout d’abord, la façon "plus correcte" de trouver le PID d’une application, comme Spotify, consiste à utiliser:
pidof spotify
J'ai construit un script qui fait le travail, je ne sais pas si c'est la meilleure façon de le faire, mais cela fonctionne parfaitement:
#!/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
Vous pouvez travailler avec est comme:
./mute_application.sh spotify mute
ou
./mute_application.sh spotify unmute
Testé avec Audacious et Vlc en cours de fonctionnement et en désactivation/désactivation du son.
Je ne peux vraiment pas écrire de script, mais j'ai modifié le script de hakermania pour en créer un autre.
Celui-ci augmentera ou diminuera le volume de l'application spécifique par incréments de 5%:
edit: en fait, ça marche en changeant toujours la dernière application ouverte. Des idées?
#!/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
Script édité pour mettre en sourdine toutes les entrées d'une application (processus multiples) et basculer par défaut:
#!/bin/bash
main() {
local action=toggle
while getopts :hu 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] appname"
echo "where: -u = ummute , -m = mute (default action is to toggle)"
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 "$@"