ValveSoftware / steam-runtime

A runtime environment for Steam applications
Other
1.18k stars 86 forks source link

/etc/asound.conf in the runtime does not provide default PulseAudio module device #623

Closed nm004 closed 11 months ago

nm004 commented 1 year ago

Your system information

Please describe your issue in as much detail as possible:

/etc/asound.conf in the container currently contains the following content, which does not work as expected: cannot get PulseAudio module as the default ALSA device, which ends in the game having no sound.

pcm.!default pulse
ctl.!default pulse

Writing this to ~/.asoundrc did not work either.

The game has sound by writing the following to ~/.asoundrc that is the semantically same as the above.

pcm.!default {
    type pulse
}
ctl.!default {
    type pulse
}

I think we need to fix this code to produce the /etc/asound.conf with the correct syntax.

Steps for reproducing this issue:

  1. Run games (Counter Strike 2 or Dota 2) without the ~/.asoundrc
  2. No Audio

Expected result

  1. Run games without the ~/.asoundrc
  2. Game has audio

Related issues

nm004 commented 1 year ago

I could confirm that this patch fixed the issue.

--- pressure-vessel/runtime.c~  2023-09-29 02:32:13.000000000 +0900
+++ pressure-vessel/runtime.c   2023-09-29 03:49:52.226273507 +0900
@@ -7833,8 +7833,8 @@
       /* Make the PulseAudio driver the default.
        * We do this unconditionally when we are under Flatpak for parity
        * with the freedesktop.org Platform. */
