Skip to main content

sim_lib_stream_alsa/
runtime.rs

1use sim_kernel::{Cx, Lib, LibManifest, Linker, LoadCx, Result, Symbol};
2use sim_lib_core::{SurfaceField, SurfacePackLib, SurfacePackSpec, SurfaceValueSpec, install_once};
3
4use crate::{alsa_backend_symbol, alsa_transport_symbol};
5
6const ALSA_LIB_ID: &str = "stream-alsa";
7
8/// Host-registered lib exporting the ALSA stream-host cards, built on the shared
9/// [`SurfacePackLib`] substrate.
10pub struct AlsaLib;
11
12impl Lib for AlsaLib {
13    fn manifest(&self) -> LibManifest {
14        alsa_pack().manifest()
15    }
16
17    fn load(&self, cx: &mut LoadCx, linker: &mut Linker<'_>) -> Result<()> {
18        alsa_pack().load(cx, linker)
19    }
20}
21
22/// Installs the [`AlsaLib`] into `cx`, idempotently.
23///
24/// Uses `install_once`, so repeated calls register the lib at most once.
25pub fn install_stream_alsa_lib(cx: &mut Cx) -> Result<()> {
26    install_once(cx, &AlsaLib)?;
27    Ok(())
28}
29
30fn alsa_symbols() -> Vec<Symbol> {
31    vec![
32        Symbol::qualified("stream", "AlsaBackend"),
33        Symbol::qualified("stream", "AlsaDefaultPcm"),
34        Symbol::qualified("stream", "AlsaHwPcm"),
35        Symbol::qualified("stream", "AlsaPlugHwPcm"),
36        Symbol::qualified("stream", "AlsaSequencerFollowUp"),
37    ]
38}
39
40fn alsa_value_spec(symbol: Symbol) -> SurfaceValueSpec {
41    let role = match symbol.name.as_ref() {
42        "AlsaBackend" => "ALSA host PCM backend card",
43        "AlsaDefaultPcm" => "ALSA default PCM fallback card",
44        "AlsaHwPcm" => "ALSA hw:* PCM naming card",
45        "AlsaPlugHwPcm" => "ALSA plughw:* PCM naming card",
46        "AlsaSequencerFollowUp" => "ALSA sequencer MIDI follow-up card",
47        _ => "ALSA card",
48    };
49    SurfaceValueSpec {
50        symbol: symbol.clone(),
51        fields: vec![
52            (Symbol::new("symbol"), SurfaceField::Symbol(symbol)),
53            (
54                Symbol::new("layer"),
55                SurfaceField::Str("stream-host".to_owned()),
56            ),
57            (Symbol::new("kind"), SurfaceField::Str("plugin".to_owned())),
58            (
59                Symbol::new("backend"),
60                SurfaceField::Symbol(alsa_backend_symbol()),
61            ),
62            (
63                Symbol::new("transport"),
64                SurfaceField::Symbol(alsa_transport_symbol()),
65            ),
66            (Symbol::new("role"), SurfaceField::Str(role.to_owned())),
67            (
68                Symbol::new("pcm-names"),
69                SurfaceField::Strs(vec![
70                    "default".to_owned(),
71                    "hw:*".to_owned(),
72                    "plughw:*".to_owned(),
73                ]),
74            ),
75            (
76                Symbol::new("sequencer-midi"),
77                SurfaceField::Str(
78                    "follow-up: keep ALSA sequencer MIDI in a MIDI adapter".to_owned(),
79                ),
80            ),
81        ],
82    }
83}
84
85fn alsa_pack() -> SurfacePackLib {
86    SurfacePackLib {
87        spec: SurfacePackSpec {
88            lib_id: Symbol::new(ALSA_LIB_ID),
89            values: alsa_symbols().into_iter().map(alsa_value_spec).collect(),
90        },
91    }
92}