Repository navigation
Conversation
should probably have an indication when not connected
tbh, I did not want to get results right away; batching would have been fine. But, BlueR seems to give the first scan result only after 10s if I set sampling period.
finally! only copying all ui from android to first release
When the iPhone takes the AirPods, BazzitePods pauses Brave. For a moment afterwards Brave still reports playing (and its stream stays uncorked), so both the route watcher and the playback listener saw "media playing here" and took the AirPods straight back, three times in seven seconds. Ignore playback for a few seconds after pausing players for another device. Also only pass ear detection to the media controller when the status changed: the AirPods repeat it, and each repeat paused the players again. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nw15uJa3wJ9BwDHoBunZoh
A take-back within 20 s of the previous rebuild didn't rebuild the output, so after a quick switch back the AirPods stayed silent until the stall check caught it 20 s later. The long limit was there to stop the PC and iPhone bouncing, which is now prevented where it starts, so keep only a 3 s window that merges duplicates. Also skip the rebuild for a take-back in the first 10 s after the link comes up: the output was just built, and that rebuild only cost a speaker mute and a slot. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nw15uJa3wJ9BwDHoBunZoh
Picking the AirPods in Control Center only shows up as OwnsConnection 00: no Smart Routing media message, and the Audio Source report that follows found the route already marked as away, so the switch was never recorded. The PC then ignored the iPhone letting go, and only the stall check brought the audio back, 11 s later, followed by a second rebuild. Record the loss and pause the stall checks on OwnsConnection 00 too, treat any switch as a borrow until the other device says it is playing media, pause stall checks for every switch, and let a stall rebuild count towards the duplicate window so a take-back right after it doesn't rebuild again. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nw15uJa3wJ9BwDHoBunZoh
When an iPhone that wasn't connected joins the AirPods, they can drop the PC's link entirely. With no link the PC never hears the iPhone let go, so the AirPods stayed away. Two fixes: - The AirPods task ends by itself when the link drops, usually before BlueZ reports the disconnect, and the supervisor pruned it as "ended on its own" without recording the lost link. Record it, so the existing reconnect-on-advert path works for any drop. - When the drop follows another device joining the AirPods within 10 s, retry the connection every 20 s for 3 minutes without waiting for adverts. Connecting doesn't take the audio from the iPhone. Other drops, such as disconnecting here, don't get these retries. Reconnect attempts and failures are now logged at info level. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nw15uJa3wJ9BwDHoBunZoh
…dverts Out of the case and busy with an iPhone, the AirPods advertise only Find My beacons from static random addresses, which the IRK can never resolve, so the reconnect-on-advert path never fired and the AirPods stayed off the PC. When they were put in the case before the drop, keep asking BlueZ to connect: every 20 s for 3 minutes, then every minute for up to 30 minutes. A failed attempt costs nothing and connecting never takes the audio from an iPhone that is playing. Drops after a local disconnect while worn still get no retries, so disconnecting the AirPods here keeps them disconnected. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nw15uJa3wJ9BwDHoBunZoh
Merges Dependabot PRs by itself only when they are patch/minor Cargo updates under linux-rust/ and the Flatpak build of that exact commit passed. Major bumps, other ecosystems and failed builds stay open for review. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GafSgAbeHTKRmrNro1JnrS
Retries after the AirPods went into the case stopped after 30 minutes, so after a day out they stayed off the PC. Keep retrying, every 3 minutes after the first half hour, until they connect. AirPods that are away when the app starts or the PC wakes from sleep are retried the same way. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nw15uJa3wJ9BwDHoBunZoh
Auto-merge safe Dependabot security updates
Bumps the cargo group with 1 update in the /linux-rust directory: [rand](https://github.com/rust-random/rand). Updates `rand` from 0.9.2 to 0.9.5 - [Release notes](https://github.com/rust-random/rand/releases) - [Changelog](https://github.com/rust-random/rand/blob/0.9.5/CHANGELOG.md) - [Commits](rust-random/rand@rand_core-0.9.2...0.9.5) --- updated-dependencies: - dependency-name: rand dependency-version: 0.9.5 dependency-type: indirect dependency-group: cargo ... Signed-off-by: dependabot[bot] <support@github.com>
…un them in CI - New test files beside each module (aacp, battery, le, overlay_feed, hub, settings, tray, pulse, utils): about 100 new tests on top of the existing 124, none needing Bluetooth, a sound server or a display. - overlay_feed: the notification fallback now returns its notifications and the overlay settings parse from a string, so both are testable without D-Bus or disk. - tests.yml runs the suite with a coverage report on every PR and on main/bazzite, with a floor so coverage can't quietly drop. - Dependabot auto-merge now waits for the tests as well as the Flatpak build. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HkZQiV1RZAkdtPGA9VxDw
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HkZQiV1RZAkdtPGA9VxDw
The offline Flatpak build vendors crates from cargo-sources.json, which still listed rand 0.9.2 after the Cargo.lock bump. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GafSgAbeHTKRmrNro1JnrS
Grouped security updates (the only kind enabled) report no update-type, so the first real Dependabot PR (#8, rand 0.9.2 -> 0.9.5) was skipped. Compare Cargo.lock at base and head instead: merge only when every changed crate stays within its semver-compatible range, no crate is added, and only linux-rust Cargo files changed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GafSgAbeHTKRmrNro1JnrS
Add automated tests for the app logic and run them on every PR
0.2.2: every switching scenario covered, overlay switch feedback, release prep
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kak6d8qzQLuZMFxXsJNCfz
…-a1ec0912cc build(deps): bump rand from 0.9.2 to 0.9.5 in /linux-rust in the cargo group across 1 directory
Fix Dependabot auto-merge skipping grouped security updates
The overlay becomes an island modelled on the iPhone's Dynamic Island: a card on connect, a slim island at rest (Compact), and one-line alerts for charging, low battery, noise control changes, the audio moving to or from another device, and disconnecting. - spring.rs: damped springs with SwiftUI's duration/bounce mapping; a retarget keeps velocity, so interrupted transitions bend smoothly. - island.rs: content model, shapes, cross-fade, ring sweep, rolling numbers and caption, all pure and unit tested. - logic.rs: event detection with priorities, mode handling, exact deadlines instead of 200 ms polling. - view.rs/glyphs.rs: island drawing; phone, monitor, battery and noise control glyphs. Contents are clipped to the island and revealed as it grows. - Frames are paced by compositor frame callbacks and only requested while something moves; at rest the overlay uses no CPU and no wakeups. The surface has a fixed size so it is never resized while shown. - Protocol: optional listening_mode. Default position is top center; Glass 0% is pure black. - --demo-story plays a scripted tour for recordings. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UJov27xWCsRzbVRci4CYKk
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UJov27xWCsRzbVRci4CYKk
… this PC Gauges no longer grey out every level just because the classic link is down: a fresh reading from the AirPods' adverts (pods in the case on a charger, case lid open) is shown live, charging included. When the link drops, what the control channel last said turns into "last seen" at once instead of looking live for up to a minute. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0186cCkmreRwvodd6Q6cZDj3
The control channel reports every setting a model has. The window now keeps those values in the hub and offers automatic ear detection, Adaptive Audio strength, noise cancellation with one AirPod, microphone choice and automatic connection, each only when the AirPods report it. Personalized volume now shows the AirPods' real state instead of a local guess. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0186cCkmreRwvodd6Q6cZDj3
… case AirPods only report the case while it is open with a pod inside; with both pods in a closed case the link drops and nothing reports. The window and tray now say "In case" instead of "Not connected" and hint "open the lid to update" under the case's last reading. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0186cCkmreRwvodd6Q6cZDj3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0186cCkmreRwvodd6Q6cZDj3
Overlay: redesign as a Dynamic Island (v0.3.0)
Bring #12 to main: battery in the case, charging while away, more AirPods settings (0.3.1)
AirPods worn out of range only came back if the PC matched their adverts, and only for 4 hours. Treat every drop like a case drop (keep retrying), except when BlueZ says this PC closed the link on purpose: listen for org.bluez.Device1.Disconnected and stay disconnected on Reason.Local. Release 0.3.2. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Author
|
Opened here by mistake, sorry; this was meant for a fork. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by David
Problem
David came home after a workday and his AirPods didn't reconnect to the PC. Logs on the PC showed the AirPods dropped at 05:56 and the app then made zero connection attempts for 18 hours.
Cause: drops were only retried eagerly when the AirPods went into the case or handed over to an iPhone. Walking out of range while wearing them fell through to the advert path, which needs the PC to recognise the AirPods' BLE adverts (they often only send Find My beacons) and gives up after
AUTO_RECONNECT_WINDOW(4 h).Fix
disconnect_watchmodule listens for BlueZ'sorg.bluez.Device1.Disconnected(reason, message)signal (BlueZ 5.87 on Bazzite has it).Reason.Localmeans this PC closed the link (KDE menu, bluetoothctl), so we stop retrying.Timeoutis range loss and always retries until back. Peer hand-offs keep their 3-minute window.disconnect_watch::plan, run when the drop is noticed and again when the reason arrives, in either order.Tests
Unit tests for reason parsing, object path to address, and the plan for each kind of drop (including the regression:
Timeout/no reason, not in case, not peer, givesUntilBack). Not built locally because David was gaming; CI runs fmt, clippy and tests.Notes
Also found the installed Flatpak is still 0.2.2, so 0.3.x was never installed on the PC.
🤖 Generated with Claude Code