From b71cf6d5bdbef44eb4cb89a478bb08caa78e6eba Mon Sep 17 00:00:00 2001 From: Andrey Arapov Date: Wed, 20 Jun 2018 00:12:16 +0200 Subject: [PATCH] build pulseaudio from sources --- Dockerfile | 72 ++++++++++++++++++++++--------------- README.md | 42 +++++++++------------- avahi-daemon.conf | 68 +++++++++++++++++++++++++++++++++++ client.conf | 3 +- daemon.conf | 9 +++-- default.pa | 89 ++++++++++++++++++++++++++++------------------ docker-compose.yml | 25 ------------- entrypoint.sh | 18 ++++++++++ 8 files changed, 210 insertions(+), 116 deletions(-) create mode 100644 avahi-daemon.conf delete mode 100644 docker-compose.yml create mode 100755 entrypoint.sh diff --git a/Dockerfile b/Dockerfile index a161688..313deb1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,35 +1,51 @@ -# Run pulseaudio server in a container -# -# TODO -# - reset volume to 80% and keep it enabled when the container runs -# +FROM ubuntu:bionic -FROM debian:jessie -MAINTAINER Andrey Arapov -# Inspired by Jessica Frazelle +RUN apt-get update +RUN DEBIAN_FRONTEND=noninteractive apt-get -y --no-install-recommends install \ + ca-certificates curl xz-utils patch intltool libtool pkg-config \ + libltdl-dev libcap-dev libsndfile1-dev libdbus-1-dev libspeexdsp-dev \ + libasound2-dev libavahi-client-dev avahi-daemon -# To avoid problems with Dialog and curses wizards -ENV DEBIAN_FRONTEND noninteractive +# libudev-dev +# libx11-xcb-dev libice-dev libsm-dev libxtst-dev dbus-x11 +# libsystemd-dev +# libglib2.0-dev -# Define a user under which the pulseaudio server will be running -ENV USER=user \ - UID=1000 \ - GROUPS=audio \ - HOME=/home/user +RUN useradd -u 1000 -m -d /home/user -s /bin/sh user && \ + usermod -aG audio user -RUN apt-get update \ - && apt-get install -yq pulseaudio pulseaudio-module-x11 \ - && rm -rf /var/lib/apt/lists +WORKDIR /home/user +USER user +RUN curl -sSLO https://www.freedesktop.org/software/pulseaudio/releases/pulseaudio-11.1.tar.xz && \ + echo "f2521c525a77166189e3cb9169f75c2ee2b82fa3fcf9476024fbc2c3a6c9cd9e pulseaudio-11.1.tar.xz" | sha256sum -c && \ + tar xf pulseaudio-11.1.tar.xz && \ + curl -sSLO http://www.linuxfromscratch.org/patches/blfs/svn/pulseaudio-11.1-glibc_2.27_fix-1.patch && \ + echo "68a9cc453fdd648a58097d53ee2c2d5e32793ea0673362e85d71b9b1f40eb52b pulseaudio-11.1-glibc_2.27_fix-1.patch" | sha256sum -c -COPY [ "default.pa", "client.conf", "daemon.conf", "/etc/pulse/" ] +RUN cd pulseaudio-11.1 && \ + patch -Np1 -i ../pulseaudio-11.1-glibc_2.27_fix-1.patch && \ + AUTOPOINT='intltoolize --automake --copy' autoreconf -fiv && \ + ./configure --prefix=/usr \ + --sysconfdir=/etc \ + --localstatedir=/var \ + --disable-bluez4 \ + --disable-bluez5 \ + --disable-rpath && \ + make -j$(getconf _NPROCESSORS_ONLN) + +USER root + +RUN cd /home/user/pulseaudio-11.1 && \ + make install && \ + rm -rf /home/user/pulseaudio-11.1 -RUN useradd -u $UID -m -d $HOME -s /usr/sbin/nologin $USER \ - && usermod -aG $GROUPS $USER \ - && chmod 0644 -- /etc/pulse/* \ - && mkdir -p $HOME/.config/pulse \ - && chown -Rh $USER:$USER -- $HOME +RUN mkdir -p /home/user/.config/pulse && \ + chown -Rh user:user -- /home/user/.config +VOLUME [ "/tmp", "/home/user/.config/pulse" ] + +COPY [ "default.pa", "client.conf", "daemon.conf", "/etc/pulse/" ] +COPY [ "avahi-daemon.conf", "/etc/avahi/" ] +COPY [ "entrypoint.sh", "/" ] +ENTRYPOINT ["/entrypoint.sh"] -WORKDIR $HOME -USER $USER -VOLUME [ "/tmp", "$HOME/.config/pulse" ] -ENTRYPOINT [ "/usr/bin/pulseaudio" ] +LABEL maintainer="andrey.arapov@nixaid.com" diff --git a/README.md b/README.md index 9a0f21b..224400a 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,30 @@ -Readme -====== +## Pulseaudio in Docker -Launching pulseaudio -``` -echo "autospawn = no" > ~/.config/pulse/client.conf -pulseaudio --kill -rm -rf ~/.config/pulse/ -docker-compose up -d -``` +Run it -If you wish your host system to use your docker pulseaudio server, e.g. -accepting Fn volume Up/Down and On/Off keys, issue the following command ``` -xprop -root -f PULSE_SERVER 8s -set PULSE_SERVER "tcp:localhost:4713" +docker run --name pulseaudio --rm -ti --device /dev/snd andrey01/pulseaudio ``` -To remove pulseaudio properties from environment variables -``` -pax11publish -e -``` +## Troubleshooting + +Enter the namespace of a running container -To test whether pulseaudio is working ``` -PULSE_SERVER="tcp:localhost:4713" pactl list -PULSE_SERVER="tcp:localhost:4713" alsamixer -PULSE_SERVER="tcp:localhost:4713" mplayer some.avi +sudo nsenter -a -t $(docker inspect -f '{{ .State.Pid }}' pulseaudio) ``` -To see what is being used by pulseaudio +## Client setup for zeroconfig auto discovery + +If you want the pulseaudio to automatically discover the published sinks, +make sure ``/etc/pulse/default.pa`` has the following line: + ``` -$ netstat -lp |grep -i pulseaudio -unix 2 [ ACC ] STREAM LISTENING 29632 2147/pulseaudio /tmp/.esd-1000/socket -unix 2 [ ACC ] STREAM LISTENING 29635 2147/pulseaudio /run/user/1000/pulse/native +load-module module-zeroconf-discover ``` -If you wish to disable annoying "popping" notification sounds +Then restart pulseaudio: + ``` -gsettings set org.gnome.desktop.sound event-sounds false +pulseaudio --kill ``` diff --git a/avahi-daemon.conf b/avahi-daemon.conf new file mode 100644 index 0000000..877f103 --- /dev/null +++ b/avahi-daemon.conf @@ -0,0 +1,68 @@ +# This file is part of avahi. +# +# avahi is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# avahi is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with avahi; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. + +# See avahi-daemon.conf(5) for more information on this configuration +# file! + +[server] +#host-name=foo +#domain-name=local +#browse-domains=0pointer.de, zeroconf.org +use-ipv4=yes +use-ipv6=yes +#allow-interfaces=eth0 +#deny-interfaces=eth1 +#check-response-ttl=no +#use-iff-running=no +#enable-dbus=no +#disallow-other-stacks=no +#allow-point-to-point=no +#cache-entries-max=4096 +#clients-max=4096 +#objects-per-client-max=1024 +#entries-per-entry-group-max=32 +ratelimit-interval-usec=1000000 +ratelimit-burst=1000 + +[wide-area] +enable-wide-area=yes + +[publish] +#disable-publishing=no +#disable-user-service-publishing=no +#add-service-cookie=no +#publish-addresses=yes +publish-hinfo=no +publish-workstation=no +#publish-domain=yes +#publish-dns-servers=192.168.50.1, 192.168.50.2 +#publish-resolv-conf-dns-servers=yes +#publish-aaaa-on-ipv4=yes +#publish-a-on-ipv6=no + +[reflector] +#enable-reflector=no +#reflect-ipv=no + +[rlimits] +#rlimit-as= +#rlimit-core=0 +#rlimit-data=8388608 +#rlimit-fsize=0 +#rlimit-nofile=768 +#rlimit-stack=8388608 +#rlimit-nproc=3 diff --git a/client.conf b/client.conf index 4e423ed..33fe25d 100644 --- a/client.conf +++ b/client.conf @@ -1,2 +1,3 @@ -autospawn = no +autospawn = yes daemon-binary = /bin/true +enable-shm = no diff --git a/daemon.conf b/daemon.conf index 19793c8..4634ef1 100644 --- a/daemon.conf +++ b/daemon.conf @@ -1,4 +1,9 @@ -exit-idle-time = 0 -flat-volumes = yes +exit-idle-time = -1 ; do not shutdown pulseaudio on client disconnect +flat-volumes = no ; avoid volume set to 100% at startup log-target = stderr log-level = 4 + +enable-deferred-volume = no ; it appears that when I SIGSTOP the pulseaudio + ; for 24.96ms and then SIGCONT I'd get: + ; "Connection died." + ; Looks like disabling this option helps. diff --git a/default.pa b/default.pa index acd1fae..7c32bb0 100644 --- a/default.pa +++ b/default.pa @@ -1,37 +1,58 @@ .nofail - # Set tsched=0 here if you experience glitchy playback. This will - # revert back to interrupt-based scheduling and should fix it. - # - # Replace the device= part if you want pulse to use a specific device - # such as "dmix" and "dsnoop" so it doesn't lock an hw: device. - # use aplay -l to find your device - # test with: speaker-test -D plughw:PCH -l 3 -t sine -c 1 - - # INPUT/RECORD - # load-module module-alsa-source device="default" tsched=1 - load-module module-alsa-source device="plughw:PCH" tsched=1 - - # OUTPUT/PLAYBACK - # load-module module-alsa-sink device="default" tsched=1 - load-module module-alsa-sink device="plughw:PCH" tsched=1 - - # TODO: the below block has not been fully testsd yet (in this Docker container) - ### Automatically load driver modules depending on the hardware available - #.ifexists module-udev-detect.so - #load-module module-udev-detect - #.else - ### Use the static hardware detection module (for systems that lack udev support) - #load-module module-detect - #.endif - - # Accept clients -- very important! - load-module module-native-protocol-unix - load-module module-native-protocol-tcp auth-ip-acl=127.0.0.0/8;172.0.0.0/8 auth-anonymous=1 - -.ifexists module-x11-publish.so - # Publish to X11 so the clients know how to connect to Pulse. - # Will clear itself on unload. - load-module module-x11-publish -.endif + ### Automatically load driver modules depending on the hardware available + .ifexists module-detect.so + ### Use the static hardware detection module (for systems that lack udev/hal support) + load-module module-detect + .endif + ### When HW detection does not work you can specify your source & sink manually. + ## Set tsched=0 here if you experience glitchy playback. This will + ## revert back to interrupt-based scheduling and should fix it. + # INPUT/RECORD: + # load-module module-alsa-source device="plughw:PCH" tsched=1 + # OUTPUT/PLAYBACK: + # load-module module-alsa-sink device="plughw:PCH" tsched=1 + + ### Load several protocols + .ifexists module-esound-protocol-unix.so + load-module module-esound-protocol-unix + .endif + load-module module-native-protocol-unix + + # Accept clients + load-module module-native-protocol-tcp auth-ip-acl=127.0.0.0/8;172.0.0.0/8 auth-anonymous=1 + + # Zeroconf (Avahi) publishing + # For the remote PulseAudio server to appear in the sound output device chooser. + load-module module-zeroconf-publish + + # .ifexists module-x11-publish.so + # # Publish to X11 so the clients know how to connect to Pulse. + # # Will clear itself on unload. + # load-module module-x11-publish + # .endif + + ### Automatically restore the volume of streams and devices + load-module module-stream-restore + load-module module-device-restore + # ? load-module module-card-restore + + ### Automatically restore the default sink/source when changed by the user + ### during runtime + ### NOTE: This should be loaded as early as possible so that subsequent modules + ### that look up the default sink/source get the right value + load-module module-default-device-restore + + ### Automatically move streams to the default sink if the sink they are + ### connected to dies, similar for sources + load-module module-rescue-streams + + ### Make sure we always have a sink around, even if it is a null sink. + load-module module-always-sink + + ### Automatically suspend sinks/sources that become idle for too long + load-module module-suspend-on-idle + + ### Enable positioned event sounds + load-module module-position-event-sounds .fail diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index b526fa9..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,25 +0,0 @@ -version: '2' - -services: - pulseaudio: - build: ./ - read_only: true - hostname: localhost - networks: - - isolated - ports: - - "4713:4713" - devices: - - /dev/snd - volumes: - - /tmp/.X11-unix:/tmp/.X11-unix - - /var/run/dbus:/var/run/dbus - environment: - DISPLAY: unix$DISPLAY - security_opt: - - seccomp:unconfined - -networks: - isolated: - external: - name: isolated diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..9dc0547 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env sh + +# Dirty workaround until this is fixed: +# Device permissions are broken in 18.02 and 17.12.1 Docker ... +# https://github.com/docker/for-linux/issues/228#issuecomment-370545814 +chgrp audio -- /dev/snd/* + +# So that dbus-daemon can create /var/run/dbus/system_bus_socket +mkdir /var/run/dbus +dbus-daemon --system --fork + +# Avahi-daemon is needed by the PulseAudio's module-zeroconf-publish. +# PulseAudio will talk to the Avahi via the Dbus. +sleep 1 +avahi-daemon -D + +sleep 1 +exec su user -c "pulseaudio $@"