Skip to content

support applications having a volume slider in-sync with the system's provided app audio slider#15731

Open
eean wants to merge 3 commits into
libsdl-org:mainfrom
eean:backendVolume
Open

support applications having a volume slider in-sync with the system's provided app audio slider#15731
eean wants to merge 3 commits into
libsdl-org:mainfrom
eean:backendVolume

Conversation

@eean

@eean eean commented May 31, 2026

Copy link
Copy Markdown
Contributor
  • [ x ] I confirm that I am the author of this code and release it to the SDL project under the Zlib license. This contribution does not contain code from other sources, including code generated by a Large Language Model ("AI").

Description

The PR is three commits - SDL_SetAudioDeviceGain supporting physical devices, a new system audio gain changed event, and a new SDL_GetPhysicalAudioDevice method - that together allow a SDL application to have a volume slider stay in sync with the system audio slider.

This enables an application volume slider to work in the expected way:
Screencast_20260531_131712.webm

This PR has the PipeWire backend implementation. I have a PulseAudio implementation that works, but needs to be cleaned up and tested more. I've tested that it has no regressions for PulseAudio and ALSA backends.

All three commits are needed to support the volume slider, but they each are doing a different part, probably easiest to review this PR by each commit.

37515a9 adds the SetDeviceGain and GetDeviceGain methods for the backends to implement. A complication here is that in the PipeWire backend the sample_frames and buffer_size manipulation was moved from stream_add_buffer_callback to PIPEWIRE_GetDeviceBuf. This is to avoid having a PipeWire callback locking device->lock, this would've caused a ABBA deadlock with the pw_thread_loop_lock in PIPEWIRE_SetDeviceGain/PIPEWIRE_GetDeviceGain.

a5a0667 adds the SDL_EVENT_AUDIO_DEVICE_GAIN_CHANGED event. SDL_AudioDeviceGainChanged_OnMainThread is modeled after, and is a lot of copy & paste from SDL_AudioDeviceDisconnected_OnMainThread. A little functional decomposition could fix this, I could do that here or in a separate refactor-only PR.

6cba251 is strictly speaking optional for the above screencast, but it would require some hacks to get there otherwise. Previously the API mostly just expected the logical device IDs, so there was no reason for a SDL_GetPhysicalAudioDevice that looks up the physical device id for a logical device. But now there's a reason to use physical device id for SDL_SetAudioDeviceGain and SDL_GetAudioDeviceGain.

@slouken slouken added this to the 3.6.0 milestone May 31, 2026
@slouken slouken requested a review from icculus May 31, 2026 21:14
@icculus

icculus commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

I dunno, I don't think I want this API.

It's not clear to me what lower-level APIs will allow for this access in the first place, but even in the PipeWire case, there's two separate volume controls: one for the app (and maybe for each stream in the app?), and the master gain slider (and maybe others, if they decide there should be a global master gain vs device vs app.

@slouken slouken modified the milestones: 3.6.0, 3.x Jun 3, 2026
@eean

eean commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

It's just unnecessarily confusing if the in-app volume slider, controlling the SDL gain, does not affect the application volume slider. PipeWire is keeping and saving the latter between sessions even. So your in-app volume slider could be at 100% while the app is 50% quieter than other applications, that's the main disconnect.

With the actual system device volume it's not confusing since it affects all applications at once. (And luckily there isn't both a master and a device volume, just device volumes.)

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