| @@ -0,0 +1,9 @@ | |||||
| ### 1.1.0 (in development) | |||||
| - Add block buffering with `config.bufferSize`. | |||||
| - Scripts must change `inputs[i]` to `inputs[i][0]` and `outputs[i]` to `outputs[i][0]`. | |||||
| - Duktape (JavaScript): Use array instead of object for RGB lights and switch lights. | |||||
| - Scripts must change `.r` to `[0]`, `.g` to `[1]`, and `.b` to `[2]` for `lights` and `switchLights`. | |||||
| ### 1.0.0 (2019-09-15) | |||||
| - Initial release. | |||||
| @@ -21,7 +21,19 @@ FLAGS += -Idep/duktape-2.4.0/src | |||||
| $(duktape): | $(duktape): | ||||
| cd dep && $(WGET) "https://duktape.org/duktape-2.4.0.tar.xz" | cd dep && $(WGET) "https://duktape.org/duktape-2.4.0.tar.xz" | ||||
| cd dep && $(SHA256) duktape-2.4.0.tar.xz 86a89307d1633b5cedb2c6e56dc86e92679fc34b05be551722d8cc69ab0771fc | |||||
| cd dep && $(UNTAR) duktape-2.4.0.tar.xz | cd dep && $(UNTAR) duktape-2.4.0.tar.xz | ||||
| # # LuaJIT | |||||
| # luajit := dep/lib/luajit.a | |||||
| # DEPS += $(luajit) | |||||
| # $(luajit): | |||||
| # cd dep && $(WGET) "http://luajit.org/download/LuaJIT-2.0.5.tar.gz" | |||||
| # cd dep && $(SHA256) LuaJIT-2.0.5.tar.gz 874b1f8297c697821f561f9b73b57ffd419ed8f4278c82e05b48806d30c1e979 | |||||
| # cd dep && $(UNTAR) LuaJIT-2.0.5.tar.gz | |||||
| # cd dep/LuaJIT-2.0.5 && $(MAKE) | |||||
| include $(RACK_DIR)/plugin.mk | include $(RACK_DIR)/plugin.mk | ||||
| @@ -15,7 +15,10 @@ function hsvToRgb(h, s, v) { | |||||
| else if (h < 5) rgb = [x, 0, c] | else if (h < 5) rgb = [x, 0, c] | ||||
| else rgb = [c, 0, x] | else rgb = [c, 0, x] | ||||
| var m = v - c | var m = v - c | ||||
| return {r: rgb[0] + m, g: rgb[1] + m, b: rgb[2] + m} | |||||
| rgb[0] += m | |||||
| rgb[1] += m | |||||
| rgb[2] += m | |||||
| return rgb | |||||
| } | } | ||||
| @@ -29,8 +32,10 @@ function process(args) { | |||||
| var rgb = hsvToRgb(h, 1, 1) | var rgb = hsvToRgb(h, 1, 1) | ||||
| args.lights[i] = rgb | args.lights[i] = rgb | ||||
| args.switchLights[i] = rgb | args.switchLights[i] = rgb | ||||
| args.outputs[i] = Math.sin(2 * Math.PI * h) * 5 + 5 | |||||
| args.outputs[i][0] = Math.sin(2 * Math.PI * h) * 5 + 5 | |||||
| } | } | ||||
| } | } | ||||
| display("Hello, world!") | display("Hello, world!") | ||||
| // 12.2us | |||||
| @@ -10,7 +10,7 @@ function process(args) { | |||||
| // Knob ranges from -5 to 5 octaves | // Knob ranges from -5 to 5 octaves | ||||
| var pitch = args.knobs[0] * 10 - 5 | var pitch = args.knobs[0] * 10 - 5 | ||||
| // Input follows 1V/oct standard | // Input follows 1V/oct standard | ||||
| pitch += args.inputs[0] | |||||
| pitch += args.inputs[0][0] | |||||
| // The relationship between 1V/oct pitch and frequency is `freq = 2^pitch`. | // The relationship between 1V/oct pitch and frequency is `freq = 2^pitch`. | ||||
| // Default frequency is middle C (C4) in Hz. | // Default frequency is middle C (C4) in Hz. | ||||
| @@ -24,5 +24,5 @@ function process(args) { | |||||
| phase %= 1 | phase %= 1 | ||||
| // Convert phase to sine output | // Convert phase to sine output | ||||
| args.outputs[0] = Math.sin(2 * Math.PI * phase) * 5 | |||||
| args.outputs[0][0] = Math.sin(2 * Math.PI * phase) * 5 | |||||
| } | } | ||||
| @@ -11,6 +11,7 @@ | |||||
| "manualUrl": "https://github.com/VCVRack/VCV-Prototype/blob/master/README.md", | "manualUrl": "https://github.com/VCVRack/VCV-Prototype/blob/master/README.md", | ||||
| "sourceUrl": "https://github.com/VCVRack/VCV-Prototype", | "sourceUrl": "https://github.com/VCVRack/VCV-Prototype", | ||||
| "donateUrl": "", | "donateUrl": "", | ||||
| "changelogUrl": "https://github.com/VCVRack/VCV-Prototype/blob/master/CHANGELOG.md", | |||||
| "modules": [ | "modules": [ | ||||
| { | { | ||||
| "slug": "Prototype", | "slug": "Prototype", | ||||
| @@ -56,6 +56,9 @@ struct DuktapeEngine : ScriptEngine { | |||||
| // frameDivider | // frameDivider | ||||
| duk_push_int(ctx, getFrameDivider()); | duk_push_int(ctx, getFrameDivider()); | ||||
| duk_put_prop_string(ctx, configIdx, "frameDivider"); | duk_put_prop_string(ctx, configIdx, "frameDivider"); | ||||
| // bufferSize | |||||
| duk_push_int(ctx, getBufferSize()); | |||||
| duk_put_prop_string(ctx, configIdx, "bufferSize"); | |||||
| } | } | ||||
| duk_put_global_string(ctx, "config"); | duk_put_global_string(ctx, "config"); | ||||
| @@ -86,6 +89,10 @@ struct DuktapeEngine : ScriptEngine { | |||||
| duk_get_prop_string(ctx, -1, "frameDivider"); | duk_get_prop_string(ctx, -1, "frameDivider"); | ||||
| setFrameDivider(duk_get_int(ctx, -1)); | setFrameDivider(duk_get_int(ctx, -1)); | ||||
| duk_pop(ctx); | duk_pop(ctx); | ||||
| // bufferSize | |||||
| duk_get_prop_string(ctx, -1, "bufferSize"); | |||||
| setBufferSize(duk_get_int(ctx, -1)); | |||||
| duk_pop(ctx); | |||||
| } | } | ||||
| duk_pop(ctx); | duk_pop(ctx); | ||||
| @@ -96,24 +103,37 @@ struct DuktapeEngine : ScriptEngine { | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| // args (keep on stack) | |||||
| duk_idx_t argsIdx = duk_push_object(ctx); | |||||
| // block (keep on stack) | |||||
| duk_idx_t blockIdx = duk_push_object(ctx); | |||||
| { | { | ||||
| // bufferSize | |||||
| int bufferSize = getBufferSize(); | |||||
| duk_push_int(ctx, bufferSize); | |||||
| duk_put_prop_string(ctx, blockIdx, "bufferSize"); | |||||
| // inputs | // inputs | ||||
| duk_idx_t inputsIdx = duk_push_array(ctx); | duk_idx_t inputsIdx = duk_push_array(ctx); | ||||
| for (int i = 0; i < NUM_ROWS; i++) { | for (int i = 0; i < NUM_ROWS; i++) { | ||||
| duk_push_number(ctx, 0.0); | |||||
| duk_idx_t inputIdx = duk_push_array(ctx); | |||||
| for (int j = 0; j < bufferSize; j++) { | |||||
| duk_push_number(ctx, 0.0); | |||||
| duk_put_prop_index(ctx, inputIdx, j); | |||||
| } | |||||
| duk_put_prop_index(ctx, inputsIdx, i); | duk_put_prop_index(ctx, inputsIdx, i); | ||||
| } | } | ||||
| duk_put_prop_string(ctx, argsIdx, "inputs"); | |||||
| duk_put_prop_string(ctx, blockIdx, "inputs"); | |||||
| // outputs | // outputs | ||||
| duk_idx_t outputsIdx = duk_push_array(ctx); | duk_idx_t outputsIdx = duk_push_array(ctx); | ||||
| for (int i = 0; i < NUM_ROWS; i++) { | for (int i = 0; i < NUM_ROWS; i++) { | ||||
| duk_push_number(ctx, 0.0); | |||||
| duk_idx_t outputIdx = duk_push_array(ctx); | |||||
| for (int j = 0; j < bufferSize; j++) { | |||||
| duk_push_number(ctx, 0.0); | |||||
| duk_put_prop_index(ctx, outputIdx, j); | |||||
| } | |||||
| duk_put_prop_index(ctx, outputsIdx, i); | duk_put_prop_index(ctx, outputsIdx, i); | ||||
| } | } | ||||
| duk_put_prop_string(ctx, argsIdx, "outputs"); | |||||
| duk_put_prop_string(ctx, blockIdx, "outputs"); | |||||
| // knobs | // knobs | ||||
| duk_idx_t knobsIdx = duk_push_array(ctx); | duk_idx_t knobsIdx = duk_push_array(ctx); | ||||
| @@ -121,7 +141,7 @@ struct DuktapeEngine : ScriptEngine { | |||||
| duk_push_number(ctx, 0.0); | duk_push_number(ctx, 0.0); | ||||
| duk_put_prop_index(ctx, knobsIdx, i); | duk_put_prop_index(ctx, knobsIdx, i); | ||||
| } | } | ||||
| duk_put_prop_string(ctx, argsIdx, "knobs"); | |||||
| duk_put_prop_string(ctx, blockIdx, "knobs"); | |||||
| // switches | // switches | ||||
| duk_idx_t switchesIdx = duk_push_array(ctx); | duk_idx_t switchesIdx = duk_push_array(ctx); | ||||
| @@ -129,76 +149,72 @@ struct DuktapeEngine : ScriptEngine { | |||||
| duk_push_number(ctx, 0.0); | duk_push_number(ctx, 0.0); | ||||
| duk_put_prop_index(ctx, switchesIdx, i); | duk_put_prop_index(ctx, switchesIdx, i); | ||||
| } | } | ||||
| duk_put_prop_string(ctx, argsIdx, "switches"); | |||||
| duk_put_prop_string(ctx, blockIdx, "switches"); | |||||
| // lights | // lights | ||||
| duk_idx_t lightsIdx = duk_push_array(ctx); | duk_idx_t lightsIdx = duk_push_array(ctx); | ||||
| for (int i = 0; i < NUM_ROWS; i++) { | for (int i = 0; i < NUM_ROWS; i++) { | ||||
| duk_idx_t lightIdx = duk_push_object(ctx); | |||||
| { | |||||
| duk_push_number(ctx, 0.0); | |||||
| duk_put_prop_string(ctx, lightIdx, "r"); | |||||
| duk_idx_t lightIdx = duk_push_array(ctx); | |||||
| for (int c = 0; c < 3; c++) { | |||||
| duk_push_number(ctx, 0.0); | duk_push_number(ctx, 0.0); | ||||
| duk_put_prop_string(ctx, lightIdx, "g"); | |||||
| duk_push_number(ctx, 0.0); | |||||
| duk_put_prop_string(ctx, lightIdx, "b"); | |||||
| duk_put_prop_index(ctx, lightIdx, c); | |||||
| } | } | ||||
| duk_put_prop_index(ctx, lightsIdx, i); | duk_put_prop_index(ctx, lightsIdx, i); | ||||
| } | } | ||||
| duk_put_prop_string(ctx, argsIdx, "lights"); | |||||
| duk_put_prop_string(ctx, blockIdx, "lights"); | |||||
| // switchLights | // switchLights | ||||
| duk_idx_t switchLightsIdx = duk_push_array(ctx); | duk_idx_t switchLightsIdx = duk_push_array(ctx); | ||||
| for (int i = 0; i < NUM_ROWS; i++) { | for (int i = 0; i < NUM_ROWS; i++) { | ||||
| duk_idx_t switchLightIdx = duk_push_object(ctx); | |||||
| { | |||||
| duk_push_number(ctx, 0.0); | |||||
| duk_put_prop_string(ctx, switchLightIdx, "r"); | |||||
| duk_idx_t switchLightIdx = duk_push_array(ctx); | |||||
| for (int c = 0; c < 3; c++) { | |||||
| duk_push_number(ctx, 0.0); | duk_push_number(ctx, 0.0); | ||||
| duk_put_prop_string(ctx, switchLightIdx, "g"); | |||||
| duk_push_number(ctx, 0.0); | |||||
| duk_put_prop_string(ctx, switchLightIdx, "b"); | |||||
| duk_put_prop_index(ctx, switchLightIdx, c); | |||||
| } | } | ||||
| duk_put_prop_index(ctx, switchLightsIdx, i); | duk_put_prop_index(ctx, switchLightsIdx, i); | ||||
| } | } | ||||
| duk_put_prop_string(ctx, argsIdx, "switchLights"); | |||||
| duk_put_prop_string(ctx, blockIdx, "switchLights"); | |||||
| } | } | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| int process(ProcessArgs& args) override { | |||||
| // args | |||||
| duk_idx_t argsIdx = duk_get_top(ctx) - 1; | |||||
| int process(ProcessBlock& block) override { | |||||
| // block | |||||
| duk_idx_t blockIdx = duk_get_top(ctx) - 1; | |||||
| { | { | ||||
| // sampleRate | // sampleRate | ||||
| duk_push_number(ctx, args.sampleRate); | |||||
| duk_put_prop_string(ctx, argsIdx, "sampleRate"); | |||||
| duk_push_number(ctx, block.sampleRate); | |||||
| duk_put_prop_string(ctx, blockIdx, "sampleRate"); | |||||
| // sampleTime | // sampleTime | ||||
| duk_push_number(ctx, args.sampleTime); | |||||
| duk_put_prop_string(ctx, argsIdx, "sampleTime"); | |||||
| duk_push_number(ctx, block.sampleTime); | |||||
| duk_put_prop_string(ctx, blockIdx, "sampleTime"); | |||||
| // inputs | // inputs | ||||
| duk_get_prop_string(ctx, argsIdx, "inputs"); | |||||
| duk_get_prop_string(ctx, blockIdx, "inputs"); | |||||
| for (int i = 0; i < NUM_ROWS; i++) { | for (int i = 0; i < NUM_ROWS; i++) { | ||||
| duk_push_number(ctx, getInput(i)); | |||||
| duk_put_prop_index(ctx, -2, i); | |||||
| duk_get_prop_index(ctx, -1, i); | |||||
| for (int j = 0; j < block.bufferSize; j++) { | |||||
| duk_push_number(ctx, block.inputs[i][j]); | |||||
| duk_put_prop_index(ctx, -2, j); | |||||
| } | |||||
| duk_pop(ctx); | |||||
| } | } | ||||
| duk_pop(ctx); | duk_pop(ctx); | ||||
| // knobs | // knobs | ||||
| duk_get_prop_string(ctx, argsIdx, "knobs"); | |||||
| duk_get_prop_string(ctx, blockIdx, "knobs"); | |||||
| for (int i = 0; i < NUM_ROWS; i++) { | for (int i = 0; i < NUM_ROWS; i++) { | ||||
| duk_push_number(ctx, getKnob(i)); | |||||
| duk_push_number(ctx, block.knobs[i]); | |||||
| duk_put_prop_index(ctx, -2, i); | duk_put_prop_index(ctx, -2, i); | ||||
| } | } | ||||
| duk_pop(ctx); | duk_pop(ctx); | ||||
| // switches | // switches | ||||
| duk_get_prop_string(ctx, argsIdx, "switches"); | |||||
| duk_get_prop_string(ctx, blockIdx, "switches"); | |||||
| for (int i = 0; i < NUM_ROWS; i++) { | for (int i = 0; i < NUM_ROWS; i++) { | ||||
| duk_push_boolean(ctx, getSwitch(i)); | |||||
| duk_push_boolean(ctx, block.switches[i]); | |||||
| duk_put_prop_index(ctx, -2, i); | duk_put_prop_index(ctx, -2, i); | ||||
| } | } | ||||
| duk_pop(ctx); | duk_pop(ctx); | ||||
| @@ -206,7 +222,7 @@ struct DuktapeEngine : ScriptEngine { | |||||
| // Duplicate process function | // Duplicate process function | ||||
| duk_dup(ctx, -2); | duk_dup(ctx, -2); | ||||
| // Duplicate args object | |||||
| // Duplicate block object | |||||
| duk_dup(ctx, -2); | duk_dup(ctx, -2); | ||||
| // Call process function | // Call process function | ||||
| if (duk_pcall(ctx, 1)) { | if (duk_pcall(ctx, 1)) { | ||||
| @@ -219,13 +235,17 @@ struct DuktapeEngine : ScriptEngine { | |||||
| // return value | // return value | ||||
| duk_pop(ctx); | duk_pop(ctx); | ||||
| // args | |||||
| // block | |||||
| { | { | ||||
| // outputs | // outputs | ||||
| duk_get_prop_string(ctx, -1, "outputs"); | duk_get_prop_string(ctx, -1, "outputs"); | ||||
| for (int i = 0; i < NUM_ROWS; i++) { | for (int i = 0; i < NUM_ROWS; i++) { | ||||
| duk_get_prop_index(ctx, -1, i); | duk_get_prop_index(ctx, -1, i); | ||||
| setOutput(i, duk_get_number(ctx, -1)); | |||||
| for (int j = 0; j < block.bufferSize; j++) { | |||||
| duk_get_prop_index(ctx, -1, j); | |||||
| block.outputs[i][j] = duk_get_number(ctx, -1); | |||||
| duk_pop(ctx); | |||||
| } | |||||
| duk_pop(ctx); | duk_pop(ctx); | ||||
| } | } | ||||
| duk_pop(ctx); | duk_pop(ctx); | ||||
| @@ -234,15 +254,9 @@ struct DuktapeEngine : ScriptEngine { | |||||
| duk_get_prop_string(ctx, -1, "lights"); | duk_get_prop_string(ctx, -1, "lights"); | ||||
| for (int i = 0; i < NUM_ROWS; i++) { | for (int i = 0; i < NUM_ROWS; i++) { | ||||
| duk_get_prop_index(ctx, -1, i); | duk_get_prop_index(ctx, -1, i); | ||||
| { | |||||
| duk_get_prop_string(ctx, -1, "r"); | |||||
| setLight(i, 0, duk_get_number(ctx, -1)); | |||||
| duk_pop(ctx); | |||||
| duk_get_prop_string(ctx, -1, "g"); | |||||
| setLight(i, 1, duk_get_number(ctx, -1)); | |||||
| duk_pop(ctx); | |||||
| duk_get_prop_string(ctx, -1, "b"); | |||||
| setLight(i, 2, duk_get_number(ctx, -1)); | |||||
| for (int c = 0; c < 3; c++) { | |||||
| duk_get_prop_index(ctx, -1, c); | |||||
| block.lights[i][c] = duk_get_number(ctx, -1); | |||||
| duk_pop(ctx); | duk_pop(ctx); | ||||
| } | } | ||||
| duk_pop(ctx); | duk_pop(ctx); | ||||
| @@ -253,15 +267,9 @@ struct DuktapeEngine : ScriptEngine { | |||||
| duk_get_prop_string(ctx, -1, "switchLights"); | duk_get_prop_string(ctx, -1, "switchLights"); | ||||
| for (int i = 0; i < NUM_ROWS; i++) { | for (int i = 0; i < NUM_ROWS; i++) { | ||||
| duk_get_prop_index(ctx, -1, i); | duk_get_prop_index(ctx, -1, i); | ||||
| { | |||||
| duk_get_prop_string(ctx, -1, "r"); | |||||
| setSwitchLight(i, 0, duk_get_number(ctx, -1)); | |||||
| duk_pop(ctx); | |||||
| duk_get_prop_string(ctx, -1, "g"); | |||||
| setSwitchLight(i, 1, duk_get_number(ctx, -1)); | |||||
| duk_pop(ctx); | |||||
| duk_get_prop_string(ctx, -1, "b"); | |||||
| setSwitchLight(i, 2, duk_get_number(ctx, -1)); | |||||
| for (int c = 0; c < 3; c++) { | |||||
| duk_get_prop_index(ctx, -1, c); | |||||
| block.switchLights[i][c] = duk_get_number(ctx, -1); | |||||
| duk_pop(ctx); | duk_pop(ctx); | ||||
| } | } | ||||
| duk_pop(ctx); | duk_pop(ctx); | ||||
| @@ -39,6 +39,8 @@ struct Prototype : Module { | |||||
| ScriptEngine* scriptEngine = NULL; | ScriptEngine* scriptEngine = NULL; | ||||
| int frame = 0; | int frame = 0; | ||||
| int frameDivider; | int frameDivider; | ||||
| ScriptEngine::ProcessBlock block; | |||||
| int bufferIndex = 0; | |||||
| Prototype() { | Prototype() { | ||||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | ||||
| @@ -64,21 +66,49 @@ struct Prototype : Module { | |||||
| return; | return; | ||||
| frame = 0; | frame = 0; | ||||
| ScriptEngine::ProcessArgs scriptArgs; | |||||
| scriptArgs.sampleRate = args.sampleRate; | |||||
| scriptArgs.sampleTime = args.sampleTime; | |||||
| { | |||||
| std::lock_guard<std::mutex> lock(scriptMutex); | |||||
| // Check for certain inside the mutex | |||||
| if (scriptEngine) { | |||||
| if (scriptEngine->process(scriptArgs)) { | |||||
| WARN("Script %s process() failed. Stopped script.", path.c_str()); | |||||
| clearScriptEngine(); | |||||
| return; | |||||
| // Inputs | |||||
| for (int i = 0; i < NUM_ROWS; i++) | |||||
| block.inputs[i][bufferIndex] = inputs[IN_INPUTS + i].getVoltage(); | |||||
| // Process block | |||||
| if (++bufferIndex >= block.bufferSize) { | |||||
| bufferIndex = 0; | |||||
| // Block settings | |||||
| block.sampleRate = args.sampleRate; | |||||
| block.sampleTime = args.sampleTime; | |||||
| // Params | |||||
| for (int i = 0; i < NUM_ROWS; i++) | |||||
| block.knobs[i] = params[KNOB_PARAMS + i].getValue(); | |||||
| for (int i = 0; i < NUM_ROWS; i++) | |||||
| block.switches[i] = params[SWITCH_PARAMS + i].getValue() > 0.f; | |||||
| // Run ScriptEngine's process function | |||||
| { | |||||
| std::lock_guard<std::mutex> lock(scriptMutex); | |||||
| // Check for certain inside the mutex | |||||
| if (scriptEngine) { | |||||
| if (scriptEngine->process(block)) { | |||||
| WARN("Script %s process() failed. Stopped script.", path.c_str()); | |||||
| clearScriptEngine(); | |||||
| return; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| // Lights | |||||
| for (int i = 0; i < NUM_ROWS; i++) | |||||
| for (int c = 0; c < 3; c++) | |||||
| lights[LIGHT_LIGHTS + i * 3 + c].setBrightness(block.lights[i][c]); | |||||
| for (int i = 0; i < NUM_ROWS; i++) | |||||
| for (int c = 0; c < 3; c++) | |||||
| lights[SWITCH_LIGHTS + i * 3 + c].setBrightness(block.switchLights[i][c]); | |||||
| } | } | ||||
| // Outputs | |||||
| for (int i = 0; i < NUM_ROWS; i++) | |||||
| outputs[OUT_OUTPUTS + i].setVoltage(block.outputs[i][bufferIndex]); | |||||
| } | } | ||||
| void clearScriptEngine() { | void clearScriptEngine() { | ||||
| @@ -98,6 +128,9 @@ struct Prototype : Module { | |||||
| // Reset settings | // Reset settings | ||||
| frameDivider = 32; | frameDivider = 32; | ||||
| frame = 0; | frame = 0; | ||||
| block.bufferSize = 1; | |||||
| std::memset(block.inputs, 0, sizeof(block.inputs)); | |||||
| bufferIndex = 0; | |||||
| } | } | ||||
| void setScriptString(std::string path, std::string script) { | void setScriptString(std::string path, std::string script) { | ||||
| @@ -183,23 +216,12 @@ int ScriptEngine::getFrameDivider() { | |||||
| void ScriptEngine::setFrameDivider(int frameDivider) { | void ScriptEngine::setFrameDivider(int frameDivider) { | ||||
| module->frameDivider = frameDivider; | module->frameDivider = frameDivider; | ||||
| } | } | ||||
| float ScriptEngine::getInput(int index) { | |||||
| return module->inputs[Prototype::IN_INPUTS + index].getVoltage(); | |||||
| } | |||||
| void ScriptEngine::setOutput(int index, float voltage) { | |||||
| module->outputs[Prototype::OUT_OUTPUTS + index].setVoltage(voltage); | |||||
| } | |||||
| float ScriptEngine::getKnob(int index) { | |||||
| return module->params[Prototype::KNOB_PARAMS + index].getValue(); | |||||
| } | |||||
| bool ScriptEngine::getSwitch(int index) { | |||||
| return module->params[Prototype::SWITCH_PARAMS + index].getValue() > 0.f; | |||||
| } | |||||
| void ScriptEngine::setLight(int index, int color, float brightness) { | |||||
| module->lights[Prototype::LIGHT_LIGHTS + index * 3 + color].setBrightness(brightness); | |||||
| int ScriptEngine::getBufferSize() { | |||||
| return module->block.bufferSize; | |||||
| } | } | ||||
| void ScriptEngine::setSwitchLight(int index, int color, float brightness) { | |||||
| module->lights[Prototype::SWITCH_LIGHTS + index * 3 + color].setBrightness(brightness); | |||||
| void ScriptEngine::setBufferSize(int bufferSize) { | |||||
| bufferSize = clamp(bufferSize, 1, MAX_BUFFER_SIZE); | |||||
| module->block.bufferSize = bufferSize; | |||||
| } | } | ||||
| @@ -219,7 +241,7 @@ struct FileChoice : LedDisplayChoice { | |||||
| } | } | ||||
| void onAction(const event::Action& e) override { | void onAction(const event::Action& e) override { | ||||
| std::string dir = asset::user(""); | |||||
| std::string dir = asset::plugin(pluginInstance, "examples"); | |||||
| char* pathC = osdialog_file(OSDIALOG_OPEN, dir.c_str(), NULL, NULL); | char* pathC = osdialog_file(OSDIALOG_OPEN, dir.c_str(), NULL, NULL); | ||||
| if (!pathC) { | if (!pathC) { | ||||
| return; | return; | ||||
| @@ -3,6 +3,7 @@ | |||||
| static const int NUM_ROWS = 6; | static const int NUM_ROWS = 6; | ||||
| static const int MAX_BUFFER_SIZE = 4096; | |||||
| struct Prototype; | struct Prototype; | ||||
| @@ -18,26 +19,29 @@ struct ScriptEngine { | |||||
| */ | */ | ||||
| virtual int run(const std::string& path, const std::string& script) {return 0;} | virtual int run(const std::string& path, const std::string& script) {return 0;} | ||||
| struct ProcessArgs { | |||||
| struct ProcessBlock { | |||||
| float sampleRate; | float sampleRate; | ||||
| float sampleTime; | float sampleTime; | ||||
| int bufferSize = 1; | |||||
| float inputs[NUM_ROWS][MAX_BUFFER_SIZE] = {}; | |||||
| float outputs[NUM_ROWS][MAX_BUFFER_SIZE] = {}; | |||||
| float knobs[NUM_ROWS] = {}; | |||||
| bool switches[NUM_ROWS] = {}; | |||||
| float lights[NUM_ROWS][3] = {}; | |||||
| float switchLights[NUM_ROWS][3] = {}; | |||||
| }; | }; | ||||
| /** Calls the script's process() method. | /** Calls the script's process() method. | ||||
| Return nonzero if failure, and set error message with setMessage(). | Return nonzero if failure, and set error message with setMessage(). | ||||
| */ | */ | ||||
| virtual int process(ProcessArgs& block) {return 0;} | |||||
| virtual int process(ProcessBlock& block) {return 0;} | |||||
| // Communication with Prototype module. | // Communication with Prototype module. | ||||
| // These cannot be called from your constructor, so initialize your engine in the run() method. | // These cannot be called from your constructor, so initialize your engine in the run() method. | ||||
| void setMessage(const std::string& message); | void setMessage(const std::string& message); | ||||
| int getFrameDivider(); | int getFrameDivider(); | ||||
| void setFrameDivider(int frameDivider); | void setFrameDivider(int frameDivider); | ||||
| float getInput(int index); | |||||
| void setOutput(int index, float voltage); | |||||
| float getKnob(int index); | |||||
| bool getSwitch(int index); | |||||
| void setLight(int index, int color, float brightness); | |||||
| void setSwitchLight(int index, int color, float brightness); | |||||
| int getBufferSize(); | |||||
| void setBufferSize(int bufferSize); | |||||
| // private | // private | ||||
| Prototype* module; | Prototype* module; | ||||
| }; | }; | ||||