@devaloop/devalang 0.0.1-beta.1 → 0.0.1-beta.2
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/.devalang +9 -10
- package/Cargo.toml +5 -4
- package/README.md +7 -5
- package/docs/CHANGELOG.md +42 -0
- package/docs/ROADMAP.md +5 -1
- package/docs/TODO.md +3 -14
- package/examples/bus.deva +10 -0
- package/examples/effect.deva +2 -0
- package/examples/filter.deva +11 -0
- package/examples/lfo.deva +9 -0
- package/examples/synth.deva +11 -1
- package/examples/synth_types.deva +17 -0
- package/out-tsc/core/functions/index.d.ts +5 -0
- package/out-tsc/core/functions/index.js +11 -0
- package/out-tsc/pkg/devalang_core.d.ts +2 -0
- package/out-tsc/pkg/devalang_core.js +17 -2
- package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +8 -7
- package/package.json +1 -1
- package/project-version.json +3 -3
- package/rust/cli/bank/api.rs +122 -122
- package/rust/cli/bank/commands.rs +33 -2
- package/rust/cli/bank/mod.rs +29 -29
- package/rust/cli/build/commands.rs +53 -3
- package/rust/cli/build/mod.rs +2 -2
- package/rust/cli/build/process.rs +26 -7
- package/rust/cli/check/mod.rs +2 -2
- package/rust/cli/discover/commands.rs +253 -253
- package/rust/cli/discover/config.rs +111 -111
- package/rust/cli/discover/fs.rs +19 -19
- package/rust/cli/discover/install.rs +103 -103
- package/rust/cli/discover/metadata.rs +48 -48
- package/rust/cli/discover/mod.rs +5 -5
- package/rust/cli/install/addon.rs +118 -118
- package/rust/cli/install/bank.rs +22 -3
- package/rust/cli/install/commands.rs +35 -35
- package/rust/cli/install/mod.rs +4 -4
- package/rust/cli/install/plugin.rs +80 -61
- package/rust/cli/login/commands.rs +124 -124
- package/rust/cli/mod.rs +12 -12
- package/rust/cli/parser.rs +46 -1
- package/rust/cli/play/commands.rs +71 -20
- package/rust/cli/play/mod.rs +5 -5
- package/rust/cli/play/process.rs +14 -5
- package/rust/cli/play/realtime.rs +91 -91
- package/rust/cli/telemetry/commands.rs +22 -22
- package/rust/cli/telemetry/event_creator.rs +80 -80
- package/rust/cli/telemetry/mod.rs +3 -3
- package/rust/cli/telemetry/send.rs +51 -51
- package/rust/cli/template/commands.rs +69 -69
- package/rust/config/driver.rs +112 -103
- package/rust/config/mod.rs +3 -3
- package/rust/config/ops.rs +26 -26
- package/rust/config/settings.rs +101 -101
- package/rust/core/audio/engine/driver.rs +220 -0
- package/rust/core/audio/engine/export.rs +169 -0
- package/rust/core/audio/engine/helpers.rs +178 -170
- package/rust/core/audio/engine/mod.rs +51 -2
- package/rust/core/audio/engine/notes/dsp.rs +85 -0
- package/rust/core/audio/engine/notes/mod.rs +44 -0
- package/rust/core/audio/engine/notes/params.rs +294 -0
- package/rust/core/audio/engine/sample/insert.rs +199 -0
- package/rust/core/audio/engine/sample/mod.rs +40 -0
- package/rust/core/audio/engine/sample/padding.rs +170 -0
- package/rust/core/audio/evaluator/condition.rs +61 -0
- package/rust/core/audio/evaluator/mod.rs +9 -0
- package/rust/core/audio/{evaluator.rs → evaluator/numeric.rs} +1 -159
- package/rust/core/audio/evaluator/rhs.rs +16 -0
- package/rust/core/audio/evaluator/string_expr.rs +94 -0
- package/rust/core/audio/interpreter/driver.rs +55 -23
- package/rust/core/audio/interpreter/mod.rs +1 -13
- package/rust/core/audio/interpreter/statements/arrow_call/interprete.rs +175 -0
- package/rust/core/audio/interpreter/statements/arrow_call/methods/chord.rs +384 -0
- package/rust/core/audio/interpreter/statements/arrow_call/methods/mod.rs +2 -0
- package/rust/core/audio/interpreter/statements/arrow_call/methods/note.rs +316 -0
- package/rust/core/audio/interpreter/statements/arrow_call/mod.rs +3 -0
- package/rust/core/audio/interpreter/statements/arrow_call/types/arp.rs +192 -0
- package/rust/core/audio/interpreter/statements/arrow_call/types/mod.rs +24 -0
- package/rust/core/audio/interpreter/statements/arrow_call/types/pad.rs +116 -0
- package/rust/core/audio/interpreter/statements/arrow_call/types/pluck.rs +97 -0
- package/rust/core/audio/interpreter/statements/arrow_call/types/sub.rs +100 -0
- package/rust/core/audio/interpreter/{automate.rs → statements/automate.rs} +16 -18
- package/rust/core/audio/interpreter/{call.rs → statements/call.rs} +5 -4
- package/rust/core/audio/interpreter/{condition.rs → statements/condition.rs} +2 -1
- package/rust/core/audio/interpreter/{function.rs → statements/function.rs} +2 -4
- package/rust/core/audio/interpreter/{let_.rs → statements/let_.rs} +2 -4
- package/rust/core/audio/interpreter/{load.rs → statements/load.rs} +2 -4
- package/rust/core/audio/interpreter/{loop_.rs → statements/loop_.rs} +2 -1
- package/rust/core/audio/interpreter/statements/mod.rs +12 -0
- package/rust/core/audio/interpreter/{sleep.rs → statements/sleep.rs} +28 -28
- package/rust/core/audio/interpreter/{spawn.rs → statements/spawn.rs} +3 -2
- package/rust/core/audio/interpreter/{tempo.rs → statements/tempo.rs} +40 -40
- package/rust/core/audio/interpreter/{trigger.rs → statements/trigger.rs} +1 -1
- package/rust/core/audio/loader/trigger.rs +2 -1
- package/rust/core/audio/mod.rs +6 -7
- package/rust/core/audio/player.rs +70 -70
- package/rust/core/audio/special/easing.rs +189 -189
- package/rust/core/audio/special/env.rs +45 -45
- package/rust/core/audio/special/math.rs +134 -134
- package/rust/core/audio/special/mod.rs +9 -9
- package/rust/core/audio/special/modulator.rs +143 -143
- package/rust/core/builder/mod.rs +45 -2
- package/rust/core/debugger/lexer.rs +27 -27
- package/rust/core/debugger/{module.rs → logs.rs} +3 -6
- package/rust/core/debugger/mod.rs +30 -30
- package/rust/core/debugger/preprocessor.rs +27 -27
- package/rust/core/debugger/store.rs +2 -4
- package/rust/core/error/mod.rs +269 -269
- package/rust/core/lexer/driver.rs +59 -61
- package/rust/core/lexer/handler/arrow.rs +82 -82
- package/rust/core/lexer/handler/at.rs +21 -21
- package/rust/core/lexer/handler/brace.rs +41 -41
- package/rust/core/lexer/handler/colon.rs +21 -21
- package/rust/core/lexer/handler/comment.rs +30 -30
- package/rust/core/lexer/handler/dot.rs +21 -21
- package/rust/core/lexer/handler/driver.rs +337 -337
- package/rust/core/lexer/handler/identifier.rs +47 -47
- package/rust/core/lexer/handler/indent.rs +66 -66
- package/rust/core/lexer/handler/mod.rs +15 -15
- package/rust/core/lexer/handler/newline.rs +23 -23
- package/rust/core/lexer/handler/number.rs +31 -31
- package/rust/core/lexer/handler/operator.rs +46 -46
- package/rust/core/lexer/handler/parenthesis.rs +41 -41
- package/rust/core/lexer/handler/slash.rs +21 -21
- package/rust/core/lexer/handler/string.rs +63 -63
- package/rust/core/lexer/mod.rs +3 -3
- package/rust/core/mod.rs +0 -1
- package/rust/core/parser/driver/block.rs +111 -0
- package/rust/core/parser/driver/cursor.rs +82 -0
- package/rust/core/parser/driver/driver_impl.rs +139 -0
- package/rust/core/parser/driver/mod.rs +6 -0
- package/rust/core/parser/driver/parse_array.rs +120 -0
- package/rust/core/parser/driver/parse_map.rs +223 -0
- package/rust/core/parser/driver/parser.rs +160 -0
- package/rust/core/parser/handler/arrow_call.rs +28 -4
- package/rust/core/parser/handler/at.rs +279 -279
- package/rust/core/parser/handler/bank.rs +104 -104
- package/rust/core/parser/handler/condition.rs +83 -83
- package/rust/core/parser/handler/dot.rs +148 -148
- package/rust/core/parser/handler/identifier/automate.rs +254 -254
- package/rust/core/parser/handler/identifier/call.rs +91 -91
- package/rust/core/parser/handler/identifier/emit.rs +70 -70
- package/rust/core/parser/handler/identifier/function.rs +113 -113
- package/rust/core/parser/handler/identifier/group.rs +89 -89
- package/rust/core/parser/handler/identifier/let_.rs +173 -173
- package/rust/core/parser/handler/identifier/mod.rs +55 -55
- package/rust/core/parser/handler/identifier/on.rs +107 -107
- package/rust/core/parser/handler/identifier/print.rs +49 -49
- package/rust/core/parser/handler/identifier/sleep.rs +96 -43
- package/rust/core/parser/handler/identifier/spawn.rs +91 -91
- package/rust/core/parser/handler/identifier/synth.rs +135 -135
- package/rust/core/parser/handler/loop_.rs +194 -194
- package/rust/core/parser/handler/mod.rs +9 -9
- package/rust/core/parser/handler/pattern.rs +1 -1
- package/rust/core/parser/handler/tempo.rs +105 -57
- package/rust/core/parser/statement.rs +10 -11
- package/rust/core/plugin/loader.rs +1 -1
- package/rust/core/plugin/mod.rs +2 -2
- package/rust/core/plugin/runner/mod.rs +11 -0
- package/rust/core/plugin/{runner.rs → runner/non_wasm.rs} +297 -347
- package/rust/core/plugin/runner/wasm32.rs +43 -0
- package/rust/core/preprocessor/loader/inject.rs +278 -0
- package/rust/core/preprocessor/loader/loader_helpers.rs +110 -0
- package/rust/core/preprocessor/loader/mod.rs +235 -0
- package/rust/core/preprocessor/module.rs +2 -7
- package/rust/core/preprocessor/{processor.rs → processor/handlers.rs} +6 -13
- package/rust/core/preprocessor/processor/mod.rs +1 -0
- package/rust/core/preprocessor/resolver/bank.rs +49 -49
- package/rust/core/preprocessor/resolver/call.rs +124 -124
- package/rust/core/preprocessor/resolver/condition.rs +95 -95
- package/rust/core/preprocessor/resolver/driver.rs +324 -324
- package/rust/core/preprocessor/resolver/function.rs +2 -2
- package/rust/core/preprocessor/resolver/group.rs +46 -18
- package/rust/core/preprocessor/resolver/let_.rs +32 -32
- package/rust/core/preprocessor/resolver/loop_.rs +318 -318
- package/rust/core/preprocessor/resolver/mod.rs +16 -16
- package/rust/core/preprocessor/resolver/pattern.rs +83 -83
- package/rust/core/preprocessor/resolver/spawn.rs +99 -99
- package/rust/core/preprocessor/resolver/synth.rs +54 -54
- package/rust/core/preprocessor/resolver/tempo.rs +48 -48
- package/rust/core/preprocessor/resolver/trigger.rs +116 -116
- package/rust/core/preprocessor/resolver/value.rs +176 -176
- package/rust/core/store/global.rs +2 -6
- package/rust/core/store/mod.rs +1 -5
- package/rust/lib.rs +18 -3
- package/rust/main.rs +27 -3
- package/rust/types/Cargo.toml +1 -1
- package/rust/types/src/addons.rs +55 -55
- package/rust/types/src/config.rs +84 -74
- package/rust/types/src/lib.rs +15 -12
- package/rust/types/src/plugin.rs +20 -0
- package/rust/types/src/store.rs +139 -0
- package/rust/types/src/telemetry.rs +85 -85
- package/rust/utils/Cargo.toml +2 -2
- package/rust/utils/src/file.rs +94 -94
- package/rust/utils/src/first_usage.rs +97 -97
- package/rust/utils/src/lib.rs +9 -9
- package/rust/utils/src/logger.rs +200 -200
- package/rust/utils/src/path.rs +129 -88
- package/rust/utils/src/signature.rs +41 -41
- package/rust/utils/src/spinner.rs +20 -20
- package/rust/utils/src/version.rs +27 -27
- package/rust/utils/src/watcher.rs +46 -46
- package/rust/web/api.rs +5 -5
- package/rust/web/cdn.rs +34 -34
- package/rust/web/mod.rs +3 -3
- package/tests/integration.rs +21 -21
- package/typescript/core/functions/index.ts +11 -0
- package/typescript/pkg/devalang_core.ts +20 -4
- package/rust/core/audio/engine/sample.rs +0 -366
- package/rust/core/audio/engine/synth.rs +0 -325
- package/rust/core/audio/interpreter/arrow_call.rs +0 -311
- package/rust/core/audio/renderer.rs +0 -54
- package/rust/core/parser/driver.rs +0 -584
- package/rust/core/preprocessor/loader.rs +0 -637
- package/rust/core/store/export.rs +0 -28
- package/rust/core/store/function.rs +0 -40
- package/rust/core/store/import.rs +0 -28
- package/rust/core/store/variable.rs +0 -51
- package/rust/core/utils/mod.rs +0 -1
- package/rust/core/utils/path.rs +0 -37
|
@@ -1,124 +1,124 @@
|
|
|
1
|
-
use crate::config::settings::set_user_config_value;
|
|
2
|
-
use crate::web::sso::get_sso_url;
|
|
3
|
-
use std::str::FromStr;
|
|
4
|
-
use tiny_http::Header;
|
|
5
|
-
use tiny_http::{Response, Server};
|
|
6
|
-
use webbrowser;
|
|
7
|
-
|
|
8
|
-
/// Handle the login command
|
|
9
|
-
/// This function initiates the login process by opening the browser and waiting for the callback.
|
|
10
|
-
#[cfg(feature = "cli")]
|
|
11
|
-
pub async fn handle_login_command() -> Result<(), String> {
|
|
12
|
-
use devalang_utils::logger::LogLevel;
|
|
13
|
-
use devalang_utils::logger::Logger;
|
|
14
|
-
use devalang_utils::spinner::start_spinner;
|
|
15
|
-
|
|
16
|
-
let logger = Logger::new();
|
|
17
|
-
|
|
18
|
-
let mut listener_port = 7878;
|
|
19
|
-
|
|
20
|
-
let test_port_already_in_use = format!("127.0.0.1:{}", listener_port);
|
|
21
|
-
while std::net::TcpListener::bind(&test_port_already_in_use).is_err() {
|
|
22
|
-
listener_port += 1;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
let redirect_uri = format!("http://127.0.0.1:{}/callback", listener_port);
|
|
26
|
-
let login_url = format!(
|
|
27
|
-
"{}/?response_type=code&referer=cli&redirect_uri={}",
|
|
28
|
-
get_sso_url(),
|
|
29
|
-
redirect_uri
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
if webbrowser::open(&login_url).is_ok() {
|
|
33
|
-
logger.log_message(LogLevel::Info, "Opening browser for login...");
|
|
34
|
-
logger.log_message(
|
|
35
|
-
LogLevel::Info,
|
|
36
|
-
&format!(
|
|
37
|
-
"If the browser does not open, please visit the following URL: {}",
|
|
38
|
-
login_url
|
|
39
|
-
),
|
|
40
|
-
);
|
|
41
|
-
} else {
|
|
42
|
-
logger.log_message(
|
|
43
|
-
LogLevel::Info,
|
|
44
|
-
"Please open the following URL in your browser to login:",
|
|
45
|
-
);
|
|
46
|
-
logger.log_message(LogLevel::Info, &login_url);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
let server = Server::http(format!("127.0.0.1:{}", listener_port)).unwrap();
|
|
50
|
-
|
|
51
|
-
let spinner = start_spinner("Waiting for authentication...");
|
|
52
|
-
|
|
53
|
-
for request in server.incoming_requests() {
|
|
54
|
-
let query = request.url().to_string();
|
|
55
|
-
if request.url().starts_with("/callback") {
|
|
56
|
-
if query.contains("session=") || query.contains("error=") {
|
|
57
|
-
let token = query.split("session=").nth(1).unwrap_or("").to_string();
|
|
58
|
-
|
|
59
|
-
if !token.is_empty() {
|
|
60
|
-
let response_html = r#"
|
|
61
|
-
<html>
|
|
62
|
-
<body>
|
|
63
|
-
<h1>Authentication Successful</h1>
|
|
64
|
-
<h2>You can now close this window.</h2>
|
|
65
|
-
</body>
|
|
66
|
-
</html>
|
|
67
|
-
"#;
|
|
68
|
-
|
|
69
|
-
let response = Response::from_string(response_html)
|
|
70
|
-
.with_status_code(200)
|
|
71
|
-
.with_header(Header::from_str("Content-Type: text/html").unwrap());
|
|
72
|
-
|
|
73
|
-
request.respond(response).unwrap();
|
|
74
|
-
|
|
75
|
-
save_token(&token);
|
|
76
|
-
|
|
77
|
-
spinner.finish_and_clear();
|
|
78
|
-
|
|
79
|
-
logger.log_message(
|
|
80
|
-
LogLevel::Success,
|
|
81
|
-
"Authentication successful. Token saved to ~/.devalang/config.json",
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
break;
|
|
85
|
-
} else {
|
|
86
|
-
spinner.finish_and_clear();
|
|
87
|
-
logger.log_message(LogLevel::Error, "Invalid session token.");
|
|
88
|
-
request
|
|
89
|
-
.respond(Response::from_string("Invalid session token."))
|
|
90
|
-
.unwrap();
|
|
91
|
-
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
} else {
|
|
95
|
-
println!("Invalid callback: {}", request.url());
|
|
96
|
-
|
|
97
|
-
spinner.finish_and_clear();
|
|
98
|
-
logger.log_message(LogLevel::Error, "Invalid callback.");
|
|
99
|
-
request
|
|
100
|
-
.respond(Response::from_string("Invalid callback."))
|
|
101
|
-
.unwrap();
|
|
102
|
-
|
|
103
|
-
break;
|
|
104
|
-
}
|
|
105
|
-
} else if request.url().starts_with("/favicon.ico") {
|
|
106
|
-
// Ignore favicon requests
|
|
107
|
-
} else {
|
|
108
|
-
spinner.finish_and_clear();
|
|
109
|
-
logger.log_message(LogLevel::Error, "Invalid request.");
|
|
110
|
-
request
|
|
111
|
-
.respond(Response::from_string("Invalid request."))
|
|
112
|
-
.unwrap();
|
|
113
|
-
|
|
114
|
-
break;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
Ok(())
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/// Save the session token to a file in the user's home directory
|
|
122
|
-
fn save_token(token: &str) {
|
|
123
|
-
set_user_config_value("session", serde_json::Value::String(token.to_string()));
|
|
124
|
-
}
|
|
1
|
+
use crate::config::settings::set_user_config_value;
|
|
2
|
+
use crate::web::sso::get_sso_url;
|
|
3
|
+
use std::str::FromStr;
|
|
4
|
+
use tiny_http::Header;
|
|
5
|
+
use tiny_http::{Response, Server};
|
|
6
|
+
use webbrowser;
|
|
7
|
+
|
|
8
|
+
/// Handle the login command
|
|
9
|
+
/// This function initiates the login process by opening the browser and waiting for the callback.
|
|
10
|
+
#[cfg(feature = "cli")]
|
|
11
|
+
pub async fn handle_login_command() -> Result<(), String> {
|
|
12
|
+
use devalang_utils::logger::LogLevel;
|
|
13
|
+
use devalang_utils::logger::Logger;
|
|
14
|
+
use devalang_utils::spinner::start_spinner;
|
|
15
|
+
|
|
16
|
+
let logger = Logger::new();
|
|
17
|
+
|
|
18
|
+
let mut listener_port = 7878;
|
|
19
|
+
|
|
20
|
+
let test_port_already_in_use = format!("127.0.0.1:{}", listener_port);
|
|
21
|
+
while std::net::TcpListener::bind(&test_port_already_in_use).is_err() {
|
|
22
|
+
listener_port += 1;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let redirect_uri = format!("http://127.0.0.1:{}/callback", listener_port);
|
|
26
|
+
let login_url = format!(
|
|
27
|
+
"{}/?response_type=code&referer=cli&redirect_uri={}",
|
|
28
|
+
get_sso_url(),
|
|
29
|
+
redirect_uri
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
if webbrowser::open(&login_url).is_ok() {
|
|
33
|
+
logger.log_message(LogLevel::Info, "Opening browser for login...");
|
|
34
|
+
logger.log_message(
|
|
35
|
+
LogLevel::Info,
|
|
36
|
+
&format!(
|
|
37
|
+
"If the browser does not open, please visit the following URL: {}",
|
|
38
|
+
login_url
|
|
39
|
+
),
|
|
40
|
+
);
|
|
41
|
+
} else {
|
|
42
|
+
logger.log_message(
|
|
43
|
+
LogLevel::Info,
|
|
44
|
+
"Please open the following URL in your browser to login:",
|
|
45
|
+
);
|
|
46
|
+
logger.log_message(LogLevel::Info, &login_url);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let server = Server::http(format!("127.0.0.1:{}", listener_port)).unwrap();
|
|
50
|
+
|
|
51
|
+
let spinner = start_spinner("Waiting for authentication...");
|
|
52
|
+
|
|
53
|
+
for request in server.incoming_requests() {
|
|
54
|
+
let query = request.url().to_string();
|
|
55
|
+
if request.url().starts_with("/callback") {
|
|
56
|
+
if query.contains("session=") || query.contains("error=") {
|
|
57
|
+
let token = query.split("session=").nth(1).unwrap_or("").to_string();
|
|
58
|
+
|
|
59
|
+
if !token.is_empty() {
|
|
60
|
+
let response_html = r#"
|
|
61
|
+
<html>
|
|
62
|
+
<body>
|
|
63
|
+
<h1>Authentication Successful</h1>
|
|
64
|
+
<h2>You can now close this window.</h2>
|
|
65
|
+
</body>
|
|
66
|
+
</html>
|
|
67
|
+
"#;
|
|
68
|
+
|
|
69
|
+
let response = Response::from_string(response_html)
|
|
70
|
+
.with_status_code(200)
|
|
71
|
+
.with_header(Header::from_str("Content-Type: text/html").unwrap());
|
|
72
|
+
|
|
73
|
+
request.respond(response).unwrap();
|
|
74
|
+
|
|
75
|
+
save_token(&token);
|
|
76
|
+
|
|
77
|
+
spinner.finish_and_clear();
|
|
78
|
+
|
|
79
|
+
logger.log_message(
|
|
80
|
+
LogLevel::Success,
|
|
81
|
+
"Authentication successful. Token saved to ~/.devalang/config.json",
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
break;
|
|
85
|
+
} else {
|
|
86
|
+
spinner.finish_and_clear();
|
|
87
|
+
logger.log_message(LogLevel::Error, "Invalid session token.");
|
|
88
|
+
request
|
|
89
|
+
.respond(Response::from_string("Invalid session token."))
|
|
90
|
+
.unwrap();
|
|
91
|
+
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
println!("Invalid callback: {}", request.url());
|
|
96
|
+
|
|
97
|
+
spinner.finish_and_clear();
|
|
98
|
+
logger.log_message(LogLevel::Error, "Invalid callback.");
|
|
99
|
+
request
|
|
100
|
+
.respond(Response::from_string("Invalid callback."))
|
|
101
|
+
.unwrap();
|
|
102
|
+
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
} else if request.url().starts_with("/favicon.ico") {
|
|
106
|
+
// Ignore favicon requests
|
|
107
|
+
} else {
|
|
108
|
+
spinner.finish_and_clear();
|
|
109
|
+
logger.log_message(LogLevel::Error, "Invalid request.");
|
|
110
|
+
request
|
|
111
|
+
.respond(Response::from_string("Invalid request."))
|
|
112
|
+
.unwrap();
|
|
113
|
+
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
Ok(())
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/// Save the session token to a file in the user's home directory
|
|
122
|
+
fn save_token(token: &str) {
|
|
123
|
+
set_user_config_value("session", serde_json::Value::String(token.to_string()));
|
|
124
|
+
}
|
package/rust/cli/mod.rs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
pub mod bank;
|
|
2
|
-
pub mod build;
|
|
3
|
-
pub mod check;
|
|
4
|
-
pub mod discover;
|
|
5
|
-
pub mod init;
|
|
6
|
-
pub mod install;
|
|
7
|
-
pub mod login;
|
|
8
|
-
pub mod parser;
|
|
9
|
-
pub mod play;
|
|
10
|
-
pub mod telemetry;
|
|
11
|
-
pub mod template;
|
|
12
|
-
pub mod update;
|
|
1
|
+
pub mod bank;
|
|
2
|
+
pub mod build;
|
|
3
|
+
pub mod check;
|
|
4
|
+
pub mod discover;
|
|
5
|
+
pub mod init;
|
|
6
|
+
pub mod install;
|
|
7
|
+
pub mod login;
|
|
8
|
+
pub mod parser;
|
|
9
|
+
pub mod play;
|
|
10
|
+
pub mod telemetry;
|
|
11
|
+
pub mod template;
|
|
12
|
+
pub mod update;
|
package/rust/cli/parser.rs
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
|
-
use clap::{Parser, Subcommand};
|
|
1
|
+
use clap::{Parser, Subcommand, ValueEnum};
|
|
2
|
+
|
|
3
|
+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)]
|
|
4
|
+
pub enum OutputFormat {
|
|
5
|
+
Wav,
|
|
6
|
+
Mid,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)]
|
|
10
|
+
pub enum AudioFormat {
|
|
11
|
+
Wav16,
|
|
12
|
+
Wav24,
|
|
13
|
+
Wav32,
|
|
14
|
+
}
|
|
2
15
|
|
|
3
16
|
#[derive(Parser)]
|
|
4
17
|
#[command(name = "devalang")]
|
|
@@ -124,6 +137,26 @@ pub enum Commands {
|
|
|
124
137
|
///
|
|
125
138
|
output: Option<String>,
|
|
126
139
|
|
|
140
|
+
#[arg(long, value_enum, value_delimiter = ',', default_value = "wav,mid")]
|
|
141
|
+
/// Which output formats to generate. Comma-separated list is accepted.
|
|
142
|
+
///
|
|
143
|
+
/// ### Default value
|
|
144
|
+
/// - `wav,mid`
|
|
145
|
+
///
|
|
146
|
+
output_format: Vec<OutputFormat>,
|
|
147
|
+
|
|
148
|
+
#[arg(long, default_value = "wav16")]
|
|
149
|
+
/// Audio format to use for file outputs (affects WAV export).
|
|
150
|
+
///
|
|
151
|
+
/// ### Default value
|
|
152
|
+
/// - `wav16`
|
|
153
|
+
///
|
|
154
|
+
audio_format: AudioFormat,
|
|
155
|
+
|
|
156
|
+
#[arg(long, default_value_t = 44100u32)]
|
|
157
|
+
/// Sample rate to use for audio export and playback (e.g. 44100, 48000)
|
|
158
|
+
sample_rate: u32,
|
|
159
|
+
|
|
127
160
|
#[arg(long, default_value_t = false)]
|
|
128
161
|
/// Whether to watch for changes and rebuild.
|
|
129
162
|
///
|
|
@@ -213,6 +246,18 @@ pub enum Commands {
|
|
|
213
246
|
/// The directory where the output files will be generated.
|
|
214
247
|
output: Option<String>,
|
|
215
248
|
|
|
249
|
+
#[arg(long, default_value_t = 44100u32)]
|
|
250
|
+
/// Sample rate to use for playback (e.g. 44100, 48000)
|
|
251
|
+
sample_rate: u32,
|
|
252
|
+
|
|
253
|
+
#[arg(long, default_value = "wav16")]
|
|
254
|
+
/// Audio format to use for file outputs (affects WAV export).
|
|
255
|
+
///
|
|
256
|
+
/// ### Default value
|
|
257
|
+
/// - `wav16`
|
|
258
|
+
///
|
|
259
|
+
audio_format: AudioFormat,
|
|
260
|
+
|
|
216
261
|
#[arg(long, default_value_t = false)]
|
|
217
262
|
/// Whether to watch for changes and re-play.
|
|
218
263
|
///
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
use crate::config::driver::ProjectConfig;
|
|
2
2
|
use devalang_utils::logger::{LogLevel, Logger};
|
|
3
|
+
use devalang_utils::path::{find_entry_file, normalize_path};
|
|
3
4
|
use std::{sync::mpsc::channel, thread};
|
|
4
5
|
|
|
5
6
|
pub use crate::cli::play::io::wav_duration_seconds;
|
|
@@ -17,12 +18,34 @@ pub fn handle_play_command(
|
|
|
17
18
|
config: Option<ProjectConfig>,
|
|
18
19
|
entry: Option<String>,
|
|
19
20
|
output: Option<String>,
|
|
21
|
+
audio_format: crate::cli::parser::AudioFormat,
|
|
22
|
+
sample_rate: u32,
|
|
20
23
|
watch: bool,
|
|
21
24
|
repeat: bool,
|
|
22
25
|
debug: bool,
|
|
23
26
|
) -> Result<(), String> {
|
|
24
27
|
let logger = Logger::new();
|
|
25
28
|
|
|
29
|
+
// Determine final audio_format and sample_rate, preferring CLI values but falling back to config defaults
|
|
30
|
+
let mut final_audio_format = audio_format;
|
|
31
|
+
let mut final_sample_rate = sample_rate;
|
|
32
|
+
if let Some(cfg) = config.as_ref() {
|
|
33
|
+
if let Some(af) = cfg.defaults.audio_format.as_ref() {
|
|
34
|
+
let af_low = af.to_lowercase();
|
|
35
|
+
final_audio_format = match af_low.as_str() {
|
|
36
|
+
"wav24" => crate::cli::parser::AudioFormat::Wav24,
|
|
37
|
+
"wav32" => crate::cli::parser::AudioFormat::Wav32,
|
|
38
|
+
_ => crate::cli::parser::AudioFormat::Wav16,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if let Some(sr) = cfg.defaults.sample_rate {
|
|
42
|
+
// Only override if CLI provided a 0 or unrealistic value (we assume CLI provides a valid value)
|
|
43
|
+
if final_sample_rate == 0 {
|
|
44
|
+
final_sample_rate = sr;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
26
49
|
let entry_path = entry
|
|
27
50
|
.or_else(|| config.as_ref().and_then(|c| c.defaults.entry.clone()))
|
|
28
51
|
.unwrap_or_default();
|
|
@@ -45,7 +68,7 @@ pub fn handle_play_command(
|
|
|
45
68
|
return Err("missing entry or output".to_string());
|
|
46
69
|
}
|
|
47
70
|
|
|
48
|
-
let entry_file = match
|
|
71
|
+
let entry_file = match find_entry_file(&entry_path) {
|
|
49
72
|
Some(p) => p,
|
|
50
73
|
None => {
|
|
51
74
|
logger.log_message(LogLevel::Error, "index.deva not found");
|
|
@@ -53,10 +76,7 @@ pub fn handle_play_command(
|
|
|
53
76
|
}
|
|
54
77
|
};
|
|
55
78
|
|
|
56
|
-
let audio_file = format!(
|
|
57
|
-
"{}/audio/index.wav",
|
|
58
|
-
crate::core::utils::path::normalize_path(&output_path)
|
|
59
|
-
);
|
|
79
|
+
let audio_file = format!("{}/audio/index.wav", normalize_path(&output_path));
|
|
60
80
|
let mut audio_player = AudioPlayer::new();
|
|
61
81
|
|
|
62
82
|
if watch && fetched_repeat {
|
|
@@ -79,8 +99,14 @@ pub fn handle_play_command(
|
|
|
79
99
|
});
|
|
80
100
|
|
|
81
101
|
// Main thread: build + play in a loop
|
|
82
|
-
let (bpm, entry_stmts, variables, functions, global_store) =
|
|
83
|
-
|
|
102
|
+
let (bpm, entry_stmts, variables, functions, global_store) = process_play(
|
|
103
|
+
&config,
|
|
104
|
+
&entry_file,
|
|
105
|
+
&output_path,
|
|
106
|
+
final_audio_format,
|
|
107
|
+
final_sample_rate,
|
|
108
|
+
debug,
|
|
109
|
+
)?;
|
|
84
110
|
audio_player.play_file_once(&audio_file);
|
|
85
111
|
// Estimate duration: base on statement count plus extra for loop iterations (1 beat per iter)
|
|
86
112
|
let loop_iters: usize = entry_stmts
|
|
@@ -130,14 +156,20 @@ pub fn handle_play_command(
|
|
|
130
156
|
// Stop previous real-time runner before restarting playback
|
|
131
157
|
stop_realtime_runner(&mut rt_runner);
|
|
132
158
|
|
|
133
|
-
let (bpm, entry_stmts, variables, functions, global_store) =
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
159
|
+
let (bpm, entry_stmts, variables, functions, global_store) = match process_play(
|
|
160
|
+
&config,
|
|
161
|
+
&entry_file,
|
|
162
|
+
&output_path,
|
|
163
|
+
final_audio_format,
|
|
164
|
+
final_sample_rate,
|
|
165
|
+
debug,
|
|
166
|
+
) {
|
|
167
|
+
Ok(v) => v,
|
|
168
|
+
Err(e) => {
|
|
169
|
+
logger.log_message(LogLevel::Error, &format!("Rebuild failed: {}", e));
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
};
|
|
141
173
|
|
|
142
174
|
logger.log_message(LogLevel::Info, "🎵 Playback started (once mode)...");
|
|
143
175
|
|
|
@@ -180,8 +212,14 @@ pub fn handle_play_command(
|
|
|
180
212
|
}
|
|
181
213
|
} else if fetched_repeat {
|
|
182
214
|
// Initial build to start from a clean slate
|
|
183
|
-
let (bpm, entry_stmts, variables, functions, global_store) =
|
|
184
|
-
|
|
215
|
+
let (bpm, entry_stmts, variables, functions, global_store) = process_play(
|
|
216
|
+
&config,
|
|
217
|
+
&entry_file,
|
|
218
|
+
&output_path,
|
|
219
|
+
final_audio_format,
|
|
220
|
+
final_sample_rate,
|
|
221
|
+
debug,
|
|
222
|
+
)?;
|
|
185
223
|
|
|
186
224
|
logger.log_message(LogLevel::Info, "🎵 Playback started (repeat mode)...");
|
|
187
225
|
|
|
@@ -241,7 +279,14 @@ pub fn handle_play_command(
|
|
|
241
279
|
|
|
242
280
|
// Rebuild in a separate thread
|
|
243
281
|
std::thread::spawn(move || {
|
|
244
|
-
if let Err(e) = process_play(
|
|
282
|
+
if let Err(e) = process_play(
|
|
283
|
+
&config_clone,
|
|
284
|
+
&entry_file,
|
|
285
|
+
&output_path,
|
|
286
|
+
final_audio_format,
|
|
287
|
+
final_sample_rate,
|
|
288
|
+
debug,
|
|
289
|
+
) {
|
|
245
290
|
eprintln!("Rebuild failed in background: {}", e);
|
|
246
291
|
}
|
|
247
292
|
});
|
|
@@ -294,8 +339,14 @@ pub fn handle_play_command(
|
|
|
294
339
|
}
|
|
295
340
|
} else {
|
|
296
341
|
// Single execution
|
|
297
|
-
let (bpm, entry_stmts, variables, functions, global_store) =
|
|
298
|
-
|
|
342
|
+
let (bpm, entry_stmts, variables, functions, global_store) = process_play(
|
|
343
|
+
&config,
|
|
344
|
+
&entry_file,
|
|
345
|
+
&output_path,
|
|
346
|
+
final_audio_format,
|
|
347
|
+
final_sample_rate,
|
|
348
|
+
debug,
|
|
349
|
+
)?;
|
|
299
350
|
|
|
300
351
|
logger.log_message(LogLevel::Info, "🎵 Playback started (once mode)...");
|
|
301
352
|
|
package/rust/cli/play/mod.rs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
pub mod commands;
|
|
2
|
-
pub mod io;
|
|
3
|
-
pub mod process;
|
|
4
|
-
pub mod realtime;
|
|
5
|
-
pub mod utils;
|
|
1
|
+
pub mod commands;
|
|
2
|
+
pub mod io;
|
|
3
|
+
pub mod process;
|
|
4
|
+
pub mod realtime;
|
|
5
|
+
pub mod utils;
|
package/rust/cli/play/process.rs
CHANGED
|
@@ -4,15 +4,15 @@ use crate::{
|
|
|
4
4
|
builder::Builder,
|
|
5
5
|
debugger::{
|
|
6
6
|
lexer::write_lexer_log_file,
|
|
7
|
-
|
|
7
|
+
logs::{write_module_function_log_file, write_module_variable_log_file},
|
|
8
8
|
preprocessor::write_preprocessor_log_file,
|
|
9
9
|
store::{write_function_log_file, write_variables_log_file},
|
|
10
10
|
},
|
|
11
11
|
preprocessor::loader::ModuleLoader,
|
|
12
12
|
store::global::GlobalStore,
|
|
13
|
-
utils::path::normalize_path,
|
|
14
13
|
},
|
|
15
14
|
};
|
|
15
|
+
use devalang_utils::path::normalize_path;
|
|
16
16
|
use devalang_utils::{
|
|
17
17
|
logger::{LogLevel, Logger},
|
|
18
18
|
spinner::start_spinner,
|
|
@@ -22,13 +22,15 @@ pub fn process_play(
|
|
|
22
22
|
_config: &Option<ProjectConfig>,
|
|
23
23
|
entry_file: &str,
|
|
24
24
|
output: &str,
|
|
25
|
+
audio_format: crate::cli::parser::AudioFormat,
|
|
26
|
+
sample_rate: u32,
|
|
25
27
|
debug: bool,
|
|
26
28
|
) -> Result<
|
|
27
29
|
(
|
|
28
30
|
f32,
|
|
29
31
|
Vec<crate::core::parser::statement::Statement>,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
devalang_types::VariableTable,
|
|
33
|
+
devalang_types::FunctionTable,
|
|
32
34
|
crate::core::store::global::GlobalStore,
|
|
33
35
|
),
|
|
34
36
|
String,
|
|
@@ -127,7 +129,14 @@ pub fn process_play(
|
|
|
127
129
|
// SECTION Building AST and Audio
|
|
128
130
|
let builder = Builder::new();
|
|
129
131
|
builder.build_ast(&modules_statements, output, false);
|
|
130
|
-
|
|
132
|
+
let audio_format_str = format!("{:?}", audio_format);
|
|
133
|
+
builder.build_audio(
|
|
134
|
+
&modules_statements,
|
|
135
|
+
output,
|
|
136
|
+
&mut global_store,
|
|
137
|
+
Some(audio_format_str),
|
|
138
|
+
Some(sample_rate),
|
|
139
|
+
);
|
|
131
140
|
|
|
132
141
|
// SECTION Logging
|
|
133
142
|
let logger = Logger::new();
|