Linux audio plays: cpal 0.17.3 fixes ALSA's stalled callback (#1785)
On some Linux setups the game was silent. The device opened, but its data callback ran once and stopped, with no error. The music position never moved. This is cpal 0.17.1's ALSA bug (RustAudio/cpal#1099, "Data callback called only once on ALSA"), fixed in 0.17.3 by setting playback's `avail_min` to one period. benilla's stream starts only at the start threshold, which is exactly that case. cpal goes to 0.17.3. alsa 0.11 and bevy_audio's unbuilt cpal 0.15 cannot share a lock (`links = "alsa"`). A lock-only stand-in for alsa 0.9 settles that, documented in `third_party/alsa-0.9`. The realtime-fallback log line now says what happens on each platform. Following the default device gets its `Deviation:` line: 1.12.1 initialises sound once (`0x7a4330`). Built on macOS, with Linux and Windows linted. Fixes #820 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit d93c231d8ebb27934791b726a0575f4c9b709446) # Conflicts: # Cargo.toml # crates/benilla-app/examples/extended_launcher.rs # docs/DEVIATIONS.md Absorbed into the octo fork. Cargo.toml unions both patch entries (our mlua-sys traceback patch and upstream's alsa 0.9 lock-only stand-in). Cargo.lock is regenerated locally rather than taken from upstream, with cargo update -p cpal@0.17.1 --precise 0.17.3: cargo reaches the same resolution (alsa 0.9.1 from the stand-in, alsa 0.11 + alsa-sys 0.4 for the built cpal, windows-* dropped), so it is our own lock, resolved here. examples/extended_launcher.rs is upstream-only and stays absent. cargo check -p benilla-app clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
co-authored by
Claude Opus 5
parent
e0895013ed
commit
f83533b2a6
Generated
+36
-112
@@ -112,20 +112,12 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||
[[package]]
|
||||
name = "alsa"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43"
|
||||
dependencies = [
|
||||
"alsa-sys",
|
||||
"bitflags 2.11.1",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alsa"
|
||||
version = "0.10.0"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c88dbbce13b232b26250e1e2e6ac18b6a891a646b8148285036ebce260ac5c3"
|
||||
checksum = "812947049edcd670a82cd5c73c3661d2e58468577ba8489de58e1a73c04cbd5d"
|
||||
dependencies = [
|
||||
"alsa-sys",
|
||||
"bitflags 2.11.1",
|
||||
@@ -135,9 +127,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alsa-sys"
|
||||
version = "0.3.1"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527"
|
||||
checksum = "ad7569085a265dd3f607ebecce7458eaab2132a84393534c95b18dcbc3f31e04"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"pkg-config",
|
||||
@@ -521,7 +513,7 @@ dependencies = [
|
||||
"bytemuck",
|
||||
"coreaudio-rs 0.13.0",
|
||||
"cosmic-text",
|
||||
"cpal 0.17.1",
|
||||
"cpal 0.17.3",
|
||||
"crossbeam-channel",
|
||||
"fontdb",
|
||||
"half",
|
||||
@@ -2624,6 +2616,20 @@ dependencies = [
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "coreaudio-rs"
|
||||
version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d5d7dca3ebcf65a035582c9ad4385371a9d9ee6537474d2a278f4e1e475bb58"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"libc",
|
||||
"objc2-audio-toolbox",
|
||||
"objc2-core-audio",
|
||||
"objc2-core-audio-types",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "coreaudio-sys"
|
||||
version = "0.2.17"
|
||||
@@ -2682,12 +2688,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cpal"
|
||||
version = "0.17.1"
|
||||
version = "0.17.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b1f9c7312f19fc2fa12fd7acaf38de54e8320ba10d1a02dcbe21038def51ccb"
|
||||
checksum = "d8942da362c0f0d895d7cac616263f2f9424edc5687364dfd1d25ef7eba506d7"
|
||||
dependencies = [
|
||||
"alsa 0.10.0",
|
||||
"coreaudio-rs 0.13.0",
|
||||
"alsa 0.11.0",
|
||||
"coreaudio-rs 0.14.2",
|
||||
"dasp_sample",
|
||||
"jni 0.21.1",
|
||||
"js-sys",
|
||||
@@ -2707,7 +2713,7 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"windows 0.62.2",
|
||||
"windows 0.61.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3110,7 +3116,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3368,8 +3374,8 @@ dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"rustversion",
|
||||
"windows-link 0.2.1",
|
||||
"windows-result 0.4.1",
|
||||
"windows-link 0.1.3",
|
||||
"windows-result 0.3.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3461,7 +3467,7 @@ dependencies = [
|
||||
"vec_map",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
"windows 0.62.2",
|
||||
"windows 0.54.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3968,7 +3974,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4567,7 +4573,7 @@ version = "0.50.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5806,7 +5812,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.12.1",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7441,7 +7447,7 @@ version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7476,23 +7482,11 @@ version = "0.61.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
|
||||
dependencies = [
|
||||
"windows-collections 0.2.0",
|
||||
"windows-collections",
|
||||
"windows-core 0.61.2",
|
||||
"windows-future 0.2.1",
|
||||
"windows-future",
|
||||
"windows-link 0.1.3",
|
||||
"windows-numerics 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
|
||||
dependencies = [
|
||||
"windows-collections 0.3.2",
|
||||
"windows-core 0.62.2",
|
||||
"windows-future 0.3.2",
|
||||
"windows-numerics 0.3.1",
|
||||
"windows-numerics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7504,15 +7498,6 @@ dependencies = [
|
||||
"windows-core 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.54.0"
|
||||
@@ -7549,19 +7534,6 @@ dependencies = [
|
||||
"windows-strings 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement 0.60.2",
|
||||
"windows-interface 0.59.3",
|
||||
"windows-link 0.2.1",
|
||||
"windows-result 0.4.1",
|
||||
"windows-strings 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.2.1"
|
||||
@@ -7570,18 +7542,7 @@ checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
|
||||
dependencies = [
|
||||
"windows-core 0.61.2",
|
||||
"windows-link 0.1.3",
|
||||
"windows-threading 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
"windows-link 0.2.1",
|
||||
"windows-threading 0.2.1",
|
||||
"windows-threading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7650,16 +7611,6 @@ dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.1.2"
|
||||
@@ -7687,15 +7638,6 @@ dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.1.0"
|
||||
@@ -7715,15 +7657,6 @@ dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
@@ -7800,15 +7733,6 @@ dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.2"
|
||||
|
||||
@@ -48,6 +48,9 @@ kira = { path = "third_party/kira" }
|
||||
# cost ~7 ms a raise — invisibly, for the raises an addon wraps in `pcall`: five a frame measured
|
||||
# 44.7 ms of VM tick with an empty error log (`third_party/mlua-sys/BENILLA.md`).
|
||||
mlua-sys = { path = "third_party/mlua-sys" }
|
||||
# A lock-only stand-in: bevy_audio's unbuilt cpal 0.15 would otherwise hold `alsa-sys` 0.3 against
|
||||
# cpal 0.17's 0.4, and a lock holds one `links = "alsa"` (`third_party/alsa-0.9/BENILLA.md`).
|
||||
alsa = { path = "third_party/alsa-0.9" }
|
||||
|
||||
# Dependencies at opt-level 3 in dev: at opt-level 0, avian/parry collision drops a run to <1 fps.
|
||||
# Line tables only, and never packed into the binary, for the reason under `[profile.dev]` below.
|
||||
|
||||
@@ -332,6 +332,13 @@ pub(super) struct Notices {
|
||||
/// The device watch: a thread that re-reads the host's default output every [`WATCH_EVERY`] and
|
||||
/// raises a notice when it changes. One-shot: the backend answers a notice by rebuilding the
|
||||
/// stream, which arms a fresh watch.
|
||||
///
|
||||
/// Deviation: a change of the default output device is followed (here and in `coreaudio.rs`), where
|
||||
/// 1.12.1 initialises its sound device once and never again (`Sound::Initialize` `0x7a4330`
|
||||
/// refuses a second call; the driver-enumeration functions `0x7a6320`-`0x7a6380` have no caller),
|
||||
/// because a headset plugged in mid-session should play at once. On ALSA the watch sees only the
|
||||
/// "default" PCM, whose id never changes, so on Linux it is the sound server (PipeWire or Pulse)
|
||||
/// that moves the stream.
|
||||
pub(super) struct Listeners {
|
||||
stop: Arc<AtomicBool>,
|
||||
thread: Option<std::thread::JoinHandle<()>>,
|
||||
|
||||
@@ -650,8 +650,8 @@ fn render_loop(
|
||||
period_ns: u64,
|
||||
) {
|
||||
// Held for the thread's life: on Windows its drop hands the MMCSS registration back.
|
||||
// `WOW_AUDIO_NO_RT=1` skips realtime for the user-interactive QoS fallback, an A/B lever for
|
||||
// the render thread preempting the compute pools.
|
||||
// `WOW_AUDIO_NO_RT=1` skips realtime for the fallback (user-interactive QoS on macOS), an A/B
|
||||
// lever for the render thread preempting the compute pools.
|
||||
let no_rt = std::env::var_os("WOW_AUDIO_NO_RT").is_some();
|
||||
let realtime = if no_rt {
|
||||
Err(anyhow::anyhow!("WOW_AUDIO_NO_RT=1"))
|
||||
@@ -667,7 +667,13 @@ fn render_loop(
|
||||
Some(realtime)
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("audio: render thread could not go realtime ({e}); using user-interactive QoS");
|
||||
// `promote_current_thread` is a no-op off macOS, so the thread keeps its normal priority.
|
||||
let fallback = if cfg!(target_os = "macos") {
|
||||
"user-interactive QoS"
|
||||
} else {
|
||||
"normal thread priority"
|
||||
};
|
||||
warn!("audio: render thread could not go realtime ({e}); using {fallback}");
|
||||
benilla_world::thread_qos::promote_current_thread(
|
||||
benilla_world::thread_qos::QosClass::UserInteractive,
|
||||
);
|
||||
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
# A lock-only stand-in for `alsa` 0.9.1
|
||||
|
||||
Written by benilla, MIT OR Apache-2.0; it contains no upstream code. Wired in through
|
||||
`[patch.crates-io]` in the workspace root.
|
||||
|
||||
Why: `alsa-sys` declares `links = "alsa"`, and a lockfile may hold one version of it. `cpal` 0.17.3,
|
||||
our audio device layer off macOS, takes `alsa` 0.11 and so `alsa-sys` 0.4. `bevy_internal` lists
|
||||
`bevy_audio` as a weak optional dependency (`bevy_audio?/android_shared_stdcxx`), which puts
|
||||
`bevy_audio`, its `cpal` 0.15.3 and so `alsa` 0.9.1 and `alsa-sys` 0.3 into the lock although the
|
||||
workspace never enables bevy's audio (`Cargo.toml`, `bevy`). The two `links` collide and the
|
||||
resolver refuses. This package satisfies `cpal` 0.15.3's `alsa = "0.9"` with no dependency on
|
||||
`alsa-sys`.
|
||||
|
||||
It is never compiled: `cargo tree --target all` holds no `cpal` 0.15. If bevy's audio were enabled,
|
||||
the build would stop at the `compile_error!` in `src/lib.rs`, which says why.
|
||||
|
||||
Drop it when the lock holds no `bevy_audio` (a bevy that no longer lists it) or when bevy's
|
||||
`cpal` takes `alsa` 0.11.
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "alsa"
|
||||
version = "0.9.1"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
description = "Lock-only stand-in for alsa 0.9.1; see BENILLA.md"
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
compile_error!(
|
||||
"third_party/alsa-0.9 is a lock-only stand-in: bevy_audio and its cpal 0.15 are not built. \
|
||||
See third_party/alsa-0.9/BENILLA.md."
|
||||
);
|
||||
Reference in New Issue
Block a user