authorgravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-03-15 20:58:07-07:00
committergravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-03-15 20:59:28-07:00
log86523418f2362aabae6d3729466100d9d200251b
tree488e6257b8e401446894bb08ad9d67c2aded1c09
parent75da6a34d58d3ef23ff082a16a6252a61654565a
signaturebadge-check Signed by SSH key SHA256:52mNGHRsVFBDED9IAX5pe+LRWUefqTbxEReunq21QvU

feat: reaper record flow


10 files changed, 373 insertions(+), 305 deletions(-)

config/reaper.ts+68-52
......@@ -1,58 +1,74 @@
1import * as config from "#config";
12import { Reaper } from "@clo/creative-control/Reaper.ts";
23import { SpeedEditor } from "@clo/creative-control/SpeedEditor.ts";
3import * as config from "#config";
44
5export default config.forApp("com.cockos.reaper", ({ speededitor: se, mac }) => {
6 const reaper = new Reaper();
5export default config.forApp(
6 "com.cockos.reaper",
7 ({ speededitor: se, mac }) => {
8 const reaper = new Reaper();
79
8 // Sync state to LEDs
9 reaper.on("transport", (transport) => {
10 console.info(transport);
11 se.leds.audioOnly = transport.recording;
12 });
13 mac.on("window", (window) => {
14 se.leds.videoOnly = Boolean(window?.title.startsWith("FX:"));
15 });
10 // Sync state to LEDs
11 reaper.on("transport", (transport) => {
12 se.leds.cut = transport.recording;
13 se.leds.dissolve = transport.recording;
14 se.leds.smoothCut = transport.recording;
15 });
16 mac.on("window", (window) => {
17 se.leds.videoOnly = Boolean(window?.title.startsWith("FX:"));
18 });
1619
17 // Keyboard Actions
18 SpeedEditor.camNumbersToNumpad(se, mac);
19 se.onPress("stopPlay", () => {
20 if(reaper.transport.recording) {
21 reaper.runAction('transport-stop-save-all-recorded-media');
22 } else {
23 reaper.runAction('transport-play-stop');
24 }
25 });
26 se.onPress("smartInsert", () => {
27 mac.toast("Add Komplete Kontrol")
28 reaper.runScript("insert_komplete_kontrol_track");
29 });
30 se.onPress("append", () => {
31 mac.toast("Add Addictive Drums")
32 reaper.runScript("insert_addictive_drums_track");
33 });
34 se.onPress("rippleOverwrite", () => {
35 mac.toast("Blank Track")
36 reaper.runScript("insert_blank_track");
37 });
38 se.onPress("audioOnly", () => {
39 if(reaper.transport.recording) {
40 reaper.runAction('transport-stop-delete-all-recorded-media');
41 reaper.runAction('transport-record');
42 } else {
43 reaper.runAction('transport-record');
44 }
45 });
46 se.onPress("videoOnly", () => {
47 if (mac.window?.title.startsWith("FX:") && mac.mainWindow) {
48 mac.focusMainWindow();
49 return;
50 }
51 reaper.runAction("track-view-fx-chain-for-current-last-touched-track");
52 });
20 // Keyboard Actions
21 SpeedEditor.camNumbersToNumpad(se, mac);
22 se.onPress("stopPlay", () => {
23 if (reaper.transport.recording) {
24 reaper.runAction("transport-stop-save-all-recorded-media");
25 } else {
26 reaper.runAction("transport-play-stop");
27 }
28 });
29 se.onPress("smartInsert", () => {
30 mac.toast("Add Komplete Kontrol");
31 reaper.runScript("insert_komplete_kontrol_track");
32 });
33 se.onPress("append", () => {
34 mac.toast("Add Addictive Drums");
35 reaper.runScript("insert_addictive_drums_track");
36 });
37 se.onPress("rippleOverwrite", () => {
38 mac.toast("Blank Track");
39 reaper.runScript("insert_blank_track");
40 });
41 se.onPress("cut", () => {
42 if (reaper.transport.recording) {
43 reaper.runAction("transport-stop-delete-all-recorded-media");
44 reaper.runAction("transport-record");
45 } else {
46 reaper.runAction("transport-record");
47 }
48 });
49 se.onPress("dissolve", () => {
50 reaper.runAction("transport-stop-delete-all-recorded-media");
51 });
52 se.onPress("smoothCut", () => {
53 if (reaper.transport.recording) {
54 reaper.runAction("transport-stop-save-all-recorded-media");
55 reaper.runAction("transport-record");
56 }
57 });
58 se.onPress("videoOnly", () => {
59 if (mac.window?.title.startsWith("FX:") && mac.mainWindow) {
60 mac.focusMainWindow();
61 return;
62 }
63 reaper.runAction("track-view-fx-chain-for-current-last-touched-track");
64 });
65 se.onPress("fullView", () => {
66 mac.pressKey("x");
67 });
5368
54 // TODO: stabilize / find a better use-case for the knob
55 se.on("jog", ({ value = 0 }) => {
56 reaper.scrub(value / 20);
57 });
58});
69 // TODO: stabilize / find a better use-case for the knob
70 // se.on("jog", ({ value = 0 }) => {
71 // reaper.scrub(value / 20);
72 // });
73 },
74);
dprint.json created+17
......@@ -0,0 +1,17 @@
1{
2 "typescript": {
3 },
4 "json": {
5 },
6 "markdown": {
7 },
8 "excludes": [
9 "**/node_modules",
10 "**/*-lock.json"
11 ],
12 "plugins": [
13 "https://plugins.dprint.dev/typescript-0.95.15.wasm",
14 "https://plugins.dprint.dev/json-0.21.1.wasm",
15 "https://plugins.dprint.dev/markdown-0.21.1.wasm"
16 ]
17}
examples/event-listener.ts+1-1
......@@ -15,7 +15,7 @@ editor.on("keypress", (key) => {
1515 }
1616});
1717editor.onDoublePress("transition", () => {
18 console.info('(double press) "Title"');
18 console.info("(double press) \"Title\"");
1919});
2020
2121console.info("init");
readme.md+4-3
......@@ -10,7 +10,8 @@ These tools only work on macOS. I don't have interest in maintaining other confi
1010
1111## Hardware
1212
13TODO:
13TODO:
14
1415- generic keyboard / karabiner elements integration?
1516- custom trackpad integration?
1617
......@@ -55,8 +56,8 @@ reaper.on("transport", (transport) => {
5556 transport.recording
5657 ? "You are recording"
5758 : transport.playing
58 ? "Playing"
59 : "Stopped"
59 ? "Playing"
60 : "Stopped",
6061 );
6162});
6263```
src/Mac.ts+142-140
......@@ -32,13 +32,13 @@ const FRONTMOST_APP_HELPER_FRAMEWORKS = [
3232 "ApplicationServices",
3333] as const;
3434const KEYBOARD_EVENT_SCRIPT = [
35 'ObjC.import("ApplicationServices");',
35 "ObjC.import(\"ApplicationServices\");",
3636 "function run(argv) {",
3737 " const payload = JSON.parse(argv[0] ?? '{}');",
3838 " const actions = Array.isArray(payload.actions) ? payload.actions : [];",
3939 " for (const action of actions) {",
4040 " if (!Number.isInteger(action.keyCode)) {",
41 ' throw new Error(`Invalid key code: ${JSON.stringify(action)}`);',
41 " throw new Error(`Invalid key code: ${JSON.stringify(action)}`);",
4242 " }",
4343 " const event = $.CGEventCreateKeyboardEvent(",
4444 " null,",
......@@ -46,139 +46,141 @@ const KEYBOARD_EVENT_SCRIPT = [
4646 " Boolean(action.isDown),",
4747 " );",
4848 " if (!event) {",
49 ' throw new Error(`Failed to create keyboard event for key code ${action.keyCode}`);',
49 " throw new Error(`Failed to create keyboard event for key code ${action.keyCode}`);",
5050 " }",
5151 " $.CGEventPost($.kCGHIDEventTap, event);",
5252 " $.CFRelease(event);",
5353 " }",
54 ' return "";',
54 " return \"\";",
5555 "}",
5656].join("\n");
5757let frontmostAppHelperBinaryPromise: Promise<string> | null = null;
5858let toastHelperBinaryPromise: Promise<string> | null = null;
5959
6060// Key codes from Carbon/HIToolbox Events.h (virtual key codes on ANSI/US layouts).
61const KEY_CODES = Object.freeze({
62 a: 0x00,
63 s: 0x01,
64 d: 0x02,
65 f: 0x03,
66 h: 0x04,
67 g: 0x05,
68 z: 0x06,
69 x: 0x07,
70 c: 0x08,
71 v: 0x09,
72 isoSection: 0x0A,
73 b: 0x0B,
74 q: 0x0C,
75 w: 0x0D,
76 e: 0x0E,
77 r: 0x0F,
78 y: 0x10,
79 t: 0x11,
80 "1": 0x12,
81 "2": 0x13,
82 "3": 0x14,
83 "4": 0x15,
84 "6": 0x16,
85 "5": 0x17,
86 equal: 0x18,
87 "9": 0x19,
88 "7": 0x1A,
89 minus: 0x1B,
90 "8": 0x1C,
91 "0": 0x1D,
92 rightBracket: 0x1E,
93 o: 0x1F,
94 u: 0x20,
95 leftBracket: 0x21,
96 i: 0x22,
97 p: 0x23,
98 return: 0x24,
99 l: 0x25,
100 j: 0x26,
101 quote: 0x27,
102 k: 0x28,
103 semicolon: 0x29,
104 backslash: 0x2A,
105 comma: 0x2B,
106 slash: 0x2C,
107 n: 0x2D,
108 m: 0x2E,
109 period: 0x2F,
110 tab: 0x30,
111 space: 0x31,
112 grave: 0x32,
113 delete: 0x33,
114 escape: 0x35,
115 rightCommand: 0x36,
116 command: 0x37,
117 shift: 0x38,
118 capsLock: 0x39,
119 option: 0x3A,
120 control: 0x3B,
121 rightShift: 0x3C,
122 rightOption: 0x3D,
123 rightControl: 0x3E,
124 function: 0x3F,
125 f17: 0x40,
126 numpadDecimal: 0x41,
127 numpadMultiply: 0x43,
128 numpadPlus: 0x45,
129 numpadClear: 0x47,
130 volumeUp: 0x48,
131 volumeDown: 0x49,
132 mute: 0x4A,
133 numpadDivide: 0x4B,
134 numpadEnter: 0x4C,
135 numpadMinus: 0x4E,
136 f18: 0x4F,
137 f19: 0x50,
138 numpadEquals: 0x51,
139 numpad0: 0x52,
140 numpad1: 0x53,
141 numpad2: 0x54,
142 numpad3: 0x55,
143 numpad4: 0x56,
144 numpad5: 0x57,
145 numpad6: 0x58,
146 numpad7: 0x59,
147 f20: 0x5A,
148 numpad8: 0x5B,
149 numpad9: 0x5C,
150 jisYen: 0x5D,
151 jisUnderscore: 0x5E,
152 jisKeypadComma: 0x5F,
153 f5: 0x60,
154 f6: 0x61,
155 f7: 0x62,
156 f3: 0x63,
157 f8: 0x64,
158 f9: 0x65,
159 jisEisu: 0x66,
160 f11: 0x67,
161 jisKana: 0x68,
162 f13: 0x69,
163 f16: 0x6A,
164 f14: 0x6B,
165 f10: 0x6D,
166 f12: 0x6F,
167 f15: 0x71,
168 help: 0x72,
169 home: 0x73,
170 pageUp: 0x74,
171 forwardDelete: 0x75,
172 f4: 0x76,
173 end: 0x77,
174 f2: 0x78,
175 pageDown: 0x79,
176 f1: 0x7A,
177 leftArrow: 0x7B,
178 rightArrow: 0x7C,
179 downArrow: 0x7D,
180 upArrow: 0x7E,
181} as const);
61const KEY_CODES = Object.freeze(
62 {
63 a: 0x00,
64 s: 0x01,
65 d: 0x02,
66 f: 0x03,
67 h: 0x04,
68 g: 0x05,
69 z: 0x06,
70 x: 0x07,
71 c: 0x08,
72 v: 0x09,
73 isoSection: 0x0A,
74 b: 0x0B,
75 q: 0x0C,
76 w: 0x0D,
77 e: 0x0E,
78 r: 0x0F,
79 y: 0x10,
80 t: 0x11,
81 "1": 0x12,
82 "2": 0x13,
83 "3": 0x14,
84 "4": 0x15,
85 "6": 0x16,
86 "5": 0x17,
87 equal: 0x18,
88 "9": 0x19,
89 "7": 0x1A,
90 minus: 0x1B,
91 "8": 0x1C,
92 "0": 0x1D,
93 rightBracket: 0x1E,
94 o: 0x1F,
95 u: 0x20,
96 leftBracket: 0x21,
97 i: 0x22,
98 p: 0x23,
99 return: 0x24,
100 l: 0x25,
101 j: 0x26,
102 quote: 0x27,
103 k: 0x28,
104 semicolon: 0x29,
105 backslash: 0x2A,
106 comma: 0x2B,
107 slash: 0x2C,
108 n: 0x2D,
109 m: 0x2E,
110 period: 0x2F,
111 tab: 0x30,
112 space: 0x31,
113 grave: 0x32,
114 delete: 0x33,
115 escape: 0x35,
116 rightCommand: 0x36,
117 command: 0x37,
118 shift: 0x38,
119 capsLock: 0x39,
120 option: 0x3A,
121 control: 0x3B,
122 rightShift: 0x3C,
123 rightOption: 0x3D,
124 rightControl: 0x3E,
125 function: 0x3F,
126 f17: 0x40,
127 numpadDecimal: 0x41,
128 numpadMultiply: 0x43,
129 numpadPlus: 0x45,
130 numpadClear: 0x47,
131 volumeUp: 0x48,
132 volumeDown: 0x49,
133 mute: 0x4A,
134 numpadDivide: 0x4B,
135 numpadEnter: 0x4C,
136 numpadMinus: 0x4E,
137 f18: 0x4F,
138 f19: 0x50,
139 numpadEquals: 0x51,
140 numpad0: 0x52,
141 numpad1: 0x53,
142 numpad2: 0x54,
143 numpad3: 0x55,
144 numpad4: 0x56,
145 numpad5: 0x57,
146 numpad6: 0x58,
147 numpad7: 0x59,
148 f20: 0x5A,
149 numpad8: 0x5B,
150 numpad9: 0x5C,
151 jisYen: 0x5D,
152 jisUnderscore: 0x5E,
153 jisKeypadComma: 0x5F,
154 f5: 0x60,
155 f6: 0x61,
156 f7: 0x62,
157 f3: 0x63,
158 f8: 0x64,
159 f9: 0x65,
160 jisEisu: 0x66,
161 f11: 0x67,
162 jisKana: 0x68,
163 f13: 0x69,
164 f16: 0x6A,
165 f14: 0x6B,
166 f10: 0x6D,
167 f12: 0x6F,
168 f15: 0x71,
169 help: 0x72,
170 home: 0x73,
171 pageUp: 0x74,
172 forwardDelete: 0x75,
173 f4: 0x76,
174 end: 0x77,
175 f2: 0x78,
176 pageDown: 0x79,
177 f1: 0x7A,
178 leftArrow: 0x7B,
179 rightArrow: 0x7C,
180 downArrow: 0x7D,
181 upArrow: 0x7E,
182 } as const,
183);
182184type MacKeyName = keyof typeof KEY_CODES;
183185
184186const KEY_NAMES = Object.freeze(Object.keys(KEY_CODES) as MacKeyName[]);
......@@ -732,12 +734,12 @@ function parseFrontmostStateLine(line: string): FrontmostState {
732734
733735function normalizeBundleId(value: unknown) {
734736 const directBundleId = typeof value === "string" ? value.trim() : "";
735 const bundleId = BUNDLE_ID_PATTERN.exec(directBundleId)?.[0] ??
736 directBundleId;
737 const bundleId = BUNDLE_ID_PATTERN.exec(directBundleId)?.[0]
738 ?? directBundleId;
737739 if (
738 bundleId === "" ||
739 bundleId === "undefined" ||
740 bundleId === "[id nil]"
740 bundleId === ""
741 || bundleId === "undefined"
742 || bundleId === "[id nil]"
741743 ) {
742744 return null;
743745 }
......@@ -837,10 +839,10 @@ function windowEquals(left: Mac.Window | null, right: Mac.Window | null) {
837839 if (!left || !right) {
838840 return left === right;
839841 }
840 return left.id === right.id &&
841 left.title === right.title &&
842 left.main === right.main &&
843 left.focused === right.focused;
842 return left.id === right.id
843 && left.title === right.title
844 && left.main === right.main
845 && left.focused === right.focused;
844846}
845847
846848function normalizeDelayMs(value: number, name: string) {
......@@ -884,9 +886,9 @@ function resolveKeyCode(key: Mac.Key): number {
884886
885887function normalizeKeyCode(keyCode: number) {
886888 if (
887 !Number.isInteger(keyCode) ||
888 keyCode < 0 ||
889 keyCode > 0xFFFF
889 !Number.isInteger(keyCode)
890 || keyCode < 0
891 || keyCode > 0xFFFF
890892 ) {
891893 throw new Error(`Mac keyCode must be an integer between 0 and 65535`);
892894 }
......@@ -946,9 +948,9 @@ function formatKeyboardDispatchError(error: unknown) {
946948 const details = extractCommandErrorOutput(error);
947949 const suffix = details ? ` ${details}` : "";
948950 return (
949 "Failed to send a macOS keyboard event via osascript. " +
950 "Make sure this process is allowed in System Settings > Privacy & Security > Accessibility." +
951 suffix
951 "Failed to send a macOS keyboard event via osascript. "
952 + "Make sure this process is allowed in System Settings > Privacy & Security > Accessibility."
953 + suffix
952954 );
953955}
954956
src/Reaper.ts+20-20
......@@ -1,6 +1,5 @@
11import { Events } from "@clo/lib/Events.ts";
22import * as log from "@clo/lib/log.ts";
3import { REAPER_ACTIONS, type ReaperActionId } from "./Reaper/actions.ts";
43import { execFile } from "node:child_process";
54import { createSocket, type Socket } from "node:dgram";
65import { readFileSync } from "node:fs";
......@@ -9,6 +8,7 @@ import { basename, dirname, join } from "node:path";
98import process from "node:process";
109import { fileURLToPath } from "node:url";
1110import { promisify } from "node:util";
11import { REAPER_ACTIONS, type ReaperActionId } from "./Reaper/actions.ts";
1212const console = log.scoped("reaper");
1313
1414export type { ReaperActionId } from "./Reaper/actions.ts";
......@@ -94,10 +94,10 @@ const DEFAULT_REAPER_OSC_TARGET_DIR = join(
9494 DEFAULT_REAPER_RESOURCE_DIR,
9595 "OSC",
9696);
97const REAPER_SCRIPT_TARGET_DIR = process.env.REAPER_SCRIPTS_DIR ??
98 DEFAULT_REAPER_SCRIPT_TARGET_DIR;
99const REAPER_OSC_TARGET_DIR = process.env.REAPER_OSC_DIR ??
100 DEFAULT_REAPER_OSC_TARGET_DIR;
97const REAPER_SCRIPT_TARGET_DIR = process.env.REAPER_SCRIPTS_DIR
98 ?? DEFAULT_REAPER_SCRIPT_TARGET_DIR;
99const REAPER_OSC_TARGET_DIR = process.env.REAPER_OSC_DIR
100 ?? DEFAULT_REAPER_OSC_TARGET_DIR;
101101const OSC_PATTERN_FILE = "CloverAutomation.ReaperOSC";
102102const OSC_PATTERN_NAME = stripReaperOscExtension(OSC_PATTERN_FILE);
103103const OSC_PATTERN_CONFIG = `# OSC pattern config file for Clover Creative Control's REAPER integration.
......@@ -174,10 +174,10 @@ export class Reaper extends Events<Reaper.EventMap> {
174174 }
175175
176176 console.info(
177 `${OSC_PATTERN_FILE} is not registered yet. ` +
178 `Add an OSC control surface manually using the "${OSC_PATTERN_NAME}" pattern, set REAPER's local listen port to ` +
179 `${this.#oscPort}, and send to ${this.#oscHost}:${this.#oscBindPort}. ` +
180 "The REAPER web interface is not required for this config."
177 `${OSC_PATTERN_FILE} is not registered yet. `
178 + `Add an OSC control surface manually using the "${OSC_PATTERN_NAME}" pattern, set REAPER's local listen port to `
179 + `${this.#oscPort}, and send to ${this.#oscHost}:${this.#oscBindPort}. `
180 + "The REAPER web interface is not required for this config.",
181181 );
182182 }
183183
......@@ -475,13 +475,13 @@ function sameTransportState(
475475 left: ReaperTransportState,
476476 right: ReaperTransportState,
477477) {
478 return left.playing === right.playing &&
479 left.paused === right.paused &&
480 left.recording === right.recording &&
481 left.repeatOn === right.repeatOn &&
482 left.positionSeconds === right.positionSeconds &&
483 left.positionString === right.positionString &&
484 left.positionBeatsString === right.positionBeatsString;
478 return left.playing === right.playing
479 && left.paused === right.paused
480 && left.recording === right.recording
481 && left.repeatOn === right.repeatOn
482 && left.positionSeconds === right.positionSeconds
483 && left.positionString === right.positionString
484 && left.positionBeatsString === right.positionBeatsString;
485485}
486486
487487function optimisticTransportPatchForAction(
......@@ -615,8 +615,8 @@ function hasManagedOscSurface(config: string) {
615615
616616 const normalizedTokens = tokens.map((token) => unquoteReaperToken(token));
617617 if (
618 normalizedTokens.includes(OSC_PATTERN_FILE) ||
619 normalizedTokens.includes(OSC_PATTERN_NAME)
618 normalizedTokens.includes(OSC_PATTERN_FILE)
619 || normalizedTokens.includes(OSC_PATTERN_NAME)
620620 ) {
621621 return true;
622622 }
......@@ -645,8 +645,8 @@ function formatError(error: unknown) {
645645
646646function unquoteReaperToken(token: string) {
647647 if (
648 (token.startsWith("'") && token.endsWith("'")) ||
649 (token.startsWith("\"") && token.endsWith("\""))
648 (token.startsWith("'") && token.endsWith("'"))
649 || (token.startsWith("\"") && token.endsWith("\""))
650650 ) {
651651 return token.slice(1, -1);
652652 }
src/Reaper/actions.ts+82-41
......@@ -52,7 +52,8 @@ export const REAPER_ACTIONS = {
5252 "action-skip-next-action-if-cc-parameter-0-mid-2017": 2017,
5353 "action-skip-next-action-if-cc-parameter-0-mid-2018": 2018,
5454 "action-skip-next-action-set-cc-parameter-to-relative-plus-1-if-action-armed-0-otherwise": 2023,
55 "action-skip-next-action-set-cc-parameter-to-relative-plus-1-if-action-toggle-state-enabled-1-if-disabled-0-if-toggle-state-unavailable": 2022,
55 "action-skip-next-action-set-cc-parameter-to-relative-plus-1-if-action-toggle-state-enabled-1-if-disabled-0-if-toggle-state-unavailable":
56 2022,
5657 "action-toggle-arm-of-next-action": 2021,
5758 "action-wait-0-1-seconds-before-next-action": 2008,
5859 "action-wait-0-5-seconds-before-next-action": 2009,
......@@ -625,7 +626,8 @@ export const REAPER_ACTIONS = {
625626 "file-open-render-queue": 40929,
626627 "file-open-render-statistics-charts-from-most-recent-render-in-web-browser": 42497,
627628 "file-open-render-statistics-charts-from-most-recent-render-in-web-browser-hide-file-paths": 42510,
628 "file-open-render-statistics-charts-from-most-recent-render-in-web-browser-hide-file-paths-and-project-regions-markers": 43343,
629 "file-open-render-statistics-charts-from-most-recent-render-in-web-browser-hide-file-paths-and-project-regions-markers":
630 43343,
629631 "file-open-render-statistics-charts-from-most-recent-render-in-web-browser-hide-project-regions-markers": 43342,
630632 "file-project-settings": 40021,
631633 "file-quit-reaper": 40004,
......@@ -1203,7 +1205,8 @@ export const REAPER_ACTIONS = {
12031205 "item-open-items-in-secondary-external-editor": 40202,
12041206 "item-paste-items-tracks": 42398,
12051207 "item-paste-items-tracks-at-mouse-position": 41221,
1206 "item-paste-items-tracks-creating-pooled-ghost-midi-items-and-automation-items-regardless-of-preferences-media-midi-and-preferences-media-automation-settings": 41072,
1208 "item-paste-items-tracks-creating-pooled-ghost-midi-items-and-automation-items-regardless-of-preferences-media-midi-and-preferences-media-automation-settings":
1209 41072,
12071210 "item-paste-items-tracks-old-style-handling-of-hidden-tracks": 40058,
12081211 "item-propagate-to-all-similarly-named-items": 41979,
12091212 "item-propagate-to-similarly-named-items-on-track": 41977,
......@@ -1256,9 +1259,12 @@ export const REAPER_ACTIONS = {
12561259 "item-properties-set-item-timebase-to-beats-position-only": 40485,
12571260 "item-properties-set-item-timebase-to-project-track-default": 40380,
12581261 "item-properties-set-item-timebase-to-time": 40433,
1259 "item-properties-set-midi-items-to-follow-project-tempo-changes-set-item-timebase-to-beats-position-length-rate": 43095,
1260 "item-properties-set-midi-items-to-use-current-tempo-and-ignore-project-tempo-changes-set-item-timebase-to-beats-position-only": 43096,
1261 "item-properties-set-midi-items-to-use-current-tempo-and-ignore-project-tempo-changes-set-item-timebase-to-time": 43094,
1262 "item-properties-set-midi-items-to-follow-project-tempo-changes-set-item-timebase-to-beats-position-length-rate":
1263 43095,
1264 "item-properties-set-midi-items-to-use-current-tempo-and-ignore-project-tempo-changes-set-item-timebase-to-beats-position-only":
1265 43096,
1266 "item-properties-set-midi-items-to-use-current-tempo-and-ignore-project-tempo-changes-set-item-timebase-to-time":
1267 43094,
12621268 "item-properties-set-take-channel-mode-to-mono-channel-03": 41388,
12631269 "item-properties-set-take-channel-mode-to-mono-channel-04": 41389,
12641270 "item-properties-set-take-channel-mode-to-mono-channel-05": 41390,
......@@ -1812,12 +1818,14 @@ export const REAPER_ACTIONS = {
18121818 "options-add-edge-points-when-moving-envelope-points-with-items": 40648,
18131819 "options-add-edge-points-when-moving-multiple-envelope-points": 42030,
18141820 "options-add-envelope-edge-points-when-ripple-editing-or-inserting-time": 40649,
1815 "options-allow-drag-drop-media-import-to-target-the-top-part-of-a-track-to-insert-a-new-track-to-receive-the-media": 42477,
1821 "options-allow-drag-drop-media-import-to-target-the-top-part-of-a-track-to-insert-a-new-track-to-receive-the-media":
1822 42477,
18161823 "options-allow-selecting-empty-takes": 41355,
18171824 "options-always-record-to-automation-items": 42212,
18181825 "options-always-trim-content-behind-razor-edits-otherwise-follow-media-item-editing-preferences": 42421,
18191826 "options-auto-crossfade-media-items-when-editing": 40041,
1820 "options-automatically-insert-automation-item-when-activating-envelope-that-is-bypassed-outside-of-automation-items-and-not-displayed-in-envelope-lane": 42220,
1827 "options-automatically-insert-automation-item-when-activating-envelope-that-is-bypassed-outside-of-automation-items-and-not-displayed-in-envelope-lane":
1828 42220,
18211829 "options-automation-item-baseline-amplitude-edits-affect-pooled-copies": 42194,
18221830 "options-automation-items-connect-to-the-underlying-envelope-on-both-sides": 42205,
18231831 "options-automation-items-connect-to-the-underlying-envelope-on-the-right-side": 42204,
......@@ -2307,8 +2315,10 @@ export const REAPER_ACTIONS = {
23072315 "sws-aw-play-stop-automatically-group-simultaneously-recorded-items-deprecated": 53503,
23082316 "sws-aw-record-automatically-group-simultaneously-recorded-items-deprecated": 53500,
23092317 "sws-aw-record-conditional-normal-or-time-selection-only": 53497,
2310 "sws-aw-record-conditional-normal-or-time-selection-only-automatically-group-simultaneously-recorded-items-deprecated": 53501,
2311 "sws-aw-record-conditional-normal-time-selection-item-selection-automatically-group-simultaneously-recorded-items-deprecated": 53502,
2318 "sws-aw-record-conditional-normal-or-time-selection-only-automatically-group-simultaneously-recorded-items-deprecated":
2319 53501,
2320 "sws-aw-record-conditional-normal-time-selection-item-selection-automatically-group-simultaneously-recorded-items-deprecated":
2321 53502,
23122322 "sws-aw-record-conditional-normal-time-selection-or-item-selection": 53498,
23132323 "sws-aw-remove-overlaps-in-selected-items-preserving-item-starts": 53496,
23142324 "sws-aw-remove-tracks-items-env-obeying-time-selection-and-leaving-children": 53554,
......@@ -2383,24 +2393,34 @@ export const REAPER_ACTIONS = {
23832393 "sws-br-apply-next-action-to-all-visible-envelopes-in-selected-tracks": 54100,
23842394 "sws-br-apply-next-action-to-all-visible-envelopes-in-selected-tracks-if-there-is-no-track-envelope-selected": 54102,
23852395 "sws-br-apply-next-action-to-all-visible-record-armed-envelopes-in-selected-tracks": 54101,
2386 "sws-br-apply-next-action-to-all-visible-record-armed-envelopes-in-selected-tracks-if-there-is-no-track-envelope-selected": 54103,
2396 "sws-br-apply-next-action-to-all-visible-record-armed-envelopes-in-selected-tracks-if-there-is-no-track-envelope-selected":
2397 54103,
23872398 "sws-br-check-for-new-sws-version": 55821,
23882399 "sws-br-contextual-toolbars": 53938,
23892400 "sws-br-convert-project-markers-to-tempo-markers": 54846,
2390 "sws-br-convert-selected-envelope-s-curve-in-time-selection-to-cc-events-in-last-clicked-cc-lane-in-last-active-midi-editor": 54051,
2391 "sws-br-convert-selected-envelope-s-curve-in-time-selection-to-cc-events-in-last-clicked-cc-lane-in-last-active-midi-editor-clear-existing-events": 54052,
2392 "sws-br-convert-selected-points-in-selected-envelope-to-cc-events-in-last-clicked-cc-lane-in-last-active-midi-editor": 54049,
2393 "sws-br-convert-selected-points-in-selected-envelope-to-cc-events-in-last-clicked-cc-lane-in-last-active-midi-editor-clear-existing-events": 54050,
2401 "sws-br-convert-selected-envelope-s-curve-in-time-selection-to-cc-events-in-last-clicked-cc-lane-in-last-active-midi-editor":
2402 54051,
2403 "sws-br-convert-selected-envelope-s-curve-in-time-selection-to-cc-events-in-last-clicked-cc-lane-in-last-active-midi-editor-clear-existing-events":
2404 54052,
2405 "sws-br-convert-selected-points-in-selected-envelope-to-cc-events-in-last-clicked-cc-lane-in-last-active-midi-editor":
2406 54049,
2407 "sws-br-convert-selected-points-in-selected-envelope-to-cc-events-in-last-clicked-cc-lane-in-last-active-midi-editor-clear-existing-events":
2408 54050,
23942409 "sws-br-copy-points-in-time-selection-in-selected-envelope-to-all-visible-envelopes-in-selected-tracks": 54072,
2395 "sws-br-copy-points-in-time-selection-in-selected-envelope-to-all-visible-envelopes-in-selected-tracks-paste-at-edit-cursor": 54076,
2396 "sws-br-copy-points-in-time-selection-in-selected-envelope-to-all-visible-record-armed-in-envelopes-of-selected-tracks": 54073,
2397 "sws-br-copy-points-in-time-selection-in-selected-envelope-to-all-visible-record-armed-in-envelopes-of-selected-tracks-paste-at-edit-cursor": 54077,
2410 "sws-br-copy-points-in-time-selection-in-selected-envelope-to-all-visible-envelopes-in-selected-tracks-paste-at-edit-cursor":
2411 54076,
2412 "sws-br-copy-points-in-time-selection-in-selected-envelope-to-all-visible-record-armed-in-envelopes-of-selected-tracks":
2413 54073,
2414 "sws-br-copy-points-in-time-selection-in-selected-envelope-to-all-visible-record-armed-in-envelopes-of-selected-tracks-paste-at-edit-cursor":
2415 54077,
23982416 "sws-br-copy-points-in-time-selection-in-selected-envelope-to-envelope-at-mouse-cursor": 54079,
23992417 "sws-br-copy-points-in-time-selection-in-selected-envelope-to-envelope-at-mouse-cursor-paste-at-edit-cursor": 54081,
24002418 "sws-br-copy-selected-points-in-selected-envelope-to-all-visible-envelopes-in-selected-tracks": 54070,
2401 "sws-br-copy-selected-points-in-selected-envelope-to-all-visible-envelopes-in-selected-tracks-paste-at-edit-cursor": 54074,
2419 "sws-br-copy-selected-points-in-selected-envelope-to-all-visible-envelopes-in-selected-tracks-paste-at-edit-cursor":
2420 54074,
24022421 "sws-br-copy-selected-points-in-selected-envelope-to-all-visible-record-armed-envelopes-in-selected-tracks": 54071,
2403 "sws-br-copy-selected-points-in-selected-envelope-to-all-visible-record-armed-envelopes-in-selected-tracks-paste-at-edit-cursor": 54075,
2422 "sws-br-copy-selected-points-in-selected-envelope-to-all-visible-record-armed-envelopes-in-selected-tracks-paste-at-edit-cursor":
2423 54075,
24042424 "sws-br-copy-selected-points-in-selected-envelope-to-envelope-at-mouse-cursor": 54078,
24052425 "sws-br-copy-selected-points-in-selected-envelope-to-to-envelope-at-mouse-cursor-paste-at-edit-cursor": 54080,
24062426 "sws-br-copy-take-media-source-file-path-of-selected-items-to-clipboard": 54503,
......@@ -2437,7 +2457,8 @@ export const REAPER_ACTIONS = {
24372457 "sws-br-delete-tempo-marker-preserve-overall-tempo-and-positions-if-possible": 54838,
24382458 "sws-br-disable-ignore-project-tempo-for-selected-midi-items": 54465,
24392459 "sws-br-disable-ignore-project-tempo-for-selected-midi-items-preserving-time-position-of-midi-events": 54466,
2440 "sws-br-enable-ignore-project-tempo-for-selected-midi-items-preserving-time-position-of-midi-events-use-tempo-at-item-s-start": 54468,
2460 "sws-br-enable-ignore-project-tempo-for-selected-midi-items-preserving-time-position-of-midi-events-use-tempo-at-item-s-start":
2461 54468,
24412462 "sws-br-enable-ignore-project-tempo-for-selected-midi-items-use-tempo-at-item-s-start": 54467,
24422463 "sws-br-exclusive-toggle-contextual-toolbar-under-mouse-cursor-preset-1": 53979,
24432464 "sws-br-exclusive-toggle-contextual-toolbar-under-mouse-cursor-preset-2": 53984,
......@@ -2594,12 +2615,16 @@ export const REAPER_ACTIONS = {
25942615 "sws-br-options-toggle-scroll-view-to-edit-cursor-on-stop": 54713,
25952616 "sws-br-options-toggle-send-all-notes-off-on-stop-play": 54691,
25962617 "sws-br-options-toggle-stop-repeat-playback-at-end-of-project": 54712,
2597 "sws-br-play-from-edit-cursor-position-and-solo-item-and-track-under-mouse-for-the-duration-perform-until-shortcut-released": 54863,
2598 "sws-br-play-from-edit-cursor-position-and-solo-track-under-mouse-for-the-duration-perform-until-shortcut-released": 54862,
2618 "sws-br-play-from-edit-cursor-position-and-solo-item-and-track-under-mouse-for-the-duration-perform-until-shortcut-released":
2619 54863,
2620 "sws-br-play-from-edit-cursor-position-and-solo-track-under-mouse-for-the-duration-perform-until-shortcut-released":
2621 54862,
25992622 "sws-br-play-from-edit-cursor-position-perform-until-shortcut-released": 54861,
26002623 "sws-br-play-from-mouse-cursor-position": 54459,
2601 "sws-br-play-from-mouse-cursor-position-and-solo-item-and-track-under-mouse-for-the-duration-perform-until-shortcut-released": 54860,
2602 "sws-br-play-from-mouse-cursor-position-and-solo-track-under-mouse-for-the-duration-perform-until-shortcut-released": 54859,
2624 "sws-br-play-from-mouse-cursor-position-and-solo-item-and-track-under-mouse-for-the-duration-perform-until-shortcut-released":
2625 54860,
2626 "sws-br-play-from-mouse-cursor-position-and-solo-track-under-mouse-for-the-duration-perform-until-shortcut-released":
2627 54859,
26032628 "sws-br-play-from-mouse-cursor-position-perform-until-shortcut-released": 54858,
26042629 "sws-br-play-pause-from-mouse-cursor-position": 54460,
26052630 "sws-br-play-stop-from-mouse-cursor-position": 54461,
......@@ -2608,14 +2633,16 @@ export const REAPER_ACTIONS = {
26082633 "sws-br-preview-media-item-under-mouse-and-pause-during-preview-start-from-mouse-cursor-position": 54726,
26092634 "sws-br-preview-media-item-under-mouse-at-track-fader-volume": 54727,
26102635 "sws-br-preview-media-item-under-mouse-at-track-fader-volume-and-pause-during-preview": 54730,
2611 "sws-br-preview-media-item-under-mouse-at-track-fader-volume-and-pause-during-preview-start-from-mouse-cursor-position": 54731,
2636 "sws-br-preview-media-item-under-mouse-at-track-fader-volume-and-pause-during-preview-start-from-mouse-cursor-position":
2637 54731,
26122638 "sws-br-preview-media-item-under-mouse-at-track-fader-volume-start-from-mouse-position": 54728,
26132639 "sws-br-preview-media-item-under-mouse-at-track-fader-volume-sync-with-next-measure": 54729,
26142640 "sws-br-preview-media-item-under-mouse-start-from-mouse-cursor-position": 54723,
26152641 "sws-br-preview-media-item-under-mouse-sync-with-next-measure": 54724,
26162642 "sws-br-preview-media-item-under-mouse-through-track": 54732,
26172643 "sws-br-preview-media-item-under-mouse-through-track-and-pause-during-preview": 54735,
2618 "sws-br-preview-media-item-under-mouse-through-track-and-pause-during-preview-start-from-mouse-cursor-position": 54736,
2644 "sws-br-preview-media-item-under-mouse-through-track-and-pause-during-preview-start-from-mouse-cursor-position":
2645 54736,
26192646 "sws-br-preview-media-item-under-mouse-through-track-start-from-mouse-position": 54733,
26202647 "sws-br-preview-media-item-under-mouse-through-track-sync-with-next-measure": 54734,
26212648 "sws-br-preview-take-under-mouse": 54752,
......@@ -2623,7 +2650,8 @@ export const REAPER_ACTIONS = {
26232650 "sws-br-preview-take-under-mouse-and-pause-during-preview-start-from-mouse-cursor-position": 54756,
26242651 "sws-br-preview-take-under-mouse-at-track-fader-volume": 54757,
26252652 "sws-br-preview-take-under-mouse-at-track-fader-volume-and-pause-during-preview": 54760,
2626 "sws-br-preview-take-under-mouse-at-track-fader-volume-and-pause-during-preview-start-from-mouse-cursor-position": 54761,
2653 "sws-br-preview-take-under-mouse-at-track-fader-volume-and-pause-during-preview-start-from-mouse-cursor-position":
2654 54761,
26272655 "sws-br-preview-take-under-mouse-at-track-fader-volume-start-from-mouse-position": 54758,
26282656 "sws-br-preview-take-under-mouse-at-track-fader-volume-sync-with-next-measure": 54759,
26292657 "sws-br-preview-take-under-mouse-start-from-mouse-cursor-position": 54753,
......@@ -2851,9 +2879,12 @@ export const REAPER_ACTIONS = {
28512879 "sws-br-select-dips-in-envelope": 54058,
28522880 "sws-br-select-dips-in-envelope-add-to-selection": 54057,
28532881 "sws-br-select-envelope-at-mouse-cursor": 54094,
2854 "sws-br-select-envelope-at-mouse-cursor-and-freehand-draw-envelope-while-snapping-points-to-left-side-grid-line-perform-until-shortcut-released": 54857,
2855 "sws-br-select-envelope-at-mouse-cursor-and-set-closest-envelope-point-s-value-to-mouse-cursor-perform-until-shortcut-released": 54855,
2856 "sws-br-select-envelope-at-mouse-cursor-and-set-closest-left-side-envelope-point-s-value-to-mouse-cursor-perform-until-shortcut-released": 54856,
2882 "sws-br-select-envelope-at-mouse-cursor-and-freehand-draw-envelope-while-snapping-points-to-left-side-grid-line-perform-until-shortcut-released":
2883 54857,
2884 "sws-br-select-envelope-at-mouse-cursor-and-set-closest-envelope-point-s-value-to-mouse-cursor-perform-until-shortcut-released":
2885 54855,
2886 "sws-br-select-envelope-at-mouse-cursor-and-set-closest-left-side-envelope-point-s-value-to-mouse-cursor-perform-until-shortcut-released":
2887 54856,
28572888 "sws-br-select-envelope-point-at-mouse-cursor": 54096,
28582889 "sws-br-select-envelope-point-at-mouse-cursor-selected-envelope-only": 54095,
28592890 "sws-br-select-envelope-points-between-grid": 54037,
......@@ -2909,14 +2940,16 @@ export const REAPER_ACTIONS = {
29092940 "sws-br-toggle-preview-media-item-under-mouse-and-pause-during-preview-start-from-mouse-cursor-position": 54741,
29102941 "sws-br-toggle-preview-media-item-under-mouse-at-track-fader-volume": 54742,
29112942 "sws-br-toggle-preview-media-item-under-mouse-at-track-fader-volume-and-pause-during-preview": 54745,
2912 "sws-br-toggle-preview-media-item-under-mouse-at-track-fader-volume-and-pause-during-preview-start-from-mouse-cursor-position": 54746,
2943 "sws-br-toggle-preview-media-item-under-mouse-at-track-fader-volume-and-pause-during-preview-start-from-mouse-cursor-position":
2944 54746,
29132945 "sws-br-toggle-preview-media-item-under-mouse-at-track-fader-volume-start-from-mouse-position": 54743,
29142946 "sws-br-toggle-preview-media-item-under-mouse-at-track-fader-volume-sync-with-next-measure": 54744,
29152947 "sws-br-toggle-preview-media-item-under-mouse-start-from-mouse-position": 54738,
29162948 "sws-br-toggle-preview-media-item-under-mouse-sync-with-next-measure": 54739,
29172949 "sws-br-toggle-preview-media-item-under-mouse-through-track": 54747,
29182950 "sws-br-toggle-preview-media-item-under-mouse-through-track-and-pause-during-preview": 54750,
2919 "sws-br-toggle-preview-media-item-under-mouse-through-track-and-pause-during-preview-start-from-mouse-cursor-position": 54751,
2951 "sws-br-toggle-preview-media-item-under-mouse-through-track-and-pause-during-preview-start-from-mouse-cursor-position":
2952 54751,
29202953 "sws-br-toggle-preview-media-item-under-mouse-through-track-start-from-mouse-position": 54748,
29212954 "sws-br-toggle-preview-media-item-under-mouse-through-track-sync-with-next-measure": 54749,
29222955 "sws-br-toggle-preview-take-under-mouse": 54767,
......@@ -2924,14 +2957,16 @@ export const REAPER_ACTIONS = {
29242957 "sws-br-toggle-preview-take-under-mouse-and-pause-during-preview-start-from-mouse-cursor-position": 54771,
29252958 "sws-br-toggle-preview-take-under-mouse-at-track-fader-volume": 54772,
29262959 "sws-br-toggle-preview-take-under-mouse-at-track-fader-volume-and-pause-during-preview": 54775,
2927 "sws-br-toggle-preview-take-under-mouse-at-track-fader-volume-and-pause-during-preview-start-from-mouse-cursor-position": 54776,
2960 "sws-br-toggle-preview-take-under-mouse-at-track-fader-volume-and-pause-during-preview-start-from-mouse-cursor-position":
2961 54776,
29282962 "sws-br-toggle-preview-take-under-mouse-at-track-fader-volume-start-from-mouse-position": 54773,
29292963 "sws-br-toggle-preview-take-under-mouse-at-track-fader-volume-sync-with-next-measure": 54774,
29302964 "sws-br-toggle-preview-take-under-mouse-start-from-mouse-position": 54768,
29312965 "sws-br-toggle-preview-take-under-mouse-sync-with-next-measure": 54769,
29322966 "sws-br-toggle-preview-take-under-mouse-through-track": 54777,
29332967 "sws-br-toggle-preview-take-under-mouse-through-track-and-pause-during-preview": 54780,
2934 "sws-br-toggle-preview-take-under-mouse-through-track-and-pause-during-preview-start-from-mouse-cursor-position": 54781,
2968 "sws-br-toggle-preview-take-under-mouse-through-track-and-pause-during-preview-start-from-mouse-cursor-position":
2969 54781,
29352970 "sws-br-toggle-preview-take-under-mouse-through-track-start-from-mouse-position": 54778,
29362971 "sws-br-toggle-preview-take-under-mouse-through-track-sync-with-next-measure": 54779,
29372972 "sws-br-toggle-show-active-mute-send-envelopes-for-selected-tracks": 54153,
......@@ -4405,13 +4440,16 @@ export const REAPER_ACTIONS = {
44054440 "sws-wait-for-next-beat-if-playing": 53664,
44064441 "sws-wait-until-end-of-loop-if-playing": 53665,
44074442 "sws-wol-adjust-envelope-or-track-height-under-mouse-cursor-midi-cc-relative-mousewheel": 54892,
4408 "sws-wol-adjust-envelope-or-track-height-under-mouse-cursor-zoom-center-to-mouse-cursor-midi-cc-relative-mousewheel": 54893,
4443 "sws-wol-adjust-envelope-or-track-height-under-mouse-cursor-zoom-center-to-mouse-cursor-midi-cc-relative-mousewheel":
4444 54893,
44094445 "sws-wol-adjust-selected-envelope-height-midi-cc-relative-mousewheel": 54886,
44104446 "sws-wol-adjust-selected-envelope-height-zoom-center-to-middle-arrange-midi-cc-relative-mousewheel": 54887,
44114447 "sws-wol-adjust-selected-envelope-height-zoom-center-to-mouse-cursor-midi-cc-relative-mousewheel": 54888,
44124448 "sws-wol-adjust-selected-envelope-or-last-touched-track-height-midi-cc-relative-mousewheel": 54889,
4413 "sws-wol-adjust-selected-envelope-or-last-touched-track-height-zoom-center-to-middle-arrange-midi-cc-relative-mousewheel": 54890,
4414 "sws-wol-adjust-selected-envelope-or-last-touched-track-height-zoom-center-to-mouse-cursor-midi-cc-relative-mousewheel": 54891,
4449 "sws-wol-adjust-selected-envelope-or-last-touched-track-height-zoom-center-to-middle-arrange-midi-cc-relative-mousewheel":
4450 54890,
4451 "sws-wol-adjust-selected-envelope-or-last-touched-track-height-zoom-center-to-mouse-cursor-midi-cc-relative-mousewheel":
4452 54891,
44154453 "sws-wol-apply-height-to-selected-envelope-slot-1": 54912,
44164454 "sws-wol-apply-height-to-selected-envelope-slot-2": 54913,
44174455 "sws-wol-apply-height-to-selected-envelope-slot-3": 54914,
......@@ -4794,8 +4832,10 @@ export const REAPER_ACTIONS = {
47944832 "toolbars-switch-to-toolbar-9": 41948,
47954833 "track-2nd-pass-render-selected-area-of-tracks-to-mono-post-fader-stem-tracks-and-mute-originals": 42415,
47964834 "track-2nd-pass-render-selected-area-of-tracks-to-mono-stem-tracks-and-mute-originals": 42418,
4797 "track-2nd-pass-render-selected-area-of-tracks-to-multichannel-parent-send-only-post-fader-stem-tracks-and-mute-originals": 42593,
4798 "track-2nd-pass-render-selected-area-of-tracks-to-multichannel-parent-send-only-stem-tracks-and-mute-originals": 42594,
4835 "track-2nd-pass-render-selected-area-of-tracks-to-multichannel-parent-send-only-post-fader-stem-tracks-and-mute-originals":
4836 42593,
4837 "track-2nd-pass-render-selected-area-of-tracks-to-multichannel-parent-send-only-stem-tracks-and-mute-originals":
4838 42594,
47994839 "track-2nd-pass-render-selected-area-of-tracks-to-multichannel-post-fader-stem-tracks-and-mute-originals": 42414,
48004840 "track-2nd-pass-render-selected-area-of-tracks-to-multichannel-stem-tracks-and-mute-originals": 42417,
48014841 "track-2nd-pass-render-selected-area-of-tracks-to-stereo-post-fader-stem-tracks-and-mute-originals": 42413,
......@@ -5012,7 +5052,8 @@ export const REAPER_ACTIONS = {
50125052 "track-rename-last-touched-track": 40696,
50135053 "track-render-selected-area-of-tracks-to-mono-post-fader-stem-tracks-and-mute-originals": 41718,
50145054 "track-render-selected-area-of-tracks-to-mono-stem-tracks-and-mute-originals": 41721,
5015 "track-render-selected-area-of-tracks-to-multichannel-parent-send-only-post-fader-stem-tracks-and-mute-originals": 42591,
5055 "track-render-selected-area-of-tracks-to-multichannel-parent-send-only-post-fader-stem-tracks-and-mute-originals":
5056 42591,
50165057 "track-render-selected-area-of-tracks-to-multichannel-parent-send-only-stem-tracks-and-mute-originals": 42592,
50175058 "track-render-selected-area-of-tracks-to-multichannel-post-fader-stem-tracks-and-mute-originals": 41717,
50185059 "track-render-selected-area-of-tracks-to-multichannel-stem-tracks-and-mute-originals": 41720,
src/Reaper/generate-actions.ts+6-15
......@@ -1,12 +1,5 @@
11import { execFile } from "node:child_process";
2import {
3 access,
4 mkdir,
5 mkdtemp,
6 readFile,
7 rm,
8 writeFile,
9} from "node:fs/promises";
2import { access, mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
103import { tmpdir } from "node:os";
114import { dirname, join, resolve } from "node:path";
125import process from "node:process";
......@@ -76,10 +69,10 @@ function parseRawActions(value: unknown): RawReaperAction[] {
7669
7770 return value.flatMap((entry) => {
7871 if (
79 !entry ||
80 typeof entry !== "object" ||
81 !("commandId" in entry) ||
82 !("name" in entry)
72 !entry
73 || typeof entry !== "object"
74 || !("commandId" in entry)
75 || !("name" in entry)
8376 ) {
8477 return [];
8578 }
......@@ -147,9 +140,7 @@ function renderActionsFile(actions: ReadonlyArray<GeneratedReaperAction>) {
147140 "// Source: REAPER main action section via kbd_enumerateActions()/kbd_getTextFromCmd().",
148141 "",
149142 "export const REAPER_ACTIONS = {",
150 ...actions.map((action) =>
151 ` ${JSON.stringify(action.actionId)}: ${action.commandId},`
152 ),
143 ...actions.map((action) => ` ${JSON.stringify(action.actionId)}: ${action.commandId},`),
153144 "} as const satisfies Record<string, number>;",
154145 "",
155146 "export type ReaperActionId = keyof typeof REAPER_ACTIONS;",
src/SpeedEditor.ts+22-22
......@@ -1,8 +1,8 @@
11import { Events } from "@clo/lib/Events.ts";
2import * as log from "@clo/lib/log.ts";
23import { defer } from "@clo/lib/ts.ts";
34import type { Dispose, Timer } from "@clo/lib/ts.ts";
45import type { Mac } from "./Mac";
5import * as log from "@clo/lib/log.ts";
66
77const SPEED_EDITOR_VENDOR_ID = 0x1edb;
88const SPEED_EDITOR_PRODUCT_ID = 0xda0e;
......@@ -215,8 +215,8 @@ export class SpeedEditor extends Events<SpeedEditor.EventMap> {
215215 }
216216
217217 onDoublePress(key: SpeedEditor.Key, listener: () => void): Dispose {
218 const listeners = this.#doublePressListeners.get(key) ??
219 new Set<() => void>();
218 const listeners = this.#doublePressListeners.get(key)
219 ?? new Set<() => void>();
220220 listeners.add(listener);
221221 this.#doublePressListeners.set(key, listeners);
222222
......@@ -236,7 +236,7 @@ export class SpeedEditor extends Events<SpeedEditor.EventMap> {
236236 this.#ready = false;
237237 this.#refreshRequested = false;
238238 this.#stopHotplugMonitoring?.();
239 this.#stopHotplugMonitoring = null
239 this.#stopHotplugMonitoring = null;
240240 this.#disconnect(false);
241241 this.emit("close");
242242 }
......@@ -267,8 +267,8 @@ export class SpeedEditor extends Events<SpeedEditor.EventMap> {
267267
268268 #matchesHotplugDevice(device: import("usb").Device) {
269269 const descriptor = device.deviceDescriptor;
270 return descriptor.idVendor === this.#options.vendorId &&
271 descriptor.idProduct === this.#options.productId;
270 return descriptor.idVendor === this.#options.vendorId
271 && descriptor.idProduct === this.#options.productId;
272272 }
273273
274274 async #refreshConnection() {
......@@ -309,8 +309,8 @@ export class SpeedEditor extends Events<SpeedEditor.EventMap> {
309309 }
310310
311311 const currentKey = getDeviceKey(this.#deviceInfo);
312 const currentStillPresent = currentKey !== null &&
313 devices.some((device) => getDeviceKey(device) === currentKey);
312 const currentStillPresent = currentKey !== null
313 && devices.some((device) => getDeviceKey(device) === currentKey);
314314
315315 if (this.#device && !currentStillPresent) {
316316 this.#disconnect(true);
......@@ -330,8 +330,8 @@ export class SpeedEditor extends Events<SpeedEditor.EventMap> {
330330
331331 #selectDevice(devices: ReadonlyArray<SpeedEditor.DeviceInfo>) {
332332 if (this.#options.path) {
333 return devices.find((device) => device.path === this.#options.path) ??
334 null;
333 return devices.find((device) => device.path === this.#options.path)
334 ?? null;
335335 }
336336
337337 return devices[0] ?? null;
......@@ -611,16 +611,16 @@ export class SpeedEditor extends Events<SpeedEditor.EventMap> {
611611 }
612612
613613 static camNumbersToNumpad(speededitor: Pick<SpeedEditor, "onPress">, mac: Pick<Mac, "pressKey">) {
614 speededitor.onPress("cam1", () => mac.pressKey('numpad1'));
615 speededitor.onPress("cam2", () => mac.pressKey('numpad2'));
616 speededitor.onPress("cam3", () => mac.pressKey('numpad3'));
617 speededitor.onPress("cam4", () => mac.pressKey('numpad4'));
618 speededitor.onPress("cam5", () => mac.pressKey('numpad5'));
619 speededitor.onPress("cam6", () => mac.pressKey('numpad6'));
620 speededitor.onPress("cam7", () => mac.pressKey('numpad7'));
621 speededitor.onPress("cam8", () => mac.pressKey('numpad8'));
622 speededitor.onPress("cam9", () => mac.pressKey('numpad9'));
623 speededitor.onPress("liveOverwrite", () => mac.pressKey('numpad0'));
614 speededitor.onPress("cam1", () => mac.pressKey("numpad1"));
615 speededitor.onPress("cam2", () => mac.pressKey("numpad2"));
616 speededitor.onPress("cam3", () => mac.pressKey("numpad3"));
617 speededitor.onPress("cam4", () => mac.pressKey("numpad4"));
618 speededitor.onPress("cam5", () => mac.pressKey("numpad5"));
619 speededitor.onPress("cam6", () => mac.pressKey("numpad6"));
620 speededitor.onPress("cam7", () => mac.pressKey("numpad7"));
621 speededitor.onPress("cam8", () => mac.pressKey("numpad8"));
622 speededitor.onPress("cam9", () => mac.pressKey("numpad9"));
623 speededitor.onPress("liveOverwrite", () => mac.pressKey("numpad0"));
624624 }
625625}
626626
......@@ -909,8 +909,8 @@ function getDeviceKey(device: SpeedEditor.DeviceInfo | null) {
909909 return null;
910910 }
911911
912 return device.path ??
913 [
912 return device.path
913 ?? [
914914 device.vendorId,
915915 device.productId,
916916 device.serialNumber ?? "",
src/config.ts+11-11
......@@ -1,3 +1,5 @@
1import { Events } from "@clo/lib/Events.ts";
2import * as console from "@clo/lib/log.ts";
13import * as ts from "@clo/lib/ts.ts";
24import type { Dispose } from "@clo/lib/ts.ts";
35import * as fs from "node:fs/promises";
......@@ -5,8 +7,6 @@ import * as path from "node:path";
57import * as url from "node:url";
68import { Mac } from "./Mac.ts";
79import { SpeedEditor } from "./SpeedEditor.ts";
8import { Events } from "@clo/lib/Events.ts";
9import * as console from "@clo/lib/log.ts";
1010
1111export interface Configure {
1212 /** Events are only active when the application is active. */
......@@ -34,9 +34,9 @@ interface AppDefinition {
3434}
3535
3636export type AppEvents = {
37 "focus": [],
38 "blur": [],
39}
37 "focus": [];
38 "blur": [];
39};
4040
4141export function forApp(
4242 bundle: Mac.BundleId,
......@@ -151,8 +151,8 @@ export class AppSpeedEditor extends Events<SpeedEditor.EventMap> {
151151 onDoublePress(key: SpeedEditor.Key, listener: () => void): Dispose {
152152 const pair = { key, listener };
153153 this.#doubleKeyEvents.add(pair);
154 this.#enabled &&
155 this.#enabledStack.use(this.#source.onDoublePress(key, listener));
154 this.#enabled
155 && this.#enabledStack.use(this.#source.onDoublePress(key, listener));
156156 return ts.defer(() => {
157157 throw new Error("TODO");
158158 });
......@@ -199,12 +199,12 @@ export async function runConfigs(dir: string) {
199199 if (!speededitor.connected) {
200200 console.warn("Speed Editor is not connected");
201201 }
202 speededitor.on('connect', () => {
202 speededitor.on("connect", () => {
203203 console.info("Speed Editor connected");
204 })
205 speededitor.on('disconnect', () => {
204 });
205 speededitor.on("disconnect", () => {
206206 console.warn("Speed Editor lost connection");
207 })
207 });
208208
209209 const instances = new Map<Mac.BundleId, AppInstance>();
210210 const pendingInstances = new Map<Mac.BundleId, Promise<AppInstance | null>>();