https://github.com/mr5niper/windowsaudiocontrol-cli-wgui
Windows Audio Command Line Interface w/GUI (pycaw + comtypes based)
https://github.com/mr5niper/windowsaudiocontrol-cli-wgui
audio-commands audio-control audio-controls command-line command-line-interface command-line-tool windows-audio
Last synced: about 1 month ago
JSON representation
Windows Audio Command Line Interface w/GUI (pycaw + comtypes based)
- Host: GitHub
- URL: https://github.com/mr5niper/windowsaudiocontrol-cli-wgui
- Owner: Mr5niper
- Created: 2025-12-15T05:41:27.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2026-04-02T10:54:23.000Z (3 months ago)
- Last Synced: 2026-04-02T15:36:33.276Z (3 months ago)
- Topics: audio-commands, audio-control, audio-controls, command-line, command-line-interface, command-line-tool, windows-audio
- Language: Python
- Homepage: https://github.com/Mr5niper/WindowsAudioControl-CLI-wGUI/
- Size: 998 KB
- Stars: 5
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: docs/README.md
Awesome Lists containing this project
README
# Windows Audio Control CLI + GUI
## audioctl.exe (pycaw/comtypes-based)
A Windows audio control utility with a scriptable CLI and an optional GUI. You can:
- **Automate common tasks:** list devices, set default playback/recording endpoints, adjust volume, mute/unmute, toggle “Listen to this device,” and control Enhancements.
- **Learn vendor toggles:** “Learn Enhancements” and “Learn FX” observe what Windows/drivers change in the registry for a specific device, then store those rules so audioctl can reproduce the same toggle later.
- **Control individual effects (FX):** once learned, per-effect toggles (e.g., BassBoost, Loudness) can be enabled/disabled on demand, even when the driver does not provide a direct API.
- **Query state safely:** fast, read-only commands return current volume, mute, listen, enhancements, and FX state for scripts, hotkeys, and status UIs.
- **Use the GUI when convenient:** the GUI provides context-aware right-click actions and guided learn workflows, while still using the CLI underneath as the source of truth.
audioctl is designed to be CLI-first for repeatability and automation; the GUI is a helper layer on top.
---
[Quick Start](#quick-start)
[Command Map (Full Tree)](#command-map-full-tree)
[List Devices](#list-devices)
[Set Default Endpoints](#set-default-devices-cli)
[Adjust Volume / Mute](#set-volume-or-muteunmute-cli)
[Listen To This Device](#listen-to-this-device-capture-only-cli)
[Audio Enhancements](#audio-enhancements-sysfx--vendor-toggles-cli)
[Query Helpers (Read‑Only)](#query-helpers-readonly)
[Diagnostic Discovery](#diagnostics--discovery-optional-readonly)
[Wait For A Device](#wait-for-a-device-to-appear-cli)
[General Exit Codes](#general-exit-codes)
[Troubleshooting](#troubleshooting)
[GUI (Graphical User Interface)](#gui-graphical-user-interface)
---
# Quick Start
- Help:
```bash
.\audioctl.exe -h
```
- No arguments (double‑click or run without args) launches the GUI:
```bash
.\audioctl.exe
```
---
## Selectors (used by most commands)
- `--id "{endpoint-id}"` (exact endpoint ID)
- `--name "substring"` (case-insensitive substring match)
- `--regex` (treat `--name` as a regex)
- `--flow Render|Capture` (optional filter for playback/recording device)
- `--index N` (Number-based index to disambiguate between multiple matches)
- `--playback-name "substring"` (Render-only name selector; for set-default)
- `--recording-name "substring"` (Capture-only name selector; for set-default)
When using the `--name`, `--playback-name`, or `--recording-name` options, commands accept partial matches against device names or descriptions. If the specified text uniquely identifies exactly one playback or recording device, that device will be targeted and an index value is not required.
---
# Command map (full tree)
```
audioctl
│
├─ list [--all] [--json]
│
├─ set-default
│ ├─ --playback-id/--playback-name [--playback-role console|multimedia|communications|all]
│ └─ --recording-id/--recording-name [--recording-role console|multimedia|communications|all]
│ [--index] [--regex]
│
├─ set-volume
│ └─ (--id | --name) [--flow Render|Capture] (--level 0..100 | --mute | --unmute)
│ [--index] [--regex]
│
├─ listen (Capture only)
│ └─ (--id | --name) (--enable | --disable)
│ [--playback-target-id []] [--playback-target-name []]
│ [--index] [--regex]
│
├─ enhancements
│ ├─ Main switch:
│ │ └─ (--id | --name) [--flow] (--enable | --disable | --learn)
│ │ [--index] [--regex] [--prefer-hklm] [--vendor-ini PATH]
│ │
│ └─ FX operations:
│ ├─ --list-fx [--json]
│ ├─ --learn-fx "FX_NAME"
│ ├─ --enable-fx "FX_NAME" | --disable-fx "FX_NAME"
│ └─ --delete-fx "FX_NAME"
│
├─ get-volume [--id|--name] [--flow] [--index] [--regex]
│
├─ get-listen [--id|--name] [--index] [--regex] (Capture)
│
├─ get-enhancements [--id|--name] [--flow] [--index] [--regex]
│
├─ get-device-state [--id|--name] [--flow] [--index] [--regex] [--vendor-ini PATH]
│
├─ diag-sysfx [--id|--name] [--flow] [--index] [--regex]
│
├─ diag-mmdevices [--id|--name] [--flow] [--index] [--regex]
│
├─ discover-enhancements [--id|--name] [--flow] [--index] [--regex]
│ └─ [--output-dir DIR] [--ini-snippet FILE]
│
└─ wait (--id|--name) [--flow] [--timeout] [--index] [--regex]
```
---
# List Devices
- Human-readable:
```ps1
.\audioctl.exe list
```
- Include disabled/disconnected:
```ps1
.\audioctl.exe list --all
```
- JSON output:
```ps1
.\audioctl.exe list --json
```
---
# Set Default Devices (CLI)
Use `.\audioctl.exe set-default` to choose the system’s default playback (Render) and/or recording (Capture) endpoints. Targets must be active (`DEVICE_STATE_ACTIVE`). On some systems, you may need an elevated console (Run as Administrator).
Roles you can set:
- console - the default device most apps use.
- multimedia - often resolved to the same device as console on most systems.
- communications - used by calling/telephony apps.
- all (applies to all three roles)
Defaults if a role is omitted:
- Playback role defaults to `all`.
- Recording role defaults to `communications`.
About Windows roles (console vs multimedia):
- On most Windows systems, “console” and “multimedia” effectively point to the same default device. If you set either one, you will typically see both flags update in the next `audioctl list` output. The tool still lets you set them independently, or set `all` for completeness and for environments where they’re distinct.
Most users want a device to be the default for everything. Use:
- `--playback-role all` for playback (Render)
- `--recording-role all` for recording (Capture)
Get IDs first (optional but recommended):
```ps1
.\audioctl.exe list --json
```
Disambiguation when multiple name matches:
- If your `--playback-name` or `--recording-name` matches more than one active device, the command will stop and print the matching candidates in GUI order with an index for each. Then rerun with `--index N` to choose the one you want.
- Example of the prompt:
```
Multiple playback matches:
[Render idx 0] Speakers (USB DAC) id={...} defaults=-
[Render idx 1] Speakers (Realtek(R) Audio) id={...} defaults=multimedia,console
Use --index to disambiguate.
```
Notes about JSON output:
- Successful commands print compact, single‑line JSON (no pretty‑printing). For pretty output, pipe to a formatter (e.g., `| jq .`).
## Examples (only using “all”)
### 1) Playback (Render) - by name
```ps1
.\audioctl.exe set-default --playback-name "Speakers" --playback-role all --index 0
```
Sample output:
```json
{"set":[{"flow":"Render","role":"all","id":"{RENDER-ENDPOINT-ID}","name":"Speakers (Realtek(R) Audio)"}]}
```
### 2) Playback (Render) - by ID
```ps1
.\audioctl.exe set-default --playback-id "{RENDER-ENDPOINT-ID}" --playback-role all
```
Sample output:
```json
{"set":[{"flow":"Render","role":"all","id":"{RENDER-ENDPOINT-ID}","name":"Speakers (USB DAC)"}]}
```
### 3) Recording (Capture) - by name
```ps1
.\audioctl.exe set-default --recording-name "USB Microphone" --recording-role all --index 0
```
Sample output:
```json
{"set":[{"flow":"Capture","role":"all","id":"{CAPTURE-ENDPOINT-ID}","name":"USB Microphone"}]}
```
### 4) Recording (Capture) - by ID
```ps1
.\audioctl.exe set-default --recording-id "{CAPTURE-ENDPOINT-ID}" --recording-role all
```
Sample output:
```json
{"set":[{"flow":"Capture","role":"all","id":"{CAPTURE-ENDPOINT-ID}","name":"Headset Mic"}]}
```
### 5) Playback + Recording - both “all” in one command
```ps1
.\audioctl.exe set-default \
--playback-id "{RENDER-ENDPOINT-ID}" --playback-role all \
--recording-id "{CAPTURE-ENDPOINT-ID}" --recording-role all
```
Sample output:
```json
{"set":[{"flow":"Render","role":"all","id":"{RENDER-ENDPOINT-ID}","name":"Speakers (Realtek(R) Audio)"},{"flow":"Capture","role":"all","id":"{CAPTURE-ENDPOINT-ID}","name":"USB Microphone"}]}
```
Additional notes:
- If list output shows both console and multimedia toggled after setting only one, that is expected on most Windows builds, they commonly map to the same endpoint.
- “device not found (active only)”: verify the device is connected/enabled and visible in `audioctl list`.
- If multiple name matches occur, rerun with `--index N` using the indices printed in the disambiguation prompt.
---
# Set Volume or Mute/Unmute (CLI)
Use `audioctl set-volume` to change an endpoint’s master volume (0–100%) or toggle its mute state. Targets must be active (`DEVICE_STATE_ACTIVE`). On name selection, prefer adding `--flow` to disambiguate between Render (playback) and Capture (recording). If multiple matches remain, add `--index N` (0‑based, GUI‑order within the flow).
Rules:
- You must specify exactly one of: `--level`, `--mute`, or `--unmute`.
- `--level` is an integer 0–100 (values outside this range are clamped by the tool).
- Either `--id` or `--name` is required for selection (with optional `--regex` for pattern matching).
Command template:
```bash
audioctl set-volume
(--id | --name ) [--flow ]
(--level <0..100> | --mute | --unmute)
[--index ] [--regex]
```
Disambiguation behavior:
- If name selection matches more than one active device and you don’t pass `--index`, the tool returns:
```
ERROR: multiple matches; specify --index
```
Rerun the command with `--flow` and/or `--index N`. Use `.\audioctl.exe list` (or `--json`) to see devices in the same GUI order.
Notes about JSON output:
- Successful commands print compact, single‑line JSON. Pipe to a formatter (e.g., `| jq .`) if you want pretty output.
## Examples
### 1) Set playback volume by name (Render, 30%)
```ps1
.\audioctl.exe set-volume --name "Speakers" --flow Render --level 30
```
Sample output:
```json
{"volumeSet":{"id":"{RENDER-ENDPOINT-ID}","name":"Speakers (Realtek(R) Audio)","level":30}}
```
### 2) Set recording volume by ID (Capture, 70%)
```ps1
.\audioctl.exe set-volume --id "{CAPTURE-ENDPOINT-ID}" --level 70
```
Sample output:
```json
{"volumeSet":{"id":"{CAPTURE-ENDPOINT-ID}","name":"USB Microphone","level":70}}
```
### 3) Mute a playback device by name (Render) with index disambiguation
If multiple “Speakers” exist, specify which one using `--index` (0‑based, GUI‑order for Render).
```ps1
.\audioctl.exe set-volume --name "Speakers" --flow Render --mute --index 0
```
Sample output:
```json
{"muteSet":{"id":"{RENDER-ENDPOINT-ID}","name":"Speakers (USB DAC)","muted":true}}
```
### 4) Unmute a recording device by ID (Capture)
```ps1
.\audioctl.exe set-volume --id "{CAPTURE-ENDPOINT-ID}" --unmute
```
Sample output:
```json
{"muteSet":{"id":"{CAPTURE-ENDPOINT-ID}","name":"USB Microphone","muted":false}}
```
### 5) Use regex name matching (Render)
```ps1
.\audioctl.exe set-volume --name "^Speakers .* Realtek\\(R\\) Audio$" --regex --flow Render --level 15
```
Sample output:
```json
{"volumeSet":{"id":"{RENDER-ENDPOINT-ID}","name":"Speakers (Realtek(R) Audio)","level":15}}
```
### 6) Name match without `--flow` and multiple results
If both Render and Capture have a device matching “USB”, you’ll see:
```
ERROR: multiple matches; specify --index
```
Disambiguate by flow and/or index:
```ps1
.\audioctl.exe set-volume --name "USB" --flow Capture --unmute --index 0
```
Sample output:
```json
{"muteSet":{"id":"{CAPTURE-ENDPOINT-ID}","name":"USB Microphone","muted":false}}
```
### 7) Error safeguard: `--level` cannot be combined with `--mute/--unmute`
Invalid example (will return an error):
```ps1
.\audioctl.exe set-volume --name "Speakers" --flow Render --level 20 --mute
```
Error:
```
ERROR: Cannot specify both --level and --mute/--unmute
```
Tips:
- Prefer `--id` for exact targeting (no disambiguation needed).
- If you get “device not found (active only)”, verify the endpoint is connected/enabled and visible in `.\audioctl.exe list`.
- The command controls the endpoint’s master scalar level and mute state (not per‑app volumes).
---
# “Listen to this device” (Capture Only, CLI)
Use `.\audioctl.exe listen` to enable or disable “Listen to this device” on a capture (recording) endpoint. The target must be active (`DEVICE_STATE_ACTIVE`). This command only operates on Capture devices; Render devices are not eligible.
You must specify exactly one of:
- `--enable`
- `--disable`
Optional playback routing:
- `--playback-target-id "{RENDER-ENDPOINT-ID}"` routes the monitored audio to a specific playback (Render) endpoint.
- `--playback-target-id ""` routes to the Windows “Default Playback Device.”
- `--playback-target-name` mirrors the above using a name match; passing the flag without a value selects “Default Playback Device.”
- If the target flag is omitted, the current routing is preserved.
Command template:
```bash
audioctl listen
(--id | --name )
(--enable | --disable)
[--playback-target-id []]
[--playback-target-name []]
[--index ] [--regex]
```
Disambiguation behavior:
- If name selection matches more than one active capture device and you don’t pass `--index`, the command prints the matching candidates in GUI order (with indices) and exits with:
```
ERROR: multiple matches; specify --index
```
Rerun with `--index N` (0‑based, GUI‑order for the Capture flow). Use `.\audioctl.exe list` (or `--json`) to see the same order.
Notes about JSON output:
- Success prints compact, single‑line JSON.
- When a retry/verification path is used, the JSON may include a `verifiedBy` field (`"com"` or `"registry"`).
## Examples
### 1) Enable Listen for a microphone by name (preserve current playback target)
```ps1
.\audioctl.exe listen --name "Microphone" --enable
```
Sample output:
```json
{"listenSet":{"id":"{CAPTURE-ENDPOINT-ID}","name":"Microphone","enabled":true}}
```
### 2) Enable listen with specific playback routing
```ps1
.\audioctl.exe listen --name "Microphone" --enable --playback-target-name "Speakers"
```
or
```ps1
.\audioctl.exe listen --id "{CAPTURE-ENDPOINT-ID}" --enable --playback-target-id "{RENDER-ENDPOINT-ID}"
```
Sample output:
```json
{"listenSet":{"id":"{CAPTURE-ENDPOINT-ID}","name":"Microphone","enabled":true,"playbackTargetId":"{RENDER-ENDPOINT-ID}","playbackTargetName":"Speakers"}}
```
### 3) Enable Listen and route to the Default Playback Device
Passing the target flags without a value selects the Windows default.
```ps1
.\audioctl.exe listen --name "Microphone" --enable --playback-target-name
```
or
```ps1
.\audioctl.exe listen --id "{CAPTURE-ENDPOINT-ID}" --enable --playback-target-id
```
Sample output:
```json
{"listenSet":{"id":"{CAPTURE-ENDPOINT-ID}","name":"Microphone","enabled":true,"playbackTargetId":"default","playbackTargetName":"Default Playback Device"}}
```
### 4) Disable Listen by exact ID
```ps1
.\audioctl.exe listen --id "{CAPTURE-ENDPOINT-ID}" --disable
```
Sample output:
```json
{"listenSet":{"id":"{CAPTURE-ENDPOINT-ID}","name":"USB Microphone","enabled":false}}
```
### 5) Use regex name matching with index disambiguation (Capture)
```ps1
.\audioctl.exe listen --name "Mic" --regex --enable --index 0
```
Sample output:
```json
{"listenSet":{"id":"{CAPTURE-ENDPOINT-ID}","name":"Studio Mic","enabled":true}}
```
### 6) Example with verification source included
```json
{"listenSet":{"id":"{CAPTURE-ENDPOINT-ID}","name":"Microphone","enabled":true,"verifiedBy":"com"}}
```
or:
```json
{"listenSet":{"id":"{CAPTURE-ENDPOINT-ID}","name":"Microphone","enabled":true,"verifiedBy":"registry"}}
```
Tips:
- This command only targets Capture devices. If you try a Render device, it won’t match.
- Use `audioctl list --json` to get both Capture (for `--id`) and Render endpoints (for routing).
- If the name matches multiple capture devices, rerun with `--index N`.
---
# Audio Enhancements (SysFX) – Vendor Toggles (CLI)
Use `.\audioctl.exe enhancements` to enable or disable “Audio Enhancements” (SysFX) on an endpoint using a vendor‑first method. Many drivers (e.g., Realtek/Waves) expose Enhancements via device‑specific registry DWORDs under MMDevices; this tool writes those DWORDs (when known) and verifies the change.
Key points:
- Control is vendor‑only at runtime: if no vendor toggle is known for the target endpoint, the command fails and asks you to use `--learn` first.
- Windows’ `Disable_SysFx` is still read for diagnostics, not used to control state here.
- HKLM writes require Administrator privileges; use `--prefer-hklm` if your driver only honors HKLM.
You must specify exactly one of:
- `--enable` (turn Enhancements ON)
- `--disable` (turn Enhancements OFF)
- `--learn` (guided manual learning to append a vendor entry to INI)
Command template:
```bash
# Toggle using vendor DWORDs (if known)
audioctl enhancements
(--id | --name ) [--flow ]
(--enable | --disable)
[--index ] [--regex]
[--prefer-hklm]
[--vendor-ini ]
# Learn a vendor DWORD (you toggle the Windows UI; the tool captures A/B and appends to INI)
audioctl enhancements
(--id | --name ) [--flow ]
--learn
[--index ] [--regex]
[--vendor-ini ]
```
## Enhancement Effects (FX)
Beyond the main switch, you can manage individual effects (per-device) after learning them.
- List learned effects for a device:
```ps1
.\audioctl.exe enhancements --id "{ENDPOINT-ID}" --list-fx
.\audioctl.exe enhancements --id "{ENDPOINT-ID}" --list-fx --json
```
- Learn a specific effect (guided, two-pass A/B):
```ps1
.\audioctl.exe enhancements --id "{ENDPOINT-ID}" --flow Render --learn-fx "BassBoost"
```
- Toggle an effect:
```ps1
.\audioctl.exe enhancements --id "{ENDPOINT-ID}" --flow Capture --enable-fx "Loudness"
.\audioctl.exe enhancements --id "{ENDPOINT-ID}" --flow Capture --disable-fx "Loudness"
```
- Delete a learned effect association for this device:
```ps1
.\audioctl.exe enhancements --id "{ENDPOINT-ID}" --delete-fx "BassBoost"
```
Notes about JSON output:
- Success prints compact, single‑line JSON, e.g.:
```json
{"enhancementsSet":{"id":"{ENDPOINT-ID}","name":"Speakers (Realtek(R) Audio)","enabled":true,"verifiedBy":"vendor:realtek_waves_primary"}}
```
- FX toggles:
```json
{"fxSet":{"id":"{ENDPOINT-ID}","name":"Speakers","fx_name":"BassBoost","enabled":true,"verifiedBy":"vendor-fx:multi:BassBoost"}}
```
---
# Query helpers (read‑only)
Fast, side‑effect‑free commands perfect for status bars, hotkeys, and scripts.
- Get current volume/mute:
```ps1
.\audioctl.exe get-volume --id "{ENDPOINT-ID}"
```
or use --name (--regex if needed)
```ps1
.\audioctl.exe get-volume --name "Speakers" --flow Render --index 0 --regex
```
Returns:
```json
{"id":"{ENDPOINT-ID}","name":"NAME","flow":"Render","volume":78,"muted":false}
```
- Get current “Listen” state (Capture):
```ps1
.\audioctl.exe get-listen --id "{ENDPOINT-ID}"
```
or use --name (--index and --regex if needed)
```ps1
.\audioctl.exe get-listen --name "Microphone" --index 0 --regex
```
Returns:
```json
{"id":"{ENDPOINT-ID}","name":"NAME","flow":"Capture","listenEnabled":true}
```
- Check status with playback routing details:
Use the `--playback-target-id` or `--playback-target-name` flags (even without values) to force the inclusion of routing data.
```ps1
.\audioctl.exe get-listen --id "{ENDPOINT-ID}" --playback-target-id
```
```json
{"id":"{ENDPOINT-ID}","name":"Microphone","flow":"Capture","listenEnabled":true,"playbackTargetId":"{RENDER-GUID}","playbackTargetName":"Headphones (External DAC)"}}
```
- Get current Enhancements state (vendor‑only):
```ps1
.\audioctl.exe get-enhancements --id "{ENDPOINT-ID}"
```
or use --name (--index and --regex if needed)
```ps1
.\audioctl.exe get-enhancements --name "Speakers" --flow Render --index 0 --regex
```
Returns:
```json
{"id":"{ENDPOINT-ID}","name":"Speakers","flow":"Render","enhancementsEnabled":true}
```
- Aggregated device state (for GUI/scripts):
```yaml
.\audioctl.exe get-device-state [--id | --name ] [--flow Render|Capture] [--index ] [--regex] [--vendor-ini PATH]
```
Returns:
```json
{"id":"{ENDPOINT-ID}","name":"NAME","flow":"Render","volume":78,"muted":false,"listenEnabled":null,"enhancementsEnabled":true,"availableFX":[{"fx_name":"BassBoost","state":true,"source":"ini"}]}
```
---
# Diagnostics & Discovery (Optional, Read‑Only)
- View live Enhancements status and vendor state:
```ps1
.\audioctl.exe diag-sysfx --name "Speakers" --flow Render
```
- Dump all MMDevices values for an endpoint (HKCU/HKLM; FxProperties/Properties):
```ps1
.\audioctl.exe diag-mmdevices --id "{RENDER-ENDPOINT-ID}" --flow Render
```
- Interactive discovery with reports (TXT/JSON) and optional INI snippet:
```ps1
.\audioctl.exe discover-enhancements --name "Speakers" --flow Render --output-dir "." --ini-snippet ".\vendor_snippets.ini"
```
---
# Wait for a Device to Appear (CLI)
Use `.\audioctl.exe wait` to block until a device becomes active (appears) or until a timeout expires. Matching is against active endpoints only (`DEVICE_STATE_ACTIVE`). When a match is found, the command prints a compact, single‑line JSON object and exits with code 0.
- Template:
```bash
audioctl wait
(--id | --name ) [--flow ]
[--timeout ] [--index ] [--regex]
```
- Exit codes:
- 0: found a matching active device
- 3: timeout
- 4: multiple matches (rerun with `--index`)
- Tips:
- Prefer `--id` when you know it.
- Add `--flow` when the name appears in both flows.
## Examples
```ps1
.\audioctl.exe wait --name "USB Headset" --timeout 30
```
When the device is found, the CLI prints the following device dictionary as a compact string:
```json
{"found":{"id": "{ENDPOINT-ID}", "name": "Headset Earphone (USB Audio Device)","flow":"Render","state":"active","isDefault":{"console":true,"multimedia":true,"communications":false},"guiIndex": 2}}
```
---
# General Exit Codes
- `0` – success
- `1` – runtime failure or invalid option combo
- `3` – device not found or wait timeout
- `4` – multiple matches; provide `--index`
- `130` – Ctrl‑C interrupted
---
# Troubleshooting
- **Set-default fails**:
- Try running in an elevated PowerShell / Command Prompt (Run as Administrator).
- **comtypes/automation errors in the EXE**:
- The build already includes a compatibility shim at the top of `audioctl/compat.py`.
- Rebuild with the provided PyInstaller command if you change Python or comtypes versions.
- **“Listen” seems unchanged**:
- Use explicit default routing: `--playback-target-id ""` (Default Playback Device).
- Check JSON output: look at `enabled` and `verifiedBy` (`"com"` or `"registry"`).
- Enhancements don’t toggle:
- First try the toggle directly:
```ps1
.\audioctl.exe enhancements --id "{ENDPOINT-ID}" --flow Render --enable
```
If you get:
```
ERROR: No vendor toggle available for this device. Use --learn to teach a vendor method.
```
then proceed to learn.
- Learn the vendor toggle (manual A/B):
```ps1
.\audioctl.exe enhancements --id "{ENDPOINT-ID}" --flow Render --learn
```
After a successful learn, re-run the toggle:
```ps1
.\audioctl.exe enhancements --id "{ENDPOINT-ID}" --flow Render --disable
```
- If learn fails or the result can’t be verified:
- Inspect live state vs vendor with:
```ps1
.\audioctl.exe diag-sysfx --id "{ENDPOINT-ID}" --flow Render
```
- Capture ON/OFF snapshots and generate a report/snippet:
```ps1
.\audioctl.exe discover-enhancements --id "{ENDPOINT-ID}" --flow Render --output-dir "." --ini-snippet ".\vendor_snippets.ini"
```
Use the suggested INI snippet or share the TXT/JSON for analysis.
- Permissions and hive preference:
- Some drivers only honor HKLM. Re-run the toggle with:
```ps1
.\audioctl.exe enhancements --id "{ENDPOINT-ID}" --flow Render --enable --prefer-hklm
```
(Run an elevated console if HKLM writes are required.)
- Confirm selection and INI placement:
- Make sure you’re targeting the correct endpoint/flow (use `--flow` and `--index` if needed).
- Verify `vendor_toggles.ini` is at the expected path (exe directory if writable, otherwise `%LOCALAPPDATA%\audioctl\vendor_toggles.ini`) and that your endpoint GUID is listed under `devices =` in the learned section.
---
# GUI (Graphical User Interface)
### Launch the GUI:
- Double-click `audioctl.exe` (no arguments), or run it without command-line options.

### Features
- A visual overview of all playback (Render) and recording (Capture) devices, clearly grouped and sorted for easy navigation and management.
- **Right-click** or **double-click** a device for actions:
- **“Set as Default (all roles)”**
- Sets the selected device as the system default for Console, Multimedia, and Communications roles.
- “Set Volume…”
- Opens a volume control dialog to precisely adjust the device’s output or input level.
- **“Mute” / “Unmute”**
- Switch the device between muted and active audio states.
- **“Toggle Listen (capture only)”**
- Enable or disable “Listen to this device” for microphones and other recording inputs.
- **“Enable/Disable Enhancements”**
- Turn vendor-provided audio enhancements on or off when a known enhancement toggle is available.
- **“Enhancement Effects”**
- Individually toggle specific enhancement effects discovered and stored in your **vendor_toggles.ini** file.
- **“Learn Enhancements”** (discover a vendor DWORD and/or effects for that device)
- Scan and identify vendor-specific enhancement DWORDs and per-effect settings for the selected device.

### Print CLI Commands
- Enable **“Print CLI commands”** in the top bar.

- Every GUI action will print the equivalent `audioctl.exe` command to the console in blue font
(useful for learning the CLI and scripting).

- Highlight a command, right-click, and copy it directly from the console:

### Refresh Devices
- Click **"Refresh"** or press `F5`.
(Processing time varies based on device count and enhancement effects)
### Notes
- Setting default devices via the GUI may require Administrator privileges; the GUI will warn when recommended.
- Group header rows (e.g., “Playback (Render)”) are not selectable and have no actions; right-click the actual device entries.
---
## Credits
### Mr5niper:
Lead Developer. Performed the original research and reverse-engineering of the Windows registry-based "Learn" logic for Enhancements and FX. Implemented critical stability shims for comtypes and pycaw to resolve apartment-lifetime issues, prevents shutdown crashes, and ensures thread-safe COM interactions. Designed the CLI-to-GUI architecture.
### Pycaw:
Used for the underlying Windows Core Audio API endpoint wrappers.
### comtypes:
Used for COM interface handling and PROPVARIANT support.
### The Windows Audio Community:
For historical research into the undocumented IPolicyConfig and IPolicyConfigFx interfaces used for default endpoint selection.
---
## Third‑Party License Texts
### pycaw - MIT License
```text
Copyright (c) Andre Miras and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
...
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
...
```
Source:
---
### comtypes - MIT License
```text
Copyright (c) Thomas Heller, Enthought, Inc., and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
...
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
...
```
Source:
---
### PyInstaller License Notice (for binary distributions)
If you distribute a PyInstaller-built executable of this project, PyInstaller is licensed under the GNU General Public License v2 (GPL-2.0) with a special exception that permits using PyInstaller to build and distribute executables, regardless of your program’s license.
Full text:
Project page:
```