Skip to content

Commit c4c5f82

Browse files
authored
Merge pull request #66 from Sendspin/chrisuthe/task/replace-portaudio-with-a-native-coreaudio-sink-on
Add a native CoreAudio sink and drop PortAudio from the macOS build
2 parents 4b034d4 + 1f532be commit c4c5f82

18 files changed

Lines changed: 1849 additions & 32 deletions

.github/workflows/build-armv6.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ jobs:
8484
-DCMAKE_BUILD_TYPE=Release
8585
-DSENDSPIN_CLI_WERROR=ON
8686
-DSENDSPIN_CLI_WITH_MDNS=ON
87+
-DSENDSPIN_CLI_WITH_PORTAUDIO=ON
8788
-DSENDSPIN_CLI_WITH_PULSE=ON
8889
-DSENDSPIN_CLI_WITH_PIPEWIRE=ON
8990
-DFETCHCONTENT_BASE_DIR="$DEPS_DIR"

.github/workflows/build.yml

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ jobs:
3434
runner: ubuntu-24.04
3535
arm32: ''
3636
with_mdns: 'ON'
37+
with_portaudio: 'ON'
3738
with_pulse: 'ON'
3839
with_pipewire: 'ON'
3940
expect_probe: 'Failed'
@@ -48,6 +49,7 @@ jobs:
4849
runner: ubuntu-24.04-arm
4950
arm32: ''
5051
with_mdns: 'ON'
52+
with_portaudio: 'ON'
5153
with_pulse: 'ON'
5254
with_pipewire: 'ON'
5355
expect_probe: 'Failed'
@@ -63,6 +65,7 @@ jobs:
6365
runner: ubuntu-24.04
6466
arm32: 'armv7'
6567
with_mdns: 'ON'
68+
with_portaudio: 'ON'
6669
with_pulse: 'ON'
6770
with_pipewire: 'ON'
6871
expect_probe: 'Failed'
@@ -78,12 +81,13 @@ jobs:
7881
runner: macos-14
7982
arm32: ''
8083
with_mdns: 'ON'
84+
with_portaudio: 'OFF'
8185
with_pulse: 'OFF'
8286
with_pipewire: 'OFF'
8387
expect_probe: 'Success'
84-
expect_backends: '^-- sendspin-cli audio backends: null, stdout, portaudio$'
88+
expect_backends: '^-- sendspin-cli audio backends: null, stdout, coreaudio$'
8589
expect_mdns: '^-- sendspin-cli mDNS: dns_sd \(Bonjour, built in\)$'
86-
runtime_packages: 'portaudio (brew). Bonjour is part of macOS.'
90+
runtime_packages: 'none. CoreAudio, AudioToolbox and Bonjour are all part of macOS.'
8791
publish: true
8892
avahi: false
8993
systemd: false
@@ -93,6 +97,7 @@ jobs:
9397
runner: ubuntu-24.04
9498
arm32: ''
9599
with_mdns: 'OFF'
100+
with_portaudio: 'ON'
96101
with_pulse: 'OFF'
97102
with_pipewire: 'OFF'
98103
expect_backends: '^-- sendspin-cli audio backends: null, stdout, alsa, portaudio$'
@@ -200,10 +205,6 @@ jobs:
200205
echo 'A 32-bit ARM binary runs on this host.'
201206
rm -f binfmt-probe binfmt-probe.c
202207
203-
- name: Install build dependencies (macOS)
204-
if: runner.os == 'macOS'
205-
run: brew install portaudio pkgconf
206-
207208
# Fetched sources and subbuild stamps only, never build outputs; keyed per leg and by CMakeLists.txt.
208209
- name: Cache the fetched sources
209210
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
@@ -216,6 +217,7 @@ jobs:
216217
- name: Configure
217218
env:
218219
WITH_MDNS: ${{ matrix.with_mdns }}
220+
WITH_PORTAUDIO: ${{ matrix.with_portaudio }}
219221
WITH_PULSE: ${{ matrix.with_pulse }}
220222
WITH_PIPEWIRE: ${{ matrix.with_pipewire }}
221223
DEPS_DIR: ${{ github.workspace }}/.deps
@@ -226,6 +228,7 @@ jobs:
226228
-DCMAKE_BUILD_TYPE=Release
227229
-DSENDSPIN_CLI_WERROR=ON
228230
-DSENDSPIN_CLI_WITH_MDNS="$WITH_MDNS"
231+
-DSENDSPIN_CLI_WITH_PORTAUDIO="$WITH_PORTAUDIO"
229232
-DSENDSPIN_CLI_WITH_PULSE="$WITH_PULSE"
230233
-DSENDSPIN_CLI_WITH_PIPEWIRE="$WITH_PIPEWIRE"
231234
-DFETCHCONTENT_BASE_DIR="$DEPS_DIR"
@@ -552,6 +555,35 @@ jobs:
552555
exit 1
553556
}
554557
558+
# What would have caught the dyld abort: a Homebrew load command is a dependency no clean
559+
# Mac has, and CI never sees it because the runner installed it.
560+
- name: Assert the macOS binary loads nothing that is not part of macOS
561+
if: matrix.publish && runner.os == 'macOS'
562+
env:
563+
NAME: ${{ steps.package.outputs.name }}
564+
run: |
565+
binary="stage/$NAME/usr/local/bin/sendspin-cli"
566+
echo 'What the staged binary loads:'
567+
otool -L "$binary"
568+
569+
# Each dependency is a tab-indented line whose first field is the install name; the
570+
# header line naming the binary itself is not indented.
571+
otool -L "$binary" | sed -n 's|^\t\([^ ]*\).*|\1|p' >load-commands.txt
572+
573+
status=0
574+
while read -r path; do
575+
case "$path" in
576+
/usr/lib/*|/System/Library/Frameworks/*|/System/Library/PrivateFrameworks/*) ;;
577+
*)
578+
echo "::error::the binary loads $path, which is not part of macOS -- a Mac without it aborts at launch"
579+
status=1
580+
;;
581+
esac
582+
done <load-commands.txt
583+
584+
rm -f load-commands.txt
585+
exit "$status"
586+
555587
# Install at the real prefix and verify the unit (not on cross legs: MemoryDenyWriteExecute= forbids qemu-user).
556588
# After Package, or a root-owned install manifest in build/ breaks the unprivileged staging install.
557589
- name: Install at the real prefix and verify the systemd unit

CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ FetchContent_MakeAvailable(sendspin)
5656
# Each backend is auto-detected; OFF forces it out.
5757
option(SENDSPIN_CLI_WITH_ALSA "Build the ALSA output backend if libasound is available" ON)
5858

59+
# macOS only; the frameworks it needs are part of the system, so there is nothing to install.
60+
option(SENDSPIN_CLI_WITH_COREAUDIO "Build the CoreAudio output backend on macOS" ON)
61+
5962
option(SENDSPIN_CLI_WITH_PORTAUDIO
6063
"Build the PortAudio output backend if libportaudio is available" ON)
6164

@@ -67,6 +70,7 @@ option(SENDSPIN_CLI_WITH_PIPEWIRE
6770

6871
set(SENDSPIN_CLI_BACKENDS null stdout)
6972
set(SENDSPIN_CLI_ALSA_ENABLED OFF)
73+
set(SENDSPIN_CLI_COREAUDIO_ENABLED OFF)
7074
set(SENDSPIN_CLI_PORTAUDIO_ENABLED OFF)
7175
set(SENDSPIN_CLI_PULSE_ENABLED OFF)
7276
set(SENDSPIN_CLI_PIPEWIRE_ENABLED OFF)
@@ -86,6 +90,12 @@ if(SENDSPIN_CLI_WITH_ALSA)
8690
endif()
8791
endif()
8892

93+
if(SENDSPIN_CLI_WITH_COREAUDIO AND APPLE)
94+
# CoreAudio and AudioToolbox ship with macOS, so there is nothing to find.
95+
set(SENDSPIN_CLI_COREAUDIO_ENABLED ON)
96+
list(APPEND SENDSPIN_CLI_BACKENDS coreaudio)
97+
endif()
98+
8999
if(SENDSPIN_CLI_WITH_PORTAUDIO)
90100
# No CMake module; IMPORTED_TARGET carries macOS framework links through.
91101
find_package(PkgConfig QUIET)
@@ -277,6 +287,13 @@ if(SENDSPIN_CLI_ALSA_ENABLED)
277287
target_compile_definitions(sendspin-cli-core PUBLIC SENDSPIN_CLI_HAVE_ALSA)
278288
endif()
279289

290+
if(SENDSPIN_CLI_COREAUDIO_ENABLED)
291+
target_sources(sendspin-cli-core PRIVATE src/coreaudio_sink.cpp)
292+
target_link_libraries(sendspin-cli-core PUBLIC
293+
"-framework CoreAudio" "-framework AudioToolbox" "-framework CoreFoundation")
294+
target_compile_definitions(sendspin-cli-core PUBLIC SENDSPIN_CLI_HAVE_COREAUDIO)
295+
endif()
296+
280297
if(SENDSPIN_CLI_PORTAUDIO_ENABLED)
281298
target_sources(sendspin-cli-core PRIVATE src/portaudio_sink.cpp)
282299
target_link_libraries(sendspin-cli-core PUBLIC PkgConfig::PORTAUDIO)

0 commit comments

Comments
 (0)