LINUX.ORG.RU

Awesome: индикатор громкости/состояния звука

 , ,


1

1

Есть вот такой виджет для Awesome: https://awesome.naquadah.org/wiki/Volume_control_and_display

Принцип работы такой - каждые 0.2 секунды он дёргает amixer и получает информацию о звуке. Мне показалось это не очень изящным решением. Поскольку включение/выключение звука/изменение громкости у меня происходят через настроенные в Awesome бинды с помощью amixer, я попробовал добавить в эти бинды и команду update_volume(volume_widget). То есть, в function() для биндов добавил update_volume(volume_widget) и убрал автообовление. Работает, но не очень: на первое нажатие сочетания клавиш нет реакции. Т.е. вот так происходит отображение:

5% - (нажал +5) - 5% - (нажал +5) - 10% - (нажал -5) - 15% - нажал (+5) - 10%

Мне хотелось бы как-нибудь реализовать отображение актуальной громкости без необходимости получать инфу каждые N секунд, а чтобы она обновлялась при изменении. Есть ли такой способ для Awesome? Заранее спасибо

★★

Если не таймером, тогда по событию. alsa (раз ты используешь amixer, то pulseaudio здесь не причём) умеет в dbus? Это всё, чем я могу тебе помочь в этом вопросе, так что на вопрос можешь не отвечать.

r3lgar ★★★★★ ()
Ответ на: комментарий от Psych218
awful.key({}, "XF86AudioRaiseVolume",
	function ()
		awful.util.spawn("amixer set Master 4%+ on")
		update_volume(volume_widget)
	end),
	awful.key({}, "XF86AudioLowerVolume",
	function ()
		awful.util.spawn("amixer set Master 4%- on")
		update_volume(volume_widget)
	end),
	awful.key({}, "XF86AudioMute",
	function ()
		awful.util.spawn("amixer set Master toggle")
		update_volume(volume_widget)
	end)

Обновление при нажатии происходит нормально, но всегда с запозданием на 1 действие.

Valdor ★★ ()
Ответ на: комментарий от Valdor

Команда запускается, и сразу переходится к следующему действию. Оно апдейтит, но до того, как команда завершится. Тут можно либо через dbus сделать, либо чуть более костыльно — добавив паузу перед update_volume(volume_widget)

Psych218 ★★★★★ ()
Ответ на: комментарий от Valdor

Через io.popen точно можно. Может ещё как-то есть.

Попробуй io.popen(«amixer set Master 4%+ on»). Должно сработать по идее. Если нет, то:

local f = io.popen("amixer set Master 4%+ on")
f:close()
Psych218 ★★★★★ ()
Последнее исправление: Psych218 (всего исправлений: 2)
Ответ на: комментарий от GGUseR

Поздно пить боржоми, когда печень отказала.

r3lgar ★★★★★ ()
Ответ на: комментарий от Valdor

Последовательность зависит от последовательности в функции, но никто не гарантирует того, что выполнение второго шага будет после завершения первого, нужно городить хуки. Через dbus надёжнее, но я в эту сторону не копал.

r3lgar ★★★★★ ()
Ответ на: комментарий от Valdor

Ну это открытие пайпа. Там из f можно читать вывод команды перед f:close(), но тебе вывод не нужен, так что открываем пайп и сразу закрываем. Быть может есть функция, которая специально предназначена для этого, но я её с ней не знаком.

Psych218 ★★★★★ ()
Ответ на: комментарий от Valdor

Это открытие потока на чтение и его последующее закрытие. На lua-users много написано полезного по языку.

r3lgar ★★★★★ ()
Ответ на: комментарий от Valdor

Тогда пичаль. городи хуки. Можно запилить дополнительное условие, при котором не будет перерисовываться виджет (кайро/панго жрёт проц, но условие может жрать его больше), если по истечению таймаута значение не изменилось.Да и таймаут у тебя сильно частый.

r3lgar ★★★★★ ()
Ответ на: комментарий от r3lgar

Я думаю, вот этот вариант (с io.popen) вполне подойдёт, а виджет я попрошу самообновляться раз в секунд 5-10 (на случай, если звук изменился как-то иначе, чем по моей команде).

Valdor ★★ ()
Ответ на: комментарий от Psych218

Т.е. я правильно понимаю, что io.popen создаёт отдельный процесс, в котором выполняется то, что сказано, в последствии с ним можно общаться, посылая всякие команды (read, write, close там), а нас интересует только тот аспект этого механизма, что закрытие пайпа произойдёт только после исполнения программы?

