Merge branch 'worktree-agent-a5cf35a576dde87f5' into worktree-dep-currency-wave
This commit is contained in:
Generated
+5
-5
@@ -5429,9 +5429,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasapi"
|
||||
version = "0.23.0"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80c3aa5d6b0e7acc3ea10cb19c334df0c8d825060f14a30d9e3b03385e6e5175"
|
||||
checksum = "ee144c215d8d31e94c1a599fbaf540ca82a7017e4f1786816b179f334fac751d"
|
||||
dependencies = [
|
||||
"log",
|
||||
"num-integer",
|
||||
@@ -5895,13 +5895,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-service"
|
||||
version = "0.7.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d24d6bcc7f734a4091ecf8d7a64c5f7d7066f45585c1861eba06449909609c8a"
|
||||
checksum = "857224b3b211c6f3616921f081ee54721ee3ad2ace2fac6a6337e032f7b4dcf2"
|
||||
dependencies = [
|
||||
"bitflags 2.13.1",
|
||||
"widestring",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -150,7 +150,7 @@ libloading = "0.8"
|
||||
x11rb = { version = "0.14", default-features = false }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
wasapi = "0.23"
|
||||
wasapi = "0.24"
|
||||
# Native D3D11VA decode (M5 of the native-decode program): the hand-declared DXVA buffer
|
||||
# layouts and the AuPlan → picparams/qmatrix/slice-control conversion that video_d3d11_native
|
||||
# submits. Windows-only because the rung is; the crate itself is cross-platform CPU code so
|
||||
|
||||
@@ -100,12 +100,14 @@ pub fn devices() -> Result<(Vec<AudioDevice>, Vec<AudioDevice>)> {
|
||||
/// audio keeps working, like the PipeWire twin's `target.object` behavior.
|
||||
/// Resolve an active endpoint by id WITHOUT `DeviceEnumerator::get_device`.
|
||||
///
|
||||
/// That helper builds its argument as `PCWSTR::from_raw(HSTRING::from(id).as_ptr())` — the
|
||||
/// `HSTRING` is a temporary, dropped at the end of that statement, so `GetDevice` reads freed
|
||||
/// memory and misses ids that are perfectly valid. Scanning the active collection touches only
|
||||
/// safe crate APIs, so it cannot regress the same way. (`punktfunk-host` fixes the same bug with
|
||||
/// raw COM instead; this crate cannot, because it pins a different `windows` revision than
|
||||
/// `wasapi` does, making the two `IMMDevice` types incompatible.)
|
||||
/// Through `wasapi 0.23` that helper built its argument as
|
||||
/// `PCWSTR::from_raw(HSTRING::from(id).as_ptr())` — the `HSTRING` was a temporary, dropped at the
|
||||
/// end of that statement, so `GetDevice` read freed memory and missed ids that are perfectly valid.
|
||||
/// `wasapi 0.24` fixed that upstream. Scanning the active collection touches only safe crate APIs,
|
||||
/// so it cannot regress the same way, and it additionally filters to ACTIVE endpoints — which is
|
||||
/// why it stays. (`punktfunk-host` routes around the same bug with raw COM instead; this crate
|
||||
/// cannot, because it pins a different `windows` revision than `wasapi` does, making the two
|
||||
/// `IMMDevice` types incompatible.)
|
||||
pub(crate) fn device_by_id(
|
||||
enumerator: &DeviceEnumerator,
|
||||
direction: &Direction,
|
||||
|
||||
@@ -920,9 +920,10 @@ fn pad_render_thread(
|
||||
let res = (|| -> anyhow::Result<()> {
|
||||
const BLOCK_ALIGN: usize = PAD_CHANNELS * 4; // f32 interleaved
|
||||
let enumerator = wasapi::DeviceEnumerator::new().context("DeviceEnumerator")?;
|
||||
// Not `get_device`: that helper resolves through a freed string — see
|
||||
// [`crate::audio::device_by_id`] (audio_wasapi.rs, mounted as `crate::audio` on
|
||||
// Windows by lib.rs's `#[path]` swap — there is no `audio_wasapi` module name).
|
||||
// Not `get_device`: that helper resolved through a freed string through wasapi 0.23, and
|
||||
// this path additionally wants the ACTIVE-only filter — see [`crate::audio::device_by_id`]
|
||||
// (audio_wasapi.rs, mounted as `crate::audio` on Windows by lib.rs's `#[path]` swap —
|
||||
// there is no `audio_wasapi` module name).
|
||||
let device = crate::audio::device_by_id(&enumerator, &Direction::Render, endpoint_id)
|
||||
.map_err(|e| anyhow!("correlated endpoint not found: {e:#}"))?;
|
||||
let mut audio_client = device.get_iaudioclient().context("IAudioClient")?;
|
||||
|
||||
@@ -278,7 +278,10 @@ windows = { version = "0.62", features = [
|
||||
# The SCM plumbing for the `service` subcommand (define_windows_service! / dispatcher / control
|
||||
# handler / ServiceManager install). Wraps the Win32 service API; the supervision loop itself uses
|
||||
# the `windows` crate above.
|
||||
windows-service = "0.7"
|
||||
# ⭐ Keep this at 0.8+: 0.7 was the LAST crate in the tree pulling `windows-sys 0.52`, so it alone
|
||||
# kept a fourth windows-sys major compiling. 0.8.1 moves to `windows-sys 0.61`, which the tree
|
||||
# already builds, and that duplicate is gone. (0.8.0 is NOT enough — it lands on 0.59.)
|
||||
windows-service = "0.8"
|
||||
# Read the GOG.com install registry (HKLM\SOFTWARE\WOW6432Node\GOG.com\Games) for the GOG store
|
||||
# provider — ergonomic + correct-by-construction vs. hand-rolled Reg* FFI for subkey enumeration.
|
||||
winreg = "0.56"
|
||||
@@ -286,7 +289,7 @@ winreg = "0.56"
|
||||
# provider — a small read-only DOM is all we need (Identity/Executable/ShellVisuals/StoreId).
|
||||
roxmltree = "0.21"
|
||||
# WASAPI loopback audio capture (default render endpoint -> 48 kHz stereo f32 for the Opus path).
|
||||
wasapi = "0.23"
|
||||
wasapi = "0.24"
|
||||
# Shared host<->driver wire contract for the pf-vdisplay IddCx virtual-display backend: the
|
||||
# control-plane IOCTL codes + `#[repr(C)] Pod` request/reply structs, defined ONCE so host<->driver
|
||||
# ABI drift is a compile error (used from `capture.rs`). The `bytemuck` that serializes those
|
||||
|
||||
@@ -509,9 +509,10 @@ pub(crate) fn restore_default_playback() {
|
||||
|
||||
/// Open a device by endpoint id, with a name for error context.
|
||||
///
|
||||
/// Resolves through [`super::pad_endpoint::open_wasapi_device`], NOT the `wasapi` crate's
|
||||
/// `DeviceEnumerator::get_device` — that one hands `GetDevice` a freed string (see the helper's
|
||||
/// docs), so it fails at random on ids that are perfectly valid.
|
||||
/// Resolves through [`super::pad_endpoint::open_wasapi_device`] rather than the `wasapi` crate's
|
||||
/// `DeviceEnumerator::get_device`: that one handed `GetDevice` a freed string through 0.23, so it
|
||||
/// failed at random on ids that are perfectly valid. `wasapi 0.24` fixed that, but we keep the one
|
||||
/// resolution path — see the helper's docs.
|
||||
pub(crate) fn open_endpoint(ep: &Endpoint) -> Result<wasapi::Device> {
|
||||
super::pad_endpoint::open_wasapi_device(&ep.1)
|
||||
.map_err(|e| anyhow!("open endpoint {:?}: {e:#}", ep.0))
|
||||
|
||||
@@ -911,13 +911,17 @@ fn open_mmdevice(endpoint_id: &str) -> Result<IMMDevice> {
|
||||
|
||||
/// Open a [`wasapi::Device`] for an endpoint id WITHOUT the crate's `DeviceEnumerator::get_device`.
|
||||
///
|
||||
/// `wasapi 0.23` builds that call's argument as
|
||||
/// `PCWSTR::from_raw(HSTRING::from(device_id).as_ptr())`. The `HSTRING` is a temporary, so it is
|
||||
/// dropped at the end of THAT statement and `IMMDeviceEnumerator::GetDevice` reads freed memory on
|
||||
/// the next line. Whether the endpoint is found then depends on what the allocator happened to
|
||||
/// Through `wasapi 0.23` that call built its argument as
|
||||
/// `PCWSTR::from_raw(HSTRING::from(device_id).as_ptr())`. The `HSTRING` was a temporary, so it was
|
||||
/// dropped at the end of THAT statement and `IMMDeviceEnumerator::GetDevice` read freed memory on
|
||||
/// the next line. Whether the endpoint was found then depended on what the allocator happened to
|
||||
/// leave behind — a heisenbug whose failure mode is `0x80070002` (ERROR_FILE_NOT_FOUND) for an id
|
||||
/// that is perfectly valid. [`open_mmdevice`] keeps its wide buffer alive across the call, so
|
||||
/// resolve there and only borrow the crate's wrapper around the resulting interface.
|
||||
/// that is perfectly valid. **`wasapi 0.24` fixed this upstream** (the `HSTRING` is now bound to a
|
||||
/// local that outlives the call), so this helper is no longer load-bearing for correctness.
|
||||
///
|
||||
/// We still resolve here, because the `IMMDevice` is wanted in its own right: [`probe_activation`]
|
||||
/// and the property-store readers below need the raw interface, so routing every lookup through
|
||||
/// [`open_mmdevice`] keeps ONE resolution path whose errors name the endpoint id.
|
||||
pub(crate) fn open_wasapi_device(endpoint_id: &str) -> Result<wasapi::Device> {
|
||||
let dev = open_mmdevice(endpoint_id)?;
|
||||
wasapi::Device::from_immdevice(dev)
|
||||
|
||||
@@ -747,9 +747,10 @@ enum DefaultKind {
|
||||
Unknown,
|
||||
}
|
||||
|
||||
/// Resolves through [`super::pad_endpoint::open_wasapi_device`], NOT the `wasapi` crate's
|
||||
/// `DeviceEnumerator::get_device` — that one hands `GetDevice` a freed string (see the helper's
|
||||
/// docs), and a spurious miss here silently downgrades a capturable default to `Unknown`.
|
||||
/// Resolves through [`super::pad_endpoint::open_wasapi_device`] rather than the `wasapi` crate's
|
||||
/// `DeviceEnumerator::get_device`: that one handed `GetDevice` a freed string through 0.23, and a
|
||||
/// spurious miss here silently downgrades a capturable default to `Unknown`. `wasapi 0.24` fixed
|
||||
/// that, but we keep the one resolution path — see the helper's docs.
|
||||
fn judge_default(wiring: &wiring_plan::Wiring, id: &str) -> DefaultKind {
|
||||
let Ok(dev) = super::pad_endpoint::open_wasapi_device(id) else {
|
||||
return DefaultKind::Unknown;
|
||||
|
||||
@@ -38,8 +38,9 @@ rustls = { version = "0.23", default-features = false, features = ["aws_lc_rs",
|
||||
punktfunk-core = { path = "../punktfunk-core", default-features = false, features = ["tls", "ureq-tls"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
# SCM QUERY_STATUS works unprivileged — the service-state probe. Same crate the host service uses.
|
||||
windows-service = "0.7"
|
||||
# SCM QUERY_STATUS works unprivileged — the service-state probe. Same crate the host service uses,
|
||||
# and it must stay in lockstep with it — see the windows-sys note on the host's declaration.
|
||||
windows-service = "0.8"
|
||||
windows = { version = "0.62", features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Graphics_Gdi",
|
||||
|
||||
Reference in New Issue
Block a user