Setel output suara HDMI secara otomatis saat terhubung / terputus

20

Saya memiliki pengaturan layar ganda pada laptop saya (menggunakan 12,04 LTS) menggunakan layar yang terhubung HDMI. Semuanya berfungsi dengan baik, tetapi setiap kali saya menghubungkan / mencabut kabel saya harus pergi ke preferensi Suara dan mengubah perangkat output suara secara manual.

Apakah ada cara untuk mengubah perangkat output suara pada koneksi / pemutusan kabel, jadi ketika saya menghubungkan display saya output suara diatur ke HDMI dan ketika saya mencabutnya suara kembali ke speaker laptop?

Salem
sumber
Masalah yang sama disini.
ThiagoPonte
Ini adalah pertama kalinya saya datang ke sini untuk bantuan tentang ini ... Saya berada di kapal yang sama pada jam 12.10. Itu menyebalkan. Sudah seperti ini sejak 10,10 dalam pengalaman saya. Harus ada konfigurasi di suatu tempat yang dapat menangani ini. EDIT: voices.canonical.com/david.henningsson/2012/04/14/… Diatur seperti itu dengan sengaja. Mengerikan.
user138216
Periksa apakah jawaban saya cocok untuk Anda.
Salem

Jawaban:

11

Demi kepentingan orang-orang yang menemukan pertanyaan ini - solusi Salem hampir bekerja untuk saya pada 13,04, saya akhirnya mengumpulkan potongan-potongan dari seluruh web, saya pikir pemecah kesepakatan bagi saya adalah kurangnya variabel lingkungan PULSE_SERVER

Inilah solusi lengkap saya, yang pada dasarnya mengulangi solusi Salem dengan beberapa bagian yang hilang. Saya juga menyebutnya sebagai skrip shell (terlepas dari kecintaan saya pada Python) karena pada awalnya saya takut skrip Python saya mengalami masalah jalur impor:


(Sama seperti jawaban Salem) Buat file /etc/udev/rules.d/hdmi_sound.rulessebagai root dengan konten:

SUBSYSTEM=="drm", ACTION=="change", RUN+="/usr/local/bin/hdmi_sound_toggle"

Buat file /usr/local/bin/hdmi_sound_togglesebagai root dengan konten:

#!/bin/sh
USER_NAME=`who | grep "(:0)" | cut -f 1 -d ' '`
USER_ID=`id -u $USER_NAME`
HDMI_STATUS=`cat /sys/class/drm/card0/*HDMI*/status`

export PULSE_SERVER="unix:/run/user/"$USER_ID"/pulse/native"

if [ $HDMI_STATUS = "connected" ]
then
    sudo -u $USER_NAME pactl --server $PULSE_SERVER set-card-profile 0 output:hdmi-stereo+input:analog-stereo
else
    sudo -u $USER_NAME pactl --server $PULSE_SERVER set-card-profile 0 output:analog-stereo+input:analog-stereo
fi

Kemudian membuatnya bisa dieksekusi dengan chmod 0755 /usr/local/bin/hdmi_sound_toggle

Saya mencoba membuat skrip ini se-generik mungkin, tetapi Anda mungkin masih perlu mengubah beberapa baris, seperti jalur file HDMI_STATUS atau profil yang digunakan. Anda dapat melihat daftar profil dengan menjalankan pactl list cardsdan melihat di bawah Profil.

Perhatikan bahwa skrip gagal untuk saya ketika saya menghapus kata kunci "ekspor" ketika mengatur PULSE_SERVER, saya pikir pactl sedang mencari variabel env

Jangan lupa memuat ulang aturan udev Anda: sudo udevadm control --reload-rules

Perbarui skrip ini diperbarui untuk 14,04. Sebelum itu, Anda akan menggunakan USER_NAME alih-alih USER_ID di mana-mana

