Jak mogę przełączać się między różnymi urządzeniami wyjściowymi audio za pomocą powłoki?

34

Używam laptopa z zewnętrznym monitorem z głośnikami. Kiedy monitor jest podłączony przez HDMI, mogę przełączać (używając GUI: Ustawienia dźwięku -> Sprzęt) pomiędzy normalnym wyjściem audio laptopa a wyjściem monitora.

Powtarzam tę procedurę dużo czasu i zacząłem się zastanawiać, czy mogę ją zautomatyzować, czy zresztą wykonać ją szybciej za pomocą powłoki.

Moja dystrybucja to Ubuntu 12.04 z gnome 3.

EDYTOWAĆ:

Próbowałem użyć pacmd, ale zlewy list dają mi tylko to urządzenie, którego aktualnie używam:

pacmd list-sinks | grep name:
name: <alsa_output.pci-0000_00_1b.0.hdmi-stereo>

Po przejściu z GUI:

pacmd list-sinks | grep name:
name: <alsa_output.pci-0000_00_1b.0.analog-stereo>

A jeśli spróbuję to zmienić, otrzymam:

pacmd set-default-sink alsa_output.pci-0000_00_1b.0.hdmi-stereo
Welcome to PulseAudio! Use "help" for usage information.
Sink alsa_output.pci-0000_00_1b.0.hdmi-stereo does not exist.
Luigi Massa Gallerano
źródło

Odpowiedzi:

28

W takim przypadku karta jest zawsze taka sama. To, co zmienia się między przełącznikiem a innym, to „profil karty”.

Tak więc rozwiązaniem, które faktycznie działało, jest:

pacmd set-card-profile <cardindex> <profilename>

W moim przypadku znalazłem wszystkie profile kart z:

pacmd list-cards

A potem mogę przełączać się między głośnikami monitora i laptopa za pomocą:

pacmd set-card-profile 0 output:hdmi-stereo

I:

pacmd set-card-profile 0 output:analog-stereo+input:analog-stereo

Gdzie 0 to indeks karty:

pacmd list-cards
Welcome to PulseAudio! Use "help" for usage information.
>>> 1 card(s) available.
    index: 0
    name: <alsa_card.pci-0000_00_1b.0>

I wreszcie, aby przyspieszyć przełączanie, skonfigurowałem dwa aliasy w moim pliku .bashrc:

alias audio-hdmi='pacmd set-card-profile 0 output:hdmi-stereo+input:analog-stereo'
alias audio-laptop='pacmd set-card-profile 0 output:analog-stereo+input:analog-stereo'

W ten sposób mogę przełączać się między dźwiękiem z monitora lub laptopa (słuchawki), wpisując w powłoce: audio-hdmi lub audio-laptop

Luigi Massa Gallerano
źródło
Hm Mój pacmd nie ma opcji „listy kart” ...
ka3ak
3

Na podstawie poprzednich stworzyłem bardzo mały skrypt, który nie tylko przełącza dźwięk, ale także wyjście wideo. Wykorzystuje disper do przełączania między wyświetlaczami.

Oto kod:

#!/bin/bash

CURRENT_PROFILE=$(pacmd list-cards | grep "active profile" | cut -d ' ' -f 3-)

if [ "$CURRENT_PROFILE" = "<output:hdmi-stereo>" ]; then
        pacmd set-card-profile 0 "output:analog-stereo+input:analog-stereo"
        disper -s
else 
        pacmd set-card-profile 0 "output:hdmi-stereo"
        disper -S        
fi

Dla mnie jest to szczególnie przydatne, ponieważ nie lubię klonować wyświetlaczy. Używam jednego lub drugiego. Konieczne może być dostosowanie profili audio do konkretnego systemu.

użytkownik56655
źródło
2

Możesz użyć pactl, przeczytaj jego stronę podręcznika, aby uzyskać więcej informacji.

favadi
źródło
2

