Skip a USB headset dongle while no headset is linked to it - #32
Open
jerrison wants to merge 1 commit into
Open
Conversation
A wireless headset dongle publishes its CoreAudio devices whenever it is
plugged in, whether or not the headset is powered on and linked. Because
auto-switching ranks by presence, the dongle wins and audio goes into a dead
link: it shows as Active while nothing comes out. Recovering means picking
another device by hand every time the headset is off, which is the problem
priorities are supposed to solve.
CoreAudio cannot tell the two states apart. Measured on a Jabra Link 390 with
the headset off and then on, the driver never publishes
kAudioDevicePropertyJackIsConnected, and DeviceIsAlive, channel counts,
available sample rates, stream formats and CanBeDefaultDevice are identical.
The dongle does report it over HID. WirelessLinkMonitor reads that bit for
dongles it knows about and applyHighestPriorityInput/Output skip a device whose
link is down. For the Jabra Link 390 the bit is HID Telephony usage 0x2A
("Line"), report 0x04 byte 1 bit 3, which reads 1 only while the headset is
linked to the dongle.
Any device the monitor does not recognise is always reported as usable, so
behaviour is unchanged for every other piece of hardware. Reading the bit needs
no Input Monitoring permission and works from an unsigned build. A link must
stay down for 3 seconds before the device is skipped, so a momentary drop
cannot pull audio away mid-call.
Rows for a device in this state are greyed and marked "not linked", so a
skipped device does not look like a bug.
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.
The problem
A wireless headset dongle publishes its CoreAudio devices whenever it is plugged in, whether or not the headset is powered on and linked to it. Auto-switching ranks by presence, so the dongle wins and audio goes into a dead link — it shows as Active while nothing comes out. The only recovery is picking another device by hand every time the headset is off, which is the problem priorities are meant to solve.
CoreAudio gives you nothing to work with here. Measured on a Jabra Link 390, headset off and then on:
kAudioDevicePropertyJackIsConnectedDeviceIsAlive1either way48kHz 2ch,hdph/hmiceither wayCanBeDefaultDevice1either wayThe fix
The dongle does report it over HID.
WirelessLinkMonitorreads that bit for dongles it recognises, andapplyHighestPriorityInput/applyHighestPriorityOutputskip a device whose link is down.For the Jabra Link 390 it is HID Telephony usage 0x2A ("Line"), report
0x04byte 1 bit 3, which reads 1 only while the headset is linked to the dongle. Adding another dongle is one entry inWirelessLinkMonitor.knownDongles.That the bit is link state and not a button press was confirmed against the hardware: powering the headset on over Bluetooth left it at
0while the headset's Bluetooth devices appeared, and when the headset later moved its link to the dongle it went to1and the Bluetooth devices were removed 1.7 seconds later.Why this should not affect anyone else
downfor a dongle inknownDongleswhose bit it actually read. Every other device takes exactly the path it takes today.Verified on the hardware
A/B on identical state — dongle plugged in, headset not linked, dongle at priority 1, default output seeded to the dongle before each run:
mainAlso checked: with the headset linked the dongle is selected normally, and
xcodebuild -scheme AudioPriorityBar -configuration Releasesucceeds with no new warnings.UI
A device in this state is greyed with an
antenna.radiowaves.left.and.right.slashicon and anot linkedlabel, so a skipped device does not read as a bug. It follows the existingwifi.slash/nosignstatus-icon pattern.Notes
Services/WirelessLinkMonitor.swift, registered in the Xcode project (the project uses a classic group list, soproject.pbxprojneeded the four usual entries).knownDongleslist starts with one entry.