@devaloop/devalang 0.0.1-alpha.16-hotfix.3 → 0.0.1-alpha.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cargo/config.toml +2 -0
- package/.devalang +10 -10
- package/.github/workflows/ci.yml +0 -1
- package/Cargo.toml +18 -2
- package/README.md +82 -34
- package/docs/CHANGELOG.md +91 -0
- package/docs/ROADMAP.md +7 -4
- package/docs/TODO.md +1 -1
- package/examples/index.deva +55 -35
- package/examples/pattern.deva +5 -5
- package/out-tsc/bin/index.d.ts +2 -0
- package/out-tsc/core/functions/index.d.ts +37 -0
- package/out-tsc/core/functions/index.js +76 -0
- package/out-tsc/core/index.d.ts +6 -0
- package/out-tsc/core/index.js +22 -0
- package/out-tsc/core/types/index.d.ts +4 -0
- package/out-tsc/core/types/index.js +20 -0
- package/out-tsc/core/types/plugin.d.ts +18 -0
- package/out-tsc/core/types/plugin.js +2 -0
- package/out-tsc/core/types/result.d.ts +27 -0
- package/out-tsc/core/types/result.js +2 -0
- package/out-tsc/core/types/statement.d.ts +106 -0
- package/out-tsc/core/types/statement.js +2 -0
- package/out-tsc/core/types/value.d.ts +43 -0
- package/out-tsc/core/types/value.js +2 -0
- package/out-tsc/index.d.ts +7 -0
- package/out-tsc/index.js +41 -2
- package/out-tsc/pkg/devalang_core.d.ts +7 -0
- package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +33 -0
- package/out-tsc/scripts/copy-wasm-dts.d.ts +1 -0
- package/out-tsc/scripts/copy-wasm-dts.js +73 -0
- package/out-tsc/scripts/postinstall.d.ts +1 -0
- package/out-tsc/scripts/postinstall.js +33 -23
- package/out-tsc/scripts/version/bump.d.ts +1 -0
- package/out-tsc/scripts/version/fetch.d.ts +1 -0
- package/out-tsc/scripts/version/index.d.ts +1 -0
- package/out-tsc/scripts/version/sync.d.ts +1 -0
- package/package.json +16 -4
- package/project-version.json +3 -3
- package/rust/cli/bank/api.rs +122 -0
- package/rust/cli/bank/commands.rs +275 -0
- package/rust/cli/bank/mod.rs +29 -0
- package/rust/cli/build/commands.rs +107 -0
- package/rust/cli/build/mod.rs +2 -0
- package/rust/cli/build/process.rs +146 -0
- package/rust/cli/{check.rs → check/mod.rs} +18 -31
- package/rust/cli/discover/commands.rs +253 -0
- package/rust/cli/discover/config.rs +111 -0
- package/rust/cli/discover/fs.rs +19 -0
- package/rust/cli/discover/install.rs +103 -0
- package/rust/cli/discover/metadata.rs +48 -0
- package/rust/cli/discover/mod.rs +5 -0
- package/rust/cli/{init.rs → init/commands.rs} +88 -87
- package/rust/cli/init/mod.rs +1 -0
- package/rust/cli/install/addon.rs +126 -0
- package/rust/cli/install/bank.rs +53 -0
- package/rust/cli/{install.rs → install/commands.rs} +9 -9
- package/rust/{installer → cli/install}/mod.rs +2 -3
- package/rust/cli/install/plugin.rs +61 -0
- package/rust/cli/{login.rs → login/commands.rs} +8 -11
- package/rust/cli/login/mod.rs +1 -0
- package/rust/cli/mod.rs +2 -2
- package/rust/cli/{driver.rs → parser.rs} +7 -2
- package/rust/cli/play/commands.rs +324 -0
- package/rust/cli/play/io.rs +17 -0
- package/rust/cli/play/mod.rs +5 -0
- package/rust/cli/play/process.rs +150 -0
- package/rust/cli/play/realtime.rs +91 -0
- package/rust/cli/play/utils.rs +23 -0
- package/rust/cli/{telemetry.rs → telemetry/commands.rs} +4 -4
- package/rust/cli/telemetry/event_creator.rs +80 -0
- package/rust/cli/telemetry/mod.rs +3 -0
- package/rust/cli/telemetry/send.rs +51 -0
- package/rust/cli/{template.rs → template/commands.rs} +1 -1
- package/rust/cli/template/mod.rs +1 -0
- package/rust/cli/{update.rs → update/commands.rs} +6 -6
- package/rust/cli/update/mod.rs +1 -0
- package/rust/config/driver.rs +57 -72
- package/rust/config/mod.rs +1 -2
- package/rust/config/ops.rs +26 -0
- package/rust/config/settings.rs +40 -42
- package/rust/core/audio/engine/helpers.rs +158 -0
- package/rust/core/audio/engine/mod.rs +7 -0
- package/rust/core/audio/engine/sample.rs +359 -0
- package/rust/core/audio/engine/synth.rs +325 -0
- package/rust/core/audio/evaluator.rs +68 -27
- package/rust/core/audio/interpreter/arrow_call.rs +113 -33
- package/rust/core/audio/interpreter/call.rs +232 -56
- package/rust/core/audio/interpreter/condition.rs +3 -2
- package/rust/core/audio/interpreter/driver.rs +206 -151
- package/rust/core/audio/interpreter/let_.rs +1 -1
- package/rust/core/audio/interpreter/load.rs +2 -1
- package/rust/core/audio/interpreter/loop_.rs +7 -6
- package/rust/core/audio/interpreter/sleep.rs +2 -1
- package/rust/core/audio/interpreter/spawn.rs +186 -54
- package/rust/core/audio/interpreter/tempo.rs +31 -10
- package/rust/core/audio/interpreter/trigger.rs +2 -2
- package/rust/core/audio/loader/trigger.rs +4 -7
- package/rust/core/audio/player.rs +6 -0
- package/rust/core/audio/renderer.rs +5 -7
- package/rust/core/audio/special/env.rs +3 -1
- package/rust/core/audio/special/math.rs +26 -6
- package/rust/core/audio/special/modulator.rs +2 -2
- package/rust/core/builder/mod.rs +9 -3
- package/rust/core/debugger/lexer.rs +1 -1
- package/rust/core/debugger/mod.rs +6 -0
- package/rust/core/debugger/module.rs +4 -4
- package/rust/core/debugger/preprocessor.rs +1 -1
- package/rust/core/debugger/store.rs +2 -2
- package/rust/core/error/mod.rs +189 -0
- package/rust/core/lexer/driver.rs +61 -0
- package/rust/core/lexer/handler/arrow.rs +1 -1
- package/rust/core/lexer/handler/at.rs +1 -1
- package/rust/core/lexer/handler/brace.rs +2 -2
- package/rust/core/lexer/handler/colon.rs +1 -1
- package/rust/core/lexer/handler/comment.rs +1 -1
- package/rust/core/lexer/handler/dot.rs +1 -1
- package/rust/core/lexer/handler/driver.rs +1 -1
- package/rust/core/lexer/handler/identifier.rs +4 -3
- package/rust/core/lexer/handler/mod.rs +1 -2
- package/rust/core/lexer/handler/number.rs +1 -1
- package/rust/core/lexer/handler/operator.rs +1 -1
- package/rust/core/lexer/handler/parenthesis.rs +2 -2
- package/rust/core/lexer/handler/slash.rs +1 -1
- package/rust/core/lexer/handler/string.rs +1 -1
- package/rust/core/lexer/mod.rs +1 -52
- package/rust/core/lexer/token.rs +91 -97
- package/rust/core/mod.rs +0 -1
- package/rust/core/parser/driver.rs +78 -22
- package/rust/core/parser/handler/arrow_call.rs +28 -8
- package/rust/core/parser/handler/at.rs +55 -21
- package/rust/core/parser/handler/bank.rs +14 -4
- package/rust/core/parser/handler/condition.rs +6 -3
- package/rust/core/parser/handler/dot.rs +5 -3
- package/rust/core/parser/handler/identifier/automate.rs +13 -16
- package/rust/core/parser/handler/identifier/call.rs +4 -4
- package/rust/core/parser/handler/identifier/emit.rs +9 -5
- package/rust/core/parser/handler/identifier/function.rs +20 -7
- package/rust/core/parser/handler/identifier/group.rs +11 -7
- package/rust/core/parser/handler/identifier/let_.rs +24 -9
- package/rust/core/parser/handler/identifier/mod.rs +6 -5
- package/rust/core/parser/handler/identifier/on.rs +16 -7
- package/rust/core/parser/handler/identifier/print.rs +6 -9
- package/rust/core/parser/handler/identifier/sleep.rs +12 -5
- package/rust/core/parser/handler/identifier/spawn.rs +4 -4
- package/rust/core/parser/handler/identifier/synth.rs +79 -9
- package/rust/core/parser/handler/loop_.rs +38 -13
- package/rust/core/parser/handler/mod.rs +1 -0
- package/rust/core/parser/handler/pattern.rs +74 -0
- package/rust/core/parser/handler/tempo.rs +9 -5
- package/rust/core/parser/mod.rs +0 -1
- package/rust/core/parser/statement.rs +6 -137
- package/rust/core/plugin/loader.rs +41 -27
- package/rust/core/plugin/runner.rs +68 -17
- package/rust/core/preprocessor/loader.rs +181 -99
- package/rust/core/preprocessor/processor.rs +9 -9
- package/rust/core/preprocessor/resolver/bank.rs +6 -8
- package/rust/core/preprocessor/resolver/call.rs +47 -23
- package/rust/core/preprocessor/resolver/condition.rs +6 -8
- package/rust/core/preprocessor/resolver/driver.rs +28 -28
- package/rust/core/preprocessor/resolver/function.rs +6 -6
- package/rust/core/preprocessor/resolver/group.rs +6 -8
- package/rust/core/preprocessor/resolver/loop_.rs +8 -10
- package/rust/core/preprocessor/resolver/mod.rs +1 -0
- package/rust/core/preprocessor/resolver/pattern.rs +75 -0
- package/rust/core/preprocessor/resolver/spawn.rs +45 -22
- package/rust/core/preprocessor/resolver/synth.rs +6 -8
- package/rust/core/preprocessor/resolver/tempo.rs +6 -8
- package/rust/core/preprocessor/resolver/trigger.rs +22 -19
- package/rust/core/preprocessor/resolver/value.rs +99 -4
- package/rust/core/store/export.rs +28 -28
- package/rust/core/store/function.rs +6 -0
- package/rust/core/store/global.rs +7 -1
- package/rust/core/store/import.rs +28 -28
- package/rust/core/store/variable.rs +16 -2
- package/rust/core/utils/mod.rs +0 -1
- package/rust/lib.rs +102 -9
- package/rust/main.rs +159 -45
- package/rust/types/Cargo.toml +11 -0
- package/rust/types/src/addons.rs +55 -0
- package/rust/types/src/ast.rs +202 -0
- package/rust/types/src/config.rs +74 -0
- package/rust/types/src/lib.rs +12 -0
- package/rust/types/src/telemetry.rs +85 -0
- package/rust/utils/Cargo.toml +26 -0
- package/rust/utils/{error.rs → src/error.rs} +186 -200
- package/rust/utils/src/file.rs +94 -0
- package/rust/utils/src/first_usage.rs +97 -0
- package/rust/utils/{mod.rs → src/lib.rs} +1 -1
- package/rust/utils/{logger.rs → src/logger.rs} +17 -12
- package/rust/utils/src/path.rs +88 -0
- package/rust/utils/src/signature.rs +41 -0
- package/rust/utils/{spinner.rs → src/spinner.rs} +3 -5
- package/rust/utils/src/version.rs +27 -0
- package/rust/utils/{watcher.rs → src/watcher.rs} +13 -1
- package/rust/web/cdn.rs +34 -0
- package/templates/minimal/README.md +98 -54
- package/templates/welcome/README.md +98 -54
- package/templates/welcome/src/index.deva +56 -8
- package/templates/welcome/src/variables.deva +2 -4
- package/tests/rust/TODO.md +0 -0
- package/tests/typescript/index.spec.ts +136 -0
- package/tests/typescript/playhead.spec.ts +36 -0
- package/tests/typescript/render_e2e.spec.ts +77 -0
- package/tsconfig.json +1 -1
- package/typescript/core/functions/index.ts +83 -0
- package/typescript/core/index.ts +6 -0
- package/typescript/core/types/index.ts +4 -0
- package/typescript/core/types/plugin.ts +19 -0
- package/typescript/core/types/result.ts +29 -0
- package/typescript/core/types/statement.ts +47 -0
- package/typescript/core/types/value.ts +29 -0
- package/typescript/index.ts +7 -2
- package/typescript/pkg/devalang_core.d.ts +4 -0
- package/typescript/scripts/copy-wasm-dts.ts +41 -0
- package/rust/cli/bank.rs +0 -462
- package/rust/cli/build.rs +0 -252
- package/rust/cli/play.rs +0 -1123
- package/rust/common/cdn.rs +0 -5
- package/rust/config/loader.rs +0 -165
- package/rust/config/stats.rs +0 -257
- package/rust/core/audio/engine.rs +0 -696
- package/rust/core/shared/bank.rs +0 -21
- package/rust/core/shared/duration.rs +0 -9
- package/rust/core/shared/mod.rs +0 -3
- package/rust/core/shared/value.rs +0 -35
- package/rust/core/utils/validation.rs +0 -35
- package/rust/installer/addon.rs +0 -84
- package/rust/installer/bank.rs +0 -62
- package/rust/installer/plugin.rs +0 -54
- package/rust/installer/utils.rs +0 -56
- package/rust/utils/file.rs +0 -38
- package/rust/utils/first_usage.rs +0 -83
- package/rust/utils/signature.rs +0 -19
- package/rust/utils/telemetry.rs +0 -292
- package/rust/utils/version.rs +0 -15
- /package/rust/{common → web}/api.rs +0 -0
- /package/rust/{common → web}/mod.rs +0 -0
- /package/rust/{common → web}/sso.rs +0 -0
|
@@ -1,142 +1,11 @@
|
|
|
1
|
-
use crate::core::
|
|
2
|
-
lexer::token::Token,
|
|
3
|
-
shared::{duration::Duration, value::Value},
|
|
4
|
-
};
|
|
5
|
-
use serde::{Deserialize, Serialize};
|
|
1
|
+
use crate::core::lexer::token::Token;
|
|
6
2
|
|
|
7
|
-
|
|
8
|
-
pub struct Statement {
|
|
9
|
-
pub kind: StatementKind,
|
|
10
|
-
pub value: Value,
|
|
11
|
-
pub indent: usize,
|
|
12
|
-
pub line: usize,
|
|
13
|
-
pub column: usize,
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
impl Statement {
|
|
17
|
-
pub fn unknown() -> Self {
|
|
18
|
-
Statement {
|
|
19
|
-
kind: StatementKind::Unknown,
|
|
20
|
-
value: Value::Null,
|
|
21
|
-
indent: 0,
|
|
22
|
-
line: 0,
|
|
23
|
-
column: 0,
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
pub fn unknown_from_token(token: &Token) -> Self {
|
|
28
|
-
Statement {
|
|
29
|
-
kind: StatementKind::Unknown,
|
|
30
|
-
value: Value::Null,
|
|
31
|
-
indent: token.indent,
|
|
32
|
-
line: token.line,
|
|
33
|
-
column: token.column,
|
|
34
|
-
}
|
|
35
|
-
}
|
|
3
|
+
pub use devalang_types::{Duration, Statement, StatementKind, Value};
|
|
36
4
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
kind: StatementKind::Error { message },
|
|
40
|
-
value: Value::Null,
|
|
41
|
-
indent: token.indent,
|
|
42
|
-
line: token.line,
|
|
43
|
-
column: token.column,
|
|
44
|
-
}
|
|
45
|
-
}
|
|
5
|
+
pub fn unknown_from_token(token: &Token) -> Statement {
|
|
6
|
+
Statement::unknown_with_pos(token.indent, token.line, token.column)
|
|
46
7
|
}
|
|
47
8
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
// ───── Core Instructions ─────
|
|
51
|
-
Tempo,
|
|
52
|
-
Bank {
|
|
53
|
-
alias: Option<String>,
|
|
54
|
-
},
|
|
55
|
-
Print,
|
|
56
|
-
Load {
|
|
57
|
-
source: String,
|
|
58
|
-
alias: String,
|
|
59
|
-
},
|
|
60
|
-
Use {
|
|
61
|
-
name: String,
|
|
62
|
-
alias: Option<String>,
|
|
63
|
-
},
|
|
64
|
-
Let {
|
|
65
|
-
name: String,
|
|
66
|
-
},
|
|
67
|
-
Automate {
|
|
68
|
-
target: String,
|
|
69
|
-
},
|
|
70
|
-
ArrowCall {
|
|
71
|
-
target: String,
|
|
72
|
-
method: String,
|
|
73
|
-
args: Vec<Value>,
|
|
74
|
-
},
|
|
75
|
-
Function {
|
|
76
|
-
name: String,
|
|
77
|
-
parameters: Vec<String>,
|
|
78
|
-
body: Vec<Statement>,
|
|
79
|
-
},
|
|
80
|
-
|
|
81
|
-
// ───── Instruments ─────
|
|
82
|
-
Synth,
|
|
83
|
-
|
|
84
|
-
// ───── Playback / Scheduling ─────
|
|
85
|
-
Trigger {
|
|
86
|
-
entity: String,
|
|
87
|
-
duration: Duration,
|
|
88
|
-
effects: Option<Value>,
|
|
89
|
-
},
|
|
90
|
-
Sleep,
|
|
91
|
-
Call {
|
|
92
|
-
name: String,
|
|
93
|
-
args: Vec<Value>,
|
|
94
|
-
},
|
|
95
|
-
Spawn {
|
|
96
|
-
name: String,
|
|
97
|
-
args: Vec<Value>,
|
|
98
|
-
},
|
|
99
|
-
Loop,
|
|
100
|
-
|
|
101
|
-
// ───── Structure & Logic ─────
|
|
102
|
-
Group,
|
|
103
|
-
|
|
104
|
-
// ───── Module System ─────
|
|
105
|
-
Include(String),
|
|
106
|
-
Export {
|
|
107
|
-
names: Vec<String>,
|
|
108
|
-
source: String,
|
|
109
|
-
},
|
|
110
|
-
Import {
|
|
111
|
-
names: Vec<String>,
|
|
112
|
-
source: String,
|
|
113
|
-
},
|
|
114
|
-
|
|
115
|
-
// ───── Conditions ─────
|
|
116
|
-
If,
|
|
117
|
-
Else,
|
|
118
|
-
ElseIf,
|
|
119
|
-
|
|
120
|
-
// ───── Internal / Utility ─────
|
|
121
|
-
Comment,
|
|
122
|
-
Indent,
|
|
123
|
-
Dedent,
|
|
124
|
-
NewLine,
|
|
125
|
-
|
|
126
|
-
// ───── Events / Live coding ─────
|
|
127
|
-
On {
|
|
128
|
-
event: String,
|
|
129
|
-
args: Option<Vec<Value>>,
|
|
130
|
-
body: Vec<Statement>,
|
|
131
|
-
},
|
|
132
|
-
Emit {
|
|
133
|
-
event: String,
|
|
134
|
-
payload: Option<Value>,
|
|
135
|
-
},
|
|
136
|
-
|
|
137
|
-
// ───── Error Handling ─────
|
|
138
|
-
Unknown,
|
|
139
|
-
Error {
|
|
140
|
-
message: String,
|
|
141
|
-
},
|
|
9
|
+
pub fn error_from_token(token: Token, message: String) -> Statement {
|
|
10
|
+
Statement::error_with_pos(token.indent, token.line, token.column, message)
|
|
142
11
|
}
|
|
@@ -1,19 +1,10 @@
|
|
|
1
|
+
use devalang_types::{PluginExport, PluginInfo as SharedPluginInfo};
|
|
2
|
+
use devalang_utils::path as path_utils;
|
|
1
3
|
use serde::Deserialize;
|
|
2
|
-
use std::path::Path;
|
|
3
4
|
use toml::Value as TomlValue;
|
|
4
5
|
|
|
5
6
|
#[derive(Debug, Deserialize, Clone)]
|
|
6
|
-
|
|
7
|
-
pub name: String,
|
|
8
|
-
pub version: Option<String>,
|
|
9
|
-
pub description: Option<String>,
|
|
10
|
-
pub author: Option<String>,
|
|
11
|
-
#[serde(skip)]
|
|
12
|
-
pub exports: Vec<ExportEntry>,
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
#[derive(Debug, Deserialize, Clone)]
|
|
16
|
-
pub struct ExportEntry {
|
|
7
|
+
struct LocalExportEntry {
|
|
17
8
|
pub name: String,
|
|
18
9
|
#[serde(rename = "type")]
|
|
19
10
|
pub kind: String,
|
|
@@ -22,24 +13,29 @@ pub struct ExportEntry {
|
|
|
22
13
|
}
|
|
23
14
|
|
|
24
15
|
#[derive(Debug, Deserialize, Clone)]
|
|
25
|
-
|
|
26
|
-
pub plugin:
|
|
16
|
+
struct LocalPluginFile {
|
|
17
|
+
pub plugin: LocalPluginInfo,
|
|
27
18
|
#[serde(default)]
|
|
28
|
-
pub export: Vec<
|
|
19
|
+
pub export: Vec<LocalExportEntry>,
|
|
29
20
|
}
|
|
30
21
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
22
|
+
#[derive(Debug, Deserialize, Clone)]
|
|
23
|
+
struct LocalPluginInfo {
|
|
24
|
+
pub name: String,
|
|
25
|
+
pub version: Option<String>,
|
|
26
|
+
pub description: Option<String>,
|
|
27
|
+
pub author: Option<String>,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
pub fn load_plugin(author: &str, name: &str) -> Result<(SharedPluginInfo, Vec<u8>), String> {
|
|
31
|
+
let root = path_utils::get_deva_dir()?;
|
|
32
|
+
let plugin_dir_preferred = root.join("plugins").join(format!("{}.{}", author, name));
|
|
37
33
|
let toml_path_preferred = plugin_dir_preferred.join("plugin.toml");
|
|
38
34
|
let wasm_path_preferred_bg = plugin_dir_preferred.join(format!("{}_bg.wasm", name));
|
|
39
35
|
let wasm_path_preferred_plain = plugin_dir_preferred.join(format!("{}.wasm", name));
|
|
40
36
|
|
|
41
37
|
// Legacy layout (fallback): ./.deva/plugin/<author>/<name>/
|
|
42
|
-
let plugin_dir_fallback = root.join("
|
|
38
|
+
let plugin_dir_fallback = root.join("plugins").join(author).join(name);
|
|
43
39
|
let toml_path_fallback = plugin_dir_fallback.join("plugin.toml");
|
|
44
40
|
let wasm_path_fallback_bg = plugin_dir_fallback.join(format!("{}_bg.wasm", name));
|
|
45
41
|
let wasm_path_fallback_plain = plugin_dir_fallback.join(format!("{}.wasm", name));
|
|
@@ -74,20 +70,38 @@ pub fn load_plugin(author: &str, name: &str) -> Result<(PluginInfo, Vec<u8>), St
|
|
|
74
70
|
|
|
75
71
|
let toml_content = std::fs::read_to_string(&toml_path)
|
|
76
72
|
.map_err(|e| format!("Failed to read '{}': {}", toml_path.display(), e))?;
|
|
77
|
-
let plugin_file:
|
|
73
|
+
let plugin_file: LocalPluginFile = toml::from_str(&toml_content)
|
|
78
74
|
.map_err(|e| format!("Failed to parse '{}': {}", toml_path.display(), e))?;
|
|
79
75
|
|
|
80
76
|
let wasm_bytes = std::fs::read(&wasm_path)
|
|
81
77
|
.map_err(|e| format!("Failed to read '{}': {}", wasm_path.display(), e))?;
|
|
82
78
|
|
|
83
|
-
|
|
84
|
-
|
|
79
|
+
// Map local parsed plugin info to shared PluginInfo
|
|
80
|
+
let mut exports: Vec<PluginExport> = Vec::new();
|
|
81
|
+
for e in plugin_file.export.iter() {
|
|
82
|
+
exports.push(PluginExport {
|
|
83
|
+
name: e.name.clone(),
|
|
84
|
+
kind: e.kind.clone(),
|
|
85
|
+
default: e.default.clone(),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let info = SharedPluginInfo {
|
|
90
|
+
author: plugin_file
|
|
91
|
+
.plugin
|
|
92
|
+
.author
|
|
93
|
+
.unwrap_or_else(|| author.to_string()),
|
|
94
|
+
name: plugin_file.plugin.name.clone(),
|
|
95
|
+
version: plugin_file.plugin.version.clone(),
|
|
96
|
+
description: plugin_file.plugin.description.clone(),
|
|
97
|
+
exports,
|
|
98
|
+
};
|
|
85
99
|
|
|
86
100
|
Ok((info, wasm_bytes))
|
|
87
101
|
}
|
|
88
102
|
|
|
89
103
|
/// Load a plugin from dot notation: "author.name"
|
|
90
|
-
pub fn load_plugin_from_dot(dot: &str) -> Result<(
|
|
104
|
+
pub fn load_plugin_from_dot(dot: &str) -> Result<(SharedPluginInfo, Vec<u8>), String> {
|
|
91
105
|
let mut parts = dot.split('.');
|
|
92
106
|
let author = parts
|
|
93
107
|
.next()
|
|
@@ -101,7 +115,7 @@ pub fn load_plugin_from_dot(dot: &str) -> Result<(PluginInfo, Vec<u8>), String>
|
|
|
101
115
|
load_plugin(author, name)
|
|
102
116
|
}
|
|
103
117
|
|
|
104
|
-
pub fn load_plugin_from_uri(uri: &str) -> Result<(
|
|
118
|
+
pub fn load_plugin_from_uri(uri: &str) -> Result<(SharedPluginInfo, Vec<u8>), String> {
|
|
105
119
|
if !uri.starts_with("devalang://plugin/") {
|
|
106
120
|
return Err("Invalid plugin URI".into());
|
|
107
121
|
}
|
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
use std::collections::HashMap;
|
|
2
|
+
|
|
3
|
+
#[cfg(not(target_arch = "wasm32"))]
|
|
2
4
|
use wasmtime::{Engine, Instance, Linker, Module, Store, TypedFunc};
|
|
3
5
|
|
|
6
|
+
#[cfg(not(target_arch = "wasm32"))]
|
|
7
|
+
type RenderFunc = TypedFunc<(i32, i32, f32, f32, i32, i32, i32), ()>;
|
|
8
|
+
|
|
9
|
+
#[cfg(not(target_arch = "wasm32"))]
|
|
4
10
|
pub struct WasmPluginRunner {
|
|
5
11
|
engine: Engine,
|
|
6
12
|
}
|
|
7
13
|
|
|
14
|
+
#[cfg(not(target_arch = "wasm32"))]
|
|
15
|
+
impl Default for WasmPluginRunner {
|
|
16
|
+
fn default() -> Self {
|
|
17
|
+
Self::new()
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
#[cfg(not(target_arch = "wasm32"))]
|
|
8
22
|
impl WasmPluginRunner {
|
|
9
23
|
pub fn new() -> Self {
|
|
10
24
|
let engine = Engine::default();
|
|
@@ -18,38 +32,32 @@ impl WasmPluginRunner {
|
|
|
18
32
|
let mut store = Store::new(&self.engine, ());
|
|
19
33
|
let linker = Linker::new(&self.engine);
|
|
20
34
|
|
|
21
|
-
// Instantiate
|
|
22
35
|
let instance = linker
|
|
23
36
|
.instantiate(&mut store, &module)
|
|
24
37
|
.map_err(|e| format!("Failed to instantiate wasm: {e}"))?;
|
|
25
38
|
|
|
26
|
-
// Get exports
|
|
27
39
|
let memory = instance
|
|
28
40
|
.get_memory(&mut store, "memory")
|
|
29
41
|
.ok_or_else(|| "WASM memory export not found".to_string())?;
|
|
30
42
|
|
|
31
|
-
// wasm-bindgen usually exports a function taking (ptr: i32, len: i32) to represent &mut [f32]
|
|
32
43
|
let func = instance
|
|
33
44
|
.get_typed_func::<(i32, i32), ()>(&mut store, "process")
|
|
34
45
|
.map_err(|_| "Exported function `process(i32,i32)` not found".to_string())?;
|
|
35
46
|
|
|
36
|
-
|
|
37
|
-
let byte_len = (buffer.len() * std::mem::size_of::<f32>()) as i32;
|
|
47
|
+
let byte_len = std::mem::size_of_val(buffer) as i32;
|
|
38
48
|
let ptr = Self::alloc_temp(&mut store, &instance, &memory, byte_len as usize)? as i32;
|
|
39
49
|
let mem_slice = memory
|
|
40
50
|
.data_mut(&mut store)
|
|
41
51
|
.get_mut(ptr as usize..(ptr as usize) + (byte_len as usize))
|
|
42
52
|
.ok_or_else(|| "Failed to get memory slice".to_string())?;
|
|
43
|
-
|
|
53
|
+
|
|
44
54
|
let src_bytes =
|
|
45
55
|
unsafe { std::slice::from_raw_parts(buffer.as_ptr() as *const u8, byte_len as usize) };
|
|
46
56
|
mem_slice.copy_from_slice(src_bytes);
|
|
47
57
|
|
|
48
|
-
// Call process
|
|
49
58
|
func.call(&mut store, (ptr, buffer.len() as i32))
|
|
50
59
|
.map_err(|e| format!("Error calling `process`: {e}"))?;
|
|
51
60
|
|
|
52
|
-
// Copy back
|
|
53
61
|
let mem_slice_after = memory
|
|
54
62
|
.data(&store)
|
|
55
63
|
.get(ptr as usize..(ptr as usize) + (byte_len as usize))
|
|
@@ -62,8 +70,6 @@ impl WasmPluginRunner {
|
|
|
62
70
|
Ok(())
|
|
63
71
|
}
|
|
64
72
|
|
|
65
|
-
/// Render a note by invoking either `render_note_<name>` or a generic `render_note(ptr,len,freq,amp,duration_ms,sample_rate,channels)`.
|
|
66
|
-
/// The buffer is interleaved stereo if channels=2. The buffer is modified in place.
|
|
67
73
|
pub fn render_note_in_place(
|
|
68
74
|
&self,
|
|
69
75
|
wasm_bytes: &[u8],
|
|
@@ -90,7 +96,7 @@ impl WasmPluginRunner {
|
|
|
90
96
|
.ok_or_else(|| "WASM memory export not found".to_string())?;
|
|
91
97
|
|
|
92
98
|
// Try specific function first
|
|
93
|
-
let mut func_opt: Option<
|
|
99
|
+
let mut func_opt: Option<RenderFunc> = None;
|
|
94
100
|
if let Some(name) = synth_name {
|
|
95
101
|
let specific = format!("render_note_{}", name);
|
|
96
102
|
if let Ok(f) = instance
|
|
@@ -113,7 +119,7 @@ impl WasmPluginRunner {
|
|
|
113
119
|
func_opt.ok_or_else(|| "Exported function `render_note` not found".to_string())?;
|
|
114
120
|
|
|
115
121
|
// Copy host buffer into wasm memory
|
|
116
|
-
let byte_len =
|
|
122
|
+
let byte_len = std::mem::size_of_val(buffer) as i32;
|
|
117
123
|
let ptr = Self::alloc_temp(&mut store, &instance, &memory, byte_len as usize)? as i32;
|
|
118
124
|
let mem_slice = memory
|
|
119
125
|
.data_mut(&mut store)
|
|
@@ -207,7 +213,7 @@ impl WasmPluginRunner {
|
|
|
207
213
|
}
|
|
208
214
|
|
|
209
215
|
// Try specific or generic render function
|
|
210
|
-
let mut func_opt: Option<
|
|
216
|
+
let mut func_opt: Option<RenderFunc> = None;
|
|
211
217
|
if let Some(name) = synth_name {
|
|
212
218
|
let specific = format!("render_note_{}", name);
|
|
213
219
|
if let Ok(f) = instance
|
|
@@ -228,7 +234,7 @@ impl WasmPluginRunner {
|
|
|
228
234
|
func_opt.ok_or_else(|| "Exported function `render_note` not found".to_string())?;
|
|
229
235
|
|
|
230
236
|
// Copy host buffer into wasm memory
|
|
231
|
-
let byte_len =
|
|
237
|
+
let byte_len = std::mem::size_of_val(buffer) as i32;
|
|
232
238
|
let ptr = Self::alloc_temp(&mut store, &instance, &memory, byte_len as usize)? as i32;
|
|
233
239
|
let mem_slice = memory
|
|
234
240
|
.data_mut(&mut store)
|
|
@@ -283,10 +289,10 @@ impl WasmPluginRunner {
|
|
|
283
289
|
// Fallback: grow memory and use end of memory as scratch space
|
|
284
290
|
let current_len = memory.data_size(&mut *store);
|
|
285
291
|
let need = size;
|
|
286
|
-
let pages_needed = (
|
|
292
|
+
let pages_needed = (current_len + need).div_ceil(0x10000) as u64; // 64KiB pages
|
|
287
293
|
let current_pages = memory.size(&mut *store);
|
|
288
|
-
if pages_needed >
|
|
289
|
-
let to_grow = pages_needed -
|
|
294
|
+
if pages_needed > current_pages {
|
|
295
|
+
let to_grow = pages_needed - current_pages;
|
|
290
296
|
memory
|
|
291
297
|
.grow(&mut *store, to_grow)
|
|
292
298
|
.map_err(|e| format!("memory.grow failed: {e}"))?;
|
|
@@ -294,3 +300,48 @@ impl WasmPluginRunner {
|
|
|
294
300
|
Ok(current_len)
|
|
295
301
|
}
|
|
296
302
|
}
|
|
303
|
+
|
|
304
|
+
// Provide a minimal stub for wasm32 target so the crate compiles there.
|
|
305
|
+
#[cfg(target_arch = "wasm32")]
|
|
306
|
+
pub struct WasmPluginRunner;
|
|
307
|
+
|
|
308
|
+
#[cfg(target_arch = "wasm32")]
|
|
309
|
+
impl WasmPluginRunner {
|
|
310
|
+
pub fn new() -> Self {
|
|
311
|
+
WasmPluginRunner
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
pub fn process_in_place(&self, _wasm_bytes: &[u8], _buffer: &mut [f32]) -> Result<(), String> {
|
|
315
|
+
Err("Wasm plugin execution is not available in wasm builds".to_string())
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
pub fn render_note_in_place(
|
|
319
|
+
&self,
|
|
320
|
+
_wasm_bytes: &[u8],
|
|
321
|
+
_buffer: &mut [f32],
|
|
322
|
+
_synth_name: Option<&str>,
|
|
323
|
+
_freq: f32,
|
|
324
|
+
_amp: f32,
|
|
325
|
+
_duration_ms: i32,
|
|
326
|
+
_sample_rate: i32,
|
|
327
|
+
_channels: i32,
|
|
328
|
+
) -> Result<(), String> {
|
|
329
|
+
Err("Wasm plugin rendering is not available in wasm builds".to_string())
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
pub fn render_note_with_params_in_place(
|
|
333
|
+
&self,
|
|
334
|
+
_wasm_bytes: &[u8],
|
|
335
|
+
_buffer: &mut [f32],
|
|
336
|
+
_synth_name: Option<&str>,
|
|
337
|
+
_freq: f32,
|
|
338
|
+
_amp: f32,
|
|
339
|
+
_duration_ms: i32,
|
|
340
|
+
_sample_rate: i32,
|
|
341
|
+
_channels: i32,
|
|
342
|
+
_params_num: &HashMap<String, f32>,
|
|
343
|
+
_params_str: Option<&HashMap<String, String>>,
|
|
344
|
+
) -> Result<(), String> {
|
|
345
|
+
Err("Wasm plugin rendering is not available in wasm builds".to_string())
|
|
346
|
+
}
|
|
347
|
+
}
|