From 0b24116dbb962aa2b98a9e2819a61f47f9b4bd51 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 11:32:37 +0100 Subject: [PATCH 01/72] Tidy up the Dockerfile for AP2 and replace the AP1 Docker stuff with a derivative of the AP2 stuff to add the s6 overlay. The argument for invoking Shairport Sync on both should be 'shairport-sync --log-to-syslog' plus whatever command line arguments you want. --- docker/Dockerfile | 26 ++-- docker/classic/Dockerfile | 113 ++++++++---------- .../etc/s6-overlay/s6-rc.d/01-dbus/finish | 2 + .../etc/s6-overlay/s6-rc.d/01-dbus/run | 4 + .../etc/s6-overlay/s6-rc.d/01-dbus/type | 1 + .../etc/s6-overlay/s6-rc.d/02-avahi/finish | 2 + .../etc/s6-overlay/s6-rc.d/02-avahi/run | 8 ++ .../etc/s6-overlay/s6-rc.d/02-avahi/type | 1 + .../etc/s6-overlay/s6-rc.d/startup/script.sh | 2 + .../etc/s6-overlay/s6-rc.d/startup/type | 1 + .../classic/etc/s6-overlay/s6-rc.d/startup/up | 1 + .../s6-rc.d/user/contents.d/01-dbus | 0 .../s6-rc.d/user/contents.d/02-avahi | 0 .../s6-rc.d/user/contents.d/startup | 0 docker/classic/start.sh | 13 -- docker/etc/s6-overlay/s6-rc.d/03-nqptp/run | 2 +- 16 files changed, 79 insertions(+), 97 deletions(-) create mode 100644 docker/classic/etc/s6-overlay/s6-rc.d/01-dbus/finish create mode 100644 docker/classic/etc/s6-overlay/s6-rc.d/01-dbus/run create mode 100644 docker/classic/etc/s6-overlay/s6-rc.d/01-dbus/type create mode 100644 docker/classic/etc/s6-overlay/s6-rc.d/02-avahi/finish create mode 100644 docker/classic/etc/s6-overlay/s6-rc.d/02-avahi/run create mode 100644 docker/classic/etc/s6-overlay/s6-rc.d/02-avahi/type create mode 100644 docker/classic/etc/s6-overlay/s6-rc.d/startup/script.sh create mode 100644 docker/classic/etc/s6-overlay/s6-rc.d/startup/type create mode 100644 docker/classic/etc/s6-overlay/s6-rc.d/startup/up create mode 100644 docker/classic/etc/s6-overlay/s6-rc.d/user/contents.d/01-dbus create mode 100644 docker/classic/etc/s6-overlay/s6-rc.d/user/contents.d/02-avahi create mode 100644 docker/classic/etc/s6-overlay/s6-rc.d/user/contents.d/startup delete mode 100644 docker/classic/start.sh diff --git a/docker/Dockerfile b/docker/Dockerfile index a34d2c50..0ba13ea8 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -16,21 +16,17 @@ RUN apk -U add \ dbus \ alsa-lib-dev \ popt-dev \ - mbedtls-dev \ soxr-dev \ avahi-dev \ libconfig-dev \ libsndfile-dev \ mosquitto-dev \ - xmltoman \ - openssh-client \ libsodium-dev \ ffmpeg-dev \ xxd \ libressl-dev \ openssl-dev \ - libplist-dev \ - libgcrypt-dev + libplist-dev ##### ALAC ##### RUN git clone https://github.com/mikebrady/alac @@ -76,7 +72,6 @@ RUN apk -U add \ dbus \ popt \ glib \ - mbedtls \ soxr \ avahi \ avahi-tools \ @@ -86,8 +81,7 @@ RUN apk -U add \ libuuid \ ffmpeg \ libsodium \ - libplist \ - libgcrypt + libplist # Copy build files. COPY --from=builder /shairport-sync/build/install/usr/local/bin/shairport-sync /usr/local/bin/shairport-sync @@ -99,18 +93,14 @@ COPY --from=builder /shairport-sync/build/install/etc/dbus-1/system.d/shairport- COPY ./docker/etc/s6-overlay/s6-rc.d /etc/s6-overlay/s6-rc.d RUN chmod +x /etc/s6-overlay/s6-rc.d/startup/script.sh -# Create non-root user for running the container -- running as the user 'shairport-sync' also allows -# Shairport Sync to provide the D-Bus and MPRIS interfaces within the container - -RUN addgroup shairport-sync -RUN adduser -D shairport-sync -G shairport-sync - -# Add the shairport-sync user to the pre-existing audio group, which has ID 29, for access to the ALSA stuff -RUN addgroup -g 29 docker_audio && addgroup shairport-sync docker_audio && addgroup shairport-sync audio +# D-Bus and MPRIS services are normally provided by the user +# 'shairport-sync' running the 'shairport-sync' app. +# However, the 'shairport-sync' user is not defined in this Docker image, +# so we get a harmless warning that the user 'shairport-sync' is unknown. +# In the Docker image, D-Bus and MPRIS services are provided by +# the root user running the 'shairport-sync' app. # Remove anything we don't need. RUN rm -rf /lib/apk/db/* ENTRYPOINT [ "/init" ] - -CMD [ "/usr/local/bin/shairport-sync", "-v", "--statistics" ] \ No newline at end of file diff --git a/docker/classic/Dockerfile b/docker/classic/Dockerfile index 0556cd94..1325049a 100644 --- a/docker/classic/Dockerfile +++ b/docker/classic/Dockerfile @@ -1,5 +1,12 @@ -FROM alpine AS builder-base -# General Build System: +FROM alpine:3.12 AS builder + +# Classic (aka AirPlay 1) Build + +# Check required arguments exist. These will be provided by the Github Action +# Workflow and are required to ensure the correct branches are being used. +ARG SHAIRPORT_SYNC_BRANCH +RUN test -n "$SHAIRPORT_SYNC_BRANCH" + RUN apk -U add \ git \ build-base \ @@ -7,63 +14,42 @@ RUN apk -U add \ automake \ libtool \ dbus \ - su-exec \ alsa-lib-dev \ - libdaemon-dev \ popt-dev \ mbedtls-dev \ soxr-dev \ avahi-dev \ libconfig-dev \ - libsndfile-dev \ mosquitto-dev \ - xmltoman - -# ALAC Build System: -FROM builder-base AS builder-alac + libsndfile-dev +##### ALAC ##### RUN git clone https://github.com/mikebrady/alac -WORKDIR alac -RUN autoreconf -fi +WORKDIR /alac +RUN autoreconf -i RUN ./configure RUN make RUN make install +WORKDIR / +##### ALAC END ##### -# Shairport Sync Build System: -FROM builder-base AS builder-sps - -# This will be modified by the Github Action Workflow and is required -# to ensure the correct branch is being used. -ARG SHAIRPORT_SYNC_BRANCH -RUN test -n "$SHAIRPORT_SYNC_BRANCH" - -COPY --from=builder-alac /usr/local/lib/libalac.* /usr/local/lib/ -COPY --from=builder-alac /usr/local/lib/pkgconfig/alac.pc /usr/local/lib/pkgconfig/alac.pc -COPY --from=builder-alac /usr/local/include /usr/local/include - +##### SPS ##### WORKDIR /shairport-sync COPY . . RUN git checkout "$SHAIRPORT_SYNC_BRANCH" -RUN autoreconf -fi -RUN ./configure \ - --with-alsa \ - --with-dummy \ - --with-pipe \ - --with-stdout \ - --with-avahi \ - --with-ssl=mbedtls \ - --with-soxr \ - --sysconfdir=/etc \ - --with-dbus-interface \ - --with-mpris-interface \ - --with-mqtt-client \ - --with-apple-alac \ - --with-convolution +WORKDIR /shairport-sync/build +RUN autoreconf -i ../ +RUN ../configure --sysconfdir=/etc --with-alsa --with-soxr --with-avahi --with-ssl=mbedtls \ + --with-metadata --with-dummy --with-pipe --with-dbus-interface \ + --with-stdout --with-mpris-interface --with-mqtt-client \ + --with-apple-alac --with-convolution RUN make -j $(nproc) -RUN make install +RUN DESTDIR=install make install +WORKDIR / +##### SPS END ##### -# Shairport Sync Runtime System: -FROM alpine +# Shairport Sync Runtime System +FROM crazymax/alpine-s6:3.12-3.1.1.2 RUN apk -U add \ alsa-lib \ @@ -75,30 +61,27 @@ RUN apk -U add \ avahi \ avahi-tools \ libconfig \ - libsndfile \ - mosquitto-libs \ - su-exec \ - libgcc \ - libgc++ + mosquitto \ + libsndfile-dev + +# Copy build files. +COPY --from=builder /shairport-sync/build/install/usr/local/bin/shairport-sync /usr/local/bin/shairport-sync +COPY --from=builder /usr/local/lib/libalac.* /usr/local/lib/ +COPY --from=builder /shairport-sync/build/install/etc/dbus-1/system.d/shairport-sync-dbus.conf /etc/dbus-1/system.d/ +COPY --from=builder /shairport-sync/build/install/etc/dbus-1/system.d/shairport-sync-mpris.conf /etc/dbus-1/system.d/ + +COPY ./docker/classic/etc/s6-overlay/s6-rc.d /etc/s6-overlay/s6-rc.d +RUN chmod +x /etc/s6-overlay/s6-rc.d/startup/script.sh + +# D-Bus and MPRIS services are normally provided by the user +# 'shairport-sync' running the 'shairport-sync' app. +# However, the 'shairport-sync' user is not defined in this Docker image, +# so we get a harmless warning that the user 'shairport-sync' is unknown. +# In the Docker image, D-Bus and MPRIS services are provided by +# the root user running the 'shairport-sync' app. + +# Remove anything we don't need. RUN rm -rf /lib/apk/db/* -COPY --from=builder-alac /usr/local/lib/libalac.* /usr/local/lib/ -COPY --from=builder-sps /etc/shairport-sync* /etc/ -COPY --from=builder-sps /etc/dbus-1/system.d/shairport-sync-dbus.conf /etc/dbus-1/system.d/ -COPY --from=builder-sps /etc/dbus-1/system.d/shairport-sync-mpris.conf /etc/dbus-1/system.d/ -COPY --from=builder-sps /usr/local/bin/shairport-sync /usr/local/bin/shairport-sync - -# Create non-root user for running the container -- running as the user 'shairport-sync' also allows -# Shairport Sync to provide the D-Bus and MPRIS interfaces within the container - -RUN addgroup shairport-sync -RUN adduser -D shairport-sync -G shairport-sync - -# Add the shairport-sync user to the pre-existing audio group, which has ID 29, for access to the ALSA stuff -RUN addgroup -g 29 docker_audio && addgroup shairport-sync docker_audio - -COPY ./docker/classic/start.sh / -RUN chmod +x /start.sh - -ENTRYPOINT [ "/start.sh" ] +ENTRYPOINT [ "/init" ] diff --git a/docker/classic/etc/s6-overlay/s6-rc.d/01-dbus/finish b/docker/classic/etc/s6-overlay/s6-rc.d/01-dbus/finish new file mode 100644 index 00000000..a8222fb0 --- /dev/null +++ b/docker/classic/etc/s6-overlay/s6-rc.d/01-dbus/finish @@ -0,0 +1,2 @@ +#!/command/execlineb -S0 +/run/s6/basedir/bin/halt \ No newline at end of file diff --git a/docker/classic/etc/s6-overlay/s6-rc.d/01-dbus/run b/docker/classic/etc/s6-overlay/s6-rc.d/01-dbus/run new file mode 100644 index 00000000..8757e5d5 --- /dev/null +++ b/docker/classic/etc/s6-overlay/s6-rc.d/01-dbus/run @@ -0,0 +1,4 @@ +#!/command/with-contenv sh +rm -rf /var/run/dbus.pid +echo "Starting dbus" +exec dbus-daemon --system --nofork \ No newline at end of file diff --git a/docker/classic/etc/s6-overlay/s6-rc.d/01-dbus/type b/docker/classic/etc/s6-overlay/s6-rc.d/01-dbus/type new file mode 100644 index 00000000..1780f9f4 --- /dev/null +++ b/docker/classic/etc/s6-overlay/s6-rc.d/01-dbus/type @@ -0,0 +1 @@ +longrun \ No newline at end of file diff --git a/docker/classic/etc/s6-overlay/s6-rc.d/02-avahi/finish b/docker/classic/etc/s6-overlay/s6-rc.d/02-avahi/finish new file mode 100644 index 00000000..a8222fb0 --- /dev/null +++ b/docker/classic/etc/s6-overlay/s6-rc.d/02-avahi/finish @@ -0,0 +1,2 @@ +#!/command/execlineb -S0 +/run/s6/basedir/bin/halt \ No newline at end of file diff --git a/docker/classic/etc/s6-overlay/s6-rc.d/02-avahi/run b/docker/classic/etc/s6-overlay/s6-rc.d/02-avahi/run new file mode 100644 index 00000000..fc509297 --- /dev/null +++ b/docker/classic/etc/s6-overlay/s6-rc.d/02-avahi/run @@ -0,0 +1,8 @@ +#!/command/with-contenv sh +sleep 5 +while [ ! -f /var/run/dbus.pid ]; do + "dbus is not running, sleeping for 5 seconds before trying to start avahi" + sleep 5 +done +echo "Starting avahi" +exec avahi-daemon --no-chroot \ No newline at end of file diff --git a/docker/classic/etc/s6-overlay/s6-rc.d/02-avahi/type b/docker/classic/etc/s6-overlay/s6-rc.d/02-avahi/type new file mode 100644 index 00000000..1780f9f4 --- /dev/null +++ b/docker/classic/etc/s6-overlay/s6-rc.d/02-avahi/type @@ -0,0 +1 @@ +longrun \ No newline at end of file diff --git a/docker/classic/etc/s6-overlay/s6-rc.d/startup/script.sh b/docker/classic/etc/s6-overlay/s6-rc.d/startup/script.sh new file mode 100644 index 00000000..c975a403 --- /dev/null +++ b/docker/classic/etc/s6-overlay/s6-rc.d/startup/script.sh @@ -0,0 +1,2 @@ +#!/bin/sh +echo "STARTING - $(date)" \ No newline at end of file diff --git a/docker/classic/etc/s6-overlay/s6-rc.d/startup/type b/docker/classic/etc/s6-overlay/s6-rc.d/startup/type new file mode 100644 index 00000000..3d92b15f --- /dev/null +++ b/docker/classic/etc/s6-overlay/s6-rc.d/startup/type @@ -0,0 +1 @@ +oneshot \ No newline at end of file diff --git a/docker/classic/etc/s6-overlay/s6-rc.d/startup/up b/docker/classic/etc/s6-overlay/s6-rc.d/startup/up new file mode 100644 index 00000000..0c609ec6 --- /dev/null +++ b/docker/classic/etc/s6-overlay/s6-rc.d/startup/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/startup/script.sh \ No newline at end of file diff --git a/docker/classic/etc/s6-overlay/s6-rc.d/user/contents.d/01-dbus b/docker/classic/etc/s6-overlay/s6-rc.d/user/contents.d/01-dbus new file mode 100644 index 00000000..e69de29b diff --git a/docker/classic/etc/s6-overlay/s6-rc.d/user/contents.d/02-avahi b/docker/classic/etc/s6-overlay/s6-rc.d/user/contents.d/02-avahi new file mode 100644 index 00000000..e69de29b diff --git a/docker/classic/etc/s6-overlay/s6-rc.d/user/contents.d/startup b/docker/classic/etc/s6-overlay/s6-rc.d/user/contents.d/startup new file mode 100644 index 00000000..e69de29b diff --git a/docker/classic/start.sh b/docker/classic/start.sh deleted file mode 100644 index 5e24ff59..00000000 --- a/docker/classic/start.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -set -e - -rm -rf /var/run/dbus.pid -#mkdir -p /var/run/dbus - -dbus-uuidgen --ensure -dbus-daemon --system - -avahi-daemon --daemonize --no-chroot - -su-exec shairport-sync shairport-sync "$@" \ No newline at end of file diff --git a/docker/etc/s6-overlay/s6-rc.d/03-nqptp/run b/docker/etc/s6-overlay/s6-rc.d/03-nqptp/run index 7af2c601..e8b59b2e 100644 --- a/docker/etc/s6-overlay/s6-rc.d/03-nqptp/run +++ b/docker/etc/s6-overlay/s6-rc.d/03-nqptp/run @@ -1,3 +1,3 @@ #!/command/with-contenv sh echo "Starting nqptp" -exec /usr/local/bin/nqptp -v \ No newline at end of file +exec /usr/local/bin/nqptp \ No newline at end of file From 1d6a378c73e21a421024e226f336fceb966cad88 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 12:44:10 +0100 Subject: [PATCH 02/72] Small documentation change. --- AIRPLAY2.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AIRPLAY2.md b/AIRPLAY2.md index 9029b462..122f1d91 100644 --- a/AIRPLAY2.md +++ b/AIRPLAY2.md @@ -9,7 +9,7 @@ Shairport Sync offers AirPlay 2 support for audio sources on iOS devices, Macs f * Realtime streams generally have a latency of about two seconds. Buffered Audio streams typically have a latency of half a second or less. * In AirPlay 2 mode, Shairport Sync reverts to "classic" AirPlay when iTunes on macOS or macOS Music plays to multiple speakers and one of more of them is compatible with AirPlay only. -- Devices running Shairport Sync in AirPlay 2 mode can be [added](https://github.com/mikebrady/shairport-sync/blob/development/ADDINGTOHOME.md) to the Home app. +- Devices running Shairport Sync in AirPlay 2 mode can be [added](ADDINGTOHOME.md) to the Home app. ## What Does Not Work - No AirPlay 2 for Windows iTunes. @@ -31,7 +31,7 @@ Here are some guidelines: * An up-to-date Linux or FreeBSD. This is important, as some of the libraries must be the latest available. * Shairport Sync will not run on a Mac because NQPTP, on which it relies, needs ports 319 and 320, which are already used by macOS. * A version of the [FFmpeg](https://www.ffmpeg.org) library with an AAC decoder capable of decoding Floating Planar -- `fltp` -- material. There is a guide [here](TROUBLESHOOTING.md#aac-decoder-issues-airplay-2-only) to help you find out if your system has it. -* An audio output, for example an ALSA device (or `sndio` in FreeBSD). The device must be capable of running at 44,100 frames per second. You can use an `sps-alsa-explore`](https://github.com/mikebrady/sps-alsa-explore) to test the suitability of hardware ALSA audio devices on your device. +* An audio output, for example an ALSA device (or `sndio` in FreeBSD). The device must be capable of running at 44,100 frames per second. You can use an [`sps-alsa-explore`](https://github.com/mikebrady/sps-alsa-explore) to test the suitability of hardware ALSA audio devices on your device. Other backends continue to work as with "classic" Shairport Sync. ## Guides From 830b2a2703cea1756f18b1407d8a8cfa657a7e03 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 16:33:14 +0100 Subject: [PATCH 03/72] Simple build_check workflow trial. --- .github/workflows/build_check.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/build_check.yml diff --git a/.github/workflows/build_check.yml b/.github/workflows/build_check.yml new file mode 100644 index 00000000..38952783 --- /dev/null +++ b/.github/workflows/build_check.yml @@ -0,0 +1,25 @@ +name: Build Check + +on: + push: + branches: [ "danger" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Install Dependencies + run: apt install --no-install-recommends build-essential git xmltoman autoconf automake \ + libtool libpopt-dev libconfig-dev libasound2-dev avahi-daemon libavahi-client-dev \ + libssl-dev libsoxr-dev libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev xxd + - name: Configure + run: | + mkdir build + cd build + autoreconf -i .. + ../configure --sysconfdir=/etc --with-alsa --with-soxr --with-avahi --with-ssl=openssl --with-systemd --with-airplay-2 + - name: make + run: Make From 7c3c37c5b2c550fa569ca8d6f19a308f3538c607 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 16:37:26 +0100 Subject: [PATCH 04/72] Adjust build_check workflow. --- .github/workflows/build_check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_check.yml b/.github/workflows/build_check.yml index 38952783..f88d6d9e 100644 --- a/.github/workflows/build_check.yml +++ b/.github/workflows/build_check.yml @@ -12,7 +12,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Install Dependencies - run: apt install --no-install-recommends build-essential git xmltoman autoconf automake \ + run: sudo apt install -y --no-install-recommends build-essential git xmltoman autoconf automake \ libtool libpopt-dev libconfig-dev libasound2-dev avahi-daemon libavahi-client-dev \ libssl-dev libsoxr-dev libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev xxd - name: Configure From abad5b1e6a146c6852b1385e1775b7fde0ffd655 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 16:39:39 +0100 Subject: [PATCH 05/72] Adjust build_check workflow. --- .github/workflows/build_check.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/build_check.yml b/.github/workflows/build_check.yml index f88d6d9e..3d64fac7 100644 --- a/.github/workflows/build_check.yml +++ b/.github/workflows/build_check.yml @@ -12,9 +12,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Install Dependencies - run: sudo apt install -y --no-install-recommends build-essential git xmltoman autoconf automake \ - libtool libpopt-dev libconfig-dev libasound2-dev avahi-daemon libavahi-client-dev \ - libssl-dev libsoxr-dev libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev xxd + run: sudo apt-install -y --no-install-recommends build-essential git xmltoman autoconf automake libtool libpopt-dev libconfig-dev libasound2-dev avahi-daemon libavahi-client-dev libssl-dev libsoxr-dev libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev xxd - name: Configure run: | mkdir build From aa73205293a4a8d50648f000fa8c408785a17dd8 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 16:41:07 +0100 Subject: [PATCH 06/72] Adjust build_check workflow. --- .github/workflows/build_check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_check.yml b/.github/workflows/build_check.yml index 3d64fac7..d8a803c0 100644 --- a/.github/workflows/build_check.yml +++ b/.github/workflows/build_check.yml @@ -12,7 +12,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Install Dependencies - run: sudo apt-install -y --no-install-recommends build-essential git xmltoman autoconf automake libtool libpopt-dev libconfig-dev libasound2-dev avahi-daemon libavahi-client-dev libssl-dev libsoxr-dev libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev xxd + run: sudo apt-get -y --no-install-recommends build-essential git xmltoman autoconf automake libtool libpopt-dev libconfig-dev libasound2-dev avahi-daemon libavahi-client-dev libssl-dev libsoxr-dev libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev xxd - name: Configure run: | mkdir build From 037ced61b0346c70af551c5628fc1dcd876c6cca Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 16:43:18 +0100 Subject: [PATCH 07/72] Adjust build_check workflow. --- .github/workflows/build_check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_check.yml b/.github/workflows/build_check.yml index d8a803c0..a0bfa204 100644 --- a/.github/workflows/build_check.yml +++ b/.github/workflows/build_check.yml @@ -12,7 +12,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Install Dependencies - run: sudo apt-get -y --no-install-recommends build-essential git xmltoman autoconf automake libtool libpopt-dev libconfig-dev libasound2-dev avahi-daemon libavahi-client-dev libssl-dev libsoxr-dev libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev xxd + run: sudo apt-get -y --no-install-recommends install build-essential git xmltoman autoconf automake libtool libpopt-dev libconfig-dev libasound2-dev avahi-daemon libavahi-client-dev libssl-dev libsoxr-dev libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev xxd - name: Configure run: | mkdir build From 87cdf45620ad5a2bd6396dd158aa7404fd723633 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 16:47:15 +0100 Subject: [PATCH 08/72] Adjust build_check workflow. --- .github/workflows/build_check.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_check.yml b/.github/workflows/build_check.yml index a0bfa204..fe2448d9 100644 --- a/.github/workflows/build_check.yml +++ b/.github/workflows/build_check.yml @@ -19,5 +19,5 @@ jobs: cd build autoreconf -i .. ../configure --sysconfdir=/etc --with-alsa --with-soxr --with-avahi --with-ssl=openssl --with-systemd --with-airplay-2 - - name: make - run: Make + - name: Make + run: make -j From 48d3d4bfc656f5ba0aa1980e5c19b4dd291a2145 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 16:50:08 +0100 Subject: [PATCH 09/72] Adjust build_check workflow. --- .github/workflows/build_check.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_check.yml b/.github/workflows/build_check.yml index fe2448d9..8bb2f354 100644 --- a/.github/workflows/build_check.yml +++ b/.github/workflows/build_check.yml @@ -20,4 +20,6 @@ jobs: autoreconf -i .. ../configure --sysconfdir=/etc --with-alsa --with-soxr --with-avahi --with-ssl=openssl --with-systemd --with-airplay-2 - name: Make - run: make -j + run: | + cd build + make -j From 993434cefbff8eed458e0476d9e5df2155209050 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 16:54:39 +0100 Subject: [PATCH 10/72] Enhance build_check workflow. --- .github/workflows/build_check.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/build_check.yml b/.github/workflows/build_check.yml index 8bb2f354..39eb153b 100644 --- a/.github/workflows/build_check.yml +++ b/.github/workflows/build_check.yml @@ -23,3 +23,14 @@ jobs: run: | cd build make -j + - name: Install + run: | + cd build + sudo make install + - invoke: + run: | + sudo systemctl shairport-sync start + - terminate: + run: | + sudo systemctl shairport-sync stop + From 26fac6750d098f0668d09d8383c40c8db1538e67 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 16:56:21 +0100 Subject: [PATCH 11/72] Enhance build_check workflow. --- .github/workflows/build_check.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_check.yml b/.github/workflows/build_check.yml index 39eb153b..fc34e90d 100644 --- a/.github/workflows/build_check.yml +++ b/.github/workflows/build_check.yml @@ -27,10 +27,10 @@ jobs: run: | cd build sudo make install - - invoke: + - name: Invoke run: | sudo systemctl shairport-sync start - - terminate: + - name: Terminate run: | sudo systemctl shairport-sync stop From 92c0a9c89cc1143e02d621d5a3cceb3fec97ee70 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 17:04:31 +0100 Subject: [PATCH 12/72] Enhance build_check workflow. --- .github/workflows/build_check.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/build_check.yml b/.github/workflows/build_check.yml index fc34e90d..59cfd383 100644 --- a/.github/workflows/build_check.yml +++ b/.github/workflows/build_check.yml @@ -13,19 +13,13 @@ jobs: - uses: actions/checkout@v3 - name: Install Dependencies run: sudo apt-get -y --no-install-recommends install build-essential git xmltoman autoconf automake libtool libpopt-dev libconfig-dev libasound2-dev avahi-daemon libavahi-client-dev libssl-dev libsoxr-dev libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev xxd - - name: Configure + - name: Build run: | mkdir build cd build autoreconf -i .. ../configure --sysconfdir=/etc --with-alsa --with-soxr --with-avahi --with-ssl=openssl --with-systemd --with-airplay-2 - - name: Make - run: | - cd build make -j - - name: Install - run: | - cd build sudo make install - name: Invoke run: | From 8b96d0cb5f10e5d58357f79d0aac8d3011617dea Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 17:07:17 +0100 Subject: [PATCH 13/72] Enhance build_check workflow. --- .github/workflows/build_check.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_check.yml b/.github/workflows/build_check.yml index 59cfd383..c0480d67 100644 --- a/.github/workflows/build_check.yml +++ b/.github/workflows/build_check.yml @@ -13,13 +13,20 @@ jobs: - uses: actions/checkout@v3 - name: Install Dependencies run: sudo apt-get -y --no-install-recommends install build-essential git xmltoman autoconf automake libtool libpopt-dev libconfig-dev libasound2-dev avahi-daemon libavahi-client-dev libssl-dev libsoxr-dev libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev xxd - - name: Build + - name: Configure run: | mkdir build cd build autoreconf -i .. ../configure --sysconfdir=/etc --with-alsa --with-soxr --with-avahi --with-ssl=openssl --with-systemd --with-airplay-2 + - name: Make + run: | + cd build make -j + - name: Install + run: | + ls -al ../scripts + cd build sudo make install - name: Invoke run: | From 9d7b56564b9fc95578ec2dccc4198b432f8aa268 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 17:12:21 +0100 Subject: [PATCH 14/72] Enhance build_check workflow. --- .github/workflows/build_check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_check.yml b/.github/workflows/build_check.yml index c0480d67..873414e9 100644 --- a/.github/workflows/build_check.yml +++ b/.github/workflows/build_check.yml @@ -25,7 +25,7 @@ jobs: make -j - name: Install run: | - ls -al ../scripts + ls -al scripts cd build sudo make install - name: Invoke From a11ca360836fe35e7d18d39aa39d3bc137b8c7b3 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 17:17:05 +0100 Subject: [PATCH 15/72] Explore build_check workflow. --- .github/workflows/build_check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_check.yml b/.github/workflows/build_check.yml index 873414e9..9edc8d4f 100644 --- a/.github/workflows/build_check.yml +++ b/.github/workflows/build_check.yml @@ -25,8 +25,8 @@ jobs: make -j - name: Install run: | - ls -al scripts cd build + ls -al scripts sudo make install - name: Invoke run: | From 7f9e8116d74e57e188711b1e46e87092307d1d65 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 17:25:27 +0100 Subject: [PATCH 16/72] Look for the shairport-sync.service file in the scripts folder in the _build_ folder, because it's generated by ./configure. Same with the SystemV init file. --- Makefile.am | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index b681ed3e..d1dfb848 100644 --- a/Makefile.am +++ b/Makefile.am @@ -267,9 +267,13 @@ if INSTALL_SYSTEMV INSTALL_SYSTEMV_TARGET = install-systemv-local +# watch out -- shairport-sync is created during the ./configure step and +# will be stored in a scripts folder in the _build_ folder +# which will be the source folder if you're not using a separate build folder + $(INSTALL_SYSTEMV_TARGET): scripts/shairport-sync $(INSTALL_USER_TARGET) install -d $(DESTDIR)$(sysconfdir)/init.d - [ -e $(DESTDIR)$(sysconfdir)/init.d/shairport-sync ] || install -m 0644 $(top_srcdir)/scripts/shairport-sync $(DESTDIR)$(sysconfdir)/init.d + [ -e $(DESTDIR)$(sysconfdir)/init.d/shairport-sync ] || install -m 0644 scripts/shairport-sync $(DESTDIR)$(sysconfdir)/init.d endif # INSTALL_SYSTEMV @@ -283,9 +287,13 @@ endif # USE_AVAHI INSTALL_SYSTEMD_TARGET = install-systemd-local +# watch out -- shairport-sync.service is created during the ./configure step and +# will be stored in a scripts folder in the _build_ folder +# which will be the source folder if you're not using a separate build folder + $(INSTALL_SYSTEMD_TARGET): scripts/$(SYSTEMD_SERVICE) $(INSTALL_USER_TARGET) install -d $(DESTDIR)$(systemdsystemunitdir) - [ -e $(DESTDIR)$(systemdsystemunitdir)/shairport-sync.service ] || install -m 0644 $(top_srcdir)/scripts/$(SYSTEMD_SERVICE) $(DESTDIR)$(systemdsystemunitdir)/shairport-sync.service + [ -e $(DESTDIR)$(systemdsystemunitdir)/shairport-sync.service ] || install -m 0644 scripts/$(SYSTEMD_SERVICE) $(DESTDIR)$(systemdsystemunitdir)/shairport-sync.service endif # INSTALL_SYSTEMD From 300bd525f35fd3e35a6187941344f88efc439813 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 17:28:56 +0100 Subject: [PATCH 17/72] Enhance build_check workflow. --- .github/workflows/build_check.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_check.yml b/.github/workflows/build_check.yml index 9edc8d4f..d83d2d07 100644 --- a/.github/workflows/build_check.yml +++ b/.github/workflows/build_check.yml @@ -26,12 +26,11 @@ jobs: - name: Install run: | cd build - ls -al scripts sudo make install - name: Invoke run: | - sudo systemctl shairport-sync start + sudo systemctl start shairport-sync - name: Terminate run: | - sudo systemctl shairport-sync stop + sudo systemctl stop shairport-sync From ad2f05288ae548ef9f7e9975b9b1f95845afceb8 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 17:39:00 +0100 Subject: [PATCH 18/72] Initial workflow for checking a basic AirPlay systemd build and install --- .../workflows/{build_check.yml => check_ap2_systemd_basic.yml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{build_check.yml => check_ap2_systemd_basic.yml} (96%) diff --git a/.github/workflows/build_check.yml b/.github/workflows/check_ap2_systemd_basic.yml similarity index 96% rename from .github/workflows/build_check.yml rename to .github/workflows/check_ap2_systemd_basic.yml index d83d2d07..a89cfd35 100644 --- a/.github/workflows/build_check.yml +++ b/.github/workflows/check_ap2_systemd_basic.yml @@ -1,4 +1,4 @@ -name: Build Check +name: Build Check Basic AP2 on systemd on: push: From 127bace0abdde04237ee721db5d2f4adf2dd775e Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 17:53:02 +0100 Subject: [PATCH 19/72] Initial full-fat build check -- omits pipewire. --- .github/workflows/check_ap2_systemd_full.yml | 36 ++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/check_ap2_systemd_full.yml diff --git a/.github/workflows/check_ap2_systemd_full.yml b/.github/workflows/check_ap2_systemd_full.yml new file mode 100644 index 00000000..cdccdc38 --- /dev/null +++ b/.github/workflows/check_ap2_systemd_full.yml @@ -0,0 +1,36 @@ +name: Build Check (Nearly) Full AP2 on systemd + +on: + push: + branches: [ "danger" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Install Dependencies + run: sudo apt-get -y --no-install-recommends install build-essential git xmltoman autoconf automake libtool libpopt-dev libconfig-dev libasound2-dev libao-dev libjack-dev libpulse-dev libsoundio-dev libsndio-dev libglib2.0-dev libmosquitto-dev avahi-daemon libavahi-client-dev libssl-dev libsoxr-dev libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev xxd + - name: Configure + run: | + mkdir build + cd build + autoreconf -i .. + ../configure --sysconfdir=/etc --with-alsa --with-ao --with-dummy --with-jack --with-pa --with-pipe --with-sndio --with-soundio --with-stdout --with-soxr --with-avahi --with-ssl=openssl --with-systemd --with-dbus-interface --with-mpris-interface --with-mqtt-client --with-airplay-2 + - name: Make + run: | + cd build + make -j + - name: Install + run: | + cd build + sudo make install + - name: Invoke + run: | + sudo systemctl start shairport-sync + - name: Terminate + run: | + sudo systemctl stop shairport-sync + From 0931323af7c2cc02dcf550b9946663522e7204c6 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 18:01:46 +0100 Subject: [PATCH 20/72] Add classic systemd build workflows. --- .../workflows/check_classic_systemd_basic.yml | 36 +++++++++++++++++++ .../workflows/check_classic_systemd_full.yml | 36 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 .github/workflows/check_classic_systemd_basic.yml create mode 100644 .github/workflows/check_classic_systemd_full.yml diff --git a/.github/workflows/check_classic_systemd_basic.yml b/.github/workflows/check_classic_systemd_basic.yml new file mode 100644 index 00000000..36534c01 --- /dev/null +++ b/.github/workflows/check_classic_systemd_basic.yml @@ -0,0 +1,36 @@ +name: Check Basic Classic on systemd + +on: + push: + branches: [ "danger" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Install Dependencies + run: sudo apt-get -y --no-install-recommends install build-essential git xmltoman autoconf automake libtool libpopt-dev libconfig-dev libasound2-dev avahi-daemon libavahi-client-dev libssl-dev libsoxr-dev + - name: Configure + run: | + mkdir build + cd build + autoreconf -i .. + ../configure --sysconfdir=/etc --with-alsa --with-soxr --with-avahi --with-ssl=openssl --with-systemd + - name: Make + run: | + cd build + make -j + - name: Install + run: | + cd build + sudo make install + - name: Invoke + run: | + sudo systemctl start shairport-sync + - name: Terminate + run: | + sudo systemctl stop shairport-sync + diff --git a/.github/workflows/check_classic_systemd_full.yml b/.github/workflows/check_classic_systemd_full.yml new file mode 100644 index 00000000..a90d09da --- /dev/null +++ b/.github/workflows/check_classic_systemd_full.yml @@ -0,0 +1,36 @@ +name: Build Check (Nearly) Full Classic on systemd + +on: + push: + branches: [ "danger" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Install Dependencies + run: sudo apt-get -y --no-install-recommends install build-essential git xmltoman autoconf automake libtool libpopt-dev libconfig-dev libasound2-dev libao-dev libjack-dev libpulse-dev libsoundio-dev libsndio-dev libglib2.0-dev libmosquitto-dev avahi-daemon libavahi-client-dev libssl-dev libsoxr-dev + - name: Configure + run: | + mkdir build + cd build + autoreconf -i .. + ../configure --sysconfdir=/etc --with-alsa --with-ao --with-dummy --with-jack --with-pa --with-pipe --with-sndio --with-soundio --with-stdout --with-soxr --with-avahi --with-ssl=openssl --with-systemd --with-dbus-interface --with-mpris-interface --with-mqtt-client + - name: Make + run: | + cd build + make -j + - name: Install + run: | + cd build + sudo make install + - name: Invoke + run: | + sudo systemctl start shairport-sync + - name: Terminate + run: | + sudo systemctl stop shairport-sync + From 29b85b4273446a9fcd79e41048b49da9fcfa4c1c Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 22:46:26 +0100 Subject: [PATCH 21/72] Try a macOS check. --- .github/workflows/check_classic_mac_basic.yml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/workflows/check_classic_mac_basic.yml diff --git a/.github/workflows/check_classic_mac_basic.yml b/.github/workflows/check_classic_mac_basic.yml new file mode 100644 index 00000000..48985a8f --- /dev/null +++ b/.github/workflows/check_classic_mac_basic.yml @@ -0,0 +1,20 @@ +name: Check Basic Classic on macOS with brew + +on: + push: + branches: [ "danger" ] + +jobs: + build: + + runs-on: macos-latest + + steps: + - uses: actions/checkout@v3 + - name: Install Dependencies + run: | + brew update + brew install autoconf + brew install automake + brew install pkg-config + brew install openssl From 9c5f230c1ce8b95344f2e86c465ad50fbfbb6165 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 22:54:24 +0100 Subject: [PATCH 22/72] Improve macOS check. --- .github/workflows/check_classic_mac_basic.yml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check_classic_mac_basic.yml b/.github/workflows/check_classic_mac_basic.yml index 48985a8f..c567230b 100644 --- a/.github/workflows/check_classic_mac_basic.yml +++ b/.github/workflows/check_classic_mac_basic.yml @@ -14,7 +14,22 @@ jobs: - name: Install Dependencies run: | brew update - brew install autoconf brew install automake - brew install pkg-config brew install openssl + brew upgrade + + - name: Set Equates + run: | + export CPPFLAGS="-I/usr/local/opt/openssl@3/include" + export LDFLAGS="-L/usr/local/opt/openssl@3/lib" + export PATH="$(brew --prefix)/opt/openssl/bin:${PATH}" + export PKG_CONFIG_PATH="$(brew --prefix)/opt/openssl/lib/pkgconfig" + + - name: Configure + run: | + autoreconf -fi + ./configure --with-os=darwin --with-ao --with-stdout --with-dns_sd --with-ssl=openssl + + - name: Make + run: | + make From e133990de7a94e73721407dbf5ac395f8bedc498 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 23:00:05 +0100 Subject: [PATCH 23/72] Improve macOS check. --- .github/workflows/check_classic_mac_basic.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check_classic_mac_basic.yml b/.github/workflows/check_classic_mac_basic.yml index c567230b..3b0b0d01 100644 --- a/.github/workflows/check_classic_mac_basic.yml +++ b/.github/workflows/check_classic_mac_basic.yml @@ -16,7 +16,7 @@ jobs: brew update brew install automake brew install openssl - brew upgrade + brew install popt - name: Set Equates run: | From d21c8c013b15c0c1378af54b834184e1d490c138 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 23:02:34 +0100 Subject: [PATCH 24/72] Improve macOS check. --- .github/workflows/check_classic_mac_basic.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/check_classic_mac_basic.yml b/.github/workflows/check_classic_mac_basic.yml index 3b0b0d01..e9cd59ad 100644 --- a/.github/workflows/check_classic_mac_basic.yml +++ b/.github/workflows/check_classic_mac_basic.yml @@ -17,6 +17,7 @@ jobs: brew install automake brew install openssl brew install popt + brew install libconfig - name: Set Equates run: | From 8f58b7fa931cdc247430e964ff2edaaf0211f6de Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 23:09:15 +0100 Subject: [PATCH 25/72] Improve macOS check. --- .github/workflows/check_classic_mac_basic.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check_classic_mac_basic.yml b/.github/workflows/check_classic_mac_basic.yml index e9cd59ad..22baa24a 100644 --- a/.github/workflows/check_classic_mac_basic.yml +++ b/.github/workflows/check_classic_mac_basic.yml @@ -23,8 +23,8 @@ jobs: run: | export CPPFLAGS="-I/usr/local/opt/openssl@3/include" export LDFLAGS="-L/usr/local/opt/openssl@3/lib" - export PATH="$(brew --prefix)/opt/openssl/bin:${PATH}" - export PKG_CONFIG_PATH="$(brew --prefix)/opt/openssl/lib/pkgconfig" + export PATH="/usr/local/opt/openssl/bin:${PATH}" + export PKG_CONFIG_PATH="/usr/local/opt/openssl@3/lib/pkgconfig" - name: Configure run: | From 60ad8bdfce28e5cf884f67a69c5f4d3e94c92ed1 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 23:13:10 +0100 Subject: [PATCH 26/72] Improve macOS check. --- .github/workflows/check_classic_mac_basic.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/check_classic_mac_basic.yml b/.github/workflows/check_classic_mac_basic.yml index 22baa24a..d76cca2c 100644 --- a/.github/workflows/check_classic_mac_basic.yml +++ b/.github/workflows/check_classic_mac_basic.yml @@ -19,15 +19,12 @@ jobs: brew install popt brew install libconfig - - name: Set Equates + - name: Configure run: | export CPPFLAGS="-I/usr/local/opt/openssl@3/include" export LDFLAGS="-L/usr/local/opt/openssl@3/lib" export PATH="/usr/local/opt/openssl/bin:${PATH}" export PKG_CONFIG_PATH="/usr/local/opt/openssl@3/lib/pkgconfig" - - - name: Configure - run: | autoreconf -fi ./configure --with-os=darwin --with-ao --with-stdout --with-dns_sd --with-ssl=openssl From ebe8508d729e19476d795bd19fc4f528ec74323e Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 28 Sep 2022 23:15:50 +0100 Subject: [PATCH 27/72] Improve macOS check. --- .github/workflows/check_classic_mac_basic.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/check_classic_mac_basic.yml b/.github/workflows/check_classic_mac_basic.yml index d76cca2c..7684b589 100644 --- a/.github/workflows/check_classic_mac_basic.yml +++ b/.github/workflows/check_classic_mac_basic.yml @@ -18,6 +18,7 @@ jobs: brew install openssl brew install popt brew install libconfig + brew install libao - name: Configure run: | From 11c10f4fda51790812815d50ec032334b93dc62b Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 10:42:47 +0100 Subject: [PATCH 28/72] Add a check for building without using a separate build folder. --- .github/workflows/check_ap2_systemd_full.yml | 10 ++---- .../check_ap2_systemd_full_build_folder.yml | 36 +++++++++++++++++++ 2 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/check_ap2_systemd_full_build_folder.yml diff --git a/.github/workflows/check_ap2_systemd_full.yml b/.github/workflows/check_ap2_systemd_full.yml index cdccdc38..3852a343 100644 --- a/.github/workflows/check_ap2_systemd_full.yml +++ b/.github/workflows/check_ap2_systemd_full.yml @@ -1,4 +1,4 @@ -name: Build Check (Nearly) Full AP2 on systemd +name: Build Check (Nearly) Full AP2 on systemd build in place on: push: @@ -15,17 +15,13 @@ jobs: run: sudo apt-get -y --no-install-recommends install build-essential git xmltoman autoconf automake libtool libpopt-dev libconfig-dev libasound2-dev libao-dev libjack-dev libpulse-dev libsoundio-dev libsndio-dev libglib2.0-dev libmosquitto-dev avahi-daemon libavahi-client-dev libssl-dev libsoxr-dev libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev xxd - name: Configure run: | - mkdir build - cd build - autoreconf -i .. - ../configure --sysconfdir=/etc --with-alsa --with-ao --with-dummy --with-jack --with-pa --with-pipe --with-sndio --with-soundio --with-stdout --with-soxr --with-avahi --with-ssl=openssl --with-systemd --with-dbus-interface --with-mpris-interface --with-mqtt-client --with-airplay-2 + autoreconf -i + ./configure --sysconfdir=/etc --with-alsa --with-ao --with-dummy --with-jack --with-pa --with-pipe --with-sndio --with-soundio --with-stdout --with-soxr --with-avahi --with-ssl=openssl --with-systemd --with-dbus-interface --with-mpris-interface --with-mqtt-client --with-airplay-2 - name: Make run: | - cd build make -j - name: Install run: | - cd build sudo make install - name: Invoke run: | diff --git a/.github/workflows/check_ap2_systemd_full_build_folder.yml b/.github/workflows/check_ap2_systemd_full_build_folder.yml new file mode 100644 index 00000000..cdccdc38 --- /dev/null +++ b/.github/workflows/check_ap2_systemd_full_build_folder.yml @@ -0,0 +1,36 @@ +name: Build Check (Nearly) Full AP2 on systemd + +on: + push: + branches: [ "danger" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Install Dependencies + run: sudo apt-get -y --no-install-recommends install build-essential git xmltoman autoconf automake libtool libpopt-dev libconfig-dev libasound2-dev libao-dev libjack-dev libpulse-dev libsoundio-dev libsndio-dev libglib2.0-dev libmosquitto-dev avahi-daemon libavahi-client-dev libssl-dev libsoxr-dev libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev xxd + - name: Configure + run: | + mkdir build + cd build + autoreconf -i .. + ../configure --sysconfdir=/etc --with-alsa --with-ao --with-dummy --with-jack --with-pa --with-pipe --with-sndio --with-soundio --with-stdout --with-soxr --with-avahi --with-ssl=openssl --with-systemd --with-dbus-interface --with-mpris-interface --with-mqtt-client --with-airplay-2 + - name: Make + run: | + cd build + make -j + - name: Install + run: | + cd build + sudo make install + - name: Invoke + run: | + sudo systemctl start shairport-sync + - name: Terminate + run: | + sudo systemctl stop shairport-sync + From ce4c470174747db1a7b1166143be588053045700 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 10:50:56 +0100 Subject: [PATCH 29/72] Add a check for building for System V. --- .github/workflows/check_ap2_systemv_full.yml | 32 ++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/check_ap2_systemv_full.yml diff --git a/.github/workflows/check_ap2_systemv_full.yml b/.github/workflows/check_ap2_systemv_full.yml new file mode 100644 index 00000000..08119510 --- /dev/null +++ b/.github/workflows/check_ap2_systemv_full.yml @@ -0,0 +1,32 @@ +name: Build Check (Nearly) Full AP2 on System V build in place + +on: + push: + branches: [ "danger" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Install Dependencies + run: sudo apt-get -y --no-install-recommends install build-essential git xmltoman autoconf automake libtool libpopt-dev libdaemon libconfig-dev libasound2-dev libao-dev libjack-dev libpulse-dev libsoundio-dev libsndio-dev libglib2.0-dev libmosquitto-dev avahi-daemon libavahi-client-dev libssl-dev libsoxr-dev libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev xxd + - name: Configure + run: | + autoreconf -i + ./configure --sysconfdir=/etc --with-alsa --with-ao --with-dummy --with-libdaemon --with-jack --with-pa --with-pipe --with-sndio --with-soundio --with-stdout --with-soxr --with-avahi --with-ssl=openssl --with-systemv --with-dbus-interface --with-mpris-interface --with-mqtt-client --with-airplay-2 + - name: Make + run: | + make -j + - name: Install + run: | + sudo make install + - name: Invoke + run: | + sudo service shairport-sync start + - name: Terminate + run: | + sudo service shairport-sync stop + From 1783b60f6542a3d7450a2fa6f3e24bc65f9ef946 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 10:53:15 +0100 Subject: [PATCH 30/72] Fix for building for System V. --- .github/workflows/check_ap2_systemv_full.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check_ap2_systemv_full.yml b/.github/workflows/check_ap2_systemv_full.yml index 08119510..8f6313e6 100644 --- a/.github/workflows/check_ap2_systemv_full.yml +++ b/.github/workflows/check_ap2_systemv_full.yml @@ -12,7 +12,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Install Dependencies - run: sudo apt-get -y --no-install-recommends install build-essential git xmltoman autoconf automake libtool libpopt-dev libdaemon libconfig-dev libasound2-dev libao-dev libjack-dev libpulse-dev libsoundio-dev libsndio-dev libglib2.0-dev libmosquitto-dev avahi-daemon libavahi-client-dev libssl-dev libsoxr-dev libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev xxd + run: sudo apt-get -y --no-install-recommends install build-essential git xmltoman autoconf automake libtool libpopt-dev libdaemon-dev libconfig-dev libasound2-dev libao-dev libjack-dev libpulse-dev libsoundio-dev libsndio-dev libglib2.0-dev libmosquitto-dev avahi-daemon libavahi-client-dev libssl-dev libsoxr-dev libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev xxd - name: Configure run: | autoreconf -i From 16a150afbb4f7beb0f6f82951c9b394aaad86b76 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 10:56:22 +0100 Subject: [PATCH 31/72] Fix for building for System V. --- .github/workflows/check_ap2_systemv_full.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check_ap2_systemv_full.yml b/.github/workflows/check_ap2_systemv_full.yml index 8f6313e6..f1b7216c 100644 --- a/.github/workflows/check_ap2_systemv_full.yml +++ b/.github/workflows/check_ap2_systemv_full.yml @@ -25,8 +25,9 @@ jobs: sudo make install - name: Invoke run: | - sudo service shairport-sync start + sudo /etc/init.d/shairport-sync start + sleep 2 - name: Terminate run: | - sudo service shairport-sync stop + sudo /etc/init.d/shairport-sync stop From 44ae68e8fa5d70d7c03a03a291635cdac3c9201f Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 10:59:51 +0100 Subject: [PATCH 32/72] Fix for building for System V. --- .github/workflows/check_ap2_systemv_full.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/check_ap2_systemv_full.yml b/.github/workflows/check_ap2_systemv_full.yml index f1b7216c..420ca860 100644 --- a/.github/workflows/check_ap2_systemv_full.yml +++ b/.github/workflows/check_ap2_systemv_full.yml @@ -25,9 +25,6 @@ jobs: sudo make install - name: Invoke run: | - sudo /etc/init.d/shairport-sync start + ls -al /etc/init.d/ sleep 2 - - name: Terminate - run: | - sudo /etc/init.d/shairport-sync stop From 1296b8f2f86c40ee707c907644f4025476ae6875 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 11:02:46 +0100 Subject: [PATCH 33/72] Fix for building for System V. --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index d1dfb848..1dc654cc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -273,7 +273,7 @@ INSTALL_SYSTEMV_TARGET = install-systemv-local $(INSTALL_SYSTEMV_TARGET): scripts/shairport-sync $(INSTALL_USER_TARGET) install -d $(DESTDIR)$(sysconfdir)/init.d - [ -e $(DESTDIR)$(sysconfdir)/init.d/shairport-sync ] || install -m 0644 scripts/shairport-sync $(DESTDIR)$(sysconfdir)/init.d + [ -e $(DESTDIR)$(sysconfdir)/init.d/shairport-sync ] || install -m 0755 scripts/shairport-sync $(DESTDIR)$(sysconfdir)/init.d endif # INSTALL_SYSTEMV From 521e97ad414ac1062b8aaeb5bb48ab2e2200b4b8 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 11:05:31 +0100 Subject: [PATCH 34/72] Fix for building for System V. --- .github/workflows/check_ap2_systemv_full.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check_ap2_systemv_full.yml b/.github/workflows/check_ap2_systemv_full.yml index 420ca860..f1b7216c 100644 --- a/.github/workflows/check_ap2_systemv_full.yml +++ b/.github/workflows/check_ap2_systemv_full.yml @@ -25,6 +25,9 @@ jobs: sudo make install - name: Invoke run: | - ls -al /etc/init.d/ + sudo /etc/init.d/shairport-sync start sleep 2 + - name: Terminate + run: | + sudo /etc/init.d/shairport-sync stop From 7933f5e3d4f1e5f67269629c5780acd559a12620 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 11:10:06 +0100 Subject: [PATCH 35/72] Fix for building for System V. --- .github/workflows/check_ap2_systemv_full.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check_ap2_systemv_full.yml b/.github/workflows/check_ap2_systemv_full.yml index f1b7216c..d6e3a50d 100644 --- a/.github/workflows/check_ap2_systemv_full.yml +++ b/.github/workflows/check_ap2_systemv_full.yml @@ -1,4 +1,4 @@ -name: Build Check (Nearly) Full AP2 on System V build in place +name: Full AP2 on System V in place on: push: From 54d9e0af82b1b2e00f20530988be80140ad7b321 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 11:18:38 +0100 Subject: [PATCH 36/72] name changes. --- .github/workflows/check_ap2_systemd_basic.yml | 2 +- .github/workflows/check_ap2_systemd_full.yml | 2 +- .github/workflows/check_ap2_systemd_full_build_folder.yml | 2 +- .github/workflows/check_ap2_systemv_full.yml | 2 +- .github/workflows/check_classic_mac_basic.yml | 2 +- .github/workflows/check_classic_systemd_basic.yml | 2 +- .github/workflows/check_classic_systemd_full.yml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/check_ap2_systemd_basic.yml b/.github/workflows/check_ap2_systemd_basic.yml index a89cfd35..33d5ae27 100644 --- a/.github/workflows/check_ap2_systemd_basic.yml +++ b/.github/workflows/check_ap2_systemd_basic.yml @@ -1,4 +1,4 @@ -name: Build Check Basic AP2 on systemd +name: Basic AP2 on systemd in build folder on: push: diff --git a/.github/workflows/check_ap2_systemd_full.yml b/.github/workflows/check_ap2_systemd_full.yml index 3852a343..c7e2bb83 100644 --- a/.github/workflows/check_ap2_systemd_full.yml +++ b/.github/workflows/check_ap2_systemd_full.yml @@ -1,4 +1,4 @@ -name: Build Check (Nearly) Full AP2 on systemd build in place +name: Full AP2 on systemd build in place on: push: diff --git a/.github/workflows/check_ap2_systemd_full_build_folder.yml b/.github/workflows/check_ap2_systemd_full_build_folder.yml index cdccdc38..065ada59 100644 --- a/.github/workflows/check_ap2_systemd_full_build_folder.yml +++ b/.github/workflows/check_ap2_systemd_full_build_folder.yml @@ -1,4 +1,4 @@ -name: Build Check (Nearly) Full AP2 on systemd +name: Full AP2 on systemd in build folder on: push: diff --git a/.github/workflows/check_ap2_systemv_full.yml b/.github/workflows/check_ap2_systemv_full.yml index d6e3a50d..eee1b468 100644 --- a/.github/workflows/check_ap2_systemv_full.yml +++ b/.github/workflows/check_ap2_systemv_full.yml @@ -1,4 +1,4 @@ -name: Full AP2 on System V in place +name: AP2 on System V in place on: push: diff --git a/.github/workflows/check_classic_mac_basic.yml b/.github/workflows/check_classic_mac_basic.yml index 7684b589..9489f3fb 100644 --- a/.github/workflows/check_classic_mac_basic.yml +++ b/.github/workflows/check_classic_mac_basic.yml @@ -1,4 +1,4 @@ -name: Check Basic Classic on macOS with brew +name: Classic on macOS with brew on: push: diff --git a/.github/workflows/check_classic_systemd_basic.yml b/.github/workflows/check_classic_systemd_basic.yml index 36534c01..952c2daa 100644 --- a/.github/workflows/check_classic_systemd_basic.yml +++ b/.github/workflows/check_classic_systemd_basic.yml @@ -1,4 +1,4 @@ -name: Check Basic Classic on systemd +name: Basic Classic on systemd on: push: diff --git a/.github/workflows/check_classic_systemd_full.yml b/.github/workflows/check_classic_systemd_full.yml index a90d09da..c648aa76 100644 --- a/.github/workflows/check_classic_systemd_full.yml +++ b/.github/workflows/check_classic_systemd_full.yml @@ -1,4 +1,4 @@ -name: Build Check (Nearly) Full Classic on systemd +name: Classic on systemd in build folder on: push: From f294b503902a677beb10ffd9fe1e5c7b848a1285 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 11:22:36 +0100 Subject: [PATCH 37/72] Try all --- .github/workflows/check_ap2_systemd_basic.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check_ap2_systemd_basic.yml b/.github/workflows/check_ap2_systemd_basic.yml index 33d5ae27..f8919861 100644 --- a/.github/workflows/check_ap2_systemd_basic.yml +++ b/.github/workflows/check_ap2_systemd_basic.yml @@ -1,4 +1,4 @@ -name: Basic AP2 on systemd in build folder +name: Basic AP2 on systemd in build folder on: push: From e56e047f79cd89be6af2dd3951fda1e409d11c58 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 12:27:12 +0100 Subject: [PATCH 38/72] Fix a layout error and reference. --- AIRPLAY2.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AIRPLAY2.md b/AIRPLAY2.md index 122f1d91..9029b462 100644 --- a/AIRPLAY2.md +++ b/AIRPLAY2.md @@ -9,7 +9,7 @@ Shairport Sync offers AirPlay 2 support for audio sources on iOS devices, Macs f * Realtime streams generally have a latency of about two seconds. Buffered Audio streams typically have a latency of half a second or less. * In AirPlay 2 mode, Shairport Sync reverts to "classic" AirPlay when iTunes on macOS or macOS Music plays to multiple speakers and one of more of them is compatible with AirPlay only. -- Devices running Shairport Sync in AirPlay 2 mode can be [added](ADDINGTOHOME.md) to the Home app. +- Devices running Shairport Sync in AirPlay 2 mode can be [added](https://github.com/mikebrady/shairport-sync/blob/development/ADDINGTOHOME.md) to the Home app. ## What Does Not Work - No AirPlay 2 for Windows iTunes. @@ -31,7 +31,7 @@ Here are some guidelines: * An up-to-date Linux or FreeBSD. This is important, as some of the libraries must be the latest available. * Shairport Sync will not run on a Mac because NQPTP, on which it relies, needs ports 319 and 320, which are already used by macOS. * A version of the [FFmpeg](https://www.ffmpeg.org) library with an AAC decoder capable of decoding Floating Planar -- `fltp` -- material. There is a guide [here](TROUBLESHOOTING.md#aac-decoder-issues-airplay-2-only) to help you find out if your system has it. -* An audio output, for example an ALSA device (or `sndio` in FreeBSD). The device must be capable of running at 44,100 frames per second. You can use an [`sps-alsa-explore`](https://github.com/mikebrady/sps-alsa-explore) to test the suitability of hardware ALSA audio devices on your device. +* An audio output, for example an ALSA device (or `sndio` in FreeBSD). The device must be capable of running at 44,100 frames per second. You can use an `sps-alsa-explore`](https://github.com/mikebrady/sps-alsa-explore) to test the suitability of hardware ALSA audio devices on your device. Other backends continue to work as with "classic" Shairport Sync. ## Guides From 94701c5d3b0e71d79ae8510d2ea2fa96b309dcba Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 12:39:37 +0100 Subject: [PATCH 39/72] Fix Bug Report template. --- .github/ISSUE_TEMPLATE/Bug Report.yaml | 31 +++++++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/Bug Report.yaml b/.github/ISSUE_TEMPLATE/Bug Report.yaml index 11e2f3a1..8017b5db 100644 --- a/.github/ISSUE_TEMPLATE/Bug Report.yaml +++ b/.github/ISSUE_TEMPLATE/Bug Report.yaml @@ -1,12 +1,12 @@ -name: Bug Report -description: File a bug report -title: "[Bug]: " -labels: ["bug"] +name: Issue Report +description: File an Issue +title: "[Problem]: " +labels: ["new issue"] body: - type: markdown attributes: value: | - Thanks for taking the time to fill out this bug report! + Thanks for taking the time to fill out this report! - type: textarea id: what-happened attributes: @@ -20,6 +20,13 @@ body: label: Relevant log output description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. render: shell + - type: textarea + id: os + attributes: + label: Operating System? + description: What Operating System are you running on ? (`uname -a`) + validations: + required: true - type: textarea id: version attributes: @@ -27,6 +34,17 @@ body: description: What version of Shairport Sync are you running? (`shairport-sync -V`) validations: required: true + - type: dropdown + id: install + attributes: + label: How did you install Shairport Sync? + options: + - Homebrew for Mac + - Docker + - A package manager (apt, yum, pkg, etc.) + - Built from source + validations: + required: true - type: checkboxes id: checked-current-issues attributes: @@ -34,4 +52,5 @@ body: description: Please check previous issues (including closed ones) for duplicates. options: - label: Confirm - required: true \ No newline at end of file + required: true + From 44c5f18b0e640138328ca4574ebafb7f4416242e Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 12:46:05 +0100 Subject: [PATCH 40/72] Add docker-build-on-formal-release.yaml and stale.yaml to the branch. --- .../docker-build-on-formal-release.yaml | 83 +++++++++++++++++++ .github/workflows/stale.yaml | 21 +++++ 2 files changed, 104 insertions(+) create mode 100644 .github/workflows/docker-build-on-formal-release.yaml create mode 100644 .github/workflows/stale.yaml diff --git a/.github/workflows/docker-build-on-formal-release.yaml b/.github/workflows/docker-build-on-formal-release.yaml new file mode 100644 index 00000000..fc698373 --- /dev/null +++ b/.github/workflows/docker-build-on-formal-release.yaml @@ -0,0 +1,83 @@ +# Builds & pushes a docker image when a "formal" release tag of the format X, X.Y or X.Y.Z occurs, where X, Y and Z are all numbers. +# It seems this yaml has to exist on the branch the tag refers to. + +# Thanks to Charles Omer for the workfow upon which this is based. + +# The following docker tags are created & pushed: +# trial, trial-classic +# not building 'latest' yet... + +name: Formal (X, X.Y or X.Y.Z) release tags -- docker build and push. + +on: + push: + tags: + - '[0-9]+\.[0-9]+\.[0-9]+' # e.g. 8.9.0 + - '[0-9]+\.[0-9]+' # e.g. 8.9 + - '[0-9]+' # e.g. 8 + - '[0-9]+\.[0-9]+rc[0-9]+' # e.g. 4.1rc0 + +env: + DOCKER_PLATFORMS: linux/386,linux/amd64,linux/arm/v6,linux/arm64,linux/arm/v7 + +jobs: + main: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Set SHAIRPORT_SYNC_BRANCH env. + run: | + raw=$(git branch -r --contains ${{ github.ref }}) + branch=${raw##*/} + echo "SHAIRPORT_SYNC_BRANCH=${branch}" >> $GITHUB_ENV + + - name: Set tag env + run: echo "GIT_TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + + - name: Determine NQPTP env (part 1). + if: ${{ env.SHAIRPORT_SYNC_BRANCH == 'development' }} + run: echo "NQPTP_BRANCH=development" >> $GITHUB_ENV + + - name: Determine NQPTP env (part 2). + if: ${{ env.SHAIRPORT_SYNC_BRANCH != 'development' }} + run: echo "NQPTP_BRANCH=main" >> $GITHUB_ENV + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to Docker Registry + uses: docker/login-action@v1 + with: + registry: ${{ secrets.DOCKER_REGISTRY }} + username: ${{ secrets.DOCKER_REGISTRY_USER }} + password: ${{ secrets.DOCKER_REGISTRY_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v2 + with: + context: ./ + file: ./docker/Dockerfile + platforms: ${{ env.DOCKER_PLATFORMS }} + push: true + tags: trial + build-args: | + SHAIRPORT_SYNC_BRANCH=${{ env.SHAIRPORT_SYNC_BRANCH }} + NQPTP_BRANCH=${{ env.NQPTP_BRANCH }} + + - name: Build and push (Classic) + uses: docker/build-push-action@v2 + with: + context: ./ + file: ./docker/classic/Dockerfile + platforms: ${{ env.DOCKER_PLATFORMS }} + push: true + tags: trial-classic + build-args: | + SHAIRPORT_SYNC_BRANCH=${{ env.SHAIRPORT_SYNC_BRANCH }} diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml new file mode 100644 index 00000000..51658c01 --- /dev/null +++ b/.github/workflows/stale.yaml @@ -0,0 +1,21 @@ +name: 'Close stale issues and PRs' +on: + schedule: + - cron: '0 0 * * *' + +permissions: + issues: write + pull-requests: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v4 + with: + stale-issue-message: 'This issue has been inactive for 45 days so will be closed 7 days from now. To prevent this, please remove the "stale" label or post a comment.' + stale-pr-message: 'This PR has been inactive for 45 days so will be closed 7 days from now. To prevent this, please remove the "stale" label or post a comment.' + operations-per-run: 100 + # These are the defaults at the time of writing. https://github.com/marketplace/actions/close-stale-issues + # days-before-stale: 45 + # days-before-close: 7 From 07426e17c8b720cb58de19ba3056c9e5c71f2031 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 12:48:37 +0100 Subject: [PATCH 41/72] Take update to CAR INSTALL. --- CAR INSTALL.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/CAR INSTALL.md b/CAR INSTALL.md index 8cc47b04..c2259a5f 100644 --- a/CAR INSTALL.md +++ b/CAR INSTALL.md @@ -215,3 +215,43 @@ Install the Raspberry Pi in your car. It should be powered from a source that is When the power source is switched on, typically when you start the car, it will take maybe a minute for the system to boot up. ### Enjoy! + +--- + +## Updating +From time to time, you may wish to update this installation. However, in order to update Shairport Sync, you must reconnect the system to a network that can access the internet. The easiest thing is to temporarily reconnect to the network you used when you created the system. To do that, you have to temporarily undo the "Final Steps" and some of the "Raspberry Pi Specific" steps you used. This will enable you to connect your device back to the network it was created on. You should then be able to update the operating system and libraries in the normal way and then update Shairport Sync. + +So, take the following steps: + +1. If it's a Raspberry Pi and you have enabled the Read-only mode, you must take the device out of Read-only mode: +Run `sudo raspi-config` and then choose `Performance Options` > `Overlay Filesystem` and choose to disable the overlay filesystem and to set the boot partition not to be write-protected. This is so that changes can be written to the file system; you can make the filesystem read-only again later. Save the changes and reboot the system. + +2. If you have disabled the `dhcpcd`, `wpa_supplicant` or `systemd-timesyncd` services as suggested in the "Optimise startup time -- Raspberry Pi Specific" section, you need to temporarily re-enable them: +`# systemctl enable dhcpcd.service` +`# systemctl enable wpa_supplicant.service` +`# systemctl enable systemd-timesyncd.service` +Reboot. + +3. To allow your device to reconnect to the network it was created on, edit `/etc/dhcpcd.conf` and comment out the following line at the start: +`denyinterfaces wlan0` +so that it looks like this: +`# denyinterfaces wlan0` +From this point on, if you reboot the machine, it will connect to the network it was configured on, i.e. the network you used when you set it up for the first time. This is because the name and password of the network it was created on would have been placed in `/etc/wpa_supplicant/wpa_supplicant` when the system was initially configured and will still be there. + +4. Reboot and do Normal Updating + + You can perform updates in the normal way -- see [UPDATING](https://github.com/mikebrady/shairport-sync/blob/master/UPDATING.md). When you are finished, you need to undo the temporary changes you made to the setup, as follows: + +5. If you had temporarily re-enabled services that are normally disabled, then it's time to disable them again: +`# systemctl disable dhcpcd.service` +`# systemctl disable wpa_supplicant.service` +`# systemctl disable systemd-timesyncd.service` + +6. To re-enable the system to create its own network, edit `/etc/dhcpcd.conf` and uncomment the line that you had temporarily commented out at the start of the update. Change: +`# denyinterfaces wlan0` +so that it looks like this: +`denyinterfaces wlan0` + +7. Reboot. The system should start as it would if it was in the car. + +8. If the device is a Raspberry Pi and you wish to make the file system read-only, connect to the system, run `sudo raspi-config` and then choose `Performance Options` > `Overlay Filesystem`. In there, choose to enable the overlay filesystem, and to set the boot partition to be write-protected. Do a final reboot and check that everyting is in order. From 01b4fbddd11aae206788c96ca543a435a2c5cfff Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 12:53:32 +0100 Subject: [PATCH 42/72] Take more uptodate version of documents --- RELEASENOTES.md | 27 ++++++++++++++++++++++++++- TROUBLESHOOTING.md | 9 +++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index bfb2c8fa..9fdc0628 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,4 +1,29 @@ -Please see the [Release Notes for 3.3](https://github.com/mikebrady/shairport-sync/releases/tag/3.3). +Version 4.1-rc0 Release Candidate +==== + +Really Big Update -- AirPlay 2! +---- +Version 4.1 brings support for AirPlay 2 operation. It works with iOS, iPadOS, macOS, HomePod mini and Apple TV sources, but not with Windows. +Limited support is available for HomeKit -- Shairport Sync speakers can be added to the Home app, though not all features are working. +AirPlay 2 operation requires a companion program called NQPTP and requires a somewhat more powerful system. Please see [AIRPLAY2.md](./AIRPLAY.md) for more. + +Note that you can still build Shairport Sync to support "classic" AirPlay (aka "AirPlay 1") as before. + +The various guides for building and updating Shairport Sync have been consolidated into [BUILD.md](./BUILD.md). + +Here is a brief list of the high-level new features and changes (more to be added): +* AirPlay 2 operation. +* Improved `libao` backend for better compatibility with HomeBrew installations. +* Improved MQTT and D-Bus facilities. +* Automatically-generated Docker images (forthcoming). + +There have been many many bug fixes and enhancements to the core operation of Shairport Sync. + +Version 3.3.9 +==== +**Bug Fix** +* Version 3.3.9 fixes a build failure with convolution raised since `automake 1.16.5` and https://git.savannah.gnu.org/cgit/automake.git/commit/?id=f4a3a70f69e1dbccb6578f39ef47835098a04624. +Further details in [Fabrice Fontaine's original PR](https://github.com/mikebrady/shairport-sync/pull/1314) to the `development` branch. Many thanks to [Fabrice Fontaine](https://github.com/ffontaine) for the bug report and for the fix. Version 3.3.8 ==== diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md index 73e9e7b9..d6436fdf 100644 --- a/TROUBLESHOOTING.md +++ b/TROUBLESHOOTING.md @@ -15,6 +15,15 @@ If you are using the default ALSA backend, don't forget to check two simple thin You can use `alsamixer` for both of theses checks. A muted output has the letter(s) `M` as its value. Select it and type `M` again to unmute. +### Audio is Delayed! +If the audio from your Shairport Sync device is delayed slightly by comparison with audio from other devices, it may be that the output device being fed by Shairport Sync is introducing a delay while it processes the audio. If your output device include any digital processing component, it probably delays the audio while it processing occurs. + +For instance, if your output device is a HDMI-connected device such as a TV or an AV Receiver, it will almost certainly delay audio by anything up to several hundred milliseconds. + +The fix for this is to ask Shairport Sync to provide the audio to the output device _slightly ahead of time_, so that by the time the output device has processed it, the audio emerges at exactly the right time. The setting to look for is in the `general` section of the Shairport Sync configuration file and is called `audio_backend_latency_offset_in_seconds`. By default it is `0.0` seconds. + +For example, if your output device is delaying audio by 100 milliseconds (0.1 seconds), set the `audio_backend_latency_offset_in_seconds` to `-0.1`, so that audio is provided to your output device 0.1 seconds early. Remember to uncomment the line by removing the initial `//` and then restart Shairport Sync (or reboot the device) for the changed setting to take effect. + ### WiFi adapter running in power-saving / low-power mode **Check Throughput** From bdfb8c4f6c1c75b645ae93f89b296bc35d44ca7a Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 14:05:37 +0100 Subject: [PATCH 43/72] Bring up to date with changes in the development branch, most of which come from the master branch. --- .github/ISSUE_TEMPLATE/Bug Report.yaml | 31 +++++-- .../docker-build-on-formal-release.yaml | 83 +++++++++++++++++++ .github/workflows/stale.yaml | 21 +++++ CAR INSTALL.md | 40 +++++++++ RELEASENOTES.md | 27 +++++- 5 files changed, 195 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/docker-build-on-formal-release.yaml create mode 100644 .github/workflows/stale.yaml diff --git a/.github/ISSUE_TEMPLATE/Bug Report.yaml b/.github/ISSUE_TEMPLATE/Bug Report.yaml index 11e2f3a1..8017b5db 100644 --- a/.github/ISSUE_TEMPLATE/Bug Report.yaml +++ b/.github/ISSUE_TEMPLATE/Bug Report.yaml @@ -1,12 +1,12 @@ -name: Bug Report -description: File a bug report -title: "[Bug]: " -labels: ["bug"] +name: Issue Report +description: File an Issue +title: "[Problem]: " +labels: ["new issue"] body: - type: markdown attributes: value: | - Thanks for taking the time to fill out this bug report! + Thanks for taking the time to fill out this report! - type: textarea id: what-happened attributes: @@ -20,6 +20,13 @@ body: label: Relevant log output description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. render: shell + - type: textarea + id: os + attributes: + label: Operating System? + description: What Operating System are you running on ? (`uname -a`) + validations: + required: true - type: textarea id: version attributes: @@ -27,6 +34,17 @@ body: description: What version of Shairport Sync are you running? (`shairport-sync -V`) validations: required: true + - type: dropdown + id: install + attributes: + label: How did you install Shairport Sync? + options: + - Homebrew for Mac + - Docker + - A package manager (apt, yum, pkg, etc.) + - Built from source + validations: + required: true - type: checkboxes id: checked-current-issues attributes: @@ -34,4 +52,5 @@ body: description: Please check previous issues (including closed ones) for duplicates. options: - label: Confirm - required: true \ No newline at end of file + required: true + diff --git a/.github/workflows/docker-build-on-formal-release.yaml b/.github/workflows/docker-build-on-formal-release.yaml new file mode 100644 index 00000000..fc698373 --- /dev/null +++ b/.github/workflows/docker-build-on-formal-release.yaml @@ -0,0 +1,83 @@ +# Builds & pushes a docker image when a "formal" release tag of the format X, X.Y or X.Y.Z occurs, where X, Y and Z are all numbers. +# It seems this yaml has to exist on the branch the tag refers to. + +# Thanks to Charles Omer for the workfow upon which this is based. + +# The following docker tags are created & pushed: +# trial, trial-classic +# not building 'latest' yet... + +name: Formal (X, X.Y or X.Y.Z) release tags -- docker build and push. + +on: + push: + tags: + - '[0-9]+\.[0-9]+\.[0-9]+' # e.g. 8.9.0 + - '[0-9]+\.[0-9]+' # e.g. 8.9 + - '[0-9]+' # e.g. 8 + - '[0-9]+\.[0-9]+rc[0-9]+' # e.g. 4.1rc0 + +env: + DOCKER_PLATFORMS: linux/386,linux/amd64,linux/arm/v6,linux/arm64,linux/arm/v7 + +jobs: + main: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Set SHAIRPORT_SYNC_BRANCH env. + run: | + raw=$(git branch -r --contains ${{ github.ref }}) + branch=${raw##*/} + echo "SHAIRPORT_SYNC_BRANCH=${branch}" >> $GITHUB_ENV + + - name: Set tag env + run: echo "GIT_TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + + - name: Determine NQPTP env (part 1). + if: ${{ env.SHAIRPORT_SYNC_BRANCH == 'development' }} + run: echo "NQPTP_BRANCH=development" >> $GITHUB_ENV + + - name: Determine NQPTP env (part 2). + if: ${{ env.SHAIRPORT_SYNC_BRANCH != 'development' }} + run: echo "NQPTP_BRANCH=main" >> $GITHUB_ENV + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to Docker Registry + uses: docker/login-action@v1 + with: + registry: ${{ secrets.DOCKER_REGISTRY }} + username: ${{ secrets.DOCKER_REGISTRY_USER }} + password: ${{ secrets.DOCKER_REGISTRY_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v2 + with: + context: ./ + file: ./docker/Dockerfile + platforms: ${{ env.DOCKER_PLATFORMS }} + push: true + tags: trial + build-args: | + SHAIRPORT_SYNC_BRANCH=${{ env.SHAIRPORT_SYNC_BRANCH }} + NQPTP_BRANCH=${{ env.NQPTP_BRANCH }} + + - name: Build and push (Classic) + uses: docker/build-push-action@v2 + with: + context: ./ + file: ./docker/classic/Dockerfile + platforms: ${{ env.DOCKER_PLATFORMS }} + push: true + tags: trial-classic + build-args: | + SHAIRPORT_SYNC_BRANCH=${{ env.SHAIRPORT_SYNC_BRANCH }} diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml new file mode 100644 index 00000000..51658c01 --- /dev/null +++ b/.github/workflows/stale.yaml @@ -0,0 +1,21 @@ +name: 'Close stale issues and PRs' +on: + schedule: + - cron: '0 0 * * *' + +permissions: + issues: write + pull-requests: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v4 + with: + stale-issue-message: 'This issue has been inactive for 45 days so will be closed 7 days from now. To prevent this, please remove the "stale" label or post a comment.' + stale-pr-message: 'This PR has been inactive for 45 days so will be closed 7 days from now. To prevent this, please remove the "stale" label or post a comment.' + operations-per-run: 100 + # These are the defaults at the time of writing. https://github.com/marketplace/actions/close-stale-issues + # days-before-stale: 45 + # days-before-close: 7 diff --git a/CAR INSTALL.md b/CAR INSTALL.md index 8cc47b04..c2259a5f 100644 --- a/CAR INSTALL.md +++ b/CAR INSTALL.md @@ -215,3 +215,43 @@ Install the Raspberry Pi in your car. It should be powered from a source that is When the power source is switched on, typically when you start the car, it will take maybe a minute for the system to boot up. ### Enjoy! + +--- + +## Updating +From time to time, you may wish to update this installation. However, in order to update Shairport Sync, you must reconnect the system to a network that can access the internet. The easiest thing is to temporarily reconnect to the network you used when you created the system. To do that, you have to temporarily undo the "Final Steps" and some of the "Raspberry Pi Specific" steps you used. This will enable you to connect your device back to the network it was created on. You should then be able to update the operating system and libraries in the normal way and then update Shairport Sync. + +So, take the following steps: + +1. If it's a Raspberry Pi and you have enabled the Read-only mode, you must take the device out of Read-only mode: +Run `sudo raspi-config` and then choose `Performance Options` > `Overlay Filesystem` and choose to disable the overlay filesystem and to set the boot partition not to be write-protected. This is so that changes can be written to the file system; you can make the filesystem read-only again later. Save the changes and reboot the system. + +2. If you have disabled the `dhcpcd`, `wpa_supplicant` or `systemd-timesyncd` services as suggested in the "Optimise startup time -- Raspberry Pi Specific" section, you need to temporarily re-enable them: +`# systemctl enable dhcpcd.service` +`# systemctl enable wpa_supplicant.service` +`# systemctl enable systemd-timesyncd.service` +Reboot. + +3. To allow your device to reconnect to the network it was created on, edit `/etc/dhcpcd.conf` and comment out the following line at the start: +`denyinterfaces wlan0` +so that it looks like this: +`# denyinterfaces wlan0` +From this point on, if you reboot the machine, it will connect to the network it was configured on, i.e. the network you used when you set it up for the first time. This is because the name and password of the network it was created on would have been placed in `/etc/wpa_supplicant/wpa_supplicant` when the system was initially configured and will still be there. + +4. Reboot and do Normal Updating + + You can perform updates in the normal way -- see [UPDATING](https://github.com/mikebrady/shairport-sync/blob/master/UPDATING.md). When you are finished, you need to undo the temporary changes you made to the setup, as follows: + +5. If you had temporarily re-enabled services that are normally disabled, then it's time to disable them again: +`# systemctl disable dhcpcd.service` +`# systemctl disable wpa_supplicant.service` +`# systemctl disable systemd-timesyncd.service` + +6. To re-enable the system to create its own network, edit `/etc/dhcpcd.conf` and uncomment the line that you had temporarily commented out at the start of the update. Change: +`# denyinterfaces wlan0` +so that it looks like this: +`denyinterfaces wlan0` + +7. Reboot. The system should start as it would if it was in the car. + +8. If the device is a Raspberry Pi and you wish to make the file system read-only, connect to the system, run `sudo raspi-config` and then choose `Performance Options` > `Overlay Filesystem`. In there, choose to enable the overlay filesystem, and to set the boot partition to be write-protected. Do a final reboot and check that everyting is in order. diff --git a/RELEASENOTES.md b/RELEASENOTES.md index bfb2c8fa..9fdc0628 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,4 +1,29 @@ -Please see the [Release Notes for 3.3](https://github.com/mikebrady/shairport-sync/releases/tag/3.3). +Version 4.1-rc0 Release Candidate +==== + +Really Big Update -- AirPlay 2! +---- +Version 4.1 brings support for AirPlay 2 operation. It works with iOS, iPadOS, macOS, HomePod mini and Apple TV sources, but not with Windows. +Limited support is available for HomeKit -- Shairport Sync speakers can be added to the Home app, though not all features are working. +AirPlay 2 operation requires a companion program called NQPTP and requires a somewhat more powerful system. Please see [AIRPLAY2.md](./AIRPLAY.md) for more. + +Note that you can still build Shairport Sync to support "classic" AirPlay (aka "AirPlay 1") as before. + +The various guides for building and updating Shairport Sync have been consolidated into [BUILD.md](./BUILD.md). + +Here is a brief list of the high-level new features and changes (more to be added): +* AirPlay 2 operation. +* Improved `libao` backend for better compatibility with HomeBrew installations. +* Improved MQTT and D-Bus facilities. +* Automatically-generated Docker images (forthcoming). + +There have been many many bug fixes and enhancements to the core operation of Shairport Sync. + +Version 3.3.9 +==== +**Bug Fix** +* Version 3.3.9 fixes a build failure with convolution raised since `automake 1.16.5` and https://git.savannah.gnu.org/cgit/automake.git/commit/?id=f4a3a70f69e1dbccb6578f39ef47835098a04624. +Further details in [Fabrice Fontaine's original PR](https://github.com/mikebrady/shairport-sync/pull/1314) to the `development` branch. Many thanks to [Fabrice Fontaine](https://github.com/ffontaine) for the bug report and for the fix. Version 3.3.8 ==== From e036d64d780224ee5e6519fdfe3cb702e99ec16a Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 14:11:59 +0100 Subject: [PATCH 44/72] Bring up to date with changes in the development branch, most of which come from the master branch. --- TROUBLESHOOTING.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md index 73e9e7b9..d6436fdf 100644 --- a/TROUBLESHOOTING.md +++ b/TROUBLESHOOTING.md @@ -15,6 +15,15 @@ If you are using the default ALSA backend, don't forget to check two simple thin You can use `alsamixer` for both of theses checks. A muted output has the letter(s) `M` as its value. Select it and type `M` again to unmute. +### Audio is Delayed! +If the audio from your Shairport Sync device is delayed slightly by comparison with audio from other devices, it may be that the output device being fed by Shairport Sync is introducing a delay while it processes the audio. If your output device include any digital processing component, it probably delays the audio while it processing occurs. + +For instance, if your output device is a HDMI-connected device such as a TV or an AV Receiver, it will almost certainly delay audio by anything up to several hundred milliseconds. + +The fix for this is to ask Shairport Sync to provide the audio to the output device _slightly ahead of time_, so that by the time the output device has processed it, the audio emerges at exactly the right time. The setting to look for is in the `general` section of the Shairport Sync configuration file and is called `audio_backend_latency_offset_in_seconds`. By default it is `0.0` seconds. + +For example, if your output device is delaying audio by 100 milliseconds (0.1 seconds), set the `audio_backend_latency_offset_in_seconds` to `-0.1`, so that audio is provided to your output device 0.1 seconds early. Remember to uncomment the line by removing the initial `//` and then restart Shairport Sync (or reboot the device) for the changed setting to take effect. + ### WiFi adapter running in power-saving / low-power mode **Check Throughput** From c269e815e6bbf1ccb7aed0808ea464ff3c2c0064 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Thu, 29 Sep 2022 16:39:01 +0100 Subject: [PATCH 45/72] Add name of client when we can get it in AP2 --- rtsp.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/rtsp.c b/rtsp.c index d61ffeb1..b03d6f4e 100644 --- a/rtsp.c +++ b/rtsp.c @@ -1622,7 +1622,7 @@ void handle_record(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp) if (conn->player_thread) warn("Connection %d: RECORD: Duplicate RECORD message -- ignored", conn->connection_number); else { - debug(1, "Connection %d: AP1 ALAC Stream, from %s:%u to self at %s:%u.", + debug(1, "Connection %d: Classic AirPlay connection from %s:%u to self at %s:%u.", conn->connection_number, conn->client_ip_string, conn->client_rtsp_port, conn->self_ip_string, conn->self_rtsp_port); activity_monitor_signify_activity(1); @@ -2830,6 +2830,15 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp) plist_t messagePlist = plist_from_rtsp_content(req); plist_t setupResponsePlist = plist_new_dict(); resp->respcode = 400; + + // see if we can get a name for the client + char *clientNameString = NULL; + plist_t nameItem = plist_dict_get_item(messagePlist, "name"); + if (nameItem != NULL) { + plist_get_string_val(nameItem, &clientNameString); + } else { + clientNameString = strdup(""); + } // see if the incoming plist contains a "streams" array plist_t streams = plist_dict_get_item(messagePlist, "streams"); @@ -2847,8 +2856,8 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp) plist_get_string_val(timingProtocol, &timingProtocolString); if (timingProtocolString) { if (strcmp(timingProtocolString, "PTP") == 0) { - debug(2, "Connection %d: AP2 PTP connection from %s:%u to self at %s:%u.", - conn->connection_number, conn->client_ip_string, conn->client_rtsp_port, + debug(1, "Connection %d: AP2 PTP connection from %s:%u (\"%s\") to self at %s:%u.", + conn->connection_number, conn->client_ip_string, conn->client_rtsp_port, clientNameString, conn->self_ip_string, conn->self_rtsp_port); conn->airplay_stream_category = ptp_stream; conn->timing_type = ts_ptp; @@ -2862,20 +2871,24 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp) send_ssnc_metadata('svip', conn->self_ip_string, strlen(conn->self_ip_string), 1); #endif } else if (strcmp(timingProtocolString, "NTP") == 0) { - debug(1, "Connection %d: SETUP: NTP setup detected.", conn->connection_number); + debug(1, "Connection %d: SETUP: NTP setup from %s:%u (\"%s\") to self at %s:%u.", + conn->connection_number, conn->client_ip_string, conn->client_rtsp_port, clientNameString, + conn->self_ip_string, conn->self_rtsp_port); conn->airplay_stream_category = ntp_stream; conn->timing_type = ts_ntp; } else if (strcmp(timingProtocolString, "None") == 0) { - debug(2, "Connection %d: SETUP: a \"None\" setup detected.", conn->connection_number); + debug(3, "Connection %d: SETUP: a \"None\" setup detected from %s:%u (\"%s\") to self at %s:%u.", + conn->connection_number, conn->client_ip_string, conn->client_rtsp_port, clientNameString, + conn->self_ip_string, conn->self_rtsp_port); // now check to see if it's got the "isRemoteControlOnly" item and check it's true plist_t isRemoteControlOnly = plist_dict_get_item(messagePlist, "isRemoteControlOnly"); if (isRemoteControlOnly != NULL) { uint8_t isRemoteControlOnlyBoolean = 0; plist_get_bool_val(isRemoteControlOnly, &isRemoteControlOnlyBoolean); if (isRemoteControlOnlyBoolean != 0) { - debug(2, "Connection %d: Remote Control connection from %s:%u to self at %s:%u.", - conn->connection_number, conn->client_ip_string, conn->client_rtsp_port, - conn->self_ip_string, conn->self_rtsp_port); + debug(1, "Connection %d: Remote Control connection from %s:%u (\"%s\") to self at %s:%u.", + conn->connection_number, conn->client_ip_string, conn->client_rtsp_port, clientNameString, + conn->self_ip_string, conn->self_rtsp_port); conn->airplay_stream_category = remote_control_stream; } else { debug(1, @@ -3354,6 +3367,8 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp) msg_add_header(resp, "Content-Type", "application/x-apple-binary-plist"); } plist_free(messagePlist); + if (clientNameString != NULL) + free(clientNameString); debug_log_rtsp_message(2, " SETUP response", resp); } #endif @@ -4407,7 +4422,9 @@ static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_messag #ifdef CONFIG_AIRPLAY_2 conn->airplay_type = ap_1; conn->timing_type = ts_ntp; - debug(1, "Connection %d. AirPlay 1 Audio Stream Detected.", conn->connection_number); + debug(1, "Connection %d: Classic AirPlay connection from %s:%u to self at %s:%u.", + conn->connection_number, conn->client_ip_string, conn->client_rtsp_port, + conn->self_ip_string, conn->self_rtsp_port); #endif conn->stream.type = ast_unknown; @@ -5460,7 +5477,7 @@ void *rtsp_listen_loop(__attribute((unused)) void *arg) { inet_ntop(conn->connection_ip_family, self_addr, conn->self_ip_string, sizeof(conn->self_ip_string)); - debug(1, "Connection %d: New connection from %s:%u to self at %s:%u.", + debug(2, "Connection %d: New connection from %s:%u to self at %s:%u.", conn->connection_number, conn->client_ip_string, conn->client_rtsp_port, conn->self_ip_string, conn->self_rtsp_port); conn->connection_start_time = get_absolute_time_in_ns(); From 84c9b8b35a28fd35fd6be08a0064bcef4a960bf4 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Fri, 30 Sep 2022 10:05:40 +0100 Subject: [PATCH 46/72] Close the DAC when the keep_dac_busy flag is changed (by the activity monitor) from true to false. Wait a little longer for the DAC to drop all frames. --- audio_alsa.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/audio_alsa.c b/audio_alsa.c index fc53ee65..19b35084 100644 --- a/audio_alsa.c +++ b/audio_alsa.c @@ -1850,7 +1850,8 @@ static int do_close() { // debug(1,"alsa: do_close() -- closing the output device"); if ((derr = snd_pcm_drop(alsa_handle))) debug(1, "Error %d (\"%s\") dropping output device.", derr, snd_strerror(derr)); - usleep(5000); // this make the function pthread cancellable + usleep(10000); // wait for the hardware to do its trick. BTW, this make the function pthread + // cancellable if ((derr = snd_pcm_hw_free(alsa_handle))) debug(1, "Error %d (\"%s\") freeing the output device hardware.", derr, snd_strerror(derr)); debug(2, "alsa: do_close() -- closing alsa handle"); @@ -2061,9 +2062,12 @@ static void *alsa_buffer_monitor_thread_code(__attribute__((unused)) void *arg) int error_count = 0; int error_detected = 0; int okb = -1; - while (error_detected == - 0) { // if too many play errors occur early on, we will turn off the disable stanby mode + // if too many play errors occur early on, we will turn off the disable standby mode + while (error_detected == 0) { + int keep_dac_busy_has_just_gone_off = 0; if (okb != config.keep_dac_busy) { + if ((okb != 0) && (config.keep_dac_busy == 0)) + keep_dac_busy_has_just_gone_off = 1; debug(2, "keep_dac_busy is now \"%s\"", config.keep_dac_busy == 0 ? "no" : "yes"); okb = config.keep_dac_busy; } @@ -2081,14 +2085,14 @@ static void *alsa_buffer_monitor_thread_code(__attribute__((unused)) void *arg) if (do_open(1) == 0) // no automatic setup of rate and speed if necessary debug(2, "alsa: alsa_buffer_monitor_thread_code() -- output device opened; " "alsa_backend_state => abm_connected"); - } else if ((alsa_backend_state == abm_connected) && (config.keep_dac_busy == 0)) { + } else if ((alsa_backend_state != abm_disconnected) && (keep_dac_busy_has_just_gone_off != 0)) { stall_monitor_start_time = 0; // frame_index = 0; // measurement_data_is_valid = 0; - debug(2, "alsa: alsa_buffer_monitor_thread_code() -- closing the output " + debug(1, "alsa: alsa_buffer_monitor_thread_code() -- closing the output " "device"); do_close(); - debug(2, "alsa: alsa_buffer_monitor_thread_code() -- alsa_backend_state " + debug(1, "alsa: alsa_buffer_monitor_thread_code() -- alsa_backend_state " "=> abm_disconnected"); } // now, if the backend is not in the abm_disconnected state From 29b01b54939f25bda39188cda55b157a4908d928 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Fri, 30 Sep 2022 10:08:11 +0100 Subject: [PATCH 47/72] Quieten some debug messages, duh. --- audio_alsa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/audio_alsa.c b/audio_alsa.c index 19b35084..62db843f 100644 --- a/audio_alsa.c +++ b/audio_alsa.c @@ -2089,10 +2089,10 @@ static void *alsa_buffer_monitor_thread_code(__attribute__((unused)) void *arg) stall_monitor_start_time = 0; // frame_index = 0; // measurement_data_is_valid = 0; - debug(1, "alsa: alsa_buffer_monitor_thread_code() -- closing the output " + debug(2, "alsa: alsa_buffer_monitor_thread_code() -- closing the output " "device"); do_close(); - debug(1, "alsa: alsa_buffer_monitor_thread_code() -- alsa_backend_state " + debug(2, "alsa: alsa_buffer_monitor_thread_code() -- alsa_backend_state " "=> abm_disconnected"); } // now, if the backend is not in the abm_disconnected state From 2bc62c7dd90abba1f164f615f4bad2772487a951 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Fri, 30 Sep 2022 10:18:51 +0100 Subject: [PATCH 48/72] Close the DAC when the keep_dac_busy flag is changed (by the activity monitor) from true to false. Wait a little longer for the DAC to drop all frames. --- audio_alsa.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/audio_alsa.c b/audio_alsa.c index fc53ee65..62db843f 100644 --- a/audio_alsa.c +++ b/audio_alsa.c @@ -1850,7 +1850,8 @@ static int do_close() { // debug(1,"alsa: do_close() -- closing the output device"); if ((derr = snd_pcm_drop(alsa_handle))) debug(1, "Error %d (\"%s\") dropping output device.", derr, snd_strerror(derr)); - usleep(5000); // this make the function pthread cancellable + usleep(10000); // wait for the hardware to do its trick. BTW, this make the function pthread + // cancellable if ((derr = snd_pcm_hw_free(alsa_handle))) debug(1, "Error %d (\"%s\") freeing the output device hardware.", derr, snd_strerror(derr)); debug(2, "alsa: do_close() -- closing alsa handle"); @@ -2061,9 +2062,12 @@ static void *alsa_buffer_monitor_thread_code(__attribute__((unused)) void *arg) int error_count = 0; int error_detected = 0; int okb = -1; - while (error_detected == - 0) { // if too many play errors occur early on, we will turn off the disable stanby mode + // if too many play errors occur early on, we will turn off the disable standby mode + while (error_detected == 0) { + int keep_dac_busy_has_just_gone_off = 0; if (okb != config.keep_dac_busy) { + if ((okb != 0) && (config.keep_dac_busy == 0)) + keep_dac_busy_has_just_gone_off = 1; debug(2, "keep_dac_busy is now \"%s\"", config.keep_dac_busy == 0 ? "no" : "yes"); okb = config.keep_dac_busy; } @@ -2081,7 +2085,7 @@ static void *alsa_buffer_monitor_thread_code(__attribute__((unused)) void *arg) if (do_open(1) == 0) // no automatic setup of rate and speed if necessary debug(2, "alsa: alsa_buffer_monitor_thread_code() -- output device opened; " "alsa_backend_state => abm_connected"); - } else if ((alsa_backend_state == abm_connected) && (config.keep_dac_busy == 0)) { + } else if ((alsa_backend_state != abm_disconnected) && (keep_dac_busy_has_just_gone_off != 0)) { stall_monitor_start_time = 0; // frame_index = 0; // measurement_data_is_valid = 0; From 97fa75e87c60a53c588b559a4cc146dc6713e820 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Fri, 30 Sep 2022 10:37:48 +0100 Subject: [PATCH 49/72] Update RELEASENOTES-DEVELOPMENT.md --- RELEASENOTES-DEVELOPMENT.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/RELEASENOTES-DEVELOPMENT.md b/RELEASENOTES-DEVELOPMENT.md index c90367b9..e2a63f6e 100644 --- a/RELEASENOTES-DEVELOPMENT.md +++ b/RELEASENOTES-DEVELOPMENT.md @@ -1,3 +1,13 @@ +Version 4.1-dev-599-g2bc62c7d +==== + +**Enhancements** +* Added some GitHub Actions to test different combinations of builds -- hopefully the result will be fewer bugs. Thanks to [Charles Omer](https://github.com/charlesomer) for the inspiration to try these in the first place. + +**Bug Fixes** +* Fixed a bug where the DAC was not closed after the active timeout when the `alsa` `disable_standby_mode` was set to `"auto"`. Thanks to [Tim Curtis](https://github.com/moodeaudio) for an exemplary [bug report](https://github.com/mikebrady/shairport-sync/issues/1546). +* Fixed a couple of bugs (found with GitHub Actions) in the installers on both `systemd` and System V systems. + Version 4.1-dev-551-g30aaabc4 ==== **Update** @@ -8,7 +18,7 @@ Version 4.1-dev-551-g30aaabc4 Version 4.1-dev-548-g7dc077e2 ==== -* Removed the workaround for the apparent bug in AirPlay 2 Buffered Streams in iOS 16.0. A number of approaches were tried. The most aurally successful is left in the code but is disabled. Basically, it delays the timing of the frames following the 2,122 frame discontinuity by 2,112 frames. This eliminates the timing discontinuity but delays the AirPlay stream by 47.9 ms, and this can be heard in some situations. So it looks as if the bug -- if that's what it is -- can't easily be worked around. It has not been fixed by iOS 16.0.2, unfortunately. +* Removed the workaround for the apparent bug in AirPlay 2 Buffered Streams in iOS 16.0. A number of approaches were tried. The most aurally successful is left in the code but is disabled. Basically, it delays the timing of the frames following the 2,112 frame discontinuity by 2,112 frames. This eliminates the timing discontinuity but delays the AirPlay stream by 47.9 ms, and this can be heard in some situations. So it looks as if the bug -- if that's what it is -- can't easily be worked around. It has not been fixed by iOS 16.0.2, unfortunately. Version 4.1-dev-543-g24f06b81 ==== From 98744211a710af654c7a2e056a71901342027546 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Sat, 1 Oct 2022 15:32:53 +0100 Subject: [PATCH 50/72] Disable the timer on the RTSP link. OwnTone doesn't supply regular traffic here. --- rtsp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rtsp.c b/rtsp.c index d61ffeb1..aa48d976 100644 --- a/rtsp.c +++ b/rtsp.c @@ -1275,7 +1275,9 @@ void clear_ptp_clock() { ssize_t read_from_rtsp_connection(rtsp_conn_info *conn, void *buf, size_t count) { // first try to read with a timeout, to see if there is any traffic... - ssize_t response = timed_read_from_rtsp_connection(conn, 10000000000L, buf, count); + // ssize_t response = timed_read_from_rtsp_connection(conn, 20000000000L, buf, count); + // actually don't use a timeout -- OwnTone doesn't supply regular traffic. + ssize_t response = timed_read_from_rtsp_connection(conn, 0, buf, count); if ((response == -1) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) { if (conn->rtsp_link_is_idle == 0) { debug(1, "Connection %d: RTSP connection is idle.", conn->connection_number); From f70d9a0f0cecf1b5f3d65b139ec33b3b68d5a2ca Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Sat, 1 Oct 2022 15:38:15 +0100 Subject: [PATCH 51/72] Update RELEASENOTES-DEVELOPMENT.md --- RELEASENOTES-DEVELOPMENT.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RELEASENOTES-DEVELOPMENT.md b/RELEASENOTES-DEVELOPMENT.md index e2a63f6e..3bd8aaa0 100644 --- a/RELEASENOTES-DEVELOPMENT.md +++ b/RELEASENOTES-DEVELOPMENT.md @@ -1,3 +1,8 @@ +Version 4.1-dev-601-g98744211 +==== +**Bug Fix** +* Recent versions of Shairport Sync have a "heartbeat" checker, to try to determine when the client has stopped running without warning -- typically when it has gone to sleep. Unfortunately, it interferes with some non-Apple clients, so it has been disabled in this update. + Version 4.1-dev-599-g2bc62c7d ==== From b653027f7457ca57b723d29f26a1f8bf3730c82f Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Mon, 3 Oct 2022 17:56:02 +0100 Subject: [PATCH 52/72] Only call the volume hook once for each volume event even when the dbus interface is included. --- ADVANCED TOPICS/Events.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/ADVANCED TOPICS/Events.md b/ADVANCED TOPICS/Events.md index 0fd15ead..26a777de 100644 --- a/ADVANCED TOPICS/Events.md +++ b/ADVANCED TOPICS/Events.md @@ -1,8 +1,14 @@ ## Events -Shairport Sync can run programs just before it starts to play an audio stream and just after it finishes. -You specify them using the `sessioncontrol` group settings `run_this_before_play_begins` and `run_this_after_play_ends`. -This is to facilitate situations where something has to be done before and after playing, e.g. switching on an amplifier beforehand -and switching it off afterwards. +Shairport Sync can run programs when certain "events" occur. The events are: +1. When Shairport Sync become `active` or `inactive`. Shairport Sync is normally in the `inactive` state when no audio is being played. When audio is sent to Shairport Sync, it will transition from `inactive` to `active`. When the audio stops, Shairport Sync will start a timer. If audio restarts before the timer reaches the value of the `active_state_timeout` configuration setting (10 seconds by default), Shairport Sync will stay `active`. However, if no more audio is received before the timer reaches the `active_state_timeout` value, Shairport Sync will transition to `inactive`. The overall effect of this is that Shairport Sync will go `active` when a track is played and will stay active in the interval between tracks, so long as the interval is less than the `active_state_timeout`. + 1. Set the `run_this_before_entering_active_state` setting to the full path name to the program to run before Shairport Sync goes `active`. + 2. Set the `run_this_after_exiting_active_state` setting to the full path name to the program to run after Shairport Sync goes `inactive`. + 3. Set the `active_state_timeout` setting to the maximum amount of time to wait for play to resume before going `inactive`. +3. When audio starts and stops playing. + 1. Set the `run_this_before_play_begins` setting to the full path name to the program to run just before Shairport Sync starts playing. + 2. Set the `run_this_after_play_ends` setting to the full path name to the program to run after Shairport Sync stops playing. +5. When the volume is adjusted. Shairport Sync can run a program whenever the volume is set or changed. You specify the full path name to the program to run using the `general` group setting `run_this_when_volume_changes`. + Set the `wait_for_completion` value to `"yes"` for Shairport Sync to wait until the respective commands have been completed before continuing. Note that the full path to the programs must be specified, and script files will not be executed unless they are marked as executable From f96fa2f793b8ec5d4465a9a736a30661af6d03d6 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Mon, 3 Oct 2022 17:56:18 +0100 Subject: [PATCH 53/72] Only call the volume hook once for each volume event even when the dbus interface is included. --- rtsp.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/rtsp.c b/rtsp.c index aa48d976..adc9db23 100644 --- a/rtsp.c +++ b/rtsp.c @@ -3523,14 +3523,16 @@ void handle_set_parameter_parameter(rtsp_conn_info *conn, rtsp_message *req, debug(2, "Connection %d: request to set AirPlay Volume to: %f.", conn->connection_number, volume); // if we are playing, go ahead and change the volume - lock_player(); - config.airplay_volume = volume; - if (playing_conn == conn) - player_volume(volume, conn); - unlock_player(); #ifdef CONFIG_DBUS_INTERFACE if (dbus_service_is_running()) { - shairport_sync_set_volume(shairportSyncSkeleton, config.airplay_volume); + shairport_sync_set_volume(shairportSyncSkeleton, volume); + } else { +#endif + lock_player(); + if (playing_conn == conn) + player_volume(volume, conn); + unlock_player(); +#ifdef CONFIG_DBUS_INTERFACE } #endif } else if (strncmp(cp, "progress: ", strlen("progress: ")) == From 821e700f7cd1b2dc964e873d20a178dd26e4e0fd Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Mon, 3 Oct 2022 18:02:01 +0100 Subject: [PATCH 54/72] Update RELEASENOTES-DEVELOPMENT.md --- RELEASENOTES-DEVELOPMENT.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RELEASENOTES-DEVELOPMENT.md b/RELEASENOTES-DEVELOPMENT.md index 3bd8aaa0..cff8c0ab 100644 --- a/RELEASENOTES-DEVELOPMENT.md +++ b/RELEASENOTES-DEVELOPMENT.md @@ -1,3 +1,8 @@ +Version 4.1-dev-604-gf96fa2f7 +==== +**Bug Fix** +* If the D-Bus interface was enabled, each change in volume control was calling the volume event hook twice. Fixed. + Version 4.1-dev-601-g98744211 ==== **Bug Fix** From 90402c6002adb86137e676a6451995a357fac5a4 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 5 Oct 2022 10:08:16 +0100 Subject: [PATCH 55/72] Update from master branch. --- ADVANCED TOPICS/Events.md | 64 ++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/ADVANCED TOPICS/Events.md b/ADVANCED TOPICS/Events.md index 26a777de..ff5c8190 100644 --- a/ADVANCED TOPICS/Events.md +++ b/ADVANCED TOPICS/Events.md @@ -1,18 +1,54 @@ -## Events -Shairport Sync can run programs when certain "events" occur. The events are: -1. When Shairport Sync become `active` or `inactive`. Shairport Sync is normally in the `inactive` state when no audio is being played. When audio is sent to Shairport Sync, it will transition from `inactive` to `active`. When the audio stops, Shairport Sync will start a timer. If audio restarts before the timer reaches the value of the `active_state_timeout` configuration setting (10 seconds by default), Shairport Sync will stay `active`. However, if no more audio is received before the timer reaches the `active_state_timeout` value, Shairport Sync will transition to `inactive`. The overall effect of this is that Shairport Sync will go `active` when a track is played and will stay active in the interval between tracks, so long as the interval is less than the `active_state_timeout`. - 1. Set the `run_this_before_entering_active_state` setting to the full path name to the program to run before Shairport Sync goes `active`. - 2. Set the `run_this_after_exiting_active_state` setting to the full path name to the program to run after Shairport Sync goes `inactive`. - 3. Set the `active_state_timeout` setting to the maximum amount of time to wait for play to resume before going `inactive`. -3. When audio starts and stops playing. - 1. Set the `run_this_before_play_begins` setting to the full path name to the program to run just before Shairport Sync starts playing. - 2. Set the `run_this_after_play_ends` setting to the full path name to the program to run after Shairport Sync stops playing. -5. When the volume is adjusted. Shairport Sync can run a program whenever the volume is set or changed. You specify the full path name to the program to run using the `general` group setting `run_this_when_volume_changes`. +# Events +Shairport Sync can run programs when certain _events_ occur. The events are: +1. When Shairport Sync goes _active_ or _inactive,_ +3. When audio play starts or stops, +5. When the volume is set or changed. + + +### Active / Inactive Events +Shairport Sync is normally in the `inactive` state when no audio is being played. + +When audio is sent to Shairport Sync, it will transition from `inactive` to `active`. + +When the audio stops, Shairport Sync will start a timer. If audio restarts before the timer reaches the value of the `active_state_timeout` setting (10 seconds by default), Shairport Sync will stay `active`. However, if no more audio is received before the timer reaches the `active_state_timeout` value, Shairport Sync will transition to `inactive`. + +The overall effect of this is that Shairport Sync will go `active` when a track starts and stays active in the interval between tracks, so long as the interval is less than the `active_state_timeout`. When the sequence of tracks ends, Shairport Sync will go `inactive`. + +* Set the `run_this_before_entering_active_state` setting to the full path name to the program to run before Shairport Sync goes `active`. +* Set the `run_this_after_exiting_active_state` setting to the full path name to the program to run after Shairport Sync goes `inactive`. +* Set the `active_state_timeout` setting to the maximum amount of time to wait for play to resume before going `inactive`. + +### Play Start / Play Stop +**Note:** Play events have been superceded by Active/Inactive events, which works better in AirPlay 2 operation. + +When audio starts, the `play begins` event occurs. When it stops, the `play ends` event occurs. + +* Set the `run_this_before_play_begins` setting to the full path name to the program to run just before Shairport Sync starts playing. +* Set the `run_this_after_play_ends` setting to the full path name to the program to run after Shairport Sync stops playing. + +### Volume Adjustment +Shairport Sync can run a program whenever the volume is set or changed. + +* Set `run_this_when_volume_changes` to the full path name to the program to run using the `general` group setting `run_this_when_volume_changes` _but also_ add a space character to the end of the name. This is because when a volume event occurs, Shairport Sync will append the new volume to the text you have specified in `run_this_when_volume_changes` and will then try to execute it. + +For example, to use the `echo` command to log the volume setting, let's say that you have found that the full path name for `echo` is `/usr/bin/echo`, then you would specify `run_this_when_volume_is_set` as follows: +``` +run_this_when_volume_is_set = "/usr/bin/echo "; +``` +(Note the extra space at the end of the path name.) Suppose the volume is set or changed to `-24.6`, then Shairport Sync will execute the command `/usr/bin/echo -24.6`. (Without that extra space, it would try to execute `/usr/bin/echo24.6`.) + +### Waiting for Completion Set the `wait_for_completion` value to `"yes"` for Shairport Sync to wait until the respective commands have been completed before continuing. -Note that the full path to the programs must be specified, and script files will not be executed unless they are marked as executable -and have the appropriate shebang `#!/bin/...` as the first line. (This behaviour may be different from other Shairports.) +### Program +The environment in which the program you specify will be very different to a login environment. In particular, the `PATH` variable will be different. This means that you can't assume that the system will look in the right directories for programs or documents. Therefore, it is _vital_ that you specify everything using a _full path name_. -Shairport Sync can run a program whenever the volume is set or changed. You specify it using the `general` group setting `run_this_when_volume_changes`. -This is to facilitate situations where something has to be done when the volume changes, e.g. adjust an external mixer value. Set the `wait_for_completion` value to `"yes"` for Shairport Sync to wait until the command has been completed before continuing. Again, please note that the full path to the program must be specified, and script files will not be executed unless they are marked as executable and have the appropriate shebang `#!/bin/...` as the first line. +For example, to get the `logger` command to log `Active Start` when Shairport Sync goes active, set `run_this_before_entering_active_state` as follows: + +``` +run_this_before_entering_active_state = "/usr/bin/logger \"Active Start\""; +``` + +You can specify a program to be executed or you can specify a script. Make sure the script file is marked as executable +and has the appropriate shebang `#!/bin/...` as the first line. Within the script, make sure all references to files are full path names. From 7d5884310cd499c5a331d6e99d53494213f462be Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 5 Oct 2022 10:44:24 +0100 Subject: [PATCH 56/72] Update AIRPLAY2.md --- AIRPLAY2.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AIRPLAY2.md b/AIRPLAY2.md index 9029b462..56675b69 100644 --- a/AIRPLAY2.md +++ b/AIRPLAY2.md @@ -23,7 +23,7 @@ for timing and synchronisation in AirPlay 2. NQPTP must run as `root` and must h Lossless and High Definition Lossless material is transcoded to AAC before it reaches Shairport Sync. ## What You Need -AirPlay 2 support needs a slightly more powerful CPU for decoding and synchronisation and more memory for bigger buffers and larger libraries. A Raspberry Pi 2 or Raspberry Pi Zero 2 W or better is recommended. +AirPlay 2 support needs a slightly more powerful CPU for decoding and synchronisation and more memory for bigger buffers and larger libraries. A system with the power of a Raspberry Pi 2 or Raspberry Pi Zero 2 W, or better, is recommended. Here are some guidelines: * Full access, including `root` privileges, to a system at least as powerful as a Raspberry Pi 2 or a Raspberry Pi Zero 2 W. @@ -33,6 +33,7 @@ Here are some guidelines: * A version of the [FFmpeg](https://www.ffmpeg.org) library with an AAC decoder capable of decoding Floating Planar -- `fltp` -- material. There is a guide [here](TROUBLESHOOTING.md#aac-decoder-issues-airplay-2-only) to help you find out if your system has it. * An audio output, for example an ALSA device (or `sndio` in FreeBSD). The device must be capable of running at 44,100 frames per second. You can use an `sps-alsa-explore`](https://github.com/mikebrady/sps-alsa-explore) to test the suitability of hardware ALSA audio devices on your device. Other backends continue to work as with "classic" Shairport Sync. +- Multiple instances of the AirPlay 2 version of Shairport Sync can not be hosted on the same system. It seems that AirPlay 2 clients are confused by having multiple AirPlay 2 players at the same IP addresses. ## Guides * A building guide is available at [BUILD.md](BUILD.md). From 79dc40189c26db0ef637b27df7c15318f3297c8c Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 5 Oct 2022 10:45:49 +0100 Subject: [PATCH 57/72] Update AIRPLAY2.md --- AIRPLAY2.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AIRPLAY2.md b/AIRPLAY2.md index 56675b69..ae2ef389 100644 --- a/AIRPLAY2.md +++ b/AIRPLAY2.md @@ -29,7 +29,7 @@ Here are some guidelines: * Full access, including `root` privileges, to a system at least as powerful as a Raspberry Pi 2 or a Raspberry Pi Zero 2 W. * Ports 319 and 320 must be free to use (i.e. they must not be in use by another service such as a PTP service) and must not be blocked by a firewall. * An up-to-date Linux or FreeBSD. This is important, as some of the libraries must be the latest available. -* Shairport Sync will not run on a Mac because NQPTP, on which it relies, needs ports 319 and 320, which are already used by macOS. +* Shairport Sync will not run in AirPlay 2 mode on a Mac because NQPTP, on which it relies, needs ports 319 and 320, which are already used by macOS. * A version of the [FFmpeg](https://www.ffmpeg.org) library with an AAC decoder capable of decoding Floating Planar -- `fltp` -- material. There is a guide [here](TROUBLESHOOTING.md#aac-decoder-issues-airplay-2-only) to help you find out if your system has it. * An audio output, for example an ALSA device (or `sndio` in FreeBSD). The device must be capable of running at 44,100 frames per second. You can use an `sps-alsa-explore`](https://github.com/mikebrady/sps-alsa-explore) to test the suitability of hardware ALSA audio devices on your device. Other backends continue to work as with "classic" Shairport Sync. From fdc9531a3b412c5abf0814ab53128b3fede4b260 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 5 Oct 2022 12:39:57 +0100 Subject: [PATCH 58/72] Remove strange calls to the D-Bus system. --- activity_monitor.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/activity_monitor.c b/activity_monitor.c index 0de7d341..896a79f9 100644 --- a/activity_monitor.c +++ b/activity_monitor.c @@ -56,8 +56,7 @@ pthread_mutex_t activity_monitor_mutex; pthread_cond_t activity_monitor_cv; void going_active(int block) { - // debug(1, "activity_monitor: state transitioning to \"active\" with%s blocking", block ? "" : - // "out"); + // debug(1, "activity_monitor: state transitioning to \"active\" with%s blocking", block ? "" : "out"); if (config.cmd_active_start) command_execute(config.cmd_active_start, "", block); #ifdef CONFIG_METADATA @@ -71,17 +70,12 @@ void going_active(int block) { #endif if (config.disable_standby_mode == disable_standby_auto) { -#ifdef CONFIG_DBUS_INTERFACE - if (dbus_service_is_running()) - shairport_sync_set_disable_standby(SHAIRPORT_SYNC(shairportSyncSkeleton), TRUE); -#endif config.keep_dac_busy = 1; } } void going_inactive(int block) { - // debug(1, "activity_monitor: state transitioning to \"inactive\" with%s blocking", block ? "" : - // "out"); + // debug(1, "activity_monitor: state transitioning to \"inactive\" with%s blocking", block ? "" : "out"); if (config.cmd_active_stop) command_execute(config.cmd_active_stop, "", block); #ifdef CONFIG_METADATA @@ -95,10 +89,6 @@ void going_inactive(int block) { #endif if (config.disable_standby_mode == disable_standby_auto) { -#ifdef CONFIG_DBUS_INTERFACE - if (dbus_service_is_running()) - shairport_sync_set_disable_standby(SHAIRPORT_SYNC(shairportSyncSkeleton), FALSE); -#endif config.keep_dac_busy = 0; } } From 06c69c69f316481e5fd24bf56fc5fd6ad32bebad Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 5 Oct 2022 12:41:54 +0100 Subject: [PATCH 59/72] When a buffered stream is paused or stopped, try to close the output device immediately. This will succeed if disable_standby mode is off. --- rtsp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rtsp.c b/rtsp.c index 76395df9..81cd1b3f 100644 --- a/rtsp.c +++ b/rtsp.c @@ -2003,6 +2003,10 @@ void handle_setrateanchori(rtsp_conn_info *conn, rtsp_message *req, rtsp_message activity_monitor_signify_activity(0); conn->ap2_play_enabled = 0; reset_anchor_info(conn); + if (config.output->stop) { + debug(2, "Connection %d: Stop the output backend.", conn->connection_number); + config.output->stop(); + } } pthread_cleanup_pop(1); // unlock the conn->flush_mutex } From 509322f1373fd44df03a84ab9454ee5a571ba755 Mon Sep 17 00:00:00 2001 From: Charles <32498151+charlesomer@users.noreply.github.com> Date: Wed, 5 Oct 2022 22:50:18 +0100 Subject: [PATCH 60/72] Docker build changes, github action updates. --- .../docker-build-on-formal-release.yaml | 83 ------------------- .github/workflows/docker-build-on-push.yaml | 42 +++++----- .github/workflows/docker-build-on-tag.yaml | 45 ++++++---- docker/README.md | 27 ++++-- docker/docker-compose.yaml | 2 +- 5 files changed, 68 insertions(+), 131 deletions(-) delete mode 100644 .github/workflows/docker-build-on-formal-release.yaml diff --git a/.github/workflows/docker-build-on-formal-release.yaml b/.github/workflows/docker-build-on-formal-release.yaml deleted file mode 100644 index fc698373..00000000 --- a/.github/workflows/docker-build-on-formal-release.yaml +++ /dev/null @@ -1,83 +0,0 @@ -# Builds & pushes a docker image when a "formal" release tag of the format X, X.Y or X.Y.Z occurs, where X, Y and Z are all numbers. -# It seems this yaml has to exist on the branch the tag refers to. - -# Thanks to Charles Omer for the workfow upon which this is based. - -# The following docker tags are created & pushed: -# trial, trial-classic -# not building 'latest' yet... - -name: Formal (X, X.Y or X.Y.Z) release tags -- docker build and push. - -on: - push: - tags: - - '[0-9]+\.[0-9]+\.[0-9]+' # e.g. 8.9.0 - - '[0-9]+\.[0-9]+' # e.g. 8.9 - - '[0-9]+' # e.g. 8 - - '[0-9]+\.[0-9]+rc[0-9]+' # e.g. 4.1rc0 - -env: - DOCKER_PLATFORMS: linux/386,linux/amd64,linux/arm/v6,linux/arm64,linux/arm/v7 - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Set SHAIRPORT_SYNC_BRANCH env. - run: | - raw=$(git branch -r --contains ${{ github.ref }}) - branch=${raw##*/} - echo "SHAIRPORT_SYNC_BRANCH=${branch}" >> $GITHUB_ENV - - - name: Set tag env - run: echo "GIT_TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - - - name: Determine NQPTP env (part 1). - if: ${{ env.SHAIRPORT_SYNC_BRANCH == 'development' }} - run: echo "NQPTP_BRANCH=development" >> $GITHUB_ENV - - - name: Determine NQPTP env (part 2). - if: ${{ env.SHAIRPORT_SYNC_BRANCH != 'development' }} - run: echo "NQPTP_BRANCH=main" >> $GITHUB_ENV - - - name: Set up QEMU - uses: docker/setup-qemu-action@v1 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Registry - uses: docker/login-action@v1 - with: - registry: ${{ secrets.DOCKER_REGISTRY }} - username: ${{ secrets.DOCKER_REGISTRY_USER }} - password: ${{ secrets.DOCKER_REGISTRY_TOKEN }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: ./ - file: ./docker/Dockerfile - platforms: ${{ env.DOCKER_PLATFORMS }} - push: true - tags: trial - build-args: | - SHAIRPORT_SYNC_BRANCH=${{ env.SHAIRPORT_SYNC_BRANCH }} - NQPTP_BRANCH=${{ env.NQPTP_BRANCH }} - - - name: Build and push (Classic) - uses: docker/build-push-action@v2 - with: - context: ./ - file: ./docker/classic/Dockerfile - platforms: ${{ env.DOCKER_PLATFORMS }} - push: true - tags: trial-classic - build-args: | - SHAIRPORT_SYNC_BRANCH=${{ env.SHAIRPORT_SYNC_BRANCH }} diff --git a/.github/workflows/docker-build-on-push.yaml b/.github/workflows/docker-build-on-push.yaml index dca048e2..1d273cad 100644 --- a/.github/workflows/docker-build-on-push.yaml +++ b/.github/workflows/docker-build-on-push.yaml @@ -1,14 +1,19 @@ -# Builds & pushes a docker image when a commit is made to one of the branches specified below. -# Tag pattern: 'unstable-[BRANCH NAME]' & 'unstable-[BRANCH NAME]-classic' +# Builds a docker image when a commit is made. Also pushes the build if the branch is 'master' or 'development'. -name: Build and push docker image based on commit to specified branches. +# Tag pattern +# 'master' - latest, latest-classic +# 'development' - development, development-classic + +name: Build and push docker (commit) on: push: - branches: [ development ] + branches: + - '**' env: DOCKER_PLATFORMS: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64 + NQPTP_BRANCH: main jobs: main: @@ -22,13 +27,16 @@ jobs: - name: Set SHAIRPORT_SYNC_BRANCH env. run: echo "SHAIRPORT_SYNC_BRANCH=${GITHUB_REF##*/}" >> $GITHUB_ENV - - name: Determine NQPTP env (part 1). - if: ${{ env.SHAIRPORT_SYNC_BRANCH == 'development' }} - run: echo "NQPTP_BRANCH=development" >> $GITHUB_ENV + - name: Is branch "master"? + if: ${{ env.SHAIRPORT_SYNC_BRANCH == 'master' }} + run: | + echo "IMAGE_TAG_BASE=latest" >> $GITHUB_ENV - - name: Determine NQPTP env (part 2). - if: ${{ env.SHAIRPORT_SYNC_BRANCH != 'development' }} - run: echo "NQPTP_BRANCH=main" >> $GITHUB_ENV + - name: Is branch "development"? + if: ${{ env.SHAIRPORT_SYNC_BRANCH == 'development' }} + run: | + echo "NQPTP_BRANCH=development" >> $GITHUB_ENV + echo "IMAGE_TAG_BASE=development" >> $GITHUB_ENV - name: Set up QEMU uses: docker/setup-qemu-action@v1 @@ -43,33 +51,25 @@ jobs: username: ${{ secrets.DOCKER_REGISTRY_USER }} password: ${{ secrets.DOCKER_REGISTRY_TOKEN }} - - name: Set tag start (part 1). - if: ${{ env.SHAIRPORT_SYNC_BRANCH == 'master' }} - run: echo "IMAGE_TAG_BASE=unstable" >> $GITHUB_ENV - - - name: Set tag start (part 2). - if: ${{ env.SHAIRPORT_SYNC_BRANCH != 'master' }} - run: echo "IMAGE_TAG_BASE=unstable-${{ env.SHAIRPORT_SYNC_BRANCH }}" >> $GITHUB_ENV - - name: Build and push uses: docker/build-push-action@v2 with: context: ./ file: ./docker/Dockerfile platforms: ${{ env.DOCKER_PLATFORMS }} - push: true + push: ${{ env.IMAGE_TAG_BASE != '' }} tags: ${{ secrets.DOCKER_IMAGE_NAME }}:${{ env.IMAGE_TAG_BASE }} build-args: | SHAIRPORT_SYNC_BRANCH=${{ env.SHAIRPORT_SYNC_BRANCH }} NQPTP_BRANCH=${{ env.NQPTP_BRANCH }} - - name: Build and push (AirPlay 1) + - name: Build and push (classic) uses: docker/build-push-action@v2 with: context: ./ file: ./docker/classic/Dockerfile platforms: ${{ env.DOCKER_PLATFORMS }} - push: true + push: ${{ env.IMAGE_TAG_BASE != '' }} tags: ${{ secrets.DOCKER_IMAGE_NAME }}:${{ env.IMAGE_TAG_BASE }}-classic build-args: | SHAIRPORT_SYNC_BRANCH=${{ env.SHAIRPORT_SYNC_BRANCH }} \ No newline at end of file diff --git a/.github/workflows/docker-build-on-tag.yaml b/.github/workflows/docker-build-on-tag.yaml index 6762a9bd..0e87ebd4 100644 --- a/.github/workflows/docker-build-on-tag.yaml +++ b/.github/workflows/docker-build-on-tag.yaml @@ -1,18 +1,22 @@ -# Builds & pushes a docker image when a tag occurs. -# It seems this yaml has to exist on the branch the tag refers to. +# Builds & pushes a docker image when a tag is created. +# Tag pattern: '[tag]' & '[tag]-classic' +# 'stable' & 'stable-classic' also, when master tagged. -# The following docker tags are created & pushed: -# [RELEASE TAG], [RELEASE TAG]-classic, +# Only pushes the tag when it matches one of the following patterns: +# X, X.Y or X.Y.Z -name: Build and push docker images on releases. +name: Build and push docker (tag) on: push: tags: - - '*' # Push events to every tag (not containing '/') + - '[0-9]+' # X + - '[0-9]+\.[0-9]+' # X.Y + - '[0-9]+\.[0-9]+\.[0-9]+' # X.Y.Z env: DOCKER_PLATFORMS: linux/386,linux/amd64,linux/arm/v6,linux/arm64,linux/arm/v7 + NQPTP_BRANCH: main jobs: main: @@ -32,22 +36,23 @@ jobs: - name: Set tag env run: echo "GIT_TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - - name: Determine NQPTP env (part 1). + - name: Is branch "master"? + if: ${{ env.SHAIRPORT_SYNC_BRANCH == 'master' }} + run: echo "STABLE_TAG=true" >> $GITHUB_ENV + + - name: Is branch "development"? if: ${{ env.SHAIRPORT_SYNC_BRANCH == 'development' }} - run: echo "NQPTP_BRANCH=development" >> $GITHUB_ENV - - - name: Determine NQPTP env (part 2). - if: ${{ env.SHAIRPORT_SYNC_BRANCH != 'development' }} - run: echo "NQPTP_BRANCH=main" >> $GITHUB_ENV + run: | + echo "NQPTP_BRANCH=development" >> $GITHUB_ENV - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to Docker Registry - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: registry: ${{ secrets.DOCKER_REGISTRY }} username: ${{ secrets.DOCKER_REGISTRY_USER }} @@ -60,18 +65,22 @@ jobs: file: ./docker/Dockerfile platforms: ${{ env.DOCKER_PLATFORMS }} push: true - tags: ${{ secrets.DOCKER_IMAGE_NAME }}:${{ env.GIT_TAG }} + tags: | + ${{ secrets.DOCKER_IMAGE_NAME }}:${{ env.GIT_TAG }} + ${{ env.STABLE_TAG == 'true' && format('{0}:stable', secrets.DOCKER_IMAGE_NAME) || '' }} build-args: | SHAIRPORT_SYNC_BRANCH=${{ env.SHAIRPORT_SYNC_BRANCH }} NQPTP_BRANCH=${{ env.NQPTP_BRANCH }} - - name: Build and push (Classic) + - name: Build and push (classic) uses: docker/build-push-action@v2 with: context: ./ file: ./docker/classic/Dockerfile platforms: ${{ env.DOCKER_PLATFORMS }} push: true - tags: ${{ secrets.DOCKER_IMAGE_NAME }}:${{ env.GIT_TAG }}-classic + tags: | + ${{ secrets.DOCKER_IMAGE_NAME }}:${{ env.GIT_TAG }}-classic + ${{ env.STABLE_TAG == 'true' && format('{0}:stable-classic', secrets.DOCKER_IMAGE_NAME) || '' }} build-args: | SHAIRPORT_SYNC_BRANCH=${{ env.SHAIRPORT_SYNC_BRANCH }} \ No newline at end of file diff --git a/docker/README.md b/docker/README.md index acabc123..2b27e77f 100644 --- a/docker/README.md +++ b/docker/README.md @@ -2,21 +2,32 @@ Available at: https://hub.docker.com/r/mikebrady/shairport-sync -Please note if you want the development version of the image including Airplay 2 support, please pull the image with the ```unstable development``` tag using the following command: -``` -docker pull mikebrady/shairport-sync:unstable-development +The following docker tags are available: ``` +[tag] +[tag]-classic -When using the below commands, you should replace mikebrady/shairport-sync with mikbrady/shairport-sync:unstable-development. +(build from newest tag) +stable +stable-classic + +(latest build from master) +latest +latest-classic + +(latest build from development) +development +development-classic +``` ## Example Docker Compose File See the `docker-compose.yaml` file in this folder for an example. -## Docker Run +## Example Docker Run ``` $ docker run -d --restart unless-stopped --net host --device /dev/snd \ - mikebrady/shairport-sync + mikebrady/shairport-sync: ``` ### Options @@ -24,7 +35,7 @@ $ docker run -d --restart unless-stopped --net host --device /dev/snd \ You can change the default commands passed to Shairport Sync. Here is an example: ``` $ docker run -d --restart unless-stopped --net host --device /dev/snd \ - mikebrady/shairport-sync:unstable-development shairport-sync -v \ + mikebrady/shairport-sync: shairport-sync -v \ --statistics -a DenSystem -d hw:0 -c PCM ``` This will sent audio to alsa hardware device `hw:0` and make use of the that device's mixer control called `PCM`. The service will be visible as `DenSystem` on the network. @@ -53,4 +64,4 @@ Requires the following secrets to be set in the repo: - `DOCKER_REGISTRY` - docker.io if using Docker Hub, else set to your registry URL. - `DOCKER_REGISTRY_TOKEN` - Access token for your registry. - `DOCKER_REGISTRY_USER` - Login user for your registry. -- `DOCKER_IMAGE_NAME` - The name of the image, for example `your-registry.com/shairport-sync` or just `your-username/shairport-sync` if using Docker Hub. +- `DOCKER_IMAGE_NAME` - The name of the image, for example `your-registry.com/shairport-sync` or just `your-username/shairport-sync` if using Docker Hub. \ No newline at end of file diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 13b5bac7..6b2394a1 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -2,7 +2,7 @@ services: shairport-sync: - image: mikebrady/shairport-sync:unstable-development + image: mikebrady/shairport-sync: network_mode: host restart: unless-stopped devices: From a0e99ed5ada5445018cda4e1b951e4e8a419352b Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Fri, 7 Oct 2022 15:43:28 +0100 Subject: [PATCH 61/72] Quieten a debug message. --- audio_dummy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/audio_dummy.c b/audio_dummy.c index 4ec1d29d..1ea68ff0 100644 --- a/audio_dummy.c +++ b/audio_dummy.c @@ -58,7 +58,7 @@ static int play(__attribute__((unused)) void *buf, __attribute__((unused)) int s // sample code using some of the extra information if (sample_type == play_samples_are_timed) { int64_t lead_time = playtime - get_absolute_time_in_ns(); - debug(1, "leadtime for frame %u is %" PRId64 " nanoseconds, i.e. %f seconds.", timestamp, + debug(2, "leadtime for frame %u is %" PRId64 " nanoseconds, i.e. %f seconds.", timestamp, lead_time, 0.000000001 * lead_time); } From 0cc97d5099a95ebe6797367127b8b994a9dac30a Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Fri, 7 Oct 2022 16:17:42 +0100 Subject: [PATCH 62/72] Start using libgcrypt again, as there appears to be a memory leak in openssl when used in the pair_ap library. --- Makefile.am | 2 +- configure.ac | 5 +++++ shairport.c | 23 +++++++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 1dc654cc..bc6710d8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ SUBDIRS = man ARFLAGS = cr -lib_pair_ap_a_CFLAGS = -Wall -g -DCONFIG_OPENSSL -pthread +lib_pair_ap_a_CFLAGS = -Wall -g -DCONFIG_GCRYPT -pthread lib_tinyhttp_a_CFLAGS = -pthread lib_dbus_interface_a_CFLAGS = -pthread lib_mpris_interface_a_CFLAGS = -pthread diff --git a/configure.ac b/configure.ac index fd233952..b0f53cd9 100644 --- a/configure.ac +++ b/configure.ac @@ -412,6 +412,11 @@ if test "x$with_airplay_2" = "xyes" ; then ]) ]) PKG_CHECK_MODULES([libsodium], [libsodium],[CFLAGS="${libsodium_CFLAGS} ${CFLAGS}" LIBS="${libsodium_LIBS} ${LIBS}"],[AC_MSG_ERROR(AirPlay 2 support requires libsodium -- libsodium-dev suggested)]) + PKG_CHECK_MODULES([libgcrypt], [libgcrypt],[CFLAGS="${libgcrypt_CFLAGS} ${CFLAGS}" LIBS="${libgcrypt_LIBS} ${LIBS}"],[ + AC_CHECK_LIB([gcrypt], [gcry_control], [], [ + AC_MSG_ERROR([Airplay 2 support requires libgcrypt -- libgcrypt-dev suggested]) + ]) + ]) PKG_CHECK_MODULES([libavutil], [libavutil],[CFLAGS="${libavutil_CFLAGS} ${CFLAGS}" LIBS="${libavutil_LIBS} ${LIBS}"],[ AC_MSG_ERROR(AirPlay 2 support requires libavutil -- libavutil-dev suggested)]) PKG_CHECK_MODULES([libavcodec], [libavcodec],[CFLAGS="${libavcodec_CFLAGS} ${CFLAGS}" LIBS="${libavcodec_LIBS} ${LIBS}"],[ diff --git a/shairport.c b/shairport.c index aec61bc7..9d1657f0 100644 --- a/shairport.c +++ b/shairport.c @@ -45,6 +45,7 @@ #ifdef CONFIG_AIRPLAY_2 #include "ptp-utilities.h" +#include #include #include #include @@ -2103,6 +2104,28 @@ int main(int argc, char **argv) { debug(1, "libsodium initialised."); } + // this code is based on + // https://www.gnupg.org/documentation/manuals/gcrypt/Initializing-the-library.html + + /* Version check should be the very first call because it + makes sure that important subsystems are initialized. + #define NEED_LIBGCRYPT_VERSION to the minimum required version. */ + +#define NEED_LIBGCRYPT_VERSION "1.5.4" + + if (!gcry_check_version(NEED_LIBGCRYPT_VERSION)) { + die("libgcrypt is too old (need %s, have %s).", NEED_LIBGCRYPT_VERSION, + gcry_check_version(NULL)); + } + + /* Disable secure memory. */ + gcry_control(GCRYCTL_DISABLE_SECMEM, 0); + + /* ... If required, other initialization goes here. */ + + /* Tell Libgcrypt that initialization has completed. */ + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); + #endif /* Mess around with the latency options */ From 7dcad083986a0b74eb1449705693729f62024eb9 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Fri, 7 Oct 2022 16:17:57 +0100 Subject: [PATCH 63/72] Fix two memory leaks. --- rtsp.c | 193 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 101 insertions(+), 92 deletions(-) diff --git a/rtsp.c b/rtsp.c index 81cd1b3f..62da82e5 100644 --- a/rtsp.c +++ b/rtsp.c @@ -1830,92 +1830,95 @@ void handle_flushbuffered(rtsp_conn_info *conn, rtsp_message *req, rtsp_message uint64_t flushUntilTS = 0; int flushFromValid = 0; plist_t messagePlist = plist_from_rtsp_content(req); - plist_t item = plist_dict_get_item(messagePlist, "flushFromSeq"); - if (item == NULL) { - debug(2, "Can't find a flushFromSeq"); - } else { - flushFromValid = 1; - plist_get_uint_val(item, &flushFromSeq); - debug(2, "flushFromSeq is %" PRId64 ".", flushFromSeq); - } + if (messagePlist != NULL) { + plist_t item = plist_dict_get_item(messagePlist, "flushFromSeq"); + if (item == NULL) { + debug(2, "Can't find a flushFromSeq"); + } else { + flushFromValid = 1; + plist_get_uint_val(item, &flushFromSeq); + debug(2, "flushFromSeq is %" PRId64 ".", flushFromSeq); + } - item = plist_dict_get_item(messagePlist, "flushFromTS"); - if (item == NULL) { - if (flushFromValid != 0) - debug(1, "flushFromSeq without flushFromTS!"); - else - debug(2, "Can't find a flushFromTS"); - } else { - plist_get_uint_val(item, &flushFromTS); + item = plist_dict_get_item(messagePlist, "flushFromTS"); + if (item == NULL) { + if (flushFromValid != 0) + debug(1, "flushFromSeq without flushFromTS!"); + else + debug(2, "Can't find a flushFromTS"); + } else { + plist_get_uint_val(item, &flushFromTS); + if (flushFromValid == 0) + debug(1, "flushFromTS without flushFromSeq!"); + debug(2, "flushFromTS is %" PRId64 ".", flushFromTS); + } + + item = plist_dict_get_item(messagePlist, "flushUntilSeq"); + if (item == NULL) { + debug(1, "Can't find the flushUntilSeq"); + } else { + plist_get_uint_val(item, &flushUntilSeq); + debug(2, "flushUntilSeq is %" PRId64 ".", flushUntilSeq); + } + + item = plist_dict_get_item(messagePlist, "flushUntilTS"); + if (item == NULL) { + debug(1, "Can't find the flushUntilTS"); + } else { + plist_get_uint_val(item, &flushUntilTS); + debug(2, "flushUntilTS is %" PRId64 ".", flushUntilTS); + } + + debug_mutex_lock(&conn->flush_mutex, 1000, 1); + // a flush with from... components will not be followed by a setanchor (i.e. a play) + // if it's a flush that will be followed by a setanchor (i.e. a play) then stop play now. if (flushFromValid == 0) - debug(1, "flushFromTS without flushFromSeq!"); - debug(2, "flushFromTS is %" PRId64 ".", flushFromTS); + conn->ap2_play_enabled = 0; + + // add the exact request as made to the linked list (not used for anything but diagnostics now) + // int flushNow = 0; + // if (flushFromValid == 0) + // flushNow = 1; + // add_flush_request(flushNow, flushFromSeq, flushFromTS, flushUntilSeq, flushUntilTS, conn); + + // now, if it's an immediate flush, replace the existing request, if any + // but it if's a deferred flush and there is an existing deferred request, + // only update the flushUntil stuff -- that seems to preserve + // the intended semantics + + // so, always replace these + conn->ap2_flush_until_sequence_number = flushUntilSeq; + conn->ap2_flush_until_rtp_timestamp = flushUntilTS; + + if ((conn->ap2_flush_requested != 0) && (conn->ap2_flush_from_valid != 0) && + (flushFromValid != 0)) { + // if there is a request already, and it's a deferred request, and the current request is also + // deferred... do nothing! -- leave the starting point in place. Yeah, yeah, we know de Morgan's + // Law, but this seems clearer + } else { + conn->ap2_flush_from_sequence_number = flushFromSeq; + conn->ap2_flush_from_rtp_timestamp = flushFromTS; + } + + conn->ap2_flush_from_valid = flushFromValid; + conn->ap2_flush_requested = 1; + + // reflect the possibly updated flush request + // add_flush_request(flushNow, conn->ap2_flush_from_sequence_number, + // conn->ap2_flush_from_rtp_timestamp, conn->ap2_flush_until_sequence_number, + // conn->ap2_flush_until_rtp_timestamp, conn); + + debug_mutex_unlock(&conn->flush_mutex, 3); + + if (flushFromValid) + debug(2, "Deferred Flush Requested"); + else + debug(2, "Immediate Flush Requested"); + + plist_free(messagePlist); + // display_all_flush_requests(conn); } - item = plist_dict_get_item(messagePlist, "flushUntilSeq"); - if (item == NULL) { - debug(1, "Can't find the flushUntilSeq"); - } else { - plist_get_uint_val(item, &flushUntilSeq); - debug(2, "flushUntilSeq is %" PRId64 ".", flushUntilSeq); - } - - item = plist_dict_get_item(messagePlist, "flushUntilTS"); - if (item == NULL) { - debug(1, "Can't find the flushUntilTS"); - } else { - plist_get_uint_val(item, &flushUntilTS); - debug(2, "flushUntilTS is %" PRId64 ".", flushUntilTS); - } - - debug_mutex_lock(&conn->flush_mutex, 1000, 1); - // a flush with from... components will not be followed by a setanchor (i.e. a play) - // if it's a flush that will be followed by a setanchor (i.e. a play) then stop play now. - if (flushFromValid == 0) - conn->ap2_play_enabled = 0; - - // add the exact request as made to the linked list (not used for anything but diagnostics now) - // int flushNow = 0; - // if (flushFromValid == 0) - // flushNow = 1; - // add_flush_request(flushNow, flushFromSeq, flushFromTS, flushUntilSeq, flushUntilTS, conn); - - // now, if it's an immediate flush, replace the existing request, if any - // but it if's a deferred flush and there is an existing deferred request, - // only update the flushUntil stuff -- that seems to preserve - // the intended semantics - - // so, always replace these - conn->ap2_flush_until_sequence_number = flushUntilSeq; - conn->ap2_flush_until_rtp_timestamp = flushUntilTS; - - if ((conn->ap2_flush_requested != 0) && (conn->ap2_flush_from_valid != 0) && - (flushFromValid != 0)) { - // if there is a request already, and it's a deferred request, and the current request is also - // deferred... do nothing! -- leave the starting point in place. Yeah, yeah, we know de Morgan's - // Law, but this seems clearer - } else { - conn->ap2_flush_from_sequence_number = flushFromSeq; - conn->ap2_flush_from_rtp_timestamp = flushFromTS; - } - - conn->ap2_flush_from_valid = flushFromValid; - conn->ap2_flush_requested = 1; - - // reflect the possibly updated flush request - // add_flush_request(flushNow, conn->ap2_flush_from_sequence_number, - // conn->ap2_flush_from_rtp_timestamp, conn->ap2_flush_until_sequence_number, - // conn->ap2_flush_until_rtp_timestamp, conn); - - debug_mutex_unlock(&conn->flush_mutex, 3); - - if (flushFromValid) - debug(2, "Deferred Flush Requested"); - else - debug(2, "Immediate Flush Requested"); - - // display_all_flush_requests(conn); - resp->respcode = 200; } @@ -2222,7 +2225,7 @@ void handle_pair_setup(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *re uint8_t *body = NULL; size_t body_len = 0; struct pair_result *result; - debug(2, "Connection %d: pair-setup Content-Length %d", conn->connection_number, + debug(2, "Connection %d: handle_pair-setup Content-Length %d", conn->connection_number, req->contentlength); if (!conn->ap2_pairing_context.setup_ctx) { @@ -2823,6 +2826,7 @@ static void check_and_send_plist_metadata(plist_t messagePlist, const char *plis plist_get_string_val(item, &value); if (value != NULL) { send_metadata('ssnc', metadata_code, value, strlen(value), NULL, 0); + free(value); } } } @@ -4173,19 +4177,22 @@ void metadata_stop(void) { int send_metadata_to_queue(pc_queue *queue, uint32_t type, uint32_t code, char *data, uint32_t length, rtsp_message *carrier, int block) { - // parameters: type, code, pointer to data or NULL, length of data or NULL, - // the rtsp_message or - // NULL + // clang-format off + // parameters: + // type, + // code, + // pointer to data or NULL, + // length of data or NULL, + // the rtsp_message or NULL, + // the rtsp_message is sent for 'core' messages, because it contains the data - // and must not be - // freed until the data has been read. So, it is passed to send_metadata to be - // retained, - // sent to the thread where metadata is processed and released (and probably - // freed). + // and must not be freed until the data has been read. + // So, it is passed to send_metadata to be retained, sent to the thread where metadata + // is processed and released (and probably freed). // The rtsp_message is also sent for certain non-'core' messages. - // The reading of the parameters is a bit complex + // The reading of the parameters is a bit complex: // If the rtsp_message field is non-null, then it represents an rtsp_message // and the data pointer is assumed to point to something within it. // The reference counter of the rtsp_message is incremented here and @@ -4195,8 +4202,10 @@ int send_metadata_to_queue(pc_queue *queue, uint32_t type, uint32_t code, char * // If the rtsp_message is NULL, then if the pointer is non-null then the data it // points to, of the length specified, is memcpy'd and passed to the metadata // handler. The handler should free it when done. + // If the rtsp_message is NULL and the pointer is also NULL, nothing further // is done. + // clang-format on metadata_package pack; pack.type = type; From fdad4fc71469ef6303f9b6cce4917fe1e0fbedc2 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Fri, 7 Oct 2022 17:07:11 +0100 Subject: [PATCH 64/72] Update RELEASENOTES-DEVELOPMENT.md --- RELEASENOTES-DEVELOPMENT.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/RELEASENOTES-DEVELOPMENT.md b/RELEASENOTES-DEVELOPMENT.md index cff8c0ab..7da49376 100644 --- a/RELEASENOTES-DEVELOPMENT.md +++ b/RELEASENOTES-DEVELOPMENT.md @@ -1,3 +1,10 @@ +Version 4.1-dev-688-g7dcad083 +==== +**Bug Fixes** +* Fixed two memory leaks in Shairport Sync. +* Reinstate the use of `libcrypt` again with the `pair_ap` library to avoid an apparent memory leak in `libcrypto`. +* Quieten a noisy debug message in the `dummy` backend. + Version 4.1-dev-604-gf96fa2f7 ==== **Bug Fix** From 4726c4d95646b0898e20bfd961f883536f084109 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Fri, 7 Oct 2022 17:10:45 +0100 Subject: [PATCH 65/72] Update BUILD.md --- BUILD.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BUILD.md b/BUILD.md index bb6aefe9..3d5bc4a9 100644 --- a/BUILD.md +++ b/BUILD.md @@ -39,7 +39,7 @@ Okay, now let's get the tools and libraries for building and installing Shairpor # apt upgrade # this is optional but recommended # apt install --no-install-recommends build-essential git xmltoman autoconf automake libtool \ libpopt-dev libconfig-dev libasound2-dev avahi-daemon libavahi-client-dev libssl-dev libsoxr-dev \ - libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev xxd + libplist-dev libsodium-dev libavutil-dev libavcodec-dev libavformat-dev uuid-dev libgcrypt-dev xxd ``` If you are building classic Shairport Sync, the list of packages is shorter: ``` @@ -54,7 +54,7 @@ For AirPlay 2 operation, _before you install the libraries_, please ensure the y # yum update # yum install make automake gcc gcc-c++ \ git xmltoman autoconf automake avahi-devel libconfig-devel openssl-devel popt-devel soxr-devel \ - ffmpeg ffmpeg-devel libplist-devel libsodium-devel libuuid-devel vim-common \ + ffmpeg ffmpeg-devel libplist-devel libsodium-devel libgcrypt-dev libuuid-devel vim-common \ alsa-lib-devel ``` If you are building classic Shairport Sync, the list of packages is shorter: From b81308b2b52cd47da68f0ddd0bcc1dcdb6d11185 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Sat, 8 Oct 2022 08:41:17 +0100 Subject: [PATCH 66/72] Temporarily add some diagnostics to configuration rerading... --- shairport.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/shairport.c b/shairport.c index 9d1657f0..97f918f4 100644 --- a/shairport.c +++ b/shairport.c @@ -600,11 +600,13 @@ int parse_options(int argc, char **argv) { // make config.cfg point to it config.cfg = &config_file_stuff; /* Get the Service Name. */ + debug(2, "looking for the general.name"); if (config_lookup_string(config.cfg, "general.name", &str)) { raw_service_name = (char *)str; } #ifdef CONFIG_LIBDAEMON /* Get the Daemonize setting. */ + debug(2, "looking for the sessioncontrol.daemonize_with_pid_file"); config_set_lookup_bool(config.cfg, "sessioncontrol.daemonize_with_pid_file", &daemonisewith); /* Get the Just_Daemonize setting. */ @@ -625,6 +627,7 @@ int parse_options(int argc, char **argv) { config.output_name = (char *)str; /* Get the port setting. */ + debug(2, "looking for the general.port"); if (config_lookup_int(config.cfg, "general.port", &value)) { if ((value < 0) || (value > 65535)) #ifdef CONFIG_AIRPLAY_2 @@ -684,6 +687,7 @@ int parse_options(int argc, char **argv) { /* Get the soxr_delay_threshold setting. */ /* Convert between the input, given in milliseconds, and the stored values in nanoseconds. */ + debug(2, "looking for the general.soxr_delay_threshold"); if (config_lookup_int(config.cfg, "general.soxr_delay_threshold", &value)) { if ((value >= 1) && (value <= 100)) config.soxr_delay_threshold = value * 1000000; @@ -696,6 +700,7 @@ int parse_options(int argc, char **argv) { #endif /* Get the statistics setting. */ + debug(2, "looking for the general.statistics"); if (config_set_lookup_bool(config.cfg, "general.statistics", &(config.statistics_requested))) { warn("The \"general\" \"statistics\" setting is deprecated. Please use the \"diagnostics\" " @@ -724,6 +729,7 @@ int parse_options(int argc, char **argv) { if (config_lookup_float(config.cfg, "general.resync_threshold_in_seconds", &dvalue)) config.resyncthreshold = dvalue; + debug(2, "looking for the general.log_verbosity"); /* Get the verbosity setting. */ if (config_lookup_int(config.cfg, "general.log_verbosity", &value)) { warn("The \"general\" \"log_verbosity\" setting is deprecated. Please use the " @@ -736,6 +742,7 @@ int parse_options(int argc, char **argv) { value); } + debug(2, "looking for the diagnostics.log_verbosity"); /* Get the verbosity setting. */ if (config_lookup_int(config.cfg, "diagnostics.log_verbosity", &value)) { if ((value >= 0) && (value <= 3)) @@ -747,6 +754,7 @@ int parse_options(int argc, char **argv) { value); } + debug(2, "looking for the diagnostics.log_show_file_and_line"); /* Get the config.debugger_show_file_and_line in debug messages setting. */ if (config_lookup_string(config.cfg, "diagnostics.log_show_file_and_line", &str)) { if (strcasecmp(str, "no") == 0) @@ -784,6 +792,7 @@ int parse_options(int argc, char **argv) { } /* Get the statistics setting. */ + debug(2, "looking for the diagnostics.statistics"); if (config_lookup_string(config.cfg, "diagnostics.statistics", &str)) { if (strcasecmp(str, "no") == 0) config.statistics_requested = 0; @@ -858,6 +867,7 @@ int parse_options(int argc, char **argv) { config.cmd_set_volume = (char *)str; } + debug(2, "looking for the general.playback_mode"); /* Get the playback_mode setting */ if (config_lookup_string(config.cfg, "general.playback_mode", &str)) { if (strcasecmp(str, "stereo") == 0) @@ -987,12 +997,14 @@ int parse_options(int argc, char **argv) { dvalue, config.missing_port_dacp_scan_interval_seconds); } + debug(2, "looking for the latencies.default"); /* Get the default latency. Deprecated! */ if (config_lookup_int(config.cfg, "latencies.default", &value)) config.userSuppliedLatency = value; #ifdef CONFIG_METADATA /* Get the metadata setting. */ + debug(2, "looking for the metadata.enabled"); if (config_lookup_string(config.cfg, "metadata.enabled", &str)) { if (strcasecmp(str, "no") == 0) config.metadata_enabled = 0; @@ -1031,6 +1043,7 @@ int parse_options(int argc, char **argv) { #endif #ifdef CONFIG_METADATA_HUB + debug(2, "looking for the metadata.cover_art_cache_directory"); if (config_lookup_string(config.cfg, "metadata.cover_art_cache_directory", &str)) { config.cover_art_cache_dir = (char *)str; } @@ -1116,12 +1129,14 @@ int parse_options(int argc, char **argv) { str); } + debug(2, "looking for the sessioncontrol.session_timeout"); if (config_lookup_int(config.cfg, "sessioncontrol.session_timeout", &value)) { config.timeout = value; config.dont_check_timeout = 0; // this is for legacy -- only set by -t 0 } #ifdef CONFIG_CONVOLUTION + debug(2, "looking for the dsp.convolution"); if (config_lookup_string(config.cfg, "dsp.convolution", &str)) { if (strcasecmp(str, "no") == 0) config.convolution = 0; @@ -1155,6 +1170,7 @@ int parse_options(int argc, char **argv) { warn("Convolution enabled but no convolution_ir_file provided"); } #endif + debug(2, "looking for the dsp.loudness"); if (config_lookup_string(config.cfg, "dsp.loudness", &str)) { if (strcasecmp(str, "no") == 0) config.loudness = 0; @@ -1187,6 +1203,7 @@ int parse_options(int argc, char **argv) { } #if defined(CONFIG_DBUS_INTERFACE) /* Get the dbus service sbus setting. */ + debug(2, "looking for dbus"); if (config_lookup_string(config.cfg, "general.dbus_service_bus", &str)) { if (strcasecmp(str, "system") == 0) config.dbus_service_bus_type = DBT_system; @@ -1200,6 +1217,7 @@ int parse_options(int argc, char **argv) { #endif #if defined(CONFIG_MPRIS_INTERFACE) + debug(2, "looking for MPRIS"); /* Get the mpris service sbus setting. */ if (config_lookup_string(config.cfg, "general.mpris_service_bus", &str)) { if (strcasecmp(str, "system") == 0) @@ -1214,6 +1232,7 @@ int parse_options(int argc, char **argv) { #endif #ifdef CONFIG_MQTT + debug(2, "looking for MQTT"); config_set_lookup_bool(config.cfg, "mqtt.enabled", &config.mqtt_enabled); if (config.mqtt_enabled && !config.metadata_enabled) { die("You need to have metadata enabled in order to use mqtt"); @@ -1290,6 +1309,7 @@ int parse_options(int argc, char **argv) { #endif #ifdef CONFIG_AIRPLAY_2 + debug(2, "looking for AP2 device id"); long long aid; // replace the airplay_device_id with this, if provided @@ -1303,12 +1323,13 @@ int parse_options(int argc, char **argv) { } #endif + debug(2, "done"); } // now, do the command line options again, but this time do them fully -- it's a unix convention // that command line // arguments have precedence over configuration file settings. - + debug(2, "looking for command line options"); optind = argc; for (j = 0; j < argc; j++) if (strcmp(argv[j], "--") == 0) @@ -1322,6 +1343,7 @@ int parse_options(int argc, char **argv) { /* Now do options processing, get portname */ int tdebuglev = 0; while ((c = poptGetNextOpt(optCon)) >= 0) { + debug(1, "cli option: %d, 0x%x, '%c'.", c, c, c); switch (c) { case 'v': tdebuglev++; @@ -1367,6 +1389,8 @@ int parse_options(int argc, char **argv) { } poptFreeContext(optCon); + + debug(1,"done with cli options"); // here, we are finally finished reading the options @@ -1653,7 +1677,7 @@ void exit_function() { } } #endif - + debug(2, "destroy config"); if (config.cfg) config_destroy(config.cfg); if (config.appName) From 489041d2cd48b73cbeb95950d5e287e75857e7ab Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Sat, 8 Oct 2022 09:32:41 +0100 Subject: [PATCH 67/72] Even more specific config file diagnostics... --- shairport.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shairport.c b/shairport.c index 97f918f4..86bf0691 100644 --- a/shairport.c +++ b/shairport.c @@ -594,7 +594,9 @@ int parse_options(int argc, char **argv) { debug(2, "looking for configuration file at full path \"%s\"", config_file_real_path); /* Read the file. If there is an error, report it and exit. */ if (config_read_file(&config_file_stuff, config_file_real_path)) { + debug(2,"configuration file opened"); free(config_file_real_path); + debug(2,"set auto_convert!"); config_set_auto_convert(&config_file_stuff, 1); // allow autoconversion from int/float to int/float // make config.cfg point to it From 3828ec1a66827ead06586808bee25dc8638e7844 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Sat, 8 Oct 2022 16:56:50 +0100 Subject: [PATCH 68/72] Fix a malloc problem caused by the space for a UUID being one byte too small -- not enough room for the trailing NUL. --- shairport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shairport.c b/shairport.c index 86bf0691..4cb9e975 100644 --- a/shairport.c +++ b/shairport.c @@ -571,7 +571,7 @@ int parse_options(int argc, char **argv) { uuid_t binuuid; uuid_generate_random(binuuid); - char *uuid = malloc(UUID_STR_LEN); + char *uuid = malloc(UUID_STR_LEN + 1); // leave space for the NUL at the end // Produces a UUID string at uuid consisting of lower-case letters uuid_unparse_lower(binuuid, uuid); config.airplay_pi = uuid; From 234c00ad994bb8cff286fe68f3215a5b9f8f61b8 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Sat, 8 Oct 2022 17:39:41 +0100 Subject: [PATCH 69/72] Remove redundant debug messages. --- shairport.c | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/shairport.c b/shairport.c index 4cb9e975..9f3ce855 100644 --- a/shairport.c +++ b/shairport.c @@ -594,21 +594,17 @@ int parse_options(int argc, char **argv) { debug(2, "looking for configuration file at full path \"%s\"", config_file_real_path); /* Read the file. If there is an error, report it and exit. */ if (config_read_file(&config_file_stuff, config_file_real_path)) { - debug(2,"configuration file opened"); free(config_file_real_path); - debug(2,"set auto_convert!"); config_set_auto_convert(&config_file_stuff, 1); // allow autoconversion from int/float to int/float // make config.cfg point to it config.cfg = &config_file_stuff; /* Get the Service Name. */ - debug(2, "looking for the general.name"); if (config_lookup_string(config.cfg, "general.name", &str)) { raw_service_name = (char *)str; } #ifdef CONFIG_LIBDAEMON /* Get the Daemonize setting. */ - debug(2, "looking for the sessioncontrol.daemonize_with_pid_file"); config_set_lookup_bool(config.cfg, "sessioncontrol.daemonize_with_pid_file", &daemonisewith); /* Get the Just_Daemonize setting. */ @@ -629,7 +625,6 @@ int parse_options(int argc, char **argv) { config.output_name = (char *)str; /* Get the port setting. */ - debug(2, "looking for the general.port"); if (config_lookup_int(config.cfg, "general.port", &value)) { if ((value < 0) || (value > 65535)) #ifdef CONFIG_AIRPLAY_2 @@ -689,7 +684,6 @@ int parse_options(int argc, char **argv) { /* Get the soxr_delay_threshold setting. */ /* Convert between the input, given in milliseconds, and the stored values in nanoseconds. */ - debug(2, "looking for the general.soxr_delay_threshold"); if (config_lookup_int(config.cfg, "general.soxr_delay_threshold", &value)) { if ((value >= 1) && (value <= 100)) config.soxr_delay_threshold = value * 1000000; @@ -702,7 +696,6 @@ int parse_options(int argc, char **argv) { #endif /* Get the statistics setting. */ - debug(2, "looking for the general.statistics"); if (config_set_lookup_bool(config.cfg, "general.statistics", &(config.statistics_requested))) { warn("The \"general\" \"statistics\" setting is deprecated. Please use the \"diagnostics\" " @@ -731,7 +724,6 @@ int parse_options(int argc, char **argv) { if (config_lookup_float(config.cfg, "general.resync_threshold_in_seconds", &dvalue)) config.resyncthreshold = dvalue; - debug(2, "looking for the general.log_verbosity"); /* Get the verbosity setting. */ if (config_lookup_int(config.cfg, "general.log_verbosity", &value)) { warn("The \"general\" \"log_verbosity\" setting is deprecated. Please use the " @@ -744,7 +736,6 @@ int parse_options(int argc, char **argv) { value); } - debug(2, "looking for the diagnostics.log_verbosity"); /* Get the verbosity setting. */ if (config_lookup_int(config.cfg, "diagnostics.log_verbosity", &value)) { if ((value >= 0) && (value <= 3)) @@ -756,7 +747,6 @@ int parse_options(int argc, char **argv) { value); } - debug(2, "looking for the diagnostics.log_show_file_and_line"); /* Get the config.debugger_show_file_and_line in debug messages setting. */ if (config_lookup_string(config.cfg, "diagnostics.log_show_file_and_line", &str)) { if (strcasecmp(str, "no") == 0) @@ -794,7 +784,6 @@ int parse_options(int argc, char **argv) { } /* Get the statistics setting. */ - debug(2, "looking for the diagnostics.statistics"); if (config_lookup_string(config.cfg, "diagnostics.statistics", &str)) { if (strcasecmp(str, "no") == 0) config.statistics_requested = 0; @@ -869,7 +858,6 @@ int parse_options(int argc, char **argv) { config.cmd_set_volume = (char *)str; } - debug(2, "looking for the general.playback_mode"); /* Get the playback_mode setting */ if (config_lookup_string(config.cfg, "general.playback_mode", &str)) { if (strcasecmp(str, "stereo") == 0) @@ -999,14 +987,12 @@ int parse_options(int argc, char **argv) { dvalue, config.missing_port_dacp_scan_interval_seconds); } - debug(2, "looking for the latencies.default"); /* Get the default latency. Deprecated! */ if (config_lookup_int(config.cfg, "latencies.default", &value)) config.userSuppliedLatency = value; #ifdef CONFIG_METADATA /* Get the metadata setting. */ - debug(2, "looking for the metadata.enabled"); if (config_lookup_string(config.cfg, "metadata.enabled", &str)) { if (strcasecmp(str, "no") == 0) config.metadata_enabled = 0; @@ -1045,7 +1031,6 @@ int parse_options(int argc, char **argv) { #endif #ifdef CONFIG_METADATA_HUB - debug(2, "looking for the metadata.cover_art_cache_directory"); if (config_lookup_string(config.cfg, "metadata.cover_art_cache_directory", &str)) { config.cover_art_cache_dir = (char *)str; } @@ -1131,14 +1116,12 @@ int parse_options(int argc, char **argv) { str); } - debug(2, "looking for the sessioncontrol.session_timeout"); if (config_lookup_int(config.cfg, "sessioncontrol.session_timeout", &value)) { config.timeout = value; config.dont_check_timeout = 0; // this is for legacy -- only set by -t 0 } #ifdef CONFIG_CONVOLUTION - debug(2, "looking for the dsp.convolution"); if (config_lookup_string(config.cfg, "dsp.convolution", &str)) { if (strcasecmp(str, "no") == 0) config.convolution = 0; @@ -1172,7 +1155,6 @@ int parse_options(int argc, char **argv) { warn("Convolution enabled but no convolution_ir_file provided"); } #endif - debug(2, "looking for the dsp.loudness"); if (config_lookup_string(config.cfg, "dsp.loudness", &str)) { if (strcasecmp(str, "no") == 0) config.loudness = 0; @@ -1205,7 +1187,6 @@ int parse_options(int argc, char **argv) { } #if defined(CONFIG_DBUS_INTERFACE) /* Get the dbus service sbus setting. */ - debug(2, "looking for dbus"); if (config_lookup_string(config.cfg, "general.dbus_service_bus", &str)) { if (strcasecmp(str, "system") == 0) config.dbus_service_bus_type = DBT_system; @@ -1219,7 +1200,6 @@ int parse_options(int argc, char **argv) { #endif #if defined(CONFIG_MPRIS_INTERFACE) - debug(2, "looking for MPRIS"); /* Get the mpris service sbus setting. */ if (config_lookup_string(config.cfg, "general.mpris_service_bus", &str)) { if (strcasecmp(str, "system") == 0) @@ -1234,7 +1214,6 @@ int parse_options(int argc, char **argv) { #endif #ifdef CONFIG_MQTT - debug(2, "looking for MQTT"); config_set_lookup_bool(config.cfg, "mqtt.enabled", &config.mqtt_enabled); if (config.mqtt_enabled && !config.metadata_enabled) { die("You need to have metadata enabled in order to use mqtt"); @@ -1311,7 +1290,6 @@ int parse_options(int argc, char **argv) { #endif #ifdef CONFIG_AIRPLAY_2 - debug(2, "looking for AP2 device id"); long long aid; // replace the airplay_device_id with this, if provided @@ -1325,13 +1303,11 @@ int parse_options(int argc, char **argv) { } #endif - debug(2, "done"); } // now, do the command line options again, but this time do them fully -- it's a unix convention // that command line // arguments have precedence over configuration file settings. - debug(2, "looking for command line options"); optind = argc; for (j = 0; j < argc; j++) if (strcmp(argv[j], "--") == 0) @@ -1345,7 +1321,6 @@ int parse_options(int argc, char **argv) { /* Now do options processing, get portname */ int tdebuglev = 0; while ((c = poptGetNextOpt(optCon)) >= 0) { - debug(1, "cli option: %d, 0x%x, '%c'.", c, c, c); switch (c) { case 'v': tdebuglev++; @@ -1391,8 +1366,6 @@ int parse_options(int argc, char **argv) { } poptFreeContext(optCon); - - debug(1,"done with cli options"); // here, we are finally finished reading the options @@ -1679,7 +1652,6 @@ void exit_function() { } } #endif - debug(2, "destroy config"); if (config.cfg) config_destroy(config.cfg); if (config.appName) From 670420eb0ff3a83e79238615bc2298b33075b688 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Sat, 8 Oct 2022 17:47:10 +0100 Subject: [PATCH 70/72] Update RELEASENOTES-DEVELOPMENT.md --- RELEASENOTES-DEVELOPMENT.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RELEASENOTES-DEVELOPMENT.md b/RELEASENOTES-DEVELOPMENT.md index 7da49376..bb6aa59d 100644 --- a/RELEASENOTES-DEVELOPMENT.md +++ b/RELEASENOTES-DEVELOPMENT.md @@ -1,3 +1,8 @@ +Version 4.1-dev-694-g234c00ad +==== +**Bug Fix** +* Fixed a memory allocation (`malloc`) bug caused by allocating on byte too few for a character string -- yep, the trailing `NUL`. Special thanks to [ageorgios](https://github.com/ageorgios) for their help in locating and fixing the bug! Thanks also to [MTxx87](https://github.com/MTxx87) and [Mike](https://github.com/xska2) for reporting what seems to be the same bug. + Version 4.1-dev-688-g7dcad083 ==== **Bug Fixes** From d54f6fe04576b96fd2915d3f357b34f9662a6dc5 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Sun, 9 Oct 2022 08:29:57 +0100 Subject: [PATCH 71/72] Update TROUBLESHOOTING.md --- TROUBLESHOOTING.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md index d6436fdf..b9a64138 100644 --- a/TROUBLESHOOTING.md +++ b/TROUBLESHOOTING.md @@ -116,6 +116,16 @@ You have installed Shairport Sync successfully, the daemon is running, you can s You have to allow connections to your Shairport Sync device from remote devices. To do so, after re-enabling UFW (see last step of the previous section), enter the following commands in shell: +**Classic AirPlay:** +``` +sudo ufw allow 3689/tcp +sudo ufw allow 5353 +sudo ufw allow 5000/tcp +sudo ufw allow 6000:6009/udp +sudo ufw allow 32768:60999/udp +``` + +**AirPlay 2:** ``` sudo ufw allow 319:320/udp sudo ufw allow 3689/tcp @@ -123,9 +133,11 @@ sudo ufw allow 5353 sudo ufw allow 5000/tcp sudo ufw allow 7000/tcp sudo ufw allow 6000:6009/udp -sudo ufw allow 35000:65535/udp +sudo ufw allow 32768:60999/udp +sudo ufw allow 32768:60999/tcp ``` -Ports 319 and 320 need to be opened for AirPlay 2 only. + +The range `32768:60999` represents the [ephemeral port range](https://en.m.wikipedia.org/wiki/Ephemeral_port) which seems to be standardised on those values. You can check UFW config by typing `sudo ufw status` in shell. Please make sure that UFW is active, especially if you have deactivated it previously for testing purposes. Check out the [ufw man pages](http://manpages.ubuntu.com/manpages/man8/ufw.8.html) for more. From b28ee3f179ccb2f4001a897d85258e2d73eb19eb Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Sun, 9 Oct 2022 08:30:44 +0100 Subject: [PATCH 72/72] Update TROUBLESHOOTING.md --- TROUBLESHOOTING.md | 1 - 1 file changed, 1 deletion(-) diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md index b9a64138..2bccf048 100644 --- a/TROUBLESHOOTING.md +++ b/TROUBLESHOOTING.md @@ -122,7 +122,6 @@ sudo ufw allow 3689/tcp sudo ufw allow 5353 sudo ufw allow 5000/tcp sudo ufw allow 6000:6009/udp -sudo ufw allow 32768:60999/udp ``` **AirPlay 2:**