Systemd: Перезагружаем pipewire после спячки

20 Jul 2021

Теги: pipewire linux systemd

Категории: HowTo

Начиная с Fedora 34 pipewire пришел на замену pulseaudio и стал довольно интересной альтернативой jackd. Так как теперь не требуется каких-либо телодвижений для того, чтобы все корректно заработало.

Конечно же без проблем не обошлось. В моём случае после спячки сервер перестает видеть докстанцию со встроенной звуковухой.

$ journalctl --user -u pipewire
...
дек 12 01:25:28 xxx pipewire[2846]: [E][000338392.259201][alsa-pcm.c:33 spa_alsa_open()] 'hw:Dock,1': playback open failed: Device or resource busy
дек 12 01:25:28 xxx pipewire[2850]: [E][000338392.261614][core.c:71 core_event_error()] core 0x56217c2f48e0: proxy 0x56217c42e9c0 id:72: bound:68 seq:1022 res:-16 (Device or resource busy) msg:"enum params id:3 (Spa:Enum:ParamId:EnumFormat) failed"
дек 12 01:25:28 xxx pipewire[2850]: [E][000338392.261651][media-session.c:1971 core_error()] error id:72 seq:1022 res:-16 (Device or resource busy): enum params id:3 (Spa:Enum:ParamId:EnumFormat) failed
...

В деве вроде бы проблему чинили, но в стейбле федоры - нет.

Единственный вариант, который приходит на ум - перезагружать сервер после спячки. Делать это каждый раз руками лень.

Сделаем сервис, который будет делать это за нас!

Однако, не все так просто. Проблема заключается в том, что systemd от пользователя запускается как отдельный процесс и не имеет доступа к системным таргетам вроде sleep/suspend и т.п.

Поэтому придется решать еще и эту проблему.

Кастомный sleep.target в юзерспейсе

  1. Скрипт ~/.local/bin/sleep_mon
    #!/bin/bash
    
    dbus-monitor --system "type='signal',interface='org.freedesktop.login1.Manager',member=PrepareForSleep" | while read x; do
        case "$x" in
            *"boolean false"*) systemctl --user --no-block stop sleep.target;;
            *"boolean true"*) systemctl --user --no-block start sleep.target;;
        esac
    done
    
  2. Таргет ~/.config/systemd/user/sleep.target
    [Unit]
    Description=User level sleep target
    StopWhenUnneeded=yes
    
  3. Скрипт для активации таргета ~/.config/systemd/user/user-sleep.service
    [Unit]
    Description=watch for sleep signal to start sleep.target
    
    [Service]
    ExecStart=%h/.local/bin/sleep_mon
    Restart=on-failure
    
    [Install]
    WantedBy=default.target
    
  4. Активируем и запускаем новый сервис
    $ systemctl --user enable user-sleep.service
    $ systemctl --user start user-sleep.service
    

Непосредственно сам сервис для перезапуска pipewire

  1. Создаем файл restart-pw.service по пути ~/.config/systemd/user.
    [Unit]
    Description=Restart pipewire after resume
    StopWhenUnneeded=true
    
    [Service]
    Type=oneshot
    RemainAfterExit=true
    ExecStop=/usr/bin/systemctl --no-block --user restart pipewire pipewire-pulse
    
    [Install]
    WantedBy=sleep.target
    
  2. Добавляем юнит в запускаемые.
    $ systemctl --user enable restart-pw.service
    
  3. Стартуем юнит
    $ systemctl --user start restart-pw.service
    
  4. Можно посмотреть статус
    $ systemctl --user status restart-pw.service
    

Литература:

MIDI: Превращаем сообщения в нажатия кнопок клавиатуры

20 Dec 2020

Теги: jackd linux midi

Категории: HowTo

Как конвертировать сообщения от midi-клавиатуры в нажатия кнопок на клавиатуре?

