1use sim_kernel::{
2 AbiVersion, Cx, Export, ExportKind, ExportRecord, ExportState, Lib, LibManifest, LibTarget,
3 Linker, Result, RuntimeId, Symbol, Version,
4};
5
6const SOUND_BRIDGE_LIB_ID: &str = "sound-bridge";
7const BRIDGE_EXPORT_KIND: &str = "Bridge";
8const REGISTRY_SYMBOL_NAME: &str = "BridgeRegistry";
9
10pub struct SoundBridgeLib;
12
13impl Lib for SoundBridgeLib {
14 fn manifest(&self) -> LibManifest {
15 LibManifest {
16 id: Symbol::new(SOUND_BRIDGE_LIB_ID),
17 version: Version(env!("CARGO_PKG_VERSION").to_owned()),
18 abi: AbiVersion { major: 0, minor: 1 },
19 target: LibTarget::HostRegistered,
20 requires: Vec::new(),
21 capabilities: Vec::new(),
22 exports: bridge_symbols()
23 .into_iter()
24 .chain(std::iter::once(registry_symbol()))
25 .map(|symbol| Export::Value { symbol })
26 .collect(),
27 }
28 }
29
30 fn load(&self, cx: &mut sim_kernel::LoadCx, linker: &mut Linker<'_>) -> Result<()> {
31 for symbol in bridge_symbols() {
32 linker.value(symbol.clone(), bridge_value(cx, symbol.clone())?)?;
33 }
34 linker.value(registry_symbol(), registry_value(cx)?)?;
35 Ok(())
36 }
37}
38
39pub fn install_sound_bridge_lib(cx: &mut Cx) -> Result<()> {
42 let lib = Symbol::new(SOUND_BRIDGE_LIB_ID);
43 if !sim_lib_core::install_once(cx, &SoundBridgeLib)? {
44 return Ok(());
45 }
46 for symbol in bridge_symbols() {
47 cx.registry_mut().append_export_record(
48 &lib,
49 ExportRecord {
50 kind: ExportKind::named(BRIDGE_EXPORT_KIND),
51 symbol,
52 state: ExportState::Resolved {
53 id: RuntimeId::Value,
54 },
55 },
56 )?;
57 }
58 Ok(())
59}
60
61fn bridge_symbols() -> Vec<Symbol> {
62 vec![
63 Symbol::qualified("sound", "MidiToSoundBridge"),
64 Symbol::qualified("sound", "VoicePool"),
65 Symbol::qualified("sound", "TimbreBank"),
66 ]
67}
68
69fn registry_symbol() -> Symbol {
70 Symbol::qualified("sound", REGISTRY_SYMBOL_NAME)
71}
72
73fn registry_value(cx: &mut sim_kernel::LoadCx) -> Result<sim_kernel::Value> {
74 let bridges = cx.factory().list(
75 bridge_symbols()
76 .into_iter()
77 .map(|symbol| cx.factory().symbol(symbol))
78 .collect::<Result<Vec<_>>>()?,
79 )?;
80 cx.factory().table(vec![
81 (
82 Symbol::new("symbol"),
83 cx.factory().symbol(registry_symbol())?,
84 ),
85 (
86 Symbol::new("layer"),
87 cx.factory().string("sound".to_owned())?,
88 ),
89 (
90 Symbol::new("kind"),
91 cx.factory().string("bridge".to_owned())?,
92 ),
93 (
94 Symbol::new("shape"),
95 cx.factory()
96 .symbol(Symbol::qualified("sound", "MidiToSoundBridge"))?,
97 ),
98 (Symbol::new("dependencies"), cx.factory().list(Vec::new())?),
99 (Symbol::new("lossless"), cx.factory().bool(false)?),
100 (Symbol::new("capabilities"), cx.factory().list(Vec::new())?),
101 (Symbol::new("bridges"), bridges),
102 ])
103}
104
105fn bridge_value(cx: &mut sim_kernel::LoadCx, symbol: Symbol) -> Result<sim_kernel::Value> {
106 let dependencies = match &*symbol.name {
107 "MidiToSoundBridge" => vec![
108 cx.factory().string("midi-core".to_owned())?,
109 cx.factory().string("sound-timbre".to_owned())?,
110 cx.factory().string("sound-tuning".to_owned())?,
111 ],
112 "VoicePool" => vec![cx.factory().string("sound-core".to_owned())?],
113 "TimbreBank" => vec![cx.factory().string("sound-timbre".to_owned())?],
114 _ => Vec::new(),
115 };
116 cx.factory().table(vec![
117 (Symbol::new("symbol"), cx.factory().symbol(symbol)?),
118 (
119 Symbol::new("layer"),
120 cx.factory().string("sound".to_owned())?,
121 ),
122 (
123 Symbol::new("kind"),
124 cx.factory().string("bridge".to_owned())?,
125 ),
126 (
127 Symbol::new("shape"),
128 cx.factory()
129 .symbol(Symbol::qualified("sound", "MidiToSoundBridge"))?,
130 ),
131 (
132 Symbol::new("dependencies"),
133 cx.factory().list(dependencies)?,
134 ),
135 (Symbol::new("lossless"), cx.factory().bool(false)?),
136 (Symbol::new("capabilities"), cx.factory().list(Vec::new())?),
137 ])
138}