Skip to content

Fix Icon Switching, System Alert Device, Add Priority Overrides per Speaker/Headphone, and Add Fast Switching#21

Open
jhenkens wants to merge 8 commits into
tobi:mainfrom
jhenkens:main
Open

Fix Icon Switching, System Alert Device, Add Priority Overrides per Speaker/Headphone, and Add Fast Switching#21
jhenkens wants to merge 8 commits into
tobi:mainfrom
jhenkens:main

Conversation

@jhenkens

Copy link
Copy Markdown

Bunch of commits - I can break them out if you like some but not all.

  1. Add a preferences window that contains the start-at-login setting intitially
  2. Fix the icon switching back to how it was in the releases - Headphone/Speaker Icon.
  3. Add the ability to assign an input device as a priority device for a given output device. This way you can prefer your webcam microphone, unless you are using your headphones, then prefer the headphone microphone.
  4. Add one-click fast switching as an option in the preferences pane. It requires a restart, but makes left click toggle between Headphone and Speakers, and right click bring up the dialog
  5. Add, with a preference, the System Default Output to be switched alongside the Default Output. This wasn't being switched before, and it seems when interacting via these APIs, OSX won't follow it like it does when you interact with their built in solutions.

Replace boolean "Quick Switch Mode" with flexible 4-action configuration
system allowing users to customize left click, right click, long left
click, and long right click behaviors.

Features:
- 4 customizable click actions with options: Toggle Mode, Show Menu, No Action
- Long press threshold: 500ms
- Validation ensures at least one action shows menu
- Migration from old isQuickSwitchEnabled setting
- Simplified app initialization (removed conditional setup)

Technical implementation:
- Custom LongPressButton overlay view to intercept mouse events
- Timer-based long press detection using run loop
- ClickActionsConfig model with JSON persistence in UserDefaults

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@jonasgantner

Copy link
Copy Markdown

This is a great PR @jhenkens , will someone approve / make this a release?
How do I get this version?

@travisp

travisp commented Apr 9, 2026

Copy link
Copy Markdown

I'm using your PR locally (along with some other changes) and I'm finding that it sometimes results in the wrong item selected:

Screenshot 2026-04-09 at 3 53 13 PM

This typically happens when my airpods switched to my iphone for a call and then back to my macbook. It works if there is a hardware change, but not just a software change, which for me is one of the main benefits of the app. It looks like this was implemented to prevent a loop in the commit Add priority override for each device:

        } else if !isCustomMode {
            logger.debug("  → Default device switched - NOT reapplying priorities (prevents loop)")
            // Just update the UI, don't reapply priorities - this prevents the loop!

I think if the priority override code introduces a loop, this loop prevention might be too broad.

@jhenkens

jhenkens commented Apr 9, 2026

Copy link
Copy Markdown
Author

Nice! Looks like you have a few nice additions.

I'm not sure exactly what the bug you are trying to describe is - I'm unsure of the before-call, during-call, after-call, expected-after-call states.

I'm guessing:
Before call - Headphone Mode
During call - ???
After call - ???
Expected after call - Reestablish headphone mode

I guess to add - I don't have AirPods, so I cannot test this and try to iterate on a fix. I'm not sure what status changes are received (and can be queried) when the headphones drop from your mac for a call, nor what the default OSX behavior would be. Seems were both writing this with Claude though, so you could probably work towards a fix as good as I could?

@travisp

travisp commented Apr 10, 2026

Copy link
Copy Markdown

Nice! Looks like you have a few nice additions.

I'm not sure exactly what the bug you are trying to describe is - I'm unsure of the before-call, during-call, after-call, expected-after-call states.

I'm guessing: Before call - Headphone Mode During call - ??? After call - ??? Expected after call - Reestablish headphone mode

I guess to add - I don't have AirPods, so I cannot test this and try to iterate on a fix. I'm not sure what status changes are received (and can be queried) when the headphones drop from your mac for a call, nor what the default OSX behavior would be. Seems were both writing this with Claude though, so you could probably work towards a fix as good as I could?

I didn't fully diagnose the issue, as I just reverted that one particular commit of yours (I didn't care too much about the priority override functionality), but I could spend some more time on it.

Airpods will be connected to multiple devices at once (e.g. iPhone and Macbook) and simply switch which device the audio is being used for. So, when I answered my iPhone call and the audio on my airpods switched to my iPhone, the airpods were still connected to my MacBook

Screenshot 2026-04-10 at 9 36 06 AM

("moved" but still connected)

Then, when I finished the call, and resumed playing music on my Macbook, the audio on the airpods switched back to the macbook. For many people this is exactly what they want and one of the things people like about the airpods, at least when it works correctly. However, I use a DJI Mic Mini microphone for dictating to my macbook as I find the quality of the transcription to be higher. MacOS stopped using my Mic Mini as the microphone (which had been selected previously) and switched to the airpods, as you can see in the screenshot in my previous comment.

However, because there was no hardware change, the anti-loop coded added in your PR doesn't trigger resetting the priority back to the DJI Mic Mini, which is what I wanted. It assumed that the device changed because of AudioPriorityBar, not MacOS.

The problem, I think, is that there are more reasons that the default device could change than that AudioPriorityBar changed it. In my mind, this was one of the main purposes of AudioPriorityBar: preventing MacOS from changing my selected audio devices, not setting the preferred audio devices when what was plugged in changed.

I have some ideas for a fix, but I'm not entirely sure why the anti-loop code was added in the first place. Was it solving an issue introduced by the "Add priority override for each device" code? Or was it just in that commit but solving a more general loop problem? It seems to me that if the default device was changed by AudioPriorityBar, the anti-loop code isn't needed because there's no issue running applyHighestPriorityInput/Output again, especially because you added a guard to applyInput/OutputDevice ("Skipping: already current device"). It shouldn't result in an infinite loop.

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.

3 participants