pub(crate) mod controls;
pub(crate) mod monitoring;
pub(crate) mod types;
use std::{collections::HashMap, sync::Arc};
use controls::InputDeviceController;
use derive_more::Debug;
use libpulse_binding::time::MicroSeconds;
use tokio::sync::oneshot;
use tokio_util::sync::CancellationToken;
pub(crate) use types::{InputDeviceParams, LiveInputDeviceParams};
use wayle_core::Property;
use wayle_traits::{ModelMonitoring, Reactive};
use crate::{
backend::{
commands::Command,
types::{CommandSender, EventSender},
},
error::Error,
types::{
device::{Device, DeviceKey, DevicePort, DeviceState, DeviceType, SourceInfo},
format::{AudioFormat, ChannelMap, SampleSpec},
},
volume::types::Volume,
};
#[derive(Clone, Debug)]
pub struct InputDevice {
#[debug(skip)]
command_tx: CommandSender,
#[debug(skip)]
event_tx: Option<EventSender>,
#[debug(skip)]
cancellation_token: Option<CancellationToken>,
pub key: DeviceKey,
pub name: Property<String>,
pub description: Property<String>,
pub card_index: Property<Option<u32>>,
pub owner_module: Property<Option<u32>>,
pub driver: Property<String>,
pub state: Property<DeviceState>,
pub volume: Property<Volume>,
pub base_volume: Property<Volume>,
pub n_volume_steps: Property<u32>,
pub muted: Property<bool>,
pub properties: Property<HashMap<String, String>>,
pub ports: Property<Vec<DevicePort>>,
pub active_port: Property<Option<String>>,
pub formats: Property<Vec<AudioFormat>>,
pub sample_spec: Property<SampleSpec>,
pub channel_map: Property<ChannelMap>,
pub monitor_of_sink: Property<Option<u32>>,
pub monitor_of_sink_name: Property<Option<String>>,
pub is_monitor: Property<bool>,
pub latency: Property<MicroSeconds>,
pub configured_latency: Property<MicroSeconds>,
pub flags: Property<u32>,
}
impl PartialEq for InputDevice {
fn eq(&self, other: &Self) -> bool {
self.key == other.key
}
}
impl Reactive for InputDevice {
type Context<'a> = InputDeviceParams<'a>;
type LiveContext<'a> = LiveInputDeviceParams<'a>;
type Error = Error;
async fn get(params: Self::Context<'_>) -> Result<Self, Self::Error> {
let (tx, rx) = oneshot::channel();
params
.command_tx
.send(Command::GetDevice {
device_key: params.device_key,
responder: tx,
})
.map_err(|_| Error::CommandChannelDisconnected)?;
let device = rx.await.map_err(|_| Error::CommandChannelDisconnected)??;
match device {
Device::Source(source) => Ok(Self::from_source(
&source,
params.command_tx.clone(),
None,
None,
)),
Device::Sink(_) => Err(Error::DeviceNotFound {
index: params.device_key.index,
device_type: DeviceType::Input,
}),
}
}
async fn get_live(params: Self::LiveContext<'_>) -> Result<Arc<Self>, Self::Error> {
let (tx, rx) = oneshot::channel();
params
.command_tx
.send(Command::GetDevice {
device_key: params.device_key,
responder: tx,
})
.map_err(|_| Error::CommandChannelDisconnected)?;
let device = rx.await.map_err(|_| Error::CommandChannelDisconnected)??;
let device = match device {
Device::Source(source) => Arc::new(Self::from_source(
&source,
params.command_tx.clone(),
Some(params.event_tx.clone()),
Some(params.cancellation_token.child_token()),
)),
Device::Sink(_) => {
return Err(Error::DeviceNotFound {
index: params.device_key.index,
device_type: DeviceType::Input,
});
}
};
device.clone().start_monitoring().await?;
Ok(device)
}
}
impl InputDevice {
pub(crate) fn from_source(
source: &SourceInfo,
command_tx: CommandSender,
event_tx: Option<EventSender>,
cancellation_token: Option<CancellationToken>,
) -> Self {
Self {
command_tx,
event_tx,
cancellation_token,
key: source.key(),
name: Property::new(source.device.name.clone()),
description: Property::new(source.device.description.clone()),
card_index: Property::new(source.device.card_index),
owner_module: Property::new(source.device.owner_module),
driver: Property::new(source.device.driver.clone()),
state: Property::new(source.device.state),
volume: Property::new(source.device.volume.clone()),
base_volume: Property::new(source.device.base_volume.clone()),
n_volume_steps: Property::new(source.device.n_volume_steps),
muted: Property::new(source.device.muted),
properties: Property::new(source.device.properties.clone()),
ports: Property::new(source.device.ports.clone()),
active_port: Property::new(source.device.active_port.clone()),
formats: Property::new(source.device.formats.clone()),
sample_spec: Property::new(source.device.sample_spec.clone()),
channel_map: Property::new(source.device.channel_map.clone()),
monitor_of_sink: Property::new(source.monitor_of_sink),
monitor_of_sink_name: Property::new(source.monitor_of_sink_name.clone()),
is_monitor: Property::new(source.is_monitor),
latency: Property::new(source.device.latency),
configured_latency: Property::new(source.device.configured_latency),
flags: Property::new(source.device.flags),
}
}
pub(crate) fn update_from_source(&self, source: &SourceInfo) {
self.name.set(source.device.name.clone());
self.description.set(source.device.description.clone());
self.card_index.set(source.device.card_index);
self.owner_module.set(source.device.owner_module);
self.driver.set(source.device.driver.clone());
self.state.set(source.device.state);
self.volume.set(source.device.volume.clone());
self.base_volume.set(source.device.base_volume.clone());
self.n_volume_steps.set(source.device.n_volume_steps);
self.muted.set(source.device.muted);
self.properties.set(source.device.properties.clone());
self.ports.set(source.device.ports.clone());
self.active_port.set(source.device.active_port.clone());
self.formats.set(source.device.formats.clone());
self.sample_spec.set(source.device.sample_spec.clone());
self.channel_map.set(source.device.channel_map.clone());
self.monitor_of_sink.set(source.monitor_of_sink);
self.monitor_of_sink_name
.set(source.monitor_of_sink_name.clone());
self.is_monitor.set(source.is_monitor);
self.latency.set(source.device.latency);
self.configured_latency
.set(source.device.configured_latency);
self.flags.set(source.device.flags);
}
pub async fn set_volume(&self, volume: Volume) -> Result<(), Error> {
InputDeviceController::set_volume(&self.command_tx, self.key, volume).await
}
pub async fn set_mute(&self, muted: bool) -> Result<(), Error> {
InputDeviceController::set_mute(&self.command_tx, self.key, muted).await
}
pub async fn set_port(&self, port: String) -> Result<(), Error> {
InputDeviceController::set_port(&self.command_tx, self.key, port).await
}
pub async fn set_as_default(&self) -> Result<(), Error> {
InputDeviceController::set_as_default(&self.command_tx, self.key).await
}
}