Вопрос или проблема
Я пишу свой собственный статус для i3/Sway, который показывает индикатор громкости, и столкнулся с проблемой.
Мне хотелось бы узнать, существует ли стандартный способ с использованием стандартных инструментов Linux — возможно, ALSA или sysfs — чтобы определить, подключены ли наушники или нет? Я предпочел бы сделать это таким образом, на случай если я когда-либо захочу переключиться с Pipewire на обычный JACK или что-то еще.
Я размещу сегмент из этого «полуработающего» решения, которое мне удалось найти в Интернете (извините, но я не могу вспомнить, кто выложил это, чтобы отдать должное этому человеку).
has_headset() { grep -A4 -ri "Headphone Playback Switch" /proc/asound/card*/* | grep "Amp-Out vals.*\[0x00\]*" }
Эта функция has_headset()
в какой-то степени работает, но проблема в том, что если наушники подключены И отключены, она не сработает. Не уверен, что означают значения “Amp-Out vals”. Кажется, что это [0x80] [0x80]
, когда наушники отключены, и [0x00] [0x00]
, когда наушники подключены и не отключены.
Я использую POSIX sh, но решения, написанные специально для Bash, также приветствуются!
has_headphone() {
for card in /proc/asound/card*; do
amixer -c"${card##*card}" cget 'iface=CARD,name=Headphone Jack'
done 2> /dev/null | grep -qw values=on
}
У меня это работает с alsa-utils 1.2.12 на Debian trixie (testing) и Аудиоустройство: Intel Corporation 7 Series/C216 Chipset Family High Definition Audio Controller (rev 04).
Смотрите также amixer -c0 contents
, чтобы увидеть все элементы управления на карте 0, если имя отличается от Headphone Jack
в вашем случае.
Ноутбук, на котором я это тестирую, имеет комбинированный TRRS-разъем для наушников и микрофона, но я все равно вижу дополнительный элемент управления Mic Jack
, который переключается на on
, когда я подключаю гарнитуру, но не наушники без микрофона (разъем TRS), поэтому для has_headset
, который проверяет, подключены ли одновременно наушники и микрофон к одной и той же карте, вы можете сделать:
jack_connected() {
amixer -c"$1" cget "iface=CARD,name=$2 Jack" 2> /dev/null |
grep -qw values=on
}
has_headset() {
for card in /proc/asound/card*; do
card=${card##*card}
jack_connected "$card" Headphone &&
jack_connected "$card" Mic &&
return
done
false
}
Обратите внимание, что под strace
я вижу, как amixer
выполняет:
openat(AT_FDCWD, "/dev/snd/controlC0", O_RDWR|O_CLOEXEC) = 3
[...]
ioctl(3, SNDRV_CTL_IOCTL_ELEM_INFO, 0x7ffc2fdc3020) = 0
Так что информация не получается из /proc
и не из /sys
.
Ответ или решение
Для обнаружения подключения наушников в вашем пользовательском статусе для i3/Sway с использованием стандартных инструментов Linux, таких как ALSA, можно воспользоваться функциональностью, предоставляемой командой amixer
. Этот способ будет независимым от используемой звуковой системы, будь то Pipewire, JACK или ALSA, и, как следствие, обеспечит большую гибкость в будущем.
1. Определение состояния наушников
Для начала следует создать функцию, называемую has_headphone()
, которая будет проверять, подключены ли наушники. Эта функция будет обращаться к управляющему интерфейсу ALSA и искать элемент управления, связанный с разъемом наушников. Используя команду amixer
, можно выполнить следующие шаги:
has_headphone() {
for card in /proc/asound/card*; do
# Извлечение номера карты
card_num="${card##*card}"
# Проверка состояния наушников
if amixer -c"$card_num" cget 'iface=CARD,name=Headphone Jack' 2>/dev/null | grep -qw values=on; then
return 0 # Наушники подключены
fi
done
return 1 # Наушники не подключены
}
2. Обработка различных типов аудиоразъемов
Если у вас есть комбинированный разъем для наушников и микрофона (TRRS), полезно также проверять, подключен ли микрофон. Для этого можно расширить функцию для проверки обоих разъемов:
jack_connected() {
amixer -c"$1" cget "iface=CARD,name=$2 Jack" 2>/dev/null | grep -qw values=on
}
has_headset() {
for card in /proc/asound/card*; do
card_num="${card##*card}"
if jack_connected "$card_num" Headphone && jack_connected "$card_num" Mic; then
return 0 # Наушники и микрофон подключены
fi
done
return 1 # Наушники или микрофон не подключены
}
3. Исполнение кода и взаимодействие со статусом
Теперь, когда функции определены, вы можете использовать их в основном скрипте, чтобы отображать соответствующий статус в вашем инструменте (например, в строке состояния):
if has_headphone; then
echo "Наушники подключены"
else
echo "Наушники не подключены"
fi
if has_headset; then
echo "Наушники и микрофон подключены"
else
echo "Наушники или микрофон не подключены"
fi
4. Заключительные замечания
Использование функций amixer
в вашем сценарии на POSIX sh
или Bash предоставит вам стабильный и совместимый способ определения состояния наушников без зависимости от конкретной звуковой подсистемы. Чтобы убедиться, что скрипт работает корректно на различных аудиокартах, рекомендуется выполнить тестирование в разных окружениях и с разными устройствами.
Следуя вышеизложенным рекомендациям, вы сможете эффективно отслеживать состояние подключения наушников и интегрировать этот функционал в ваш кастомный статус для менеджера окон, что повысит интерфейс вашего программного обеспечения и улучшит пользовательский опыт.