Daniel
sumber
1
Perhatikan bahwa saya perlu menambahkan | uniqperintah USER_NAME. Perhatikan juga bahwa pengaturan suara di Ubuntu bisa menipu. Saya tidak melihat perubahan pada panel pengaturan suara, tetapi begitu saya memainkan sesuatu, audio akan beralih bolak-balik dengan lancar saya juga memperhatikan bahwa setelah beberapa kali mencolokkan dan mencabut HDMI, skrip berhenti dijalankan (mungkin beberapa semacam bug di udev).
FuegoFro
1
Saya menambahkan | sort -uke nama pengguna karena mengatakan opsi tambahan elemer elemer --- Nama pengguna saya. Sama seperti solusi FuegoFro di penghujung hari.
elemer82
Saya menggunakan | grep -v pts, karena saya benar-benar mendapatkan pengguna "root" di sana juga — karena fakta bahwa saya mengedit skrip via kate, yang memiliki terminal root terbuka.
Auspex
Terus dapatkan "Koneksi gagal: Sambungan ditolak pa_context_connect () gagal: Sambungan ditolak" saat menjalankan pactl. : \
Tomislav Nakic-Alfirevic
7

Saya akhirnya berhasil membuat pekerjaan ini menggunakan udev. Jadi jika seseorang menginginkan perilaku yang sama di sini adalah langkah-langkahnya:

Pertama kita perlu membuat file /etc/udev/rules.d/hdmi_sound.rulesdengan konten berikut:

    SUBSYSTEM=="drm", ACTION=="change", RUN+="/usr/local/bin/hdmi_sound_toggle"

ini akan membuat udeveksekusi skrip hdmi_sound_togglesetiap kali ada perubahan dalam koneksi HDMI. Skrip itu harus memiliki izin eksekusi dan isinya adalah sebagai berikut:

#!/usr/bin/env python

import subprocess
from syslog import syslog

def output(cmd):
    return subprocess.check_output(cmd, shell=True)

# the following variables may need some modification.
user = "my_username"
card = "/sys/class/drm/card0"
dev_speaker = "output:analog-stereo+input:analog-stereo"
dev_hdmi = "output:hdmi-stereo+input:analog-stereo"
#

interfaces = output("ls {0}".format(card), ).split("\n")

vga = filter(lambda x: "VGA" in x, interfaces)[0]
hdmi = filter(lambda x: "HDMI" in x, interfaces)[0]

syslog("HDMI connection was changed!")

hdmi_connected = output("cat {0}/{1}/status".format(card,hdmi)).startswith("connected")
title = "HDMI was {0}".format("connected" if hdmi_connected else "disconnected")
message = "Audio output has changed to {opt}.".format(opt = "HDMI" if hdmi_connected else "built-in speakers")

cmd = "sudo -u " + user + " /usr/bin/pactl set-card-profile 0 " + (dev_hdmi if hdmi_connected else dev_speaker)

syslog("HDMI was connected." if hdmi_connected else "HDMI was disconnected.")
try:
    a = output(cmd)
    output("sudo -u {0} notify-send \"{1}\" \"{2}\"".format(user, title, message))
    syslog("Audio output changed.")
except Exception as ex:
    syslog("Error changing output device: " + str(ex))

Mungkin ini dapat dengan mudah dibuat dalam bash, tetapi karena bahasa utama saya adalah python, saya menggunakannya. Semuanya berfungsi kecuali notifikasi: tidak muncul, saya benar-benar tidak tahu mengapa. Jika seseorang tahu cara memperbaikinya, tolong katakan sesuatu.

Catatan: nama skrip / aturan udev dapat diubah, tetapi Anda harus menggunakan path lengkap.

Salem
sumber
3

Berdasarkan Salem 's jawaban dan daniel jawaban' s

Saya mengambil jawaban Salem dan jawaban daniel dan membuat beberapa perubahan yang diperlukan, solusi mereka tidak berhasil untuk saya di luar kotak:

(Mirip dengan jawaban Salem).

Buat file /etc/udev/rules.d/hdmi_sound.rulessebagai root dengan konten:

SUBSYSTEM=="drm", RUN+="/usr/local/bin/hdmi_sound_toggle"

Catatan ACTION=="change", tidak ada!

