sim_lib_stream_host/capability.rs
1//! Host backend capability metadata and browse card helpers.
2
3use sim_kernel::{Expr, Symbol};
4
5/// Capability advertised by a host backend.
6///
7/// Each variant names one host-integration feature a backend may support, such
8/// as a media direction, hotplug/reconnect handling, or the deterministic fake
9/// transport used during validation.
10///
11/// # Examples
12///
13/// ```
14/// use sim_lib_stream_host::HostBackendCapability;
15///
16/// let symbol = HostBackendCapability::Duplex.symbol();
17/// assert_eq!(symbol.as_qualified_str(), "stream/host-capability/duplex");
18/// ```
19#[derive(Clone, Copy, Debug, PartialEq, Eq)]
20pub enum HostBackendCapability {
21 /// Backend can capture audio from a host input device.
22 AudioInput,
23 /// Backend can render audio to a host output device.
24 AudioOutput,
25 /// Backend can receive MIDI from a host input port.
26 MidiInput,
27 /// Backend can send MIDI to a host output port.
28 MidiOutput,
29 /// Backend can drive a single full-duplex (input and output) device.
30 Duplex,
31 /// Backend reports device arrival and removal at runtime.
32 Hotplug,
33 /// Backend can re-establish a dropped device or peer connection.
34 Reconnect,
35 /// Backend can enumerate and plan without opening hardware streams.
36 Offline,
37 /// Backend is a deterministic fake used for validation rather than hardware.
38 Fake,
39}
40
41impl HostBackendCapability {
42 /// Returns the stable qualified symbol naming this capability.
43 pub fn symbol(self) -> Symbol {
44 match self {
45 Self::AudioInput => Symbol::qualified("stream/host-capability", "audio-input"),
46 Self::AudioOutput => Symbol::qualified("stream/host-capability", "audio-output"),
47 Self::MidiInput => Symbol::qualified("stream/host-capability", "midi-input"),
48 Self::MidiOutput => Symbol::qualified("stream/host-capability", "midi-output"),
49 Self::Duplex => Symbol::qualified("stream/host-capability", "duplex"),
50 Self::Hotplug => Symbol::qualified("stream/host-capability", "hotplug"),
51 Self::Reconnect => Symbol::qualified("stream/host-capability", "reconnect"),
52 Self::Offline => Symbol::qualified("stream/host-capability", "offline"),
53 Self::Fake => Symbol::qualified("stream/host-capability", "fake"),
54 }
55 }
56}
57
58/// Emits a browse card for a missing backend capability.
59pub fn missing_capability_card_expr(backend: &Symbol, capability: HostBackendCapability) -> Expr {
60 Expr::Map(vec![
61 (
62 Expr::Symbol(Symbol::new("subject")),
63 Expr::Symbol(backend.clone()),
64 ),
65 (
66 Expr::Symbol(Symbol::new("kind")),
67 Expr::Symbol(Symbol::qualified("stream", "host-missing-capability")),
68 ),
69 (
70 Expr::Symbol(Symbol::new("capability")),
71 Expr::Symbol(capability.symbol()),
72 ),
73 ])
74}