Skip to content

PR: Add pbpctui extension - A Terminal User Interface - #22

Open
CGH0S7 wants to merge 14 commits into
qzed:mainfrom
CGH0S7:tui
Open

CGH0S7 wants to merge 14 commits into
qzed:mainfrom
CGH0S7:tui

Conversation

@CGH0S7

@CGH0S7 CGH0S7 commented Dec 31, 2025

Copy link
Copy Markdown

Description

This PR introduces pbpctui, a new crate in the workspace providing a TUI (Terminal User Interface) for interacting with the Pixel Buds Pro.

It serves as a visual wrapper around the pbpctrl CLI, allowing users to monitor device status and adjust settings in a more interactive way.

Features

  • Status Dashboard: Real-time view of:
    • Connection status (Local/Remote peer)
    • Battery levels (Left, Right, Case) & Charging status
    • Firmware versions & Serial numbers
  • Settings Editor: Interactive controls for:
    • ANC Modes: Off, Active, Adaptive, Aware
    • Audio: 5-band EQ, Volume Balance, Mono Audio
    • Smart Features: Multipoint, In-Ear Detection (OHD), Speech Detection
    • System: Touch Controls, Diagnostics, Volume Notifications

Implementation Details

  • Built with ratatui and crossterm for the UI.
  • Uses tokio for async runtime and process management.
  • Acts as a frontend that spawns pbpctrl subprocesses to fetch data (show ...) and apply settings (set ...).
  • Polling mechanism to keep status updated.

Dependencies

  • ratatui
  • crossterm
  • tokio
  • anyhow
  • regex

Usage

cargo run -p pbpctui

or install:

cargo install --path tui
pbpctui

Additional Changes

  • Dependency Update: Upgraded the bluer crate to a newer version to align with recent BlueZ changes and reduce the risk of future incompatibilities.
    • No behavior changes intended.
    • Existing APIs used by pbpctrl / pbpctui remain compatible.

This adds a new TUI application in the 'tui' directory that provides
a user-friendly interface for managing Pixel Buds Pro headphones.
The TUI is built using ratatui and interacts with the pbpctrl CLI
binary to perform operations.

Features:
- Status dashboard with battery levels, firmware info, and placement.
- Settings management for ANC, multipoint, sensors, and more.
- Polling for real-time status updates.
- Robust parsing of CLI output.
- **Status Page:** Added display for ANC, Multipoint, In-Ear Detection, and Hold Gestures.
- **Settings Page:**
    - Split Equalizer into 5 adjustable bands.
    - Implemented numeric adjustment (Left/Right keys) for Balance and EQ.
    - Added 'j'/'k' keys for navigation.
    - Increased layout spacing for better readability.
    - Removed 'Hold Gestures' (moved to Status).
- **Error Handling:** Display errors in the UI footer instead of printing to stderr.
- **Deps:** Updated 'bluer' to v0.17.4 to resolve future-incompatibility warnings.
- **Refactor:** Improved settings polling and update logic.
@CGH0S7

CGH0S7 commented Dec 31, 2025

Copy link
Copy Markdown
Author

Screenshots:
屏幕截图_20251231_161144
屏幕截图_20251231_161157

@qzed

qzed commented Jan 3, 2026

Copy link
Copy Markdown
Owner

Thanks for the PR, it's a nice idea.

I have a couple of notes: I think it would be better to not call the binary but use libmaestro directly. That doesn't require the pbpctrl binary to be at a specific path and also gives you more direct control. Specifically, it would allow you to use

pub fn subscribe_to_settings_changes(&mut self) -> Result<StreamResponse<SettingsRsp>, Error> {
which allows you to update display values when settings have changed externally (either other app or through gestures).

@CGH0S7

CGH0S7 commented Jan 4, 2026

Copy link
Copy Markdown
Author

Thanks for the review and the positive feedback!

Using libmaestro directly is a cleaner design and avoids the dependency on the pbpctrl binary path. I initially went with spawning the CLI to keep the first version simple and decoupled, but I agree that integrating with libmaestro is the better long-term approach.

I’ll look into refactoring pbpctui to use libmaestro directly and see how best to structure the async event handling around the settings stream. This may take a bit of rework, but I think it’s worth doing properly.

Thanks again for the suggestion and for pointing me to the relevant API. I'll update the PR once the changes are ready.

CGH0S7 added 7 commits January 4, 2026 11:17
…dates

- Removed dependency on pbpctrl CLI binary.
- Integrated libmaestro service directly for communication.
- Implemented reactive UI updates using settings and runtime subscriptions.
- Fixed deadlocks by spawning the RPC client in a concurrent background task.
- Added reconnection logic with timeouts to prevent TUI freezes.
- Resolved Local/Remote Peer status information display.
- Modified libmaestro RPC markers to implement Send, allowing multi-task usage.
- Fixed clippy lints and ensured clean compilation.
…ection

- Changed connection retry warnings from warn to debug level to reduce UI noise
- Filter transient connection errors (not available, not connected) from error display
- Clear subscription streams immediately when client task completes to prevent blocking
- Filter connection reset errors (os error 104) as they are expected on disconnect
- Changed subscription error handling from break to setting None to maintain loop stability
Added Send + Sync + 'static bounds to the Backend::Error associated type in run_app to satisfy anyhow::Result requirements.
@CGH0S7

CGH0S7 commented Jan 5, 2026

Copy link
Copy Markdown
Author

Hi, I've completed the refactoring as we discussed. Here’s a summary of the changes:

  • Direct Integration: pbpctui now uses libmaestro directly instead of spawning pbpctrl as a subprocess.

  • Real-time Updates: I’ve implemented the subscribe_to_settings_changes API as you suggested. The UI now stays in sync with external changes in real-time.

  • Stability & Testing: I’ve been using and testing this version for a while now. Most initial bugs and edge cases have been resolved, and it feels stable for daily use.

  • Conflict Resolution: I have also resolved the merge conflicts with the latest main branch.

@CGH0S7

CGH0S7 commented Jan 6, 2026

Copy link
Copy Markdown
Author

Fixed unused_assignments warnings in maestro_client.rs. Sorry for the oversight—I was using a nightly toolchain and didn't see these warnings until I switched back to stable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants