Hybrid pipeline: RPPBuilder writes VST3/MIDI/audio skeleton, ReaScript handles built-in plugins (ReaEQ, ReaComp) via TrackFX_AddByName + TrackFX_SetParam with multi-action dispatch, adaptive API check, and builtin plugin auto-detection from PLUGIN_REGISTRY. 326 tests (298 existing + 28 new), 12/12 spec scenarios compliant.
99 lines
4.7 KiB
Markdown
99 lines
4.7 KiB
Markdown
# reascript-builtin-fx Specification
|
|
|
|
Built-in REAPER plugin (ReaEQ, ReaComp, etc.) insertion and parameter configuration via ReaScript API, complementing RPPBuilder's VST3/MIDI/audio skeleton.
|
|
|
|
## Requirements
|
|
|
|
### Requirement: Insert Built-in FX via API
|
|
The ReaScript SHALL insert built-in REAPER plugins using `TrackFX_AddByName(fxname, instantiate=1)`, reading from command JSON's `plugins_to_add` list.
|
|
|
|
#### Scenario: Insert ReaEQ on target track
|
|
- GIVEN `plugins_to_add: [{"track_name": "Bass", "fx_name": "ReaEQ"}]`
|
|
- WHEN add_plugins action runs
|
|
- THEN `TrackFX_AddByName` is called on track "Bass" and the FX index is recorded in result
|
|
|
|
#### Scenario: Track not found
|
|
- GIVEN `plugins_to_add` references a non-existent track name
|
|
- WHEN insertion runs
|
|
- THEN an error with the track name is written to result; script continues to next plugin
|
|
|
|
### Requirement: Configure FX Parameters
|
|
The ReaScript SHALL call `TrackFX_SetParam(track, fx_idx, param_idx, value)` for each entry in a plugin's `params` dict.
|
|
|
|
#### Scenario: Set ReaEQ frequency and gain
|
|
- GIVEN ReaEQ at FX index 0 on "Bass" with `params: {"2": 200.0, "5": 3.0}`
|
|
- WHEN configure_fx_params runs
|
|
- THEN `SetParam(track, 0, 2, 200.0)` and `SetParam(track, 0, 5, 3.0)` are called
|
|
|
|
#### Scenario: Unknown param index
|
|
- GIVEN a params entry maps to a non-exposed index
|
|
- WHEN `TrackFX_SetParam` is called
|
|
- THEN the call proceeds (REAPER silently ignores invalid indices); no error raised
|
|
|
|
### Requirement: Post-Insertion Verification
|
|
After insertion, the ReaScript MUST verify the plugin loaded by calling `TrackFX_GetFXName`. A case-insensitive name match marks success; mismatch produces an error.
|
|
|
|
#### Scenario: Plugin loaded successfully
|
|
- GIVEN ReaEQ inserted at FX index 0
|
|
- WHEN verification runs
|
|
- THEN `GetFXName` returns "ReaEQ" (case-insensitive) and result marks it "ok"
|
|
|
|
#### Scenario: Plugin failed to load
|
|
- GIVEN insertion returned index -1 or name mismatch
|
|
- WHEN verification runs
|
|
- THEN result records `"failed to load ReaEQ on track Bass"`
|
|
|
|
### Requirement: Graceful API Degradation
|
|
The ReaScript SHALL check `TrackFX_AddByName`/`TrackFX_SetParam` availability at startup. If absent, it MUST exit with `{"status": "error"}` without attempting insertion.
|
|
|
|
#### Scenario: API functions missing
|
|
- GIVEN the REAPER version lacks `TrackFX_AddByName`
|
|
- WHEN `check_api()` runs
|
|
- THEN result is `{"status": "error", "message": "missing API: TrackFX_AddByName"}` and insertion is skipped
|
|
|
|
---
|
|
# Delta for reascript-generator
|
|
|
|
## ADDED Requirements
|
|
|
|
### Requirement: Multi-Action Dispatch
|
|
`ReaScriptCommand.action` SHALL accept an ordered string list. The generator MUST dispatch one script block per action in order. A string value like `"calibrate"` SHALL be treated as `["calibrate"]` for backward compat. Absent/empty SHALL default to `["calibrate"]`.
|
|
|
|
#### Scenario: Ordered pipeline
|
|
- GIVEN `action=["add_plugins", "verify_fx", "calibrate", "render"]`
|
|
- WHEN `_build_script()` runs
|
|
- THEN script contains insert → verify → calibrate → render blocks, each gated by its presence in the list
|
|
|
|
#### Scenario: String backward compat
|
|
- GIVEN `action="calibrate"`
|
|
- WHEN `_build_script()` runs
|
|
- THEN output matches current single-block behavior
|
|
|
|
### Requirement: Built-in FX Script Blocks
|
|
The generator SHALL produce code for `add_plugins` (iterates `plugins_to_add`, calls `TrackFX_AddByName`, verifies) and `configure_fx_params` (iterates same list, calls `TrackFX_SetParam`). Both SHALL be conditional on their action appearing in the list.
|
|
|
|
#### Scenario: Generate add_plugins + configure_fx_params
|
|
- GIVEN `plugins_to_add` with one ReaEQ entry + params, `action=["add_plugins", "configure_fx_params"]`
|
|
- WHEN script executes in REAPER
|
|
- THEN plugin is inserted then all specified params are configured
|
|
|
|
## MODIFIED Requirements
|
|
|
|
### Requirement: Extended Command/Result Schema
|
|
Command JSON SHALL include optional `plugins_to_add: [{"track_name": str, "fx_name": str, "params": {str: float}}]`. Result JSON SHALL include optional `added_plugins: [{"fx_name": str, "instance_id": int}]`.
|
|
(Previously: no plugin insertion fields.)
|
|
|
|
#### Scenario: plugins_to_add round-trip
|
|
- GIVEN command with `plugins_to_add=[{"track_name": "Bass", "fx_name": "ReaEQ", "params": {"2": 200.0}}]`
|
|
- WHEN script executes successfully
|
|
- THEN result includes `added_plugins: [{"fx_name": "ReaEQ", "instance_id": 0}]`
|
|
|
|
### Requirement: Adaptive API Check
|
|
`check_api()` SHALL require `TrackFX_AddByName`/`TrackFX_SetParam` when the action list includes `add_plugins` or `configure_fx_params`. For calibrate-only commands, the required set SHALL remain unchanged.
|
|
(Previously: required API set was static.)
|
|
|
|
#### Scenario: API check adapts
|
|
- GIVEN `action=["add_plugins"]`
|
|
- WHEN `check_api()` runs
|
|
- THEN `TrackFX_AddByName` and `TrackFX_SetParam` are required; absence produces error result
|