Valdor ★★ ()
Последнее исправление: Valdor (всего исправлений: 1)
Ответ на: комментарий от Psych218

Спасибо, воспринял. И последний вопрос по теме - где можно про pipe прочитать, как про явление? По запросам programming pipe, lua pipe я не нашёл объяснения сути происходящего.

Valdor ★★ ()
Ответ на: комментарий от Valdor

Вот где почитать, не знаю. Попробуй вместо pipe гуглить popen, эта функция так называется во многих языках (как минимум ещё в питоне помимо луа).

Psych218 ★★★★★ ()

С pulseaudio можно повесить демоном вот такую штуку:

pactl subscribe|while read x
do
    if (echo ${x}|grep "^Event '.*' on sink #[0-9]\+"); then
        echo 'vicious.force({myvolume})'|DISPLAY=0.0 awesome-client >/dev/null 2>&1
    fi
done
С чистой alsa даже не знаю как сделать чтобы отобразило мгновенно при изменении звука не из awesome.

liaonau ()
Ответ на: комментарий от liaonau

Сэр, вы подсказали мне прекрасное решение:

awful.util.spawn_with_shell('amixer set Master 4%- on && echo "update_volume(volume_widget)" | awesome-client')

Работает, как надо.

Valdor ★★ ()
Ответ на: комментарий от annulen

Спасибо, но уже не нужно. С помощью указанных выше пайпов у меня теперь виджет кажет актуальную информацию. И я могу быть уверен, что он не дёргает алсу каждые 0.2 секунды, а то кто знает, как этот микшер работает :)

Valdor ★★ ()
Ответ на: комментарий от Valdor

annulen, Psych218, в списках рассылки Awesome посоветовали: os.execute() делает то, что надо, и без всяких пайпов.

Valdor ★★ ()
Ответ на: комментарий от Valdor

Когда ты выполняешь какой-то код внутри конфига Awesome, на это время обработка событий прекращается. Поэтому для сохранения отзывчивости нужно минимизировать количество такого кода, в особенности приводящего к вызову внешних процессов, т.е. отдельные индикаторы намного предпочтитетльнее

Насколько я понял, awful.util.spawn_with_shell делает внутри двойной форк («демонизацию»), т.е. WM заблокируется только на время первого вызова fork(2), в то время как os.execute заблокирует WM от начала до конца работы вызываемого приложения

annulen ★★★★★ ()
Ответ на: комментарий от annulen

Ну вот, видимо, как раз, из-за того, что не происходит блокировки ВМ, виджет у меня обновлялся быстрее, чем выполнялась команда по изменению громкости. Так что, пусть уж лучше блокируется.

Valdor ★★ ()
Ответ на: комментарий от annulen

Я не нашёл, как заставить его показывать циферки. Плохо искал?

Valdor ★★ ()
Ответ на: комментарий от annulen

Кстати, а разве вариант с пайпами тоже вызывает блокировку? В моём представлении, пайп - отдельная сущность.

Valdor ★★ ()
Ответ на: комментарий от Valdor

В варианте с spawn_with_shell (если я правильно понял и он действительно форкает) блокировка будет на время выполнения fork, это намного дольше, чем вызов обычной функции на Lua, но намного быстрее, чем ждать завершения процесса в варианте с execute.

Сам «пайп» внутри шелл-строчки - это вызов целой кучи программ:

1) /bin/sh парсит содержимое 'amixer set Master 4%- on && echo «update_volume(volume_widget)» | awesome-client';

2) шелл вызывает amixer;

3) шелл проверят код возврата amixer, если он равен нулю, вызывается программу echo (встроенная функция не используется, джае если это bash, так как дальше стоит пайп), stdout echo перенаправляется на входной дескриптор пайпа (man 2 pipe)

4) шелл запускает awesome-client, в stdin которого устанавливает выходной дескриптор пайпа. awesome-client передает сообщение в процесс awesome через D-Bus.

annulen ★★★★★ ()

Я не очень понял что такое update_volume, не пользуюсь awesome. У себя в i3 я просто дергаю pulseaudio на увеличение громкости и отправляю сигнал в i3blocks «обнови виджет звука». Он тогда обновляет виджет звука, одно происходит строго после второго, и сразу отображается актуальное значение

vertexua ★★★★★ ()
Ответ на: комментарий от annulen

Тогда, наверное, опттимальным путём будет spawn_with_shell, а обновление виджета вызвать через awesome-client в рамках spawn_with_shell.

Valdor ★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.