Lightweight headset battery monitor for Linux
A fast, minimal system tray app that shows battery and connection status for wireless/USB headsets. Real-time updates via D-Bus, desktop notifications, and only 39 KB thanks to demoscene-inspired optimizations.
| Feature | Description |
|---|---|
| System Tray | Native emoji icons with device count badge |
| Notifications | Low battery, charging complete, device disconnect |
| Headless Mode | Run without tray (--no-tray) for servers/scripts |
| Systemd Service | Auto-start on login with user service |
| Multi-Device | Submenu with individual status per device |
| Real-time | Instant updates via D-Bus/UPower |
| Lightweight | 39 KB binary, minimal resource usage |
| Settings GUI | Configure notification preferences and thresholds |
Click to expand
System tray with battery status and multi-device menu
yay -S headsetstatusDependencies:
- CMake >= 3.16
- Qt6 (Core, Widgets, DBus)
- UPower
- C++17 compiler
git clone https://github.com/mewset/headsetstatus.git
cd headsetstatus
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
sudo cmake --install build --prefix /usrBuild with unit tests
cmake -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=ON
cmake --build build
ctest --test-dir build --output-on-failure# GUI mode (system tray)
HeadsetStatus
# Headless mode (notifications only)
HeadsetStatus --no-tray
# Show version
HeadsetStatus --version| Option | Description |
|---|---|
-h, --help |
Show help |
-v, --version |
Show version |
-n, --no-tray |
Headless mode (no system tray) |
-d, --debug |
Enable debug output |
systemctl --user enable --now headsetstatus.service# ~/.config/hypr/hyprland.conf
exec-once = HeadsetStatus
# ~/.config/sway/config
exec HeadsetStatuscp /usr/share/applications/HeadsetStatus.desktop ~/.config/autostart/Settings are stored in ~/.config/headsetstatus/config.ini.
Access via tray menu > Settings, or edit directly:
[notifications]
enabled=true
lowBatteryThreshold=20
notifyOnLowBattery=true
notifyOnChargingComplete=true
notifyOnDisconnect=trueAuto-detection for 20+ brands:
Jabra, Bose, Sony, Sennheiser, JBL, Beats, HyperX, SteelSeries, Razer, Logitech, Corsair, Plantronics, Audio-Technica, Beyerdynamic, AKG, Skullcandy, Anker, AirPods, Galaxy Buds, Pixel Buds, Surface Headphones
Missing your headset? Open an issue.
| Requirement | Notes |
|---|---|
| Linux | D-Bus support required |
| Qt6 | Core, Widgets, DBus modules |
| UPower | Battery status provider |
| Notification daemon | Optional: libnotify, dunst, mako, swaync |
HeadsetStatus/
├── main.cpp # Application entry, CLI parsing, D-Bus listener
├── src/
│ ├── HeadsetManager # UPower D-Bus device discovery and filtering
│ ├── TrayIconController# System tray icon, menu, emoji rendering
│ ├── NotificationManager# D-Bus notification sending
│ ├── ConfigManager # Persistent settings (QSettings)
│ ├── SettingsDialog # Qt GUI for preferences
│ └── HeadsetDevice # Device data struct
└── tests/ # Qt Test unit tests
| Component | Technology |
|---|---|
| Language | C++17 |
| Framework | Qt6 |
| IPC | D-Bus / UPower |
| Build | CMake 3.16+ |
| Size | 39 KB (LTO + UPX) |
| Tests | Qt Test |
Demoscene-inspired techniques for minimal binary:
- LTO (Link Time Optimization)
- Symbol hiding (
-fvisibility=hidden) - Section garbage collection (
-ffunction-sections -fdata-sections) - Binary stripping (all symbols removed)
- UPX LZMA compression (if available)
Result: 431 KB → 39 KB (91% reduction)
PRs welcome! Please:
- Follow existing code style
- Test before submitting
- Use clear commit messages
- Add tests for new functionality
# Debug build with tests
cmake -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=ON
cmake --build build
# Run tests
ctest --test-dir build --output-on-failure
# Run with debug output
./build/HeadsetStatus --debugSee CHANGELOG.md for version history.
- Headless mode (
--no-tray) - CLI arguments:
--version,--help,--no-tray,--debug - Systemd user service
- 91% binary size reduction (431 KB → 39 KB)
MIT © mewset
39 KB of pure battery anxiety relief