<# MIDI Grid installer. Registers the scripts as Reaper actions and binds them, by editing reaper-kb.ini directly. This is done rather than via "Import key map" because Reaper's importer silently converts unresolved script bindings into "No-op (no action)" entries -- see README, Installation notes. REAPER MUST BE CLOSED. It rewrites reaper-kb.ini on exit and will discard anything written while it is running. Usage: powershell -ExecutionPolicy Bypass -File install.ps1 powershell -ExecutionPolicy Bypass -File install.ps1 -Uninstall #> [CmdletBinding()] param( [string] $ScriptDir = $PSScriptRoot, [string] $ResourcePath = "$env:APPDATA\REAPER", [switch] $Uninstall ) $ErrorActionPreference = 'Stop' $kb = Join-Path $ResourcePath 'reaper-kb.ini' if (-not (Test-Path $kb)) { throw "reaper-kb.ini not found at $kb" } if (Get-Process reaper* -ErrorAction SilentlyContinue) { throw "REAPER is running. Close it completely and run this again." } # id, section, description, script filename $actions = @( @('RSmidigrid_open', 0, 'MIDI Grid: Open selected item in grid mode', 'MidiGrid_OpenInGrid.lua'), @('RSmidigrid_daemon', 0, 'MIDI Grid: Preview daemon (auto-started)', 'MidiGrid_Daemon.lua'), @('RSmidigrid_mode', 32060, 'MIDI Grid: Toggle grid mode', 'MidiGrid_ToggleMode.lua'), @('RSmidigrid_left', 32060, 'MIDI Grid: Cursor left one cell', 'MidiGrid_Left.lua'), @('RSmidigrid_right', 32060, 'MIDI Grid: Cursor right one cell', 'MidiGrid_Right.lua'), @('RSmidigrid_up', 32060, 'MIDI Grid: Pitch up one scale degree', 'MidiGrid_Up.lua'), @('RSmidigrid_down', 32060, 'MIDI Grid: Pitch down one scale degree', 'MidiGrid_Down.lua'), @('RSmidigrid_cell', 32060, 'MIDI Grid: Toggle note at cursor cell', 'MidiGrid_ToggleCell.lua'), @('RSmidigrid_hold', 32060, 'MIDI Grid: Toggle hold mode', 'MidiGrid_ToggleHold.lua'), @('RSmidigrid_audit', 32060, 'MIDI Grid: Repeat current cell', 'MidiGrid_AuditionCell.lua'), @('RSmidigrid_scale', 32060, 'MIDI Grid: Set root and scale', 'MidiGrid_SetScale.lua') ) # flags, keycode, section, id # flags: 1 base, +4 Shift, +8 Ctrl, +16 Alt # section: 0 = Main, 32060 = MIDI Editor $keys = @( @(21, 71, 0, 'RSmidigrid_open'), @(17, 71, 32060, 'RSmidigrid_mode'), @(1, 32805, 32060, 'RSmidigrid_left'), @(1, 32807, 32060, 'RSmidigrid_right'), @(1, 32806, 32060, 'RSmidigrid_up'), @(1, 32808, 32060, 'RSmidigrid_down'), @(1, 13, 32060, 'RSmidigrid_cell'), @(17, 72, 32060, 'RSmidigrid_hold'), @(17, 65, 32060, 'RSmidigrid_audit'), @(17, 83, 32060, 'RSmidigrid_scale') ) $backup = "$kb.midigrid-backup" if (-not (Test-Path $backup)) { Copy-Item $kb $backup Write-Host "Backed up original to $backup" } $lines = [System.Collections.Generic.List[string]]::new() $lines.AddRange([System.IO.File]::ReadAllLines($kb)) # Drop any previous MIDI Grid lines so re-running is idempotent. for ($i = $lines.Count - 1; $i -ge 0; $i--) { if ($lines[$i] -match '(?i)RSmidigrid') { $lines.RemoveAt($i) } } if ($Uninstall) { [System.IO.File]::WriteAllLines($kb, $lines, (New-Object System.Text.UTF8Encoding($false))) Write-Host "Removed MIDI Grid actions and bindings." Write-Host "Note: keys it had taken over (arrows, Enter) are now unbound in the" Write-Host "MIDI editor. Rebind them, or restore $backup." return } foreach ($a in $actions) { $path = Join-Path $ScriptDir $a[3] if (-not (Test-Path $path)) { throw "Missing script: $path" } $lines.Insert(0, ('SCR 4 {0} {1} "{2}" {3}' -f $a[1], $a[0], $a[2], $path)) } # KEY lines reference the *named command*, which is the SCR id with a # leading underscore. Without it Reaper cannot resolve the binding and the # key silently does nothing. foreach ($k in $keys) { $new = 'KEY {0} {1} _{3} {2}' -f $k[0], $k[1], $k[2], $k[3] $pat = '^KEY {0} {1} \S+ {2}(\s|$)' -f $k[0], $k[1], $k[2] $found = $false for ($i = 0; $i -lt $lines.Count; $i++) { if ($lines[$i] -match $pat) { $lines[$i] = $new; $found = $true; break } } if (-not $found) { $lines.Add($new) } } [System.IO.File]::WriteAllLines($kb, $lines, (New-Object System.Text.UTF8Encoding($false))) Write-Host "Installed $($actions.Count) actions and $($keys.Count) key bindings." Write-Host "Start REAPER, select a MIDI item, and press Alt+Shift+G."