use sim_kernel::Symbol;
use crate::model::{
HostOpenPlan, stream_host_capability, stream_host_device_read_effect_kind,
stream_host_device_write_effect_kind,
};
use super::AudioDeviceCard;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Placement {
Modeled,
Hardware {
transport: Symbol,
},
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DeviceKind {
Audio,
Midi,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DeviceDirection {
Input,
Output,
Duplex,
}
impl DeviceDirection {
pub fn effect_kinds(self) -> Vec<Symbol> {
match self {
Self::Input => vec![stream_host_device_read_effect_kind()],
Self::Output => vec![stream_host_device_write_effect_kind()],
Self::Duplex => vec![
stream_host_device_read_effect_kind(),
stream_host_device_write_effect_kind(),
],
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct DeviceRecord {
pub id: Symbol,
pub display_name: String,
pub kind: DeviceKind,
pub direction: DeviceDirection,
pub placement: Placement,
}
impl DeviceRecord {
pub fn modeled_midi_input(id: &str, name: impl Into<String>) -> Self {
Self::modeled(id, name, DeviceKind::Midi, DeviceDirection::Input)
}
pub fn modeled_midi_output(id: &str, name: impl Into<String>) -> Self {
Self::modeled(id, name, DeviceKind::Midi, DeviceDirection::Output)
}
pub fn modeled_audio_output(id: &str, name: impl Into<String>) -> Self {
Self::modeled(id, name, DeviceKind::Audio, DeviceDirection::Output)
}
pub fn modeled_audio_from_card(card: &AudioDeviceCard) -> Self {
Self::audio_from_card(card, Placement::Modeled)
}
pub fn audio_from_card(card: &AudioDeviceCard, placement: Placement) -> Self {
let direction = match (card.channels_in > 0, card.channels_out > 0) {
(true, true) => DeviceDirection::Duplex,
(true, false) => DeviceDirection::Input,
(false, true) | (false, false) => DeviceDirection::Output,
};
Self {
id: card.key.0.clone(),
display_name: card.display_name.clone(),
kind: DeviceKind::Audio,
direction,
placement,
}
}
pub fn open_plan(&self) -> HostOpenPlan {
HostOpenPlan::new(
self.plan_backend_symbol(),
self.id.clone(),
self.direction.effect_kinds(),
vec![stream_host_capability()],
)
}
fn modeled(
id: &str,
name: impl Into<String>,
kind: DeviceKind,
direction: DeviceDirection,
) -> Self {
Self {
id: Symbol::new(id),
display_name: name.into(),
kind,
direction,
placement: Placement::Modeled,
}
}
fn plan_backend_symbol(&self) -> Symbol {
match &self.placement {
Placement::Modeled => Symbol::qualified("stream/host", "modeled-catalog"),
Placement::Hardware { transport } => transport.clone(),
}
}
}