From 2eea949cf8c3163390f4e3a26b5bf443d298d8a8 Mon Sep 17 00:00:00 2001 From: Roderick van Domburg Date: Tue, 19 May 2026 22:47:02 +0200 Subject: [PATCH 1/5] feat: add Default impls and new() constructors --- CHANGELOG.md | 12 +++++++ src/host/aaudio/java_interface/definitions.rs | 3 +- src/host/aaudio/mod.rs | 16 ++++++--- src/host/asio/stream.rs | 6 ++-- src/host/audioworklet/mod.rs | 15 ++++++--- src/host/coreaudio/ios/enumerate.rs | 6 ++-- src/host/coreaudio/ios/mod.rs | 7 +++- src/host/coreaudio/macos/mod.rs | 2 +- src/host/null/mod.rs | 33 ++++++++++++++++--- src/host/pipewire/device.rs | 9 ++++- src/host/wasapi/mod.rs | 2 +- src/host/webaudio/mod.rs | 11 +++++-- src/lib.rs | 6 ++-- 13 files changed, 99 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index afbe164d5..d737f6e58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,17 +30,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 to select 48 kHz or 44.1 kHz from a range. - `realtime` feature for high-priority audio scheduling without a D-Bus build dependency. - Add `CODE_OF_CONDUCT.md`, `CONTRIBUTING.md` and `SECURITY.md`. +- `BufferSize` now implements `Default` (returns `BufferSize::Default`). - **AAudio**: Streams now request `PERFORMANCE_MODE_LOW_LATENCY` when the `realtime` feature is enabled; stream error callback receives `ErrorKind::RealtimeDenied` if not granted. - **AAudio**: `Device` now implements `PartialEq`, `Eq`, `Hash`, and `Debug`. +- **AAudio**: `Host` and `Device` now implement `Default`; added `Device::new()`. - **ALSA**: `device_by_id()` now accepts PCM shorthand names such as `hw:0,0` and `plughw:foo`. - **ASIO**: `Device` now implements `Debug`. +- **AudioWorklet**: `Device` and `Host` now implement `Default`; added `Device::new()`. +- **CoreAudio**: `Host` now implements `Default`. - **CoreAudio**: tvOS target support (Tier 3, requires nightly). - **CoreAudio**: `Device` now implements `PartialEq`, `Eq`, and `Hash`. +- **CoreAudio (iOS)**: `Device` now implements `Default`; added `Device::new()`. +- **Custom**: `SupportedBufferSize` now implements `Default` (returns + `SupportedBufferSize::Unknown`). - **JACK**: `Device` now implements `PartialEq`, `Eq`, and `Hash`. +- **Null**: `Device`, `Host`, `Stream`, `SupportedInputConfigs`, and `SupportedOutputConfigs` now + implement `Default`, added `new()` on each. - **PipeWire**: New host for Linux and some BSDs using the PipeWire API. - **PulseAudio**: New host for Linux and some BSDs using the PulseAudio API. - **WASAPI**: `Device` now implements `PartialEq`, `Eq`, `Hash`, and `Debug`. +- **WASAPI**: `Host` now implements `Default`. +- **WebAudio**: `Device` and `Host` now implement `Default`; added `Device::new()`. ### Changed @@ -178,6 +189,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **ASIO**: Fix `driver.sample_rate()` failures at stream creation being silently ignored. - **ASIO**: Fix callbacks firing before `build_*_stream` returns the `Stream` handle. - **ASIO**: Fix overrun not being reported when the driver reports `kAsioOverload`. +- **AudioWorklet**: Fix `Devices::default()` to enumerate only if `Host::is_available()`. - **CoreAudio**: Fix default output streams silently stopping when the system default output device is unplugged; they now reroute automatically or report `ErrorKind::DeviceNotAvailable`. - **CoreAudio**: Fix undefined behaviour and silent failure in loopback device creation. diff --git a/src/host/aaudio/java_interface/definitions.rs b/src/host/aaudio/java_interface/definitions.rs index 0c4e4251a..ffe6fb810 100644 --- a/src/host/aaudio/java_interface/definitions.rs +++ b/src/host/aaudio/java_interface/definitions.rs @@ -75,10 +75,11 @@ pub struct AudioDeviceInfo { /** * The type of audio device */ -#[derive(Debug, Clone, Copy, FromPrimitive)] +#[derive(Debug, Clone, Copy, Default, FromPrimitive)] #[non_exhaustive] #[repr(i32)] pub enum AudioDeviceType { + #[default] Unknown = 0, AuxLine = 19, BleBroadcast = 30, diff --git a/src/host/aaudio/mod.rs b/src/host/aaudio/mod.rs index b31ed8268..39a402b66 100644 --- a/src/host/aaudio/mod.rs +++ b/src/host/aaudio/mod.rs @@ -121,10 +121,18 @@ const SAMPLE_RATES: [i32; 15] = [ /// The same default for blocking operations as Oboe uses const DEFAULT_TIMEOUT_NANOS: i64 = 2_000_000_000; +#[derive(Default)] pub struct Host; -#[derive(Clone, Debug)] + +#[derive(Clone, Debug, Default)] pub struct Device(Option); +impl Device { + pub fn new() -> Self { + Self::default() + } +} + /// Stream wraps AudioStream in Arc> to provide Send + Sync semantics. /// /// While the underlying ndk::audio::AudioStream is neither Send nor Sync in ndk 0.9.0 @@ -191,16 +199,16 @@ impl HostTrait for Host { .collect::>() .into_iter()) } else { - Ok(vec![Device(None)].into_iter()) + Ok(vec![Device::new()].into_iter()) } } fn default_input_device(&self) -> Option { - Some(Device(None)) + Some(Device::default()) } fn default_output_device(&self) -> Option { - Some(Device(None)) + Some(Device::default()) } } diff --git a/src/host/asio/stream.rs b/src/host/asio/stream.rs index dec23b1ac..57de1d234 100644 --- a/src/host/asio/stream.rs +++ b/src/host/asio/stream.rs @@ -24,6 +24,7 @@ use crate::{ /// Shared state for extending the 32-bit `timeGetTime()` millisecond counter into a /// monotonic 64-bit nanosecond value, shared between `now()` and audio callbacks. +#[derive(Default)] struct TimeBase { last_ns: AtomicU64, epoch_ns: AtomicU64, @@ -34,10 +35,7 @@ const TIMEGETIME_WRAP_NS: u64 = (u32::MAX as u64 + 1) * 1_000_000; impl TimeBase { fn new() -> Self { - Self { - last_ns: AtomicU64::new(0), - epoch_ns: AtomicU64::new(0), - } + Self::default() } /// Convert a nanosecond timestamp to a monotonic `StreamInstant`. diff --git a/src/host/audioworklet/mod.rs b/src/host/audioworklet/mod.rs index 1b6491596..78f6b9c8c 100644 --- a/src/host/audioworklet/mod.rs +++ b/src/host/audioworklet/mod.rs @@ -30,9 +30,15 @@ use crate::dependent_module; /// Content is false if the iterator is empty. pub struct Devices(bool); -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] pub struct Device; +impl Device { + pub fn new() -> Self { + Self + } +} + impl fmt::Display for Device { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let desc = self.description().map_err(|_| fmt::Error)?; @@ -40,6 +46,7 @@ impl fmt::Display for Device { } } +#[derive(Default)] pub struct Host; pub struct Stream { @@ -103,7 +110,7 @@ impl HostTrait for Host { } fn default_output_device(&self) -> Option { - Some(Device) + Some(Device::default()) } } @@ -408,7 +415,7 @@ impl Drop for Stream { impl Default for Devices { fn default() -> Self { - Self(true) + Self(Host::is_available()) } } @@ -418,7 +425,7 @@ impl Iterator for Devices { fn next(&mut self) -> Option { if self.0 { self.0 = false; - Some(Device) + Some(Device::new()) } else { None } diff --git a/src/host/coreaudio/ios/enumerate.rs b/src/host/coreaudio/ios/enumerate.rs index f5a74935c..e496ada23 100644 --- a/src/host/coreaudio/ios/enumerate.rs +++ b/src/host/coreaudio/ios/enumerate.rs @@ -14,7 +14,7 @@ impl Devices { impl Default for Devices { fn default() -> Self { - Self(vec![Device].into_iter()) + Self(vec![Device::new()].into_iter()) } } @@ -27,9 +27,9 @@ impl Iterator for Devices { } pub fn default_input_device() -> Option { - Some(Device) + Some(Device::default()) } pub fn default_output_device() -> Option { - Some(Device) + Some(Device::default()) } diff --git a/src/host/coreaudio/ios/mod.rs b/src/host/coreaudio/ios/mod.rs index cc54c2dcf..a4283baaa 100644 --- a/src/host/coreaudio/ios/mod.rs +++ b/src/host/coreaudio/ios/mod.rs @@ -36,7 +36,7 @@ use session_event_manager::SessionEventManager; // These days the default of iOS is now F32 and no longer I16 const SUPPORTED_SAMPLE_FORMAT: SampleFormat = SampleFormat::F32; -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] pub struct Device; impl fmt::Display for Device { @@ -46,6 +46,7 @@ impl fmt::Display for Device { } } +#[derive(Default)] pub struct Host; impl Host { @@ -76,6 +77,10 @@ impl HostTrait for Host { } impl Device { + pub fn new() -> Self { + Self + } + fn description(&self) -> Result { // Query AVAudioSession to determine actual input/output availability // SAFETY: AVAudioSession::sharedInstance() returns the global audio session singleton diff --git a/src/host/coreaudio/macos/mod.rs b/src/host/coreaudio/macos/mod.rs index 82b0b0ee1..d740bb4d8 100644 --- a/src/host/coreaudio/macos/mod.rs +++ b/src/host/coreaudio/macos/mod.rs @@ -25,7 +25,7 @@ mod property_listener; pub use device::Device; /// Coreaudio host, the default host on macOS. -#[derive(Debug)] +#[derive(Debug, Default)] pub struct Host; impl Host { diff --git a/src/host/null/mod.rs b/src/host/null/mod.rs index 37eb1c650..463c68558 100644 --- a/src/host/null/mod.rs +++ b/src/host/null/mod.rs @@ -15,7 +15,7 @@ use crate::{ #[derive(Default)] pub struct Devices; -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] pub struct Device; impl fmt::Display for Device { @@ -25,20 +25,27 @@ impl fmt::Display for Device { } } +#[derive(Default)] pub struct Host; -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)] pub struct Stream; // Compile-time assertion that Stream is Send and Sync crate::assert_stream_send!(Stream); crate::assert_stream_sync!(Stream); -#[derive(Clone)] +#[derive(Clone, Default)] pub struct SupportedInputConfigs; -#[derive(Clone)] +#[derive(Clone, Default)] pub struct SupportedOutputConfigs; +impl Device { + pub fn new() -> Self { + Self + } +} + impl Host { #[allow(dead_code)] pub fn new() -> Result { @@ -46,6 +53,24 @@ impl Host { } } +impl Stream { + pub fn new() -> Self { + Self + } +} + +impl SupportedInputConfigs { + pub fn new() -> Self { + Self + } +} + +impl SupportedOutputConfigs { + pub fn new() -> Self { + Self + } +} + impl Devices { pub fn new() -> Result { Ok(Self) diff --git a/src/host/pipewire/device.rs b/src/host/pipewire/device.rs index dd67af326..7df75fb7a 100644 --- a/src/host/pipewire/device.rs +++ b/src/host/pipewire/device.rs @@ -55,8 +55,8 @@ pub(crate) enum Class { #[derive(Clone, Debug, Default, Copy)] pub enum Role { - Sink, #[default] + Sink, Source, Duplex, StreamOutput, @@ -697,11 +697,18 @@ impl From for Request { } /// Per-node rate and quantum discovered during device enumeration. +#[derive(Default)] struct NodeOverrides { rate: Option, quantum: Option, } +impl NodeOverrides { + fn new() -> Self { + Self::default() + } +} + /// Parses a PipeWire fraction string like "1/48000" or "256/48000" into its parts. fn parse_fraction(s: &str) -> Option<(u32, u32)> { let mut it = s.splitn(2, '/'); diff --git a/src/host/wasapi/mod.rs b/src/host/wasapi/mod.rs index 18e5e4f86..3562d4014 100644 --- a/src/host/wasapi/mod.rs +++ b/src/host/wasapi/mod.rs @@ -23,7 +23,7 @@ mod stream; /// Note: If you use a WASAPI output device as an input device it will /// transparently enable loopback mode (see /// https://docs.microsoft.com/en-us/windows/win32/coreaudio/loopback-recording). -#[derive(Debug)] +#[derive(Debug, Default)] pub struct Host; impl Host { diff --git a/src/host/webaudio/mod.rs b/src/host/webaudio/mod.rs index cb05372c3..8c642004b 100644 --- a/src/host/webaudio/mod.rs +++ b/src/host/webaudio/mod.rs @@ -37,7 +37,7 @@ type ClosureHandle = Arc>>>; /// Content is false if the iterator is empty. pub struct Devices(bool); -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] pub struct Device; impl fmt::Display for Device { @@ -47,6 +47,7 @@ impl fmt::Display for Device { } } +#[derive(Default)] pub struct Host; pub struct Stream { @@ -112,6 +113,10 @@ impl Devices { } impl Device { + pub fn new() -> Self { + Self + } + fn description(&self) -> Result { Ok(DeviceDescriptionBuilder::new("Default Device") .direction(DeviceDirection::Output) @@ -634,7 +639,7 @@ impl Iterator for Devices { fn next(&mut self) -> Option { if self.0 { self.0 = false; - Some(Device) + Some(Device::new()) } else { None } @@ -648,7 +653,7 @@ fn default_input_device() -> Option { fn default_output_device() -> Option { if is_webaudio_available() { - Some(Device) + Some(Device::default()) } else { None } diff --git a/src/lib.rs b/src/lib.rs index de042cfc9..7e338d407 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -368,8 +368,9 @@ impl std::str::FromStr for DeviceId { /// [`BufferSize::Fixed(x)`]: BufferSize::Fixed /// [`SupportedBufferSize`]: SupportedStreamConfig::buffer_size /// [`SupportedStreamConfig`]: SupportedStreamConfig -#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] pub enum BufferSize { + #[default] Default, Fixed(FrameCount), } @@ -420,7 +421,7 @@ pub struct StreamConfig { } /// Describes the minimum and maximum supported buffer size for the device -#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] pub enum SupportedBufferSize { Range { min: FrameCount, @@ -428,6 +429,7 @@ pub enum SupportedBufferSize { }, /// In the case that the platform provides no way of getting the default /// buffer size before starting a stream. + #[default] Unknown, } From 88b9cbf37991c54366590287c10a6e0bd50264ff Mon Sep 17 00:00:00 2001 From: Roderick van Domburg Date: Tue, 19 May 2026 22:59:08 +0200 Subject: [PATCH 2/5] refactor: remove redundant helpers and Default impls --- src/host/asio/stream.rs | 11 +++-------- src/host/jack/stream.rs | 3 +-- src/host/pipewire/device.rs | 7 ------- 3 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/host/asio/stream.rs b/src/host/asio/stream.rs index 57de1d234..37309c8cd 100644 --- a/src/host/asio/stream.rs +++ b/src/host/asio/stream.rs @@ -34,10 +34,6 @@ struct TimeBase { const TIMEGETIME_WRAP_NS: u64 = (u32::MAX as u64 + 1) * 1_000_000; impl TimeBase { - fn new() -> Self { - Self::default() - } - /// Convert a nanosecond timestamp to a monotonic `StreamInstant`. fn to_stream_instant(&self, ns: u64) -> StreamInstant { // `Relaxed` is sufficient: callbacks run on a single ASIO thread. The only @@ -58,9 +54,8 @@ impl TimeBase { const ASIO_EVENT_DEBOUNCE: Duration = Duration::from_millis(500); #[repr(u8)] -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] enum StreamState { - #[default] Starting = 0, Paused = 1, Playing = 2, @@ -209,7 +204,7 @@ impl Device { let mut current_buffer_size = buffer_size as i32; let mut last_buffer_index: i32 = -1; - let time_base = Arc::new(TimeBase::new()); + let time_base = Arc::new(TimeBase::default()); let time_base_cb = Arc::clone(&time_base); // Set the input callback. @@ -542,7 +537,7 @@ impl Device { let mut current_buffer_size = buffer_size as i32; let mut last_buffer_index: i32 = -1; - let time_base = Arc::new(TimeBase::new()); + let time_base = Arc::new(TimeBase::default()); let time_base_cb = Arc::clone(&time_base); let callback_id = driver.add_callback(move |callback_info| unsafe { diff --git a/src/host/jack/stream.rs b/src/host/jack/stream.rs index de6ea0f46..f643ef0d7 100644 --- a/src/host/jack/stream.rs +++ b/src/host/jack/stream.rs @@ -12,9 +12,8 @@ use crate::{ }; #[repr(u8)] -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] enum StreamState { - #[default] Starting = 0, Paused = 1, Playing = 2, diff --git a/src/host/pipewire/device.rs b/src/host/pipewire/device.rs index 7df75fb7a..2fa955fae 100644 --- a/src/host/pipewire/device.rs +++ b/src/host/pipewire/device.rs @@ -697,18 +697,11 @@ impl From for Request { } /// Per-node rate and quantum discovered during device enumeration. -#[derive(Default)] struct NodeOverrides { rate: Option, quantum: Option, } -impl NodeOverrides { - fn new() -> Self { - Self::default() - } -} - /// Parses a PipeWire fraction string like "1/48000" or "256/48000" into its parts. fn parse_fraction(s: &str) -> Option<(u32, u32)> { let mut it = s.splitn(2, '/'); From 6906ccbd872e54a566e811a8cf87343b93446fe8 Mon Sep 17 00:00:00 2001 From: Roderick van Domburg Date: Tue, 19 May 2026 23:22:48 +0200 Subject: [PATCH 3/5] refactor: make SupportedStreamConfig Copy and tidy derives --- CHANGELOG.md | 1 + src/host/aaudio/java_interface/audio_features.rs | 2 +- src/host/alsa/mod.rs | 4 ++-- src/host/asio/stream.rs | 2 +- src/host/coreaudio/macos/device.rs | 2 +- src/host/jack/stream.rs | 2 +- src/host/pipewire/device.rs | 4 ++-- src/host/pipewire/stream.rs | 3 +-- src/lib.rs | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d737f6e58..604c51c8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `realtime` feature for high-priority audio scheduling without a D-Bus build dependency. - Add `CODE_OF_CONDUCT.md`, `CONTRIBUTING.md` and `SECURITY.md`. - `BufferSize` now implements `Default` (returns `BufferSize::Default`). +- `SupportedStreamConfig` now implements `Copy`. - **AAudio**: Streams now request `PERFORMANCE_MODE_LOW_LATENCY` when the `realtime` feature is enabled; stream error callback receives `ErrorKind::RealtimeDenied` if not granted. - **AAudio**: `Device` now implements `PartialEq`, `Eq`, `Hash`, and `Debug`. diff --git a/src/host/aaudio/java_interface/audio_features.rs b/src/host/aaudio/java_interface/audio_features.rs index bbd88090c..50e2be832 100644 --- a/src/host/aaudio/java_interface/audio_features.rs +++ b/src/host/aaudio/java_interface/audio_features.rs @@ -9,7 +9,7 @@ use super::{ /** * The Android audio features */ -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy)] pub enum AudioFeature { LowLatency, Output, diff --git a/src/host/alsa/mod.rs b/src/host/alsa/mod.rs index f967811f4..6e2cbca12 100644 --- a/src/host/alsa/mod.rs +++ b/src/host/alsa/mod.rs @@ -667,7 +667,7 @@ impl Default for Device { } /// Strategy for pre-filling an output buffer with the equilibrium value. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Debug)] enum EquilibriumFill { /// Equilibrium is represented as a single repeating byte value. Byte(u8), @@ -704,7 +704,7 @@ impl EquilibriumFill { } // How callback timestamps are produced. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] enum TimestampMode { // Hardware timestamps are unavailable (e.g. PulseAudio ALSA plugin returns zero htstamp). // Timestamps are monotonic elapsed time since stream creation, sourced from Instant::now(). diff --git a/src/host/asio/stream.rs b/src/host/asio/stream.rs index 37309c8cd..c74e9e15e 100644 --- a/src/host/asio/stream.rs +++ b/src/host/asio/stream.rs @@ -54,7 +54,7 @@ impl TimeBase { const ASIO_EVENT_DEBOUNCE: Duration = Duration::from_millis(500); #[repr(u8)] -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq)] enum StreamState { Starting = 0, Paused = 1, diff --git a/src/host/coreaudio/macos/device.rs b/src/host/coreaudio/macos/device.rs index 077019abb..783c9e5f7 100644 --- a/src/host/coreaudio/macos/device.rs +++ b/src/host/coreaudio/macos/device.rs @@ -214,7 +214,7 @@ fn set_sample_rate( Ok(()) } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Copy)] enum AudioUnitMode { /// HAL Output AudioUnit with input enabled, pinned to a specific device. Input, diff --git a/src/host/jack/stream.rs b/src/host/jack/stream.rs index f643ef0d7..72a6fc46d 100644 --- a/src/host/jack/stream.rs +++ b/src/host/jack/stream.rs @@ -12,7 +12,7 @@ use crate::{ }; #[repr(u8)] -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq)] enum StreamState { Starting = 0, Paused = 1, diff --git a/src/host/pipewire/device.rs b/src/host/pipewire/device.rs index 2fa955fae..cccf744d8 100644 --- a/src/host/pipewire/device.rs +++ b/src/host/pipewire/device.rs @@ -54,7 +54,7 @@ pub(crate) enum Class { } #[derive(Clone, Debug, Default, Copy)] -pub enum Role { +enum Role { #[default] Sink, Source, @@ -668,7 +668,7 @@ impl DeviceTrait for Device { } } -#[derive(Debug, Clone, Default)] +#[derive(Clone, Default)] struct Settings { rate: SampleRate, allow_rates: Box<[SampleRate]>, diff --git a/src/host/pipewire/stream.rs b/src/host/pipewire/stream.rs index 32907f7dd..da69b8953 100644 --- a/src/host/pipewire/stream.rs +++ b/src/host/pipewire/stream.rs @@ -68,8 +68,7 @@ impl Drop for PwInitGuard { } } -#[derive(Debug, Clone, Copy)] -pub enum StreamCommand { +pub(super) enum StreamCommand { Toggle(bool), Stop, } diff --git a/src/lib.rs b/src/lib.rs index 7e338d407..749f4c16e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -471,7 +471,7 @@ pub(crate) mod iter { /// Describes a single supported stream configuration, retrieved via either a /// [`SupportedStreamConfigRange`] instance or one of the /// [`Device::default_input/output_config`](traits::DeviceTrait#required-methods) methods. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct SupportedStreamConfig { channels: ChannelCount, sample_rate: SampleRate, From 9d38ad1049567910327dfec72dd252c9336183ee Mon Sep 17 00:00:00 2001 From: Roderick van Domburg Date: Tue, 19 May 2026 23:30:55 +0200 Subject: [PATCH 4/5] fix: address review points --- CHANGELOG.md | 3 +-- src/host/audioworklet/mod.rs | 4 ++-- src/host/coreaudio/ios/enumerate.rs | 6 +++--- src/host/webaudio/mod.rs | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 604c51c8d..0cd617ab1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `realtime` feature for high-priority audio scheduling without a D-Bus build dependency. - Add `CODE_OF_CONDUCT.md`, `CONTRIBUTING.md` and `SECURITY.md`. - `BufferSize` now implements `Default` (returns `BufferSize::Default`). +- `SupportedBufferSize` now implements `Default` (returns `SupportedBufferSize::Unknown`). - `SupportedStreamConfig` now implements `Copy`. - **AAudio**: Streams now request `PERFORMANCE_MODE_LOW_LATENCY` when the `realtime` feature is enabled; stream error callback receives `ErrorKind::RealtimeDenied` if not granted. @@ -43,8 +44,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **CoreAudio**: tvOS target support (Tier 3, requires nightly). - **CoreAudio**: `Device` now implements `PartialEq`, `Eq`, and `Hash`. - **CoreAudio (iOS)**: `Device` now implements `Default`; added `Device::new()`. -- **Custom**: `SupportedBufferSize` now implements `Default` (returns - `SupportedBufferSize::Unknown`). - **JACK**: `Device` now implements `PartialEq`, `Eq`, and `Hash`. - **Null**: `Device`, `Host`, `Stream`, `SupportedInputConfigs`, and `SupportedOutputConfigs` now implement `Default`, added `new()` on each. diff --git a/src/host/audioworklet/mod.rs b/src/host/audioworklet/mod.rs index 78f6b9c8c..81df38b80 100644 --- a/src/host/audioworklet/mod.rs +++ b/src/host/audioworklet/mod.rs @@ -110,7 +110,7 @@ impl HostTrait for Host { } fn default_output_device(&self) -> Option { - Some(Device::default()) + Some(Device) } } @@ -425,7 +425,7 @@ impl Iterator for Devices { fn next(&mut self) -> Option { if self.0 { self.0 = false; - Some(Device::new()) + Some(Device) } else { None } diff --git a/src/host/coreaudio/ios/enumerate.rs b/src/host/coreaudio/ios/enumerate.rs index e496ada23..f5a74935c 100644 --- a/src/host/coreaudio/ios/enumerate.rs +++ b/src/host/coreaudio/ios/enumerate.rs @@ -14,7 +14,7 @@ impl Devices { impl Default for Devices { fn default() -> Self { - Self(vec![Device::new()].into_iter()) + Self(vec![Device].into_iter()) } } @@ -27,9 +27,9 @@ impl Iterator for Devices { } pub fn default_input_device() -> Option { - Some(Device::default()) + Some(Device) } pub fn default_output_device() -> Option { - Some(Device::default()) + Some(Device) } diff --git a/src/host/webaudio/mod.rs b/src/host/webaudio/mod.rs index 8c642004b..d4866a5ac 100644 --- a/src/host/webaudio/mod.rs +++ b/src/host/webaudio/mod.rs @@ -639,7 +639,7 @@ impl Iterator for Devices { fn next(&mut self) -> Option { if self.0 { self.0 = false; - Some(Device::new()) + Some(Device) } else { None } @@ -653,7 +653,7 @@ fn default_input_device() -> Option { fn default_output_device() -> Option { if is_webaudio_available() { - Some(Device::default()) + Some(Device) } else { None } From 438d1a610fcd7bc93949ba902629de5575cbdff3 Mon Sep 17 00:00:00 2001 From: Roderick van Domburg Date: Tue, 19 May 2026 23:41:38 +0200 Subject: [PATCH 5/5] fix: address review points --- src/host/audioworklet/mod.rs | 6 +++++- src/host/pipewire/stream.rs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/host/audioworklet/mod.rs b/src/host/audioworklet/mod.rs index 81df38b80..d578cd9ca 100644 --- a/src/host/audioworklet/mod.rs +++ b/src/host/audioworklet/mod.rs @@ -110,7 +110,11 @@ impl HostTrait for Host { } fn default_output_device(&self) -> Option { - Some(Device) + if Self::is_available() { + Some(Device) + } else { + None + } } } diff --git a/src/host/pipewire/stream.rs b/src/host/pipewire/stream.rs index da69b8953..0cf4d8b7d 100644 --- a/src/host/pipewire/stream.rs +++ b/src/host/pipewire/stream.rs @@ -82,7 +82,7 @@ pub struct Stream { } impl Stream { - pub(crate) fn new( + pub(super) fn new( handle: JoinHandle<()>, controller: pw::channel::Sender, last_quantum: Arc,