Где это может потребоваться - это в приложениях, которые не умеют в миди, но умеют в хоткеи. Например musescore - это приложение очень плохо умеет в миди.

Создадим простейший скрипт midi-to-keyboard. Все что он делает - это слушает события на шине и транслирует их в нажатия кнопок клавиатуры.

#!/usr/bin/env bash
THROTTLE=150
old_time=0
last_change=0
#aseqdump -p "Arturia MiniLab mkII" | \
aseqdump -p "System" | \
while IFS=" ," read src ev1 ev2 ch label1 data1 label2 data2 rest; do
    current_time=$(($(date +%s%N)/1000000))
    diff=$(($current_time-$old_time))
    if [[ $diff -gt $THROTTLE && "$ch" = 15 ]]; then
        # тротлинг событий обязателен
        change=0
        case $data1 in
            48 ) # effects 1
                if [[ $data2 -gt 64 ]]; then
                    xdotool key Right
                    change=1
                elif [[ $data2 -lt 64 ]]; then
                    xdotool key Left
                    change=1
                fi
            ;;
            49 ) # effects 2
                if [[ $data2 -gt 64 ]]; then
                    xdotool key Up
                    change=1
                elif [[ $data2 -lt 64 ]]; then
                    xdotool key Down
                    change=1
                fi
            ;;
        esac
        if [[ change -eq 1 ]]; then
            echo "Change after $(($current_time-$old_time))"
            old_time=$current_time
        fi
    fi
done

Литература:

PulseAudio: Перенаправление потоков аля jackd

11 Oct 2020

Теги: jackd linux pulseaudio

Категории: HowTo

Что мы хотим? Мы хотим подмешать к микрофонному сигналу еще что-то. Например дополнительный сигнал с другой звуковой карты для того, чтобы по скайпу с кем-то поджемить на гитаре\ударке.

В jackd это сделать довольно просто - там куча графических роутеров. Но что делать если надо подмешать сигнал в pulse?

Возьмем самый простой пример: нужно подмешать к звуку микрофона аудио из браузера.

mic -> skype <- ff

Просто так это работать не будет. Потребуется виртуальное loopback-устройство, которое будет смешивать сигналы, а после остальное по будет использовать его как микрофон.

skype ^ |mic -> loopback <- ff

1 - Создаем устройство

Создаем само устройство и задаем ему описание чтобы в панели управления бло что-то вразумительное, а не “Пустой выход”.

$ pacmd load-module module-null-sink sink_name=fx-sink 42 $ pacmd update-sink-proplist fx-sink device.description=Виртуальный_микрофон_вход $ pacmd update-source-proplist fx-sink.monitor device.description=Виртуальный_микрофон_выход

Цифру, которая выдает первая команда можно запомнить. Это идентификатор, по которому можно sink удалить.

2 - Перенаправляем микрофонный выход на это устройство

$ pactl load-module module-loopback source=alsa_input sink=fx-sink 43

Номер так же можно запомнить чтобы потом удалить ассоциацию.

Теперь в качестве устройства для ввода в панели управления (ставим как дефолтный девайс) или в программе выбираем fx-sink.monitor. Он будет называться “Виртуальный_микрофон_выход” (выше мы прописали в описании).

Чтобы посмотреть что писать в аргументе source просматриваем вывод команды

$ pactl list-sinks

Тут нам нужно найти содержимое поля name системного микрофона.

Источники:

Jackd: Измеряем задержку аудио сигнала в цепочке обработки

06 Sep 2020

Теги: аудио jackd linux

Категории: HowTo

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

Но что на самом деле означает эта задержка? Это лишь время, которое будет затрачено на обработку сигнала после поступления его в роутер (в моем случае в роли роутера выступает jackd).

А как измерить полную задержку вместе со временем на обработку и перевод сигнала в аналог?

jack_iodelay - утилита генерирует тестовый сигнал, который можно направить в роутере куда угодно, потом вернуть на вход этой же утилиты и посмотреть в консоли что получится.

