diff --git a/staging/vhost-device-sound/src/audio_backends/alsa.rs b/staging/vhost-device-sound/src/audio_backends/alsa.rs index 59b8c6e..2042b0f 100644 --- a/staging/vhost-device-sound/src/audio_backends/alsa.rs +++ b/staging/vhost-device-sound/src/audio_backends/alsa.rs @@ -13,7 +13,7 @@ use std::{ use alsa::{ pcm::{Access, Format, HwParams, State, PCM}, - Direction, PollDescriptors, ValueOr, + PollDescriptors, ValueOr, }; use virtio_queue::Descriptor; use vm_memory::Bytes; @@ -22,13 +22,19 @@ use super::AudioBackend; use crate::{ device::ControlMessage, stream::{PCMState, Stream}, - virtio_sound::{ - self, VirtioSndPcmSetParams, VIRTIO_SND_D_INPUT, VIRTIO_SND_D_OUTPUT, VIRTIO_SND_S_BAD_MSG, - VIRTIO_SND_S_NOT_SUPP, - }, - Result as CrateResult, + virtio_sound::{self, VirtioSndPcmSetParams, VIRTIO_SND_S_BAD_MSG, VIRTIO_SND_S_NOT_SUPP}, + Direction, Result as CrateResult, }; +impl From for alsa::Direction { + fn from(val: Direction) -> Self { + match val { + Direction::Output => Self::Playback, + Direction::Input => Self::Capture, + } + } +} + type AResult = std::result::Result; #[derive(Clone, Debug)] @@ -55,17 +61,7 @@ fn update_pcm( *pcm_.lock().unwrap() = { let streams = streams.read().unwrap(); let s = &streams[stream_id]; - let pcm = PCM::new( - "default", - match s.direction { - d if d == VIRTIO_SND_D_OUTPUT => Direction::Playback, - d if d == VIRTIO_SND_D_INPUT => Direction::Capture, - // We initialize the stream direction ourselves in device.rs, so it should never - // have another value. - _ => unreachable!(), - }, - false, - )?; + let pcm = PCM::new("default", s.direction.into(), false)?; { let rate = match s.params.rate { @@ -390,7 +386,11 @@ impl AlsaBackend { // Initialize with a dummy value, which will be updated every time we call // `update_pcm`. - let pcm = Arc::new(Mutex::new(PCM::new("default", Direction::Playback, false)?)); + let pcm = Arc::new(Mutex::new(PCM::new( + "default", + Direction::Output.into(), + false, + )?)); let mtx = Arc::clone(&pcm); let streams = Arc::clone(&streams); diff --git a/staging/vhost-device-sound/src/audio_backends/pipewire.rs b/staging/vhost-device-sound/src/audio_backends/pipewire.rs index 497c984..ba0b4e5 100644 --- a/staging/vhost-device-sound/src/audio_backends/pipewire.rs +++ b/staging/vhost-device-sound/src/audio_backends/pipewire.rs @@ -37,23 +37,32 @@ use super::AudioBackend; use crate::{ device::ControlMessage, virtio_sound::{ - VirtioSndPcmSetParams, VIRTIO_SND_D_INPUT, VIRTIO_SND_D_OUTPUT, VIRTIO_SND_PCM_FMT_A_LAW, - VIRTIO_SND_PCM_FMT_FLOAT, VIRTIO_SND_PCM_FMT_FLOAT64, VIRTIO_SND_PCM_FMT_MU_LAW, - VIRTIO_SND_PCM_FMT_S16, VIRTIO_SND_PCM_FMT_S18_3, VIRTIO_SND_PCM_FMT_S20, - VIRTIO_SND_PCM_FMT_S20_3, VIRTIO_SND_PCM_FMT_S24, VIRTIO_SND_PCM_FMT_S24_3, - VIRTIO_SND_PCM_FMT_S32, VIRTIO_SND_PCM_FMT_S8, VIRTIO_SND_PCM_FMT_U16, - VIRTIO_SND_PCM_FMT_U18_3, VIRTIO_SND_PCM_FMT_U20, VIRTIO_SND_PCM_FMT_U20_3, - VIRTIO_SND_PCM_FMT_U24, VIRTIO_SND_PCM_FMT_U24_3, VIRTIO_SND_PCM_FMT_U32, - VIRTIO_SND_PCM_FMT_U8, VIRTIO_SND_PCM_RATE_11025, VIRTIO_SND_PCM_RATE_16000, - VIRTIO_SND_PCM_RATE_176400, VIRTIO_SND_PCM_RATE_192000, VIRTIO_SND_PCM_RATE_22050, - VIRTIO_SND_PCM_RATE_32000, VIRTIO_SND_PCM_RATE_384000, VIRTIO_SND_PCM_RATE_44100, - VIRTIO_SND_PCM_RATE_48000, VIRTIO_SND_PCM_RATE_5512, VIRTIO_SND_PCM_RATE_64000, - VIRTIO_SND_PCM_RATE_8000, VIRTIO_SND_PCM_RATE_88200, VIRTIO_SND_PCM_RATE_96000, - VIRTIO_SND_S_BAD_MSG, VIRTIO_SND_S_NOT_SUPP, + VirtioSndPcmSetParams, VIRTIO_SND_PCM_FMT_A_LAW, VIRTIO_SND_PCM_FMT_FLOAT, + VIRTIO_SND_PCM_FMT_FLOAT64, VIRTIO_SND_PCM_FMT_MU_LAW, VIRTIO_SND_PCM_FMT_S16, + VIRTIO_SND_PCM_FMT_S18_3, VIRTIO_SND_PCM_FMT_S20, VIRTIO_SND_PCM_FMT_S20_3, + VIRTIO_SND_PCM_FMT_S24, VIRTIO_SND_PCM_FMT_S24_3, VIRTIO_SND_PCM_FMT_S32, + VIRTIO_SND_PCM_FMT_S8, VIRTIO_SND_PCM_FMT_U16, VIRTIO_SND_PCM_FMT_U18_3, + VIRTIO_SND_PCM_FMT_U20, VIRTIO_SND_PCM_FMT_U20_3, VIRTIO_SND_PCM_FMT_U24, + VIRTIO_SND_PCM_FMT_U24_3, VIRTIO_SND_PCM_FMT_U32, VIRTIO_SND_PCM_FMT_U8, + VIRTIO_SND_PCM_RATE_11025, VIRTIO_SND_PCM_RATE_16000, VIRTIO_SND_PCM_RATE_176400, + VIRTIO_SND_PCM_RATE_192000, VIRTIO_SND_PCM_RATE_22050, VIRTIO_SND_PCM_RATE_32000, + VIRTIO_SND_PCM_RATE_384000, VIRTIO_SND_PCM_RATE_44100, VIRTIO_SND_PCM_RATE_48000, + VIRTIO_SND_PCM_RATE_5512, VIRTIO_SND_PCM_RATE_64000, VIRTIO_SND_PCM_RATE_8000, + VIRTIO_SND_PCM_RATE_88200, VIRTIO_SND_PCM_RATE_96000, VIRTIO_SND_S_BAD_MSG, + VIRTIO_SND_S_NOT_SUPP, }, - Error, Result, Stream, + Direction, Error, Result, Stream, }; +impl From for spa::Direction { + fn from(val: Direction) -> Self { + match val { + Direction::Output => Self::Output, + Direction::Input => Self::Input, + } + } +} + // SAFETY: Safe as the structure can be sent to another thread. unsafe impl Send for PwBackend {} @@ -378,15 +387,9 @@ impl AudioBackend for PwBackend { stream_listener.insert(stream_id, listener_stream); - let direction = match stream_params[stream_id as usize].direction { - VIRTIO_SND_D_OUTPUT => spa::Direction::Output, - VIRTIO_SND_D_INPUT => spa::Direction::Input, - _ => panic!("Invalid direction"), - }; - stream .connect( - direction, + stream_params[stream_id as usize].direction.into(), Some(pw::constants::ID_ANY), pw::stream::StreamFlags::RT_PROCESS | pw::stream::StreamFlags::AUTOCONNECT diff --git a/staging/vhost-device-sound/src/device.rs b/staging/vhost-device-sound/src/device.rs index a8c1e8a..facc6a6 100644 --- a/staging/vhost-device-sound/src/device.rs +++ b/staging/vhost-device-sound/src/device.rs @@ -29,7 +29,7 @@ use crate::{ audio_backends::{alloc_audio_backend, AudioBackend}, stream::{Buffer, Error as StreamError, Stream}, virtio_sound::{self, *}, - ControlMessageKind, Error, IOMessage, Result, SoundConfig, + ControlMessageKind, Direction, Error, IOMessage, Result, SoundConfig, }; pub struct VhostUserSoundThread { @@ -291,7 +291,7 @@ impl VhostUserSoundThread { p.features = s.params.features; p.formats = s.formats; p.rates = s.rates; - p.direction = s.direction; + p.direction = s.direction as u8; p.channels_min = s.channels_min; p.channels_max = s.channels_max; buf.extend_from_slice(p.as_slice()); @@ -605,12 +605,12 @@ impl VhostUserSoundBackend { let streams = vec![ Stream { id: 0, - direction: VIRTIO_SND_D_OUTPUT, + direction: Direction::Output, ..Stream::default() }, Stream { id: 1, - direction: VIRTIO_SND_D_INPUT, + direction: Direction::Input, ..Stream::default() }, ]; diff --git a/staging/vhost-device-sound/src/lib.rs b/staging/vhost-device-sound/src/lib.rs index e0649a5..467098d 100644 --- a/staging/vhost-device-sound/src/lib.rs +++ b/staging/vhost-device-sound/src/lib.rs @@ -42,6 +42,30 @@ use virtio_queue::DescriptorChain; pub type SoundDescriptorChain = DescriptorChain>>; pub type Result = std::result::Result; +/// Stream direction. +/// +/// Equivalent to `VIRTIO_SND_D_OUTPUT` and `VIRTIO_SND_D_INPUT`. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[repr(u8)] +pub enum Direction { + /// [`VIRTIO_SND_D_OUTPUT`](crate::virtio_sound::VIRTIO_SND_D_OUTPUT) + Output = VIRTIO_SND_D_OUTPUT, + /// [`VIRTIO_SND_D_INPUT`](crate::virtio_sound::VIRTIO_SND_D_INPUT) + Input = VIRTIO_SND_D_INPUT, +} + +impl TryFrom for Direction { + type Error = Error; + + fn try_from(val: u8) -> std::result::Result { + Ok(match val { + virtio_sound::VIRTIO_SND_D_OUTPUT => Self::Output, + virtio_sound::VIRTIO_SND_D_INPUT => Self::Input, + other => return Err(Error::InvalidMessageValue(stringify!(Direction), other)), + }) + } +} + /// Custom error types #[derive(Debug, ThisError)] pub enum Error { @@ -59,6 +83,8 @@ pub enum Error { HandleUnknownEvent, #[error("Invalid control message code {0}")] InvalidControlMessage(u32), + #[error("Invalid value in {0}: {1}")] + InvalidMessageValue(&'static str, u8), #[error("Failed to create a new EventFd")] EventFdCreate(IoError), #[error("Request missing data buffer")] diff --git a/staging/vhost-device-sound/src/stream.rs b/staging/vhost-device-sound/src/stream.rs index 5217539..5cddff3 100644 --- a/staging/vhost-device-sound/src/stream.rs +++ b/staging/vhost-device-sound/src/stream.rs @@ -6,7 +6,7 @@ use std::{collections::VecDeque, sync::Arc}; use thiserror::Error as ThisError; use vm_memory::{Address, Bytes, Le32, Le64}; -use crate::{virtio_sound::*, IOMessage, SUPPORTED_FORMATS, SUPPORTED_RATES}; +use crate::{virtio_sound::*, Direction, IOMessage, SUPPORTED_FORMATS, SUPPORTED_RATES}; /// Stream errors. #[derive(Debug, ThisError, PartialEq)] @@ -172,7 +172,7 @@ pub struct Stream { pub params: PcmParams, pub formats: Le64, pub rates: Le64, - pub direction: u8, + pub direction: Direction, pub channels_min: u8, pub channels_max: u8, pub state: PCMState, @@ -183,7 +183,7 @@ impl Default for Stream { fn default() -> Self { Self { id: 0, - direction: VIRTIO_SND_D_OUTPUT, + direction: Direction::Output, formats: SUPPORTED_FORMATS.into(), rates: SUPPORTED_RATES.into(), params: PcmParams::default(),