Skip to main content

sim_lib_stream_coreaudio/
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::{
5    coreaudio_backend_symbol, coreaudio_transport_symbol, macos_audio_backend_priority,
6    macos_midi_backend_priority,
7};
8
9const COREAUDIO_LIB_ID: &str = "stream-coreaudio";
10
11/// Host-registered lib exporting the CoreAudio stream-host cards, built on the
12/// shared [`SurfacePackLib`] substrate.
13pub struct CoreAudioLib;
14
15impl Lib for CoreAudioLib {
16    fn manifest(&self) -> LibManifest {
17        coreaudio_pack().manifest()
18    }
19
20    fn load(&self, cx: &mut LoadCx, linker: &mut Linker<'_>) -> Result<()> {
21        coreaudio_pack().load(cx, linker)
22    }
23}
24
25/// Installs [`CoreAudioLib`] into `cx` exactly once.
26///
27/// Repeated calls are idempotent: the lib's surface cards are registered on the
28/// first install and skipped thereafter.
29pub fn install_stream_coreaudio_lib(cx: &mut Cx) -> Result<()> {
30    install_once(cx, &CoreAudioLib)?;
31    Ok(())
32}
33
34fn coreaudio_symbols() -> Vec<Symbol> {
35    vec![
36        Symbol::qualified("stream", "CoreAudioBackend"),
37        Symbol::qualified("stream", "CoreAudioNativeFallback"),
38        Symbol::qualified("stream", "MacosAudioBackendPriority"),
39        Symbol::qualified("stream", "MacosMidiBackendPriority"),
40    ]
41}
42
43fn coreaudio_value_spec(symbol: Symbol) -> SurfaceValueSpec {
44    let role = match symbol.name.as_ref() {
45        "CoreAudioBackend" => "CoreAudio host PCM backend card",
46        "CoreAudioNativeFallback" => "CoreAudio native fallback policy card",
47        "MacosAudioBackendPriority" => "macOS audio backend priority card",
48        "MacosMidiBackendPriority" => "macOS MIDI backend priority card",
49        _ => "CoreAudio card",
50    };
51    SurfaceValueSpec {
52        symbol: symbol.clone(),
53        fields: vec![
54            (Symbol::new("symbol"), SurfaceField::Symbol(symbol)),
55            (
56                Symbol::new("layer"),
57                SurfaceField::Str("stream-host".to_owned()),
58            ),
59            (Symbol::new("kind"), SurfaceField::Str("plugin".to_owned())),
60            (
61                Symbol::new("backend"),
62                SurfaceField::Symbol(coreaudio_backend_symbol()),
63            ),
64            (
65                Symbol::new("transport"),
66                SurfaceField::Symbol(coreaudio_transport_symbol()),
67            ),
68            (Symbol::new("role"), SurfaceField::Str(role.to_owned())),
69            (
70                Symbol::new("audio-priority"),
71                SurfaceField::Symbols(macos_audio_backend_priority()),
72            ),
73            (
74                Symbol::new("midi-priority"),
75                SurfaceField::Symbols(macos_midi_backend_priority()),
76            ),
77            (
78                Symbol::new("native-policy"),
79                SurfaceField::Str(
80                    "Use native CoreAudio when PortAudio or RtAudio is insufficient".to_owned(),
81                ),
82            ),
83        ],
84    }
85}
86
87fn coreaudio_pack() -> SurfacePackLib {
88    SurfacePackLib {
89        spec: SurfacePackSpec {
90            lib_id: Symbol::new(COREAUDIO_LIB_ID),
91            values: coreaudio_symbols()
92                .into_iter()
93                .map(coreaudio_value_spec)
94                .collect(),
95        },
96    }
97}