Skip to content

output/osx: move the default device query into a function - #2556

Open
valentynkit wants to merge 2 commits into
MusicPlayerDaemon:masterfrom
valentynkit:osx-default-device-on-demand
Open

output/osx: move the default device query into a function#2556
valentynkit wants to merge 2 commits into
MusicPlayerDaemon:masterfrom
valentynkit:osx-default-device-on-demand

Conversation

@valentynkit

Copy link
Copy Markdown

Disconnect a Bluetooth headset during playback and the output never opens again, even once the headset is back and is the default output device:

mixer: Failed to read mixer for "CoreAudio": The operation couldn't be completed. (OSStatus error 560947818.)
exception: Failed to open "CoreAudio" (osx); The operation couldn't be completed. (OSStatus error 560947818.)
player: problems opening audio device while playing "..."

That is kAudioHardwareBadObjectError. Create() resolves dev_id once, and osx_output_set_device() only refreshes it for kAudioUnitSubType_HALOutput. With kAudioUnitSubType_DefaultOutput or kAudioUnitSubType_SystemOutput it is never updated, so once that device is gone the id stays dead and GetVolume(), SetVolume() and Open() all fail until a restart.

Re-resolving in Enable() would not help either. InternalEnable() returns early once really_enabled is set, and the open failure path never clears it, so Enable() runs once per process.

Since both subtypes track the default device anyway, query it on demand instead of caching it. The hog_device calls keep using the stored id so Disable() still releases the device Enable() hogged.

#932 hit the same error in 2020. Its case (*), a device pinned by name disappearing, needs different handling and is not addressed here.

First commit is preparation, no functional change. Tested on macOS arm64 with mixer_type "hardware" and no device set. Before, the output stays unopenable until restart. After, playback recovers on the next open and the log stays clean. Full build, no new warnings.

Both commits apply to v0.24.x if you want a separate PR for that branch.

Preparation for querying the default device more than once; no
functional change.
dev_id is resolved once in Create() and never updated for the
kAudioUnitSubType_DefaultOutput and kAudioUnitSubType_SystemOutput
subtypes, because osx_output_set_device() returns early unless the
subtype is kAudioUnitSubType_HALOutput.  Once that device goes away,
the stored id stays invalid for the rest of the process and
reconnecting does not help, so GetVolume(), SetVolume() and Open()
all keep failing with kAudioHardwareBadObjectError until MPD is
restarted.  Enable() runs only once, so re-resolving there would not
help either.

This is easy to hit with Bluetooth headphones: disconnect them during
playback and it cannot be resumed afterwards.  Both subtypes follow
the current default device anyway, so query it on demand instead of
caching it.  The hog_device calls keep using the stored id so
Disable() releases the same device Enable() hogged.
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.

1 participant