Skip to main content

sim_lib_music_notation/
runtime.rs

1use sim_kernel::{
2    Cx, ExportKind, ExportRecord, ExportState, Lib, LibManifest, Linker, LoadCx, Result, RuntimeId,
3    Symbol,
4};
5use sim_lib_core::{SurfaceField, SurfacePackLib, SurfacePackSpec, SurfaceValueSpec, install_once};
6
7const MUSIC_NOTATION_LIB_ID: &str = "music-notation";
8const EXPORT_KIND_NAME: &str = "NotationCodec";
9
10/// Host-registered lib exporting the LilyPond subset notation-codec card, built
11/// on the shared [`SurfacePackLib`] substrate.
12pub struct MusicNotationLib;
13
14impl Lib for MusicNotationLib {
15    fn manifest(&self) -> LibManifest {
16        music_notation_pack().manifest()
17    }
18
19    fn load(&self, cx: &mut LoadCx, linker: &mut Linker<'_>) -> Result<()> {
20        music_notation_pack().load(cx, linker)
21    }
22}
23
24/// Installs the music-notation lib into `cx` and records its codec export.
25///
26/// Idempotent: returns early if the lib is already installed.
27pub fn install_music_notation_lib(cx: &mut Cx) -> Result<()> {
28    if !install_once(cx, &MusicNotationLib)? {
29        return Ok(());
30    }
31    let lib = Symbol::new(MUSIC_NOTATION_LIB_ID);
32    cx.registry_mut().append_export_record(
33        &lib,
34        ExportRecord {
35            kind: ExportKind::named(EXPORT_KIND_NAME),
36            symbol: notation_symbol(),
37            state: ExportState::Resolved {
38                id: RuntimeId::Value,
39            },
40        },
41    )?;
42    Ok(())
43}
44
45fn notation_symbol() -> Symbol {
46    Symbol::qualified("music", "LilyPondSubsetCodec")
47}
48
49fn notation_value_spec() -> SurfaceValueSpec {
50    SurfaceValueSpec {
51        symbol: notation_symbol(),
52        fields: vec![
53            (
54                Symbol::new("symbol"),
55                SurfaceField::Symbol(notation_symbol()),
56            ),
57            (Symbol::new("layer"), SurfaceField::Str("music".to_owned())),
58            (Symbol::new("kind"), SurfaceField::Str("plugin".to_owned())),
59            (
60                Symbol::new("shape"),
61                SurfaceField::Symbol(Symbol::qualified("music", "NotationCodec")),
62            ),
63            (
64                Symbol::new("dependencies"),
65                SurfaceField::Strs(vec!["music-core".to_owned(), "pitch-core".to_owned()]),
66            ),
67            (Symbol::new("lossless"), SurfaceField::Bool(false)),
68            (Symbol::new("capabilities"), SurfaceField::Symbols(vec![])),
69            (
70                Symbol::new("surface"),
71                SurfaceField::Str("lilypond-subset".to_owned()),
72            ),
73        ],
74    }
75}
76
77fn music_notation_pack() -> SurfacePackLib {
78    SurfacePackLib {
79        spec: SurfacePackSpec {
80            lib_id: Symbol::new(MUSIC_NOTATION_LIB_ID),
81            values: vec![notation_value_spec()],
82        },
83    }
84}