Buat file /usr/local/bin/hdmi_sound_togglesebagai root dengan konten:

#!/bin/sh
USER_NAME=`who | grep "(:0)" | cut -f 1 -d ' '| sort -u`
USER_ID=`id -u $USER_NAME`
HDMI_STATUS=`cat /sys/class/drm/card0/*HDMI*/status`

export PULSE_SERVER="unix:/run/user/"$USER_ID"/pulse/native"

if [ $HDMI_STATUS = "connected" ]
then
    sudo -u $USER_NAME pactl --server $PULSE_SERVER set-card-profile 0 output:hdmi-stereo+input:analog-stereo
else
    sudo -u $USER_NAME pactl --server $PULSE_SERVER set-card-profile 0 output:analog-stereo+input:analog-stereo
fi

Catatan USER_NAME =who | grep "(:0)" | cut -f 1 -d ' '| sort -u Saya menambahkan| sort -ukarena jika tidak kembali dengan -elemer elemer elemernamaku 3 kali.

Kemudian membuatnya bisa dieksekusi dengan chmod 0755 /usr/local/bin/hdmi_sound_toggle

Jangan lupa memuat ulang aturan udev Anda: sudo udevadm control --reload-rules

Penting skrip ini diperbarui untuk 14,04. Sebelum itu, Anda akan menggunakan USER_NAME alih-alih USER_ID di mana-mana

Penghargaan: Salem dan daniel .

elemer82
sumber
1

Ubuntu 16.04 - 17.04 Jawaban

Ini berfungsi untuk Ubuntu 16.04 - 17.04 yang memperkenalkan bug dengan Pulse Audio 8. Buat file hotplugtv(atau hotplug-hdmijika Anda mau) dan salin di baris berikut:

#!/bin/bash

# NAME: hotplugtv
# PATH: /home/$USER/bin
# DESC: Update pulseaudio output device when HDMI TV plugged / unplugged
# CALL: called from /etc/udev/rules.d/99-hotplugtv.rules 
#       and /home/$USER/bin/lock-screen-timer
# DATE: Created Nov 26, 2016.
# NOTE: logs output using log-file
# UPDT: Dec 14, 2016 - Sometimes /sys/class/drm/card0 & sometimes /sys/class/drm/card1
#       so use /sys/class/dmcard* instead.
#       Dec 21, 2016 - Relocated to /home/$USER/bin for calling by lock-screen-timer
#       Aug 06, 2017 - Convert from home grown log-file to universal logger command.

if [[ $(cat /sys/class/drm/card*-HDMI-A-1/status | grep -Ec "^connected") -eq 1 ]]; then
        logger -t /home/rick/bin/log-hotplugtv "HDMI TV connected"
        /bin/sleep 2;
        export PULSE_RUNTIME_PATH="/run/user/1000/pulse/";
        sudo -u rick -E pacmd set-card-profile 0 output:hdmi-stereo;
else
        logger -t /home/rick/bin/log-hotplugtv "HDMI TV disconnected"
        export PULSE_RUNTIME_PATH="/run/user/1000/pulse/";
        sudo -u rick -E pacmd set-card-profile 0 output:analog-stereo;
fi

exit 0

PENTING: Ubah nama pengguna "rick" menjadi nama pengguna Anda.

Untuk memanggil skrip ini dari udevselama peristiwa hot-plug membuat file yang /etc/udev/rules.d/99-hotplugtv.rulesberisi:

ACTION=="change", SUBSYSTEM=="drm", ENV{HOTPLUG}=="1", RUN+="/home/rick/bin/hotplugtv"

Ubah /home/rick/bin/ke jalur tempat Anda meletakkan hotplugtvskrip.

WinEunuuchs2Unix
sumber
Terima kasih banyak! Ini bekerja di Ubuntu 17.04 juga! Ini telah menggangguku sejak lama dan itu adalah solusi sederhana :)
Georgi Koemdzhiev
1
Sama-sama. Terima kasih atas komentar yang mengkonfirmasi bahwa diperlukan untuk 17,04 juga.
WinEunuuchs2Unix