Files
wiicompiled/runtime/src/external_audio_macos.cpp
T
theofficialgman 279ce8328f Macos support into main (#228)
* macos: add x86_64 Intel support

* (feat) Apple Silicon macOS CI building and Setup.pkg documentation (#118)

* docs(macos): document Setup.pkg installation

Add Apple Silicon macOS CI coverage for runtime configuration, substrate tests, and Setup.pkg packaging alongside the macOS installation instructions.

* macos: pin Apple Silicon deployment target

* fix(macos): restore Retro Rewind local builds

* macos: package universal setup tools

* ci: build macOS input expression tests

* runtime: Do not force 14.0 minimum anymore

new minimum is 12.0

* macos: support older libc++ algorithms

* macos: allow undefined MTLLogStateDescriptor for older SDKs

* tests: deflake input expression timing window test

* build: Fix mac tests

* translator: emit null statement after continuation labels for C++17 compatibility

* feat(macos): add MetalFX spatial upscaling

* Fix automatic music muting on macOS

Co-Authored-By: Michael G <10155689+DarthMDev@users.noreply.github.com>
Co-Authored-By: Daan Vervacke <23398694+DaanVervacke@users.noreply.github.com>

* Address CodeRabbit review comments and integrate upstream TLS cmake

* Remove version requirement for running package CI

Co-Authored-By: Michael G <10155689+DarthMDev@users.noreply.github.com>

* publish-app: fix dependency discovery from build dir, handle spaces in paths, and fail on missing deps

* publish-app: preserve subdirectory suffix during @rpath dependency lookup

* cmake: synchronize CMAKE_SYSTEM_PROCESSOR with CMAKE_OSX_ARCHITECTURES on macOS

* fix rpaths

---------

Co-authored-by: DarthM <mgracer48@yahoo.com>
Co-authored-by: Michael G <10155689+DarthMDev@users.noreply.github.com>
Co-authored-by: Daan Vervacke <23398694+DaanVervacke@users.noreply.github.com>
Co-authored-by: patchzyy <64382339+patchzyy@users.noreply.github.com>
2026-10-03 11:07:15 +02:00

88 lines
3.4 KiB
C++

#if defined(__APPLE__)
#include "external_audio_macos.h"
#include <CoreAudio/CoreAudio.h>
#include <unistd.h>
#include <vector>
namespace MusicAttenuation {
namespace {
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 140200
constexpr auto kProcessObjectList = kAudioHardwarePropertyProcessObjectList;
constexpr auto kProcessPid = kAudioProcessPropertyPID;
constexpr auto kProcessRunningOutput = kAudioProcessPropertyIsRunningOutput;
#else
// Public Core Audio selector ABI values, for SDKs predating process objects.
// The runtime HasProperty check still determines whether the OS supports them.
constexpr AudioObjectPropertySelector kProcessObjectList = 'prs#';
constexpr AudioObjectPropertySelector kProcessPid = 'ppid';
constexpr AudioObjectPropertySelector kProcessRunningOutput = 'piro';
#endif
template <typename T>
bool ReadAudioProcessProperty(AudioObjectID object, AudioObjectPropertySelector selector,
T& value) noexcept {
const AudioObjectPropertyAddress address{
selector, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain};
UInt32 size = sizeof(value);
return AudioObjectGetPropertyData(object, &address, 0, nullptr, &size, &value) == noErr &&
size == sizeof(value);
}
} // namespace
MacOSAudioStatus QueryMacOSExternalAudio() noexcept {
const AudioObjectPropertyAddress address{
kProcessObjectList,
kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain};
// Probe the property instead of raising the game's minimum macOS version.
if (!AudioObjectHasProperty(kAudioObjectSystemObject, &address)) {
return {};
}
// Processes may start between the size and data queries. Retry a changed
// list a bounded number of times; subsequent monitor polls also retry.
for (int attempt = 0; attempt < 3; ++attempt) {
UInt32 size = 0;
if (AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &address,
0, nullptr, &size) != noErr ||
size % sizeof(AudioObjectID) != 0) {
return {};
}
if (size == 0) {
return {true, false};
}
std::vector<AudioObjectID> processes(size / sizeof(AudioObjectID));
const auto result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &address,
0, nullptr, &size, processes.data());
if (result == kAudioHardwareBadPropertySizeError) {
continue;
}
if (result != noErr || size % sizeof(AudioObjectID) != 0 ||
size / sizeof(AudioObjectID) > processes.size()) {
return {};
}
const pid_t ownPid = getpid();
for (size_t index = 0; index < size / sizeof(AudioObjectID); ++index) {
pid_t pid = 0;
UInt32 runningOutput = 0;
// An exiting process may disappear mid-query. Never count an
// unknown PID or our own SDL output as external playback.
if (ReadAudioProcessProperty(processes[index], kProcessPid, pid) &&
pid > 0 && pid != ownPid &&
ReadAudioProcessProperty(processes[index], kProcessRunningOutput,
runningOutput) && runningOutput != 0) {
return {true, true};
}
}
return {true, false};
}
return {};
}
} // namespace MusicAttenuation
#endif