mirror of
https://github.com/patchzyy/wiicompiled
synced 2026-10-05 17:03:41 -04:00
279ce8328f
* 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>
110 lines
4.2 KiB
C++
110 lines
4.2 KiB
C++
#include "external_audio_macos.h"
|
|
|
|
#include <CoreAudio/CoreAudio.h>
|
|
#include <unistd.h>
|
|
#include <cstring>
|
|
#include <iostream>
|
|
#include <stdexcept>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
struct Process {
|
|
pid_t pid;
|
|
UInt32 output;
|
|
bool disappeared = false;
|
|
};
|
|
std::vector<Process> processes;
|
|
bool supported = true;
|
|
bool queryFailed = false;
|
|
int sizeRaces = 0;
|
|
|
|
void Require(bool condition, const char* message) {
|
|
if (!condition) throw std::runtime_error(message);
|
|
}
|
|
|
|
void Expect(bool available, bool playing, const char* message) {
|
|
const auto status = MusicAttenuation::QueryMacOSExternalAudio();
|
|
Require(status.available == available && status.playing == playing, message);
|
|
}
|
|
} // namespace
|
|
|
|
// Fake only the Core Audio boundary so the production enumeration and process
|
|
// filtering run unchanged, without depending on other apps on the test machine.
|
|
// Use the public selector ABI values so these mocks also build with older SDKs.
|
|
extern "C" Boolean AudioObjectHasProperty(AudioObjectID object,
|
|
const AudioObjectPropertyAddress* address) {
|
|
Require(object == kAudioObjectSystemObject &&
|
|
address->mSelector == 'prs#',
|
|
"Must query the system process list");
|
|
return supported;
|
|
}
|
|
|
|
extern "C" OSStatus AudioObjectGetPropertyDataSize(
|
|
AudioObjectID, const AudioObjectPropertyAddress*, UInt32, const void*, UInt32* size) {
|
|
if (queryFailed) return kAudioHardwareUnspecifiedError;
|
|
*size = static_cast<UInt32>(processes.size() * sizeof(AudioObjectID));
|
|
return noErr;
|
|
}
|
|
|
|
extern "C" OSStatus AudioObjectGetPropertyData(
|
|
AudioObjectID object, const AudioObjectPropertyAddress* address, UInt32,
|
|
const void*, UInt32* size, void* data) {
|
|
Require(address->mScope == kAudioObjectPropertyScopeGlobal, "Must use global scope");
|
|
if (object == kAudioObjectSystemObject) {
|
|
if (sizeRaces > 0) {
|
|
--sizeRaces;
|
|
return kAudioHardwareBadPropertySizeError;
|
|
}
|
|
for (size_t i = 0; i < processes.size(); ++i) {
|
|
static_cast<AudioObjectID*>(data)[i] = static_cast<AudioObjectID>(i + 100);
|
|
}
|
|
*size = static_cast<UInt32>(processes.size() * sizeof(AudioObjectID));
|
|
return noErr;
|
|
}
|
|
const auto& process = processes.at(object - 100);
|
|
if (process.disappeared) return kAudioHardwareBadObjectError;
|
|
if (address->mSelector == 'ppid') {
|
|
std::memcpy(data, &process.pid, sizeof(process.pid));
|
|
*size = sizeof(process.pid);
|
|
} else {
|
|
Require(address->mSelector == 'piro',
|
|
"Input-only activity must not count as playback");
|
|
Require(process.pid != getpid(), "Must exclude the game's own output");
|
|
std::memcpy(data, &process.output, sizeof(process.output));
|
|
*size = sizeof(process.output);
|
|
}
|
|
return noErr;
|
|
}
|
|
|
|
int main() {
|
|
supported = false;
|
|
Expect(false, false, "Older macOS must report unavailable");
|
|
supported = true;
|
|
Expect(true, false, "An empty process list is available but inactive");
|
|
processes = {{getpid(), 1}};
|
|
Expect(true, false, "Game audio alone must not trigger muting");
|
|
processes.push_back({getpid() + 1, 0});
|
|
Expect(true, false, "An idle or input-only app must not trigger muting");
|
|
processes.back().output = 1;
|
|
Expect(true, true, "External playback must trigger muting");
|
|
processes.back().output = 0;
|
|
Expect(true, false, "Stopping playback must restore music");
|
|
processes.back().output = 1;
|
|
processes.back().disappeared = true;
|
|
Expect(true, false, "Exiting apps must not leave music muted");
|
|
processes.push_back({getpid() + 2, 1});
|
|
Expect(true, true, "A disappearing app must not hide another active player");
|
|
sizeRaces = 1;
|
|
Expect(true, true, "A growing process list must be retried");
|
|
sizeRaces = 3;
|
|
Expect(false, false, "List retries must be bounded");
|
|
Expect(true, true, "Later polls must recover from list races");
|
|
queryFailed = true;
|
|
Expect(false, false, "Query failure must clear playing state");
|
|
queryFailed = false;
|
|
Expect(true, true, "Monitoring must recover from query failure");
|
|
processes = {{0, 1}};
|
|
Expect(true, false, "Unknown PIDs must not count as external playback");
|
|
std::cout << "macOS external audio tests passed\n";
|
|
}
|