Для измерения нам потребуется небольшой патч чтобы соединить один из входов интерфейса с выходом.

После этого запускаем утилиту, коммутируем нужный вход и выход в роутере и смотрим на результат в консоли.

Показатели задержки сигнала

Общая задержка составляет в среднем 820 фреймов. Чтобы узнать задержку в миллисекундах делим это число на частоту семплирования. (96кГц). Это 8,5мс.

Поле extra loopback latency содержит лаг, который был вызван ЦАП’ом и АЦП.

Задержка зависит и от настроек джека. От количества семплов и периодов на буфер

Для текущего теста 2 периода на буфер и 128 сэмплов. Итого 384. И ~430 фреймов - это задержка на железе. В сумме и получается ~820.

Можно пользоваться опциям -I и -O. Они отдельно позволяют посмотреть задержку по входу и выходу сигнала.

Linux: Настраиваем МФУ pantum

29 Aug 2020

Теги: cups администрирование linux sane

Категории: HowTo

Есть такие новые китайские принтеры (относительноо новые) Pantum. В них и wifi, и поддержка linux из коробки. Достал я и себе такое чудо платы лутом делать и шаблоны для фоторезиста печатать.

Настроить wifi в принтере (если он есть) без смартфона не получится - лезем туда и делаем все по инструкции (она с картинками).

Теперь надо поставить драйвера и настроить сканирование и печать по wifi. Если у вас убунту или дебиан, то драйвера скачиваются и устанавливаются в виде пакета. Если федора, то придется немного покомпилировать.

Пакеты для fedora

Предварительно потребуется собрать библиотеку libjpeg so.8. Иначе вы не сможете поставить sane-драйвера.

nothing provides libjpeg so.8()(64bit) needed by pantum-m6xxx-sane-1 4 0-2 fc28 x86_64
$ sudo dnf install rpm-build spectool git
$ rpmdev-setuptree
$ git clone https://github.com/RussianFedora/compat-libjpeg8.git
$ cd compat-libjpeg8
$ spectool --all --get-files --directory ~/rpmbuild/SOURCES compat-libjpeg8.spec
$ rpmbuild -bb compat-libjpeg8.spec
$ sudo dnf install ~/rpmbuild/RPMS/$(uname -m)/compat-libjpeg8-1.5.3-3.fc32.x86_64.rpm

А теперь можно собирать и ставить драйвера для pantum.

$ sudo dnf install rpm-build spectool git
$ rpmdev-setuptree
$ git clone https://github.com/EasyCoding/pantum-m6xxx.git
$ cd pantum-m6xxx
$ spectool --all --get-files --directory ~/rpmbuild/SOURCES pantum-m6xxx.spec
$ rpmbuild -bb pantum-m6xxx.spec
$ sudo dnf install ~/rpmbuild/RPMS/$(uname -m)/pantum-m6xxx-*.rpm

Настройка cups

Заходим в веб-интерфейс и добавляем принтер. Никаких сложностей нет.

Настройка sane

Тут сложнее. Ставим sane-backend, а потом добавляем удаленный сканер.

sudo dnf install sane-backends-daemon

Добавляем в /etc/sane.d/dll.conf

pantum6500
pantum_mfp

Получаем доменный адрес принтера через avahi. Я уже писал о том, как работать без локального днс.

$ avahi-browse-domains -alr

Среди полученных адресов вы увидите адрес принтера Pantum-XXXXXX.local. Этот адрес надо добавить в /etc/sane.d/net.conf.

Запускаем saned.

$ sudo systemctl start saned.socket

Проверяем наличие сканера.

$ scanimage -L 
device `v4l:/dev/video0' is a Noname HD WebCam: HD WebCam virtual device 
device `airscan:e0:Pantum M6500W series[XXXXX]' is a eSCL Pantum M6500W series[XXXXX] eSCL network scanner

Литература