-      const gchar *alsa_config = "pcm.!default pulse\n"
-                                 "ctl.!default pulse\n";
+      const gchar *alsa_config = "pcm.!default { type pulse }\n"
+                                 "ctl.!default { type pulse }\n";

       if (bwrap != NULL)
         {
TTimo commented 1 year ago

This will be addressed a different way through SDL3 updates in CS2 and Dota2.

nm004 commented 1 year ago

Thank you for your reply. I understand the CS2 and Dota2 issues will be addressed in the SDL3 updates, however should we stay /etc/asound.conf as it is now? I believe this issue may affect other games that do not use SDL3.

nm004 commented 1 year ago

@smcv The CS2 and Dota2's sound issues are fixed for now (btw, congrats and gj for all developers and contributors). However, this issue still can be observed. Below is the diff of the outputs of aplay -L, one is from the current unpatched runtime, and the other is the patched runtime.

--- unpatched   2023-09-29 09:59:53.965990593 +0900
+++ patched 2023-09-29 10:07:31.445481581 +0900
@@ -14,6 +14,7 @@
     Plugin for channel upmix (4,6,8)
 vdownmix
     Plugin for channel downmix (stereo) with a simple spacialization
+default
 hw:CARD=HDMI,DEV=3
     HDA ATI HDMI, HDMI 0
     Direct hardware device without any conversions

The patched runtime has the default device, but the unpatched runtime does not.

To be precise, I invoked SteamLinuxRuntime_sniper/run -- /run/host/usr/bin/aplay -L (I think it's a bit hacky), though, I suppose different OSs (not Fedora) would give the same result.

Finally, excuse me for bothering you all.

smcv commented 1 year ago

If this is correct and portable to all OSs, then I think we probably do want this change. @TTimo or @kisak-valve, please could you reopen this for now?

However, the asound.conf that is currently written out worked on the OSs I tested it on (most likely Debian, Ubuntu and/or Arch) and I'm concerned that making it work on @nm004's Fedora 38 could have the side-effect of making it regress elsewhere, so this will need more testing.

smcv commented 1 year ago

The only reason why this was useful for CS2 and Dota 2 was that they had their own copy of SDL, which had accidentally been compiled without PulseAudio audio output support. This has now been fixed in the affected games.

The wrong SDL build meant that they could only output audio via libasound (alsa-lib) or Pipewire, with libasound as a higher priority, and Pipewire only as an opt-in (because of libsdl-org/SDL#7541: there's currently no good way to detect whether Pipewire is in the Pulseaudio-like audio-server role, or whether it's just there for its video capabilities).

Now that CS2 and Dota have been fixed, this is a much lower severity and priority: it's only beneficial for the minority of games that output directly via libasound, instead of via some middleware library like SDL or OpenAL that can auto-detect Pulseaudio on its own. The example that I know about is Shadowrun Returns (#371).

smcv commented 1 year ago

libasound configuration syntax is not amazingly well-documented, but as far as I can tell, the asound.conf that we currently install:

pcm.!default pulse
ctl.!default pulse

has the semantics of: whatever the default audio and control device currently is, overwrite it (that's what the ! does) with an alias pointing to a device named pulse.

The sniper container runtime defines the device named pulse in its /etc/alsa/conf.d/50-pulseaudio.conf, so I'm surprised that doesn't work... but if that device isn't getting created, for whatever reason, then it won't work.

For the configuration that @nm004 proposes:

pcm.!default {
    type pulse
}
ctl.!default {
    type pulse
}

the semantics are a bit different. Instead of making default an alias for pulse, I think the proposed configuration overwrites default with a completely new device, with its type set to pulse (which will make libasound load libasound_module_pcm_pulse.so and libasound_module_ctl_pulse.so as the implementation for this device).

The proposed configuration matches what appears in /etc/alsa/conf.d/99-pulseaudio-default.conf.example in both the soldier and sniper runtimes, which seems like evidence that this is something that ought to work. I don't remember whether there's any particular reason why we used the other way before.

nm004 commented 1 year ago

@smcv Thank you for your reply and giving me correct information.

libasound configuration syntax is not amazingly well-documented, but as far as I can tell, the asound.conf that we currently install:

pcm.!default pulse
ctl.!default pulse

has the semantics of: whatever the default audio and control device currently is, overwrite it (that's what the ! does) with an alias pointing to a device named pulse.

In that sense, below could be the correct configuration if I am not mistaken.

pcm.!default {
    @func refer
    name pcm.pulse
}
ctl.!default {
    @func refer
    name ctl.pulse
}

The @func refer copies the specified configuration node name (documentation). About runtime functions in configuration files is documented here.

That configuration (with ~/.asoundrc) gives me this aplay -L result that is run in the sniper container (I omitted unnecessary part):

upmix
    Plugin for channel upmix (4,6,8)
vdownmix
    Plugin for channel downmix (stereo) with a simple spacialization
default
    PulseAudio Sound Server
hw:CARD=HDMI,DEV=3
    HDA ATI HDMI, HDMI 0
    Direct hardware device without any conversions
smcv commented 1 year ago

The @func refer copies the specified configuration node name

I think if we change this at all, we want to use what @nm004 initially suggested (which is functionally equivalent to /etc/alsa/conf.d/99-pulseaudio-default.conf.example) rather than some more complicated thing.

I haven't been able to reproduce the problem described here, though, and neither has a colleague. I downloaded the alsa-utils from Debian 11 (which sniper is based on), extracted its aplay binary as ~/tmp/sniper_aplay, and tried:

$ ~/SteamLibrary/steamapps/common/SteamLinuxRuntime_sniper/_v2-entry-point -- xterm
(in the resulting xterm)
$ ~/tmp/sniper_aplay -L
$ ~/tmp/sniper_aplay ~/tmp/demo.wav
$ ~/tmp/sniper_aplay -D default demo.wav
$ ~/tmp/sniper_aplay -D pulse demo.wav
$ ~/tmp/sniper_aplay demo.wav

... and the result was that default is not listed in -L, but playback works successfully via either default, pulse or an unspecified device.

smcv commented 1 year ago

SDL's alsa audio backend seems to be a bit inconsistent about whether it will use pluggable backends or not: when asked to list devices, it only lists real hardware-backed devices, but when not told to use a specific device, it will output to the default pulseaudio device.

CS2/Dota 2 were only using the alsa backend as a result of a bug, though (specifically a misbuilt SDL binary), so I don't think audio output for CS2, Dota 2 or other SDL games is really of interest here: if aplay works, then I think that's success.

I think we should still try what @nm004 suggested, but not as part of the same hotfix as fixing #624.

nm004 commented 12 months ago

... and the result was that default is not listed in -L, but playback works successfully via either default, pulse or an unspecified device.

I tested the same case too, and could see the same result as you do. I don't have any idea why pcm.!default { type pulse } config worked for SDL3's audio issue, but OTOH, pcm.!default pulse did not.

smcv commented 11 months ago

Today's client_beta branches of soldier and sniper (versioned 0.20231016.x) set up pcm.!default { type pulse }.

I don't know why that was advantageous for SDL3 either, but moving closer to what's in /etc/alsa/conf.d/99-pulseaudio-default.conf.example seems like a good thing in general if it doesn't trigger any regressions.

smcv commented 11 months ago

Since the original reproducer for this was some misconfigured versions of CS2 and Dota 2 that are no longer available, and we don't know a way to reproduce the bug with a game that works correctly, I think we can close this now.