Files
btd700linux/README.md
T
Justin 3de4ca48e0
AppImage / build (push) Has been cancelled
AppImage / release (push) Has been cancelled
Tests / unit (de, 3.10) (push) Has been cancelled
Tests / unit (de, 3.14) (push) Has been cancelled
Tests / unit (en, 3.10) (push) Has been cancelled
Tests / unit (en, 3.14) (push) Has been cancelled
Ship AppImage with bundled GTK runtime and automated releases
2026-09-05 21:32:30 +02:00

273 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<p align="center">
<img src="packaging/btd700-control.svg" width="80" alt="BTD 700 Control icon">
</p>
<h1 align="center">BTD 700 Control for Linux</h1>
<p align="center">Your dongle. Your codecs. A native Linux app and system tray menu.</p>
<p align="center">
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT license"></a>
<img src="https://img.shields.io/badge/platform-Linux-informational" alt="Linux">
<img src="https://img.shields.io/badge/UI-English%20%2F%20Deutsch-green" alt="English and German interface">
<a href="https://github.com/justin-eckenweber/btd700linux/actions/workflows/tests.yml"><img src="https://github.com/justin-eckenweber/btd700linux/actions/workflows/tests.yml/badge.svg" alt="Tests"></a>
</p>
<p align="center">
<a href="#install">Install</a> ·
<a href="https://github.com/justin-eckenweber/btd700linux/releases/latest">Download AppImage</a> ·
<a href="README.de.md">Deutsche Anleitung</a> ·
<a href="https://github.com/justin-eckenweber/btd700linux/issues">Report an issue</a>
</p>
An independent, open-source control app for the **Sennheiser BTD 700** USB Bluetooth
transmitter. Choose audio modes and codecs, manage the headphone connection, and
configure Auracast without Windows or Wine. Built with Python, GTK 4 and libadwaita.
**Controls only. No firmware updates, firmware downloads or update mode.** Once
installed, the app works offline and does not send telemetry.
> **AI-developed · Experimental · No warranty**
>
> This project was developed with AI (OpenAI Codex), including protocol research,
> implementation, documentation and tests. It is an independent community project,
> not official Sennheiser software. **There is no guarantee that it will work with
> your hardware, firmware or Linux setup.** It is provided as is, without warranty,
> under the [MIT license](LICENSE). Use it at your own risk.
## Screenshots
Actual application windows on Linux, using **fictional demo data**. No mockups or
AI-generated images. The app follows your desktop's light/dark appearance.
<p align="center">
<img src="docs/screenshots/main-window.png" width="46%" alt="English app: active codec, audio mode and headphone connection">
<img src="docs/screenshots/auracast-settings.png" width="46%" alt="English app: Auracast name, password protection, broadcast quality and startup settings">
</p>
## What you can control
| Feature | Window | System tray |
|---|:---:|:---:|
| Standard, Gaming and Auracast modes | ✓ | ✓ |
| Active codec, audio format and connection status | ✓ | ✓ |
| Codec selection supported by the current connection | ✓ | ✓ |
| Bluetooth Classic, LE Audio or automatic transport | ✓ | ✓ |
| Connect / disconnect previously paired headphones | ✓ | ✓ |
| Auracast discovery, quality and password protection | ✓ | ✓ |
| Auracast name and password | ✓ | Opens the editor |
| Factory reset, with confirmation | ✓ | Opens confirmation |
The tray menu stays available when you close the window. On GNOME, it uses the
same StatusNotifier/AppIndicator mechanism as apps such as Discord and JetBrains
Toolbox. Use **Quit** to close the app completely. Without a tray host, closing the
window quits the app instead.
## Install
### AppImage (x86-64)
[Download the AppImage from GitHub Releases](https://github.com/justin-eckenweber/btd700linux/releases/latest).
It includes Python, GTK, libadwaita and the tray library. Requires **glibc 2.39+**
(for example Ubuntu 24.04 or newer, or the tested Bazzite 44 desktop).
```bash
chmod +x BTD_700_Control-0.3.0-x86_64.AppImage
./BTD_700_Control-0.3.0-x86_64.AppImage
```
Put it in a permanent folder, then optionally run it with `--install-desktop` to
add an application-menu entry. Enable **Start at login** inside the app for tray
autostart. Use `--remove-desktop` to remove both entries. Keep the AppImage at the
same path; after moving it, recreate the menu entry and toggle autostart off/on.
If FUSE is unavailable, start with
`APPIMAGE_EXTRACT_AND_RUN=1 ./BTD_700_Control-0.3.0-x86_64.AppImage`.
See the [AppImage guide](docs/APPIMAGE.md) for permanent extraction, build instructions,
checksums and dependency sources. USB permissions and the desktop's tray host are
still required; GNOME needs a StatusNotifier/AppIndicator extension.
### Run from source
You can also run the Python source directly, without compiling or using pip.
#### 1. Install the system libraries
Requirements: **Python 3.10+**, PyGObject, **GTK 4.10+**, **libadwaita 1.5+** and
libdbusmenu with GObject introspection. A graphical desktop session is needed for
the window and tray; the CLI only needs Python's standard library.
**Ubuntu 24.04+ / Debian with sufficiently recent GTK and libadwaita:**
```bash
sudo apt install git python3 python3-gi gir1.2-gtk-4.0 gir1.2-adw-1 gir1.2-dbusmenu-glib-0.4
```
**Fedora Workstation:**
```bash
sudo dnf install git python3 python3-gobject gtk4 libadwaita libdbusmenu
```
**Bazzite / other immutable desktops:** try running the app first. The tested
Bazzite system already included every required library. The Fedora command above
is for a mutable Fedora installation, not an instruction to layer packages on Bazzite.
On **GNOME**, enable a StatusNotifier/AppIndicator extension if you do not already
have a working tray, for example
[AppIndicator and KStatusNotifierItem Support](https://extensions.gnome.org/extension/615/appindicator-support/).
KDE Plasma provides a tray host. Other desktops may work but have not been tested.
Package references: [Fedora libdbusmenu](https://packages.fedoraproject.org/pkgs/libdbusmenu/libdbusmenu/),
[Ubuntu introspection package](https://packages.ubuntu.com/noble/gir1.2-dbusmenu-glib-0.4).
#### 2. Download and run
```bash
git clone https://github.com/justin-eckenweber/btd700linux.git
cd btd700linux
./run.sh
```
Or [download the v0.3.0 source ZIP](https://github.com/justin-eckenweber/btd700linux/archive/refs/tags/v0.3.0.zip),
extract it, and run `bash run.sh` inside the extracted folder.
Want to explore without touching any hardware?
```bash
./run.sh --demo
```
#### 3. Add it to your application menu
```bash
python3 install.py
```
Open **BTD 700 Control** from the application menu. Keep the downloaded project
folder in place: the launcher points to it. Enable **Start at login** inside the
app if you want it to start quietly in the tray. Autostart is off by default.
```bash
./run.sh --background # Start directly in the tray
python3 install.py --uninstall # Remove launcher and autostart entry
```
### USB permissions
If the app reports that USB access is denied, use the rule from the source checkout
or download `70-btd700-control.rules` from the same AppImage release (adjust its path below):
```bash
sudo install -m 0644 packaging/70-btd700-control.rules /etc/udev/rules.d/70-btd700-control.rules
sudo udevadm control --reload-rules
```
Unplug and reconnect the dongle afterwards. The rule grants the active local user
access to the **control interface** of USB device `3542:3001`; it excludes the second
interface used for updates. Run the app as your normal user, not with `sudo`.
No audio driver is detached or replaced.
## English and German
The app, tray, CLI help and application error messages follow the system language:
German for German locales, English otherwise. You can override this explicitly:
```bash
./run.sh --language en
./run.sh --language de
BTD700_LANGUAGE=en ./run.sh --background
```
Quit an already running instance before changing the language; launching it again
normally brings the existing window to the front.
## Using the controls
- **Codecs:** the dongle reports the choices available for the current connection.
Select a codec in Standard mode; Gaming mode manages its own codec. A codec
supported in principle is not necessarily offered with every pair of headphones.
- **Audio format:** bit depth and sample rate are read from the dongle. Set the USB
output sample rate in your audio system, such as PipeWire; this app does not
force 96 kHz or claim bit-perfect or lossless transmission.
- **Pairing:** use the physical dongle button to pair headphones. **Connect** reuses
an existing pairing.
- **Auracast:** select Auracast mode to start broadcasting. **Publicly discoverable**
controls advertising/discovery, not whether audio is transmitted.
- **Name and password:** 416 ASCII letters/digits; names may contain internal
spaces. An empty name restores the device's default name. Leave the password
field blank to keep the current password; turn off Password protection to
broadcast without it. Passwords are not stored on disk or included in status output.
- **Factory reset:** deletes saved settings and pairings. It always requires
confirmation in the UI.
## Command line
Quit the tray app before using the CLI: one instance owns the dongle at a time.
```bash
./run.sh devices
./run.sh status
./run.sh mode standard
./run.sh mode gaming
./run.sh mode standard --transport auto
./run.sh codec adaptive
./run.sh disconnect
./run.sh connect
./run.sh auracast --name 'Living Room' --quality high --public on
./run.sh auracast --password --encryption on # Hidden password prompt
./run.sh mode auracast
```
`status` prints JSON without reading a password. With multiple dongles, place
`--device /dev/hidrawN` before the subcommand; use the path reported by `devices`.
The numeric fields in JSON retain their protocol meanings across languages.
## Compatibility and limitations
Developed and tested on **Bazzite / GNOME with a BTD 700 running firmware 3.11.0**.
The owner confirmed that the app works with their dongle. That is not a complete
compatibility matrix or a guarantee for other firmware and receivers.
- Real hardware: device discovery, state/configuration reads, native window and
tray integration verified.
- Automated tests: protocol parsing, allowed commands, readback, input validation,
localization and demo-backed GTK/D-Bus menu interactions.
- Still needed: systematic hardware write tests, more receivers/firmware versions,
other desktops, and independent testing by more users.
- BTD 600 and other Sennheiser devices are **not supported** by this driver.
- Reconfiguring modes or broadcasts can interrupt audio. Multi-step settings are
not atomic; unplugging the dongle midway can leave partially applied changes.
[Validation notes](docs/VALIDATION.md) · [Protocol and research sources](docs/PROTOCOL.md)
## Contribute
Bug reports, compatibility reports, translations and reviewed patches are welcome.
See [CONTRIBUTING.md](CONTRIBUTING.md) for what to include and how to run tests.
Please do not attach broadcast passwords, device serial numbers, original vendor
executables or firmware images.
```bash
python3 -m unittest discover -s tests -v
BTD700_LANGUAGE=en python3 tools/check_gui.py # Desktop session; simulated dongle
BTD700_LANGUAGE=de python3 tools/check_gui.py
python3 tools/capture_screenshots.py # Regenerate the README screenshots
```
The separate `tools/check_hardware.py --run` is an opt-in hardware test that changes
settings, including the broadcast password, and attempts to restore the originals.
It is never run by CI or the demo tests. Read it before deliberately using it.
## License and independence
The project's own code and documentation are licensed under **[MIT](LICENSE)**.
The AI-development and no-warranty notice above is intentional; please keep it
visible when describing this project.
Sennheiser, BTD 700, aptX and Auracast names identify the compatible product and
technologies. This project is not affiliated with, endorsed by or supported by
Sennheiser, Sonova or Qualcomm. No vendor code, firmware or logos are included.
System libraries and original vendor software retain their own licenses;
see [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).