Skrypt Pythona Lukasa ( https://github.com/lkettenb/sound-output-switcher , zamieszczony powyżej) do implementacji apletu powiadamiającego działa dobrze. Potrzebuje pakietu appindicator. Można to zainstalować za pomocą

sudo apt-get install python-appindicator
P.Windridge
źródło
3
W odpowiedzi podaj co najmniej kilka słów wyjaśniających, co to jest skrypt i dlaczego jest on przydatny.
derobert
0

Jak powiedziałem tutaj (prawdopodobnie duplikat), alternatywa dla Sound Switcher Indicator (która wymaga dodania PPA):

W jednej linii

W moim przypadku było hdmi-stereo-extra1+inputprofil, więc w jednej linii będzie: [[ $(pacmd list-cards | grep "active profile" | cut -d " " -f 3-) = "<output:hdmi-stereo-extra1+input:analog-stereo>" ]] && pacmd set-card-profile 0 "output:analog-stereo+input:analog-stereo" || pacmd set-card-profile 0 "output:hdmi-stereo-extra1+input:analog-stereo".

Możesz użyć niestandardowego skrótu, aby go wykonać bash -c(ostrzeże Cię, jeśli wystąpi konflikt z innym skrótem):

wprowadź opis zdjęcia tutaj

Możesz także dodać aliasdo swojego .bashrc.

W skrypcie

Wprowadziłem kilka zmian w oparciu o odpowiedź @ user829996 (i tutaj @ user56655):

#!/bin/bash
set -euo pipefail # strict mode

activeProfile() { pacmd list-cards | grep "active profile" | cut -d " " -f 3-; }
CURRENT_PROFILE="$(eval activeProfile)"

# If it doesn't work run  pacmd list-cards  and try the other outputs from profile section
ANALOG_PROFILE="output:analog-stereo+input:analog-stereo"
HDMI_PROFILE="output:hdmi-stereo-extra1+input:analog-stereo"

if [ "$CURRENT_PROFILE" = "<output:hdmi-stereo-extra1+input:analog-stereo>" ] ; then
  pacmd set-card-profile 0 "$ANALOG_PROFILE"
else
    pacmd set-card-profile 0 "$HDMI_PROFILE"
fi

activeProfile
Pablo A.
źródło
0

Utworzyłem następujący skrypt Pythona, który wykonuje następujące czynności:

  1. Przełącz domyślne urządzenie na następne urządzenie na liście (z zawijaniem) niezależnie od identyfikatora
  2. Przenosi wszystkie działające aplikacje na to urządzenie.
  3. Wysyła powiadomienia do GUI z nazwą urządzenia.
#!/usr/bin/env python3
import subprocess
# Toggle default device to the next device (wrap around the list)
cards_info = subprocess.run(['pacmd','list-sinks'], stdout=subprocess.PIPE)
card_indexes = subprocess.run(['grep', 'index'], stdout=subprocess.PIPE, input=cards_info.stdout)
indexes_list = card_indexes.stdout.decode().splitlines()
card_descriptions = subprocess.run(['grep', 'device.description'], stdout=subprocess.PIPE, input=cards_info.stdout)
indices = [i for i, s in enumerate(indexes_list) if '*' in s]
if (len(indices) != 1):
    print("Error finding default device")
    exit(1)
default_index = indices[0]
next_default = 0
if (default_index != (len(indexes_list) - 1)):
    next_default = default_index + 1
next_default_index =  (indexes_list[next_default].split("index: ",1)[1])
subprocess.run(['pacmd','set-default-sink %s' %(next_default_index)], stdout=subprocess.PIPE)

# Move all existing applications to the new default device
inputs_info = subprocess.run(['pacmd','list-sink-inputs'], stdout=subprocess.PIPE)
inputs_indexes = subprocess.run(['grep', 'index'], stdout=subprocess.PIPE, input=inputs_info.stdout)
inputs_indexes_list = inputs_indexes.stdout.decode().splitlines()
for line in inputs_indexes_list:
    input_index =  (line.split("index: ",1)[1])
    subprocess.run(['pacmd','move-sink-input %s %s' %(input_index, next_default_index)], stdout=subprocess.PIPE)

# Send notification to the GUI
descriptions_list = card_descriptions.stdout.decode().splitlines()
if (len(descriptions_list) == len(indexes_list)):
    description =  (descriptions_list[next_default].split("= ",1)[1])[1:-1]
    args = ["notify-send", "Default audio card changed", 'Default audio card was set to %s' %(description)]
    subprocess.run(args, stdout=subprocess.PIPE)

Przypisałem skrót klawiaturowy do skryptu, a moje życie jest teraz szczęśliwe

Nimrod.s
źródło