audacity4-mcp 0.1.0__tar.gz

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.
Files changed (45) hide show
  1. audacity4_mcp-0.1.0/.github/dependabot.yml +11 -0
  2. audacity4_mcp-0.1.0/.github/workflows/ci.yml +52 -0
  3. audacity4_mcp-0.1.0/.github/workflows/publish.yml +59 -0
  4. audacity4_mcp-0.1.0/.gitignore +6 -0
  5. audacity4_mcp-0.1.0/AUDACITY4_RESEARCH.md +460 -0
  6. audacity4_mcp-0.1.0/CHANGELOG.md +47 -0
  7. audacity4_mcp-0.1.0/CONTRIBUTING.md +86 -0
  8. audacity4_mcp-0.1.0/LICENSE +190 -0
  9. audacity4_mcp-0.1.0/PKG-INFO +132 -0
  10. audacity4_mcp-0.1.0/README.md +103 -0
  11. audacity4_mcp-0.1.0/SECURITY.md +26 -0
  12. audacity4_mcp-0.1.0/docs/INSTALLATION.md +93 -0
  13. audacity4_mcp-0.1.0/docs/TOOLS.md +204 -0
  14. audacity4_mcp-0.1.0/pyproject.toml +66 -0
  15. audacity4_mcp-0.1.0/server4/__init__.py +0 -0
  16. audacity4_mcp-0.1.0/server4/bridge_client.py +106 -0
  17. audacity4_mcp-0.1.0/server4/main.py +17 -0
  18. audacity4_mcp-0.1.0/server4/tool_registry.py +12 -0
  19. audacity4_mcp-0.1.0/server4/tools/__init__.py +0 -0
  20. audacity4_mcp-0.1.0/server4/tools/analysis_tools.py +342 -0
  21. audacity4_mcp-0.1.0/server4/tools/cleanup_tools.py +648 -0
  22. audacity4_mcp-0.1.0/server4/tools/edit_tools.py +94 -0
  23. audacity4_mcp-0.1.0/server4/tools/effects_tools.py +588 -0
  24. audacity4_mcp-0.1.0/server4/tools/generate_tools.py +160 -0
  25. audacity4_mcp-0.1.0/server4/tools/label_tools.py +217 -0
  26. audacity4_mcp-0.1.0/server4/tools/project_tools.py +184 -0
  27. audacity4_mcp-0.1.0/server4/tools/realtime_effects_tools.py +143 -0
  28. audacity4_mcp-0.1.0/server4/tools/selection_tools.py +158 -0
  29. audacity4_mcp-0.1.0/server4/tools/track_tools.py +125 -0
  30. audacity4_mcp-0.1.0/server4/tools/transcription_tools.py +576 -0
  31. audacity4_mcp-0.1.0/server4/tools/transport_tools.py +62 -0
  32. audacity4_mcp-0.1.0/tests/__init__.py +0 -0
  33. audacity4_mcp-0.1.0/tests/test_analysis_tools.py +40 -0
  34. audacity4_mcp-0.1.0/tests/test_bridge_client.py +160 -0
  35. audacity4_mcp-0.1.0/tests/test_cleanup_tools.py +179 -0
  36. audacity4_mcp-0.1.0/tests/test_edit_tools.py +52 -0
  37. audacity4_mcp-0.1.0/tests/test_effects_tools.py +332 -0
  38. audacity4_mcp-0.1.0/tests/test_generate_tools.py +105 -0
  39. audacity4_mcp-0.1.0/tests/test_project_tools.py +208 -0
  40. audacity4_mcp-0.1.0/tests/test_realtime_effects_tools.py +196 -0
  41. audacity4_mcp-0.1.0/tests/test_selection_tools.py +235 -0
  42. audacity4_mcp-0.1.0/tests/test_tools.py +30 -0
  43. audacity4_mcp-0.1.0/tests/test_track_tools.py +165 -0
  44. audacity4_mcp-0.1.0/tests/test_transcription_tools.py +175 -0
  45. audacity4_mcp-0.1.0/tests/test_transport_tools.py +131 -0
@@ -0,0 +1,11 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "pip"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+
8
+ - package-ecosystem: "github-actions"
9
+ directory: "/"
10
+ schedule:
11
+ interval: "weekly"
@@ -0,0 +1,52 @@
1
+ name: CI
2
+
3
+ "on":
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint:
11
+ # Static analysis only - version/OS independent, so this runs once
12
+ # instead of being duplicated across the full test matrix below.
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v7
16
+ - uses: actions/setup-python@v7
17
+ with:
18
+ python-version: "3.12"
19
+ - run: pip install -e ".[dev]"
20
+ - name: Run ruff
21
+ run: ruff check .
22
+
23
+ test:
24
+ runs-on: ${{ matrix.os }}
25
+ # Hard backstop: a hung test would otherwise run until GitHub's default
26
+ # 360-minute job timeout. 10 minutes is generous for a suite that
27
+ # normally finishes in seconds.
28
+ timeout-minutes: 10
29
+ strategy:
30
+ fail-fast: false
31
+ matrix:
32
+ os: [ubuntu-latest, windows-latest, macos-latest]
33
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
34
+
35
+ steps:
36
+ - uses: actions/checkout@v7
37
+
38
+ - name: Set up Python ${{ matrix.python-version }}
39
+ uses: actions/setup-python@v7
40
+ with:
41
+ python-version: ${{ matrix.python-version }}
42
+
43
+ - name: Install dependencies
44
+ run: pip install -e ".[dev]"
45
+
46
+ - name: Run tests
47
+ run: pytest tests/ -x -q
48
+
49
+ # Note: these unit tests run against a mocked bridge, not a real
50
+ # Audacity4-Dev instance - they verify the Python wrapper layer only.
51
+ # There is no CI coverage yet for the C++ mcp module or live
52
+ # end-to-end behavior against a running Audacity 4 fork.
@@ -0,0 +1,59 @@
1
+ name: Publish to PyPI
2
+
3
+ # Fires automatically on every version tag push (git tag vX.Y.Z && git push
4
+ # --tags), or manually via workflow_dispatch - no manual `twine upload` step,
5
+ # and no PyPI token stored anywhere in this repo. Uses PyPI's Trusted
6
+ # Publisher (OIDC) mechanism instead: PyPI is configured (once, on pypi.org)
7
+ # to trust this exact workflow in this exact repo, so GitHub can prove its
8
+ # identity to PyPI without a shared secret to store, rotate, or leak.
9
+ "on":
10
+ push:
11
+ tags:
12
+ - "v*"
13
+ workflow_dispatch:
14
+
15
+ jobs:
16
+ test:
17
+ # Gate: publishing requires the tagged commit itself to pass tests, not
18
+ # just whatever main's CI run said earlier - a tag can point anywhere.
19
+ runs-on: ${{ matrix.os }}
20
+ timeout-minutes: 10
21
+ strategy:
22
+ fail-fast: false
23
+ matrix:
24
+ os: [ubuntu-latest, windows-latest, macos-latest]
25
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
26
+ steps:
27
+ - uses: actions/checkout@v7
28
+ - uses: actions/setup-python@v7
29
+ with:
30
+ python-version: ${{ matrix.python-version }}
31
+ - run: pip install -e ".[dev]"
32
+ - run: pytest tests/ -x -q
33
+
34
+ build:
35
+ needs: test
36
+ runs-on: ubuntu-latest
37
+ steps:
38
+ - uses: actions/checkout@v7
39
+ - uses: actions/setup-python@v7
40
+ with:
41
+ python-version: "3.12"
42
+ - run: python -m pip install --upgrade build
43
+ - run: python -m build
44
+ - uses: actions/upload-artifact@v7
45
+ with:
46
+ name: dist
47
+ path: dist/
48
+
49
+ publish:
50
+ needs: build
51
+ runs-on: ubuntu-latest
52
+ permissions:
53
+ id-token: write # required for Trusted Publishing - do not remove
54
+ steps:
55
+ - uses: actions/download-artifact@v8
56
+ with:
57
+ name: dist
58
+ path: dist/
59
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,6 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .pytest_cache/
4
+ *.egg-info/
5
+ .venv/
6
+ venv/
@@ -0,0 +1,460 @@
1
+ # Audacity 4 — Reverse Engineering Research
2
+ # Conducted March 2026 (Alpha Build)
3
+ # PRIVATE — Do not publish
4
+
5
+ ## Overview
6
+ Audacity 4 is a complete rewrite on the MuseScore/Muse framework (Qt6/QML).
7
+ The old wxWidgets codebase is gone. mod-script-pipe is gone.
8
+ New architecture uses a JavaScript scripting engine with dispatcher actions.
9
+
10
+ ## Source Code
11
+ - Main repo: https://github.com/audacity/audacity.git
12
+ - Muse framework (submodule): https://github.com/musescore/framework_tmp.git
13
+
14
+ ---
15
+
16
+ ## 1. Dispatcher Action System
17
+
18
+ Central command system. All operations go through `dispatcher()->dispatch()`.
19
+
20
+ ### Action URI Pattern
21
+ ```
22
+ action://<module>/<verb>?param=value
23
+ ```
24
+
25
+ ### Complete Action Map (200+ actions)
26
+
27
+ #### Playback (25+ actions)
28
+ - `action://playback/play` — Play
29
+ - `action://playback/pause` — Pause
30
+ - `action://playback/stop` — Stop
31
+ - `action://playback/rewind-start` — Rewind to start
32
+ - `action://playback/rewind-end` — Rewind to end
33
+ - `action://playback/seek` — Seek to position
34
+ - `action://playback/level` — Set playback level
35
+ - `toggle-loop-region` — Loop playback
36
+ - `metronome` — Toggle metronome
37
+ - `playback-time` — Set playback time
38
+ - `playback-bpm` — Set tempo
39
+ - `playback-time-signature` — Set time signature
40
+ - `action://playback/change-api` — Change audio host
41
+ - `action://playback/change-playback-device` — Change playback device
42
+ - `action://playback/change-recording-device` — Change recording device
43
+ - `action://playback/change-input-channels` — Change input channels
44
+ - `rescan-devices` — Rescan audio devices
45
+ - `clear-loop-region` — Clear loop region
46
+ - `set-loop-region-to-selection` — Set loop to selection
47
+ - `set-selection-to-loop` — Set selection to loop
48
+
49
+ #### Record (6 actions)
50
+ - `action://record/start` — Record
51
+ - `action://record/pause` — Pause recording
52
+ - `action://record/stop` — Stop recording
53
+ - `action://record/level` — Set record level
54
+ - `action://record/toggle-mic-metering` — Show mic metering
55
+ - `action://record/toggle-input-monitoring` — Input monitoring
56
+
57
+ #### Track Edit (60+ actions)
58
+ ##### Clipboard
59
+ - `action://trackedit/copy` — Copy
60
+ - `action://trackedit/cut` — Cut
61
+ - `action://trackedit/paste-default` — Paste
62
+ - `action://trackedit/paste-insert` — Paste (pushes clips)
63
+ - `action://trackedit/paste-overlap` — Paste (overlaps)
64
+ - `action://trackedit/paste-insert-all-tracks-ripple` — Paste (preserves sync)
65
+ - `action://trackedit/delete` — Delete
66
+ - `action://trackedit/undo` — Undo
67
+ - `action://trackedit/redo` — Redo
68
+
69
+ ##### Clip Operations
70
+ - `split` — Split
71
+ - `join` — Join selected clips
72
+ - `disjoin` — Split at silences
73
+ - `duplicate` — Duplicate
74
+ - `merge-selected-on-tracks` — Merge selected clips
75
+ - `clip-export` — Export clip
76
+ - `clip-pitch-speed-open` — Open pitch/speed dialog
77
+ - `clip-render-pitch-speed` — Render pitch/speed
78
+ - `trim-audio-outside-selection` — Trim
79
+ - `silence-audio-selection` — Silence
80
+ - `group-clips` / `ungroup-clips` — Group/ungroup
81
+ - `stretch-clip-to-match-tempo` — Stretch with tempo
82
+
83
+ ##### Ripple Editing
84
+ - `cut-per-clip-ripple` / `cut-per-track-ripple` / `cut-all-tracks-ripple`
85
+ - `delete-per-track-ripple` / `delete-all-tracks-ripple`
86
+
87
+ ##### Track Management
88
+ - `track-rename` — Rename track
89
+ - `track-duplicate` — Duplicate track
90
+ - `track-delete` — Delete track
91
+ - `track-move-up` / `track-move-down` / `track-move-top` / `track-move-bottom`
92
+ - `track-change-rate-custom` — Change sample rate
93
+ - `track-make-stereo` — Make stereo
94
+ - `track-swap-channels` — Swap L/R
95
+ - `track-split-stereo-to-lr` / `track-split-stereo-to-center`
96
+ - `track-resample` — Resample
97
+ - `new-mono-track` / `new-stereo-track` / `new-label-track`
98
+
99
+ ##### Track View
100
+ - `action://trackedit/track-view-waveform` — Waveform view
101
+ - `action://trackedit/track-view-spectrogram` — Spectrogram view
102
+ - `action://trackedit/track-view-multi` — Multi view
103
+ - `action://trackedit/global-view-spectrogram` — Toggle spectral
104
+ - `action://trackedit/clip/change-color-auto` — Auto clip color
105
+ - `action://trackedit/track/change-format?format=N` — Change format
106
+ - `action://trackedit/track/change-rate?rate=N` — Change rate
107
+
108
+ ##### Labels
109
+ - `label-add` / `label-delete` / `label-cut` / `label-copy`
110
+
111
+ ##### Track View Navigation
112
+ - `track-view-item-move-left/right/up/down`
113
+ - `track-view-item-extend-left/right`
114
+ - `track-view-item-reduce-left/right`
115
+ - `track-view-next-panel/prev-panel/next-item/prev-item`
116
+ - `track-view-next-track/prev-track/first-track/last-track`
117
+ - `track-view-toggle-selection/range-selection`
118
+ - `track-view-item-context-menu`
119
+
120
+ #### Project (80+ actions)
121
+ ##### File
122
+ - `file-new` / `file-open` / `file-save` / `file-save-as` / `file-save-backup`
123
+ - `file-close` / `clear-recent`
124
+ - `project-import` — Import
125
+ - `export-audio` — Export audio
126
+ - `export-labels` — Export labels
127
+ - `export-midi` — Export MIDI
128
+
129
+ ##### Edit
130
+ - `duplicate` / `insert` / `rename-item` / `trim-clip`
131
+ - `split-into-new-track` / `silence-audio`
132
+ - Label operations: `cut-labels`, `copy-labels`, `delete-labels`, `split-labels`, `join-labels`, `silence-labels`, `disjoin-labels`
133
+ - `manage-labels` / `manage-metadata`
134
+
135
+ ##### Selection
136
+ - `select-all` / `select-all-tracks` / `clear-selection`
137
+ - `select-left-of-playback-position` / `select-right-of-playback-position`
138
+ - `select-track-start-to-cursor` / `select-cursor-to-track-end`
139
+ - `select-previous-clip` / `select-next-clip`
140
+ - `toggle-spectral-selection` / `zero-cross`
141
+
142
+ ##### View
143
+ - `zoom-in` / `zoom-out` / `zoom-to-selection` / `zoom-toggle` / `zoom-reset`
144
+ - `fit-project-to-window` / `fit-view-to-project`
145
+ - `collapse-all-tracks` / `expand-all-tracks`
146
+ - `toggle-effects` / `toggle-metadata-editor` / `toggle-history`
147
+
148
+ ##### Record Menu
149
+ - `record-on-current-track` / `record-on-new-track`
150
+ - `set-up-timed-recording` / `punch-and-roll-record`
151
+ - `toggle-sound-activated-recording` / `set-sound-activation-level`
152
+
153
+ ##### Track Menu
154
+ - `duplicate-track` / `remove-tracks` / `mixdown-to`
155
+ - Alignment: `align-end-to-end`, `align-together`, `align-start-to-zero`, `align-start-to-playhead`, etc.
156
+ - `sort-by-time` / `sort-by-name` / `keep-tracks-synchronised`
157
+
158
+ ##### Effects/Generate/Analyze Menu
159
+ - `effect-plugin-manager` / `generate-plugin-manager` / `analyze-plugin-manager`
160
+ - `add-realtime-effects`
161
+ - `favourite-effect-1/2/3`
162
+ - `contrast-analyzer` / `plot-spectrum`
163
+
164
+ ##### Tools
165
+ - `manage-macros` / `apply-macros-palette`
166
+ - `nyquist-prompt` / `nyquist-plugin-installer`
167
+ - `sample-data-export` / `sample-data-import` / `raw-data-import`
168
+ - `reset-configuration`
169
+
170
+ #### Effects (8 static + dynamic per-effect)
171
+ - `repeat-last-effect` — Repeat last effect
172
+ - `realtimeeffect-remove` — Remove realtime effect
173
+ - `action://effects/presets/apply` — Apply preset
174
+ - `action://effects/presets/save` — Save preset
175
+ - `action://effects/presets/delete` — Delete preset
176
+ - `action://effects/presets/import` / `export` — Import/export preset
177
+ - `action://effects/toggle_vendor_ui` — Toggle vendor UI
178
+ - `action://effects/open?effectId=<id>` — Open effect (dynamic)
179
+ - `action://effects/realtime-add?effectId=<id>` — Add realtime effect (dynamic)
180
+ - `action://effects/realtime-replace?effectId=<id>` — Replace realtime effect (dynamic)
181
+
182
+ #### App Shell (25+ actions)
183
+ - `quit` / `restart` / `fullscreen`
184
+ - `preference-dialog` / `audio-settings`
185
+ - Layout toggles: `toggle-transport`, `toggle-tracks`, `toggle-instruments`, `inspector`, etc.
186
+ - Global aliases: `action://copy` → `action://trackedit/copy`, etc.
187
+
188
+ #### Project Scene (20+ actions)
189
+ - Tools: `clip-gain`, `split-tool`, `snap`
190
+ - View: `minutes-seconds-ruler`, `beats-measures-ruler`, `toggle-vertical-rulers`
191
+ - `show-master-track` / `toggle-rms-in-waveform` / `toggle-clipping-in-waveform`
192
+ - `clip-properties` / `clip-rename` / `clip-pitch-speed`
193
+ - `play-position-decrease` / `play-position-increase`
194
+
195
+ ---
196
+
197
+ ## 2. Two Script Engines
198
+
199
+ ### Autobot Scripts (internal testing)
200
+ Location: `C:\Program Files\Audacity 4\autobotscripts\`
201
+ Global object: `api` (ScriptApi)
202
+
203
+ Available APIs:
204
+ - `api.dispatcher` — dispatch actions (FULL ACCESS)
205
+ - `api.keyboard` — simulate keyboard input
206
+ - `api.navigation` — navigate UI
207
+ - `api.shortcuts` — trigger shortcuts
208
+ - `api.accessibility` — UI element tree
209
+ - `api.process` — process control
210
+ - `api.filesystem` — file access
211
+ - `api.interactive` — dialogs
212
+ - `api.log` — logging
213
+ - `api.autobot` — test runner (sleep, setInterval, etc.)
214
+ - `api.context` — script context
215
+
216
+ Usage:
217
+ ```javascript
218
+ api.dispatcher.dispatch("file-new");
219
+ api.dispatcher.dispatch("zoom-x-percent", [100]);
220
+ api.keyboard.key("Ctrl+S");
221
+ api.autobot.sleep(1000);
222
+ ```
223
+
224
+ ### Extensions (user plugins)
225
+ Location: `C:\Users\<user>\AppData\Local\Audacity\Audacity4\extensions\`
226
+ Global object: `api` (ExtApi)
227
+
228
+ Available APIs:
229
+ - `api.log` — logging
230
+ - `api.interactive` — dialogs
231
+ - `api.theme` — theme info
232
+ - `api.websocket` — WebSocket client
233
+ - `api.websocketserver` — WebSocket server
234
+
235
+ BLOCKED APIs (commented out in source for security):
236
+ - ~~api.dispatcher~~ — "Providing these APIs requires approval"
237
+ - ~~api.keyboard~~
238
+ - ~~api.navigation~~
239
+ - ~~api.shortcuts~~
240
+ - ~~api.accessibility~~
241
+ - ~~api.process~~
242
+ - ~~api.filesystem~~
243
+
244
+ ### Key Difference
245
+ Autobot = full control, no networking
246
+ Extensions = networking (WebSocket), no control
247
+
248
+ ---
249
+
250
+ ## 3. Extension System
251
+
252
+ ### Manifest Format (manifest.json)
253
+ ```json
254
+ {
255
+ "uri": "muse://extensions/my-extension",
256
+ "type": "macros",
257
+ "title": "My Extension",
258
+ "description": "What it does",
259
+ "version": "1.0.0",
260
+ "apiversion": 2,
261
+ "actions": [
262
+ {
263
+ "code": "main",
264
+ "path": "main.js",
265
+ "type": "macros",
266
+ "title": "Run",
267
+ "func": "main",
268
+ "show_on_appmenu": true
269
+ }
270
+ ]
271
+ }
272
+ ```
273
+
274
+ ### Types
275
+ - `"macros"` — JS only, no UI
276
+ - `"form"` — QML with UI
277
+ - `"composite"` — both
278
+
279
+ ### Install Paths
280
+ - Bundled: `<install_dir>/extensions/`
281
+ - User: `C:\Users\<user>\AppData\Local\Audacity\Audacity4\extensions\`
282
+ - Packaged as `.mext` (zip with manifest.json)
283
+
284
+ ### Module System
285
+ CommonJS-style `require()` / `exports` / `module` available.
286
+
287
+ ---
288
+
289
+ ## 4. VST3 Support (Full Backend — UI Not Wired Yet in Alpha)
290
+
291
+ ### Effect ID Format
292
+ ```
293
+ Effect_Audacity_Audacity_<SymbolName>_Built-in Effect: <SymbolName>
294
+ ```
295
+
296
+ ### VST3 Plugin ID Format
297
+ ```
298
+ Effect_<Family>_<Vendor>_<Symbol>_<Path>
299
+ ```
300
+
301
+ ### Scan Paths
302
+ - Windows: `%PROGRAMFILES%\Common Files\VST3\`
303
+ - macOS: `~/Library/Audio/Plug-ins/VST3/`, `/Library/Audio/Plug-ins/VST3/`
304
+ - Linux: `~/.vst3/`, `/usr/lib/vst3/`, `/usr/local/lib/vst3/`
305
+
306
+ ### Programmatic Parameter Control
307
+ ```cpp
308
+ // Read all parameters
309
+ ParameterInfoList parameters(EffectInstanceId instanceId);
310
+
311
+ // ParameterInfo contains:
312
+ // - id, name, units ("dB", "Hz", "%")
313
+ // - type (Toggle, Dropdown, Slider, Numeric, ReadOnly)
314
+ // - minValue, maxValue, defaultValue, currentValue
315
+ // - currentValueString ("440 Hz", "-3.5 dB")
316
+ // - stepCount, enumValues, isLogarithmic, canAutomate
317
+
318
+ // Set parameter
319
+ bool setParameterValue(EffectInstanceId, parameterId, double value);
320
+
321
+ // Apply effect without UI dialog
322
+ DoEffect(pluginID, project, EffectManager::kConfigured);
323
+ ```
324
+
325
+ ### Realtime Effects Chain
326
+ ```cpp
327
+ // Add VST to track (trackId = -2 for master bus)
328
+ addRealtimeEffect(trackId, effectId);
329
+ removeRealtimeEffect(trackId, state);
330
+ replaceRealtimeEffect(trackId, effectListIndex, newEffectId);
331
+ moveRealtimeEffect(state, newIndex);
332
+ setIsActive(state, active);
333
+ ```
334
+
335
+ ### Preset System
336
+ ```cpp
337
+ // Factory presets
338
+ PresetIdList factoryPresets(effectId);
339
+ // User presets
340
+ PresetIdList userPresets(effectId);
341
+ // Apply/save/import/export
342
+ applyPreset(instanceId, presetId);
343
+ saveCurrentAsPreset(instanceId, presetName);
344
+ importPreset(instanceId, filePath);
345
+ exportPreset(instanceId, filePath);
346
+ ```
347
+
348
+ ### Builtin Effect Symbols
349
+ Amplify, Bass and Treble, Change Pitch, Change Speed, Change Tempo,
350
+ Chirp, Click removal, Compressor, Distortion, DTMF Tones, Echo,
351
+ Equalization, Fade In, Fade Out, Find Clipping, Graphic EQ, Invert,
352
+ Limiter, Noise, Noise Reduction, Normalize, Normalize Loudness,
353
+ Paulstretch, Phaser, Repair, Repeat, Reverse, Reverb, Silence,
354
+ Sliding Stretch, Stereo To Mono, Tone, Truncate silence, Wahwah,
355
+ Auto Duck
356
+
357
+ ---
358
+
359
+ ## 5. WebSocket API (If Compiled)
360
+
361
+ Default OFF: `MUSE_MODULE_NETWORK_WEBSOCKET=OFF` in CMake.
362
+
363
+ ### Server API (available to extensions)
364
+ ```javascript
365
+ var server = api.websocketserver;
366
+ server.listen(8765, function(clientId) {
367
+ server.onMessage(clientId, function(message) {
368
+ var data = JSON.parse(message);
369
+ server.send(clientId, JSON.stringify({ result: "ok" }));
370
+ });
371
+ });
372
+ ```
373
+
374
+ ### Client API
375
+ ```javascript
376
+ var ws = api.websocket;
377
+ ws.open(8084, function(socketId) {
378
+ ws.onMessage(socketId, function(message) { ... });
379
+ ws.send(socketId, JSON.stringify({ ... }));
380
+ });
381
+ ```
382
+
383
+ - Text messages only (no binary)
384
+ - No protocol defined — raw strings, parse your own JSON
385
+ - Server name: `"muse_extension"`
386
+ - Client IDs start at 2001
387
+
388
+ ---
389
+
390
+ ## 6. IPC Mechanisms Found
391
+
392
+ | Mechanism | Purpose | External Access |
393
+ |-----------|---------|:---:|
394
+ | QLocalServer/Socket | Multi-window coordination | No |
395
+ | QTcpServer (OAuth) | Cloud sign-in redirect capture | No |
396
+ | WebSocket (extension API) | Plugin networking | Yes (if compiled) |
397
+ | mod-script-pipe | GONE in v4 | N/A |
398
+
399
+ ---
400
+
401
+ ## 7. Bridge Architecture (Planned)
402
+
403
+ ### Target: Extension with WebSocket + Dispatcher
404
+ Requires two changes to build from source:
405
+ 1. `MUSE_MODULE_NETWORK_WEBSOCKET=ON` in CMake
406
+ 2. Uncomment `api.dispatcher` in `muse_framework/framework/extensions/api/extapi.h`
407
+
408
+ ```
409
+ ┌─────────────────────┐ WebSocket ┌──────────────────┐
410
+ │ AudacityMCP Server │ ◄────────────────► │ Audacity 4 │
411
+ │ (Python/FastMCP) │ localhost:8765 │ Extension │
412
+ │ 99+ tools │ │ (bridge.js) │
413
+ └─────────────────────┘ │ ↓ │
414
+ │ dispatcher() │
415
+ │ → 200+ actions │
416
+ │ → VST3 control │
417
+ └──────────────────┘
418
+ ```
419
+
420
+ ### Source Files to Modify
421
+ - `muse_framework/framework/extensions/api/extapi.h` — uncomment dispatcher property
422
+ - `CMakeLists.txt` or build config — set `MUSE_MODULE_NETWORK_WEBSOCKET=ON`
423
+ - Create extension: `manifest.json` + `bridge.js`
424
+
425
+ ---
426
+
427
+ ## 8. Key Source File Locations
428
+
429
+ ```
430
+ audacity/
431
+ ├── src/
432
+ │ ├── appshell/internal/applicationuiactions.cpp — app actions
433
+ │ ├── playback/internal/playbackuiactions.cpp — transport
434
+ │ ├── record/internal/recorduiactions.cpp — recording
435
+ │ ├── trackedit/internal/trackedituiactions.cpp — editing (biggest)
436
+ │ ├── project/internal/projectuiactions.cpp — file/menu
437
+ │ ├── projectscene/internal/projectsceneuiactions.cpp — view/tools
438
+ │ ├── effects/
439
+ │ │ ├── effects_base/internal/effectsuiactions.cpp — effect actions
440
+ │ │ ├── effects_base/ieffectparametersprovider.h — param API
441
+ │ │ ├── builtin_collection/ — builtin effects
442
+ │ │ └── vst/internal/vstparameterextractorservice.* — VST param bridge
443
+ │ └── au3cloud/ — cloud/OAuth
444
+ ├── au3/
445
+ │ ├── libraries/au3-vst3/ — VST3 host engine
446
+ │ └── libraries/au3-builtin-effects/ — legacy effects
447
+ └── muse_framework/
448
+ └── framework/
449
+ ├── autobot/internal/api/ — autobot JS API
450
+ ├── extensions/ — plugin system
451
+ │ ├── api/extapi.h — extension API (MODIFY THIS)
452
+ │ └── internal/extensionsloader.cpp — manifest parser
453
+ ├── network/api/
454
+ │ ├── websocketserverapi.* — WS server
455
+ │ └── websocketapi.* — WS client
456
+ ├── actions/
457
+ │ ├── iactionsdispatcher.h — dispatcher interface
458
+ │ └── actiontypes.h — ActionData, ActionQuery
459
+ └── vst/internal/ — VST host framework
460
+ ```
@@ -0,0 +1,47 @@
1
+ # Changelog
2
+
3
+ All notable changes to Audacity4MCP will be documented in this file.
4
+
5
+ This is early alpha under active daily development.
6
+
7
+ ## [0.1.0] - 2026-09-05
8
+
9
+ ### Realtime/VST3 Effects: New Surface, Three Real Bugs Found Along the Way
10
+
11
+ Built the whole non-destructive effects path this session: `add_realtime_effect`, `list_realtime_effects`, `remove_realtime_effect`, `set_realtime_effect_active`, `list_effect_parameters`, `set_effect_parameter`, `list_effect_presets`, `apply_effect_preset`. This is now the priority effects surface — most users want to tweak a plugin's settings live (reverb decay, EQ curve, compressor ratio), not permanently bake an effect in.
12
+
13
+ Confirming this actually worked against a real VST3 (Valhalla VintageVerb, then FabFilter Pro-Q 3 / Pro-C 2) surfaced three separate, real bugs:
14
+
15
+ - **Realtime effect instances were never registered with `IEffectInstancesRegister`.** Only the UI's own settings-panel dialog does this registration today (`RealtimeEffectViewerDialogModel::reload()`) — headless MCP calls got "Effect instance not found" for every parameter read/write. Fixed by replicating that exact registration pattern (idempotent, checked on first use) in the C++ controller.
16
+ - **`setParameterValue()` silently failed to stick on VST3 plugins.** Calls reported success and even echoed a plausible-looking value, but an independent fresh re-read showed nothing had changed. Root cause: VST3 plugins require `beginParameterGesture()`/`setParameterValue()`/`endParameterGesture()` bracketing to distinguish real automation from a spurious write — a bare call silently no-ops. Fixed by wrapping every write in the gesture calls; verified via a second, independent parameter read after the fact, not just trusting the immediate response.
17
+ - **A Unity-build ambiguous-symbol compile error** (`C2872: 'TranslatableString'`) when linking `au3wrap` into the mcp module — a legacy AU3 header pulled in transitively declares its own non-`muse::` `TranslatableString`, colliding with `using namespace muse;` in the Unity-merged command registrar. Fixed with `SKIP_UNITY_BUILD_INCLUSION ON` on the affected file, matching an existing pattern already used elsewhere in the fork.
18
+
19
+ ### Fixed: Bridge Read Buffer Silently Broke on Large Parameter Dumps
20
+
21
+ `bridge_client.py`'s `asyncio.open_connection()` used the default 64KB `StreamReader` line limit. FabFilter Pro-Q 3 (a 24-band EQ) reports 492 real automatable parameters in one response — comfortably over that limit — and the call raised `LimitOverrunError`. Fixed by passing `limit=16*1024*1024` explicitly.
22
+
23
+ ### Fixed: `transport_play_region` Ignored the Region It Just Selected
24
+
25
+ Originally composed `select-time` + `play-stop` (a toggle). Live testing proved `play-stop` just resumes wherever playback last was, ignoring the just-set selection entirely. Root cause: `play-stop` and "play this specific selection" are genuinely different actions in Audacity 4 (`PlaybackController::playSelectionAction()`, `action://playback/play-selection`). Added the missing `play-selection` command and switched the tool to use it — verified live (a 60s-offset region reported `playPosition: 62.08` after ~2s of playback, matching offset + elapsed correctly).
26
+
27
+ ### Known Limitation, Not Fixed Here: VST3 Discrete/List Parameters Don't Persist
28
+
29
+ Continuous VST3 parameters (frequency, gain, Q, threshold, ratio, attack/release, mix) work correctly through `set_effect_parameter` — verified via independent re-reads. Discrete/list-type parameters (e.g. FabFilter Pro-Q 3's per-band "Shape" selector) do not, even with correct value encoding (raw index and normalized fraction both tested). Root-caused to `VST3Wrapper::FlushParameters` — Audacity's own documented workaround for "plugins that read parameter values directly from the DSP model" — being a no-op for any realtime effect instance, since those stay `mActive == true` for their entire life (confirmed with actual audio playback running during the test, ruling out a "just needs a process() call" explanation). The fix, if pursued, lives in Audacity 4's own VST3 host code, not this server. See [README's Known Gaps](README.md#known-gaps).
30
+
31
+ ### Verified Existing Effects Against the Real Plugin Registry, Not Source Presence
32
+
33
+ Several v3 effects were initially wrapped based on source files existing in the fork's tree (Echo, Phaser, Wahwah, Distortion, Repeat, ChangeTempo, ChangeSpeed, Equalization, AutoDuck) — all failed live with "Effect not found." Root cause: source presence in `au3/src/effects/*.cpp` does not mean an effect is actually compiled into this fork's build. Ground truth is the real runtime-generated `known_audio_plugins.json`. Removed all 11 wrappers rather than ship tools that can never succeed; same technique later confirmed `StereoToMono`, `project_edit_metadata`, `analyze_contrast`, `analyze_plot_spectrum`, and `analyze_find_clipping` as genuinely absent too.
34
+
35
+ ### Added
36
+
37
+ - `project_get_info`, `track_get_info`, `select_clip`, `transport_get_play_position`, `list_effects` and the full realtime-effects surface above on the C++ side, plus matching Python wrappers.
38
+ - Analysis tools: `analyze_beat_finder`, `analyze_label_sounds`, `analyze_sample_data_export`.
39
+ - Generators: `generate_silence`, `generate_rhythm_track` (full real parameter set, not a v3 port — tempo/swing/click-type/pitch all confirmed against v4's actual Rhythm Track effect).
40
+ - Full label-region composite ops: `label_cut_regions`, `label_delete_regions`, `label_silence_regions`, `label_split_regions`, `label_join_regions`, plus `label_add_at`, `label_add_batch`, `label_get_all`, `label_find`, `label_regular_intervals`, `label_delete_audio_at`.
41
+ - Full edit/selection/track surfaces ported and verified against v4's real interfaces (not v3's parameter names, which don't carry over — v4 renamed and restructured extensively).
42
+
43
+ ### Initial Commits
44
+
45
+ - `6cec293` — Initial commit: Audacity 4 MCP server with audio cleanup pipelines (podcast, audiobook, interview, vocal, live, music mastering, lo-fi).
46
+ - `c2e99a7` — Removed dead pre-discovery scaffolding, fixed a stale tool-count assertion.
47
+ - `ef22bf5` — Python wrappers for the first 7 playback/project MCP commands built on the C++ side.