Tonight I finally had time to play some Dishonored 2 for the first time in months - or so I thought. I started the game and was met with silence. I opened pwvucontrol to check my volume levels, but they seemed fine. I switched back to the game and thanks to having a dual-screen setup, I saw a muted audio stream pop up in pwvucontrol. Alt-Tab to change the volume on the stream and the stream disappears, because the game immediately stops playing sound.

After hours of searching the net and reading about sources, sinks, streams and default volumes I finally got fed up with trying to do it properly. Instead I engaged in redneck engineering: In a shell, I ran a command that uses sleep to give myself time to switch to the game and then runs wpctl and some sed to get the Stream ID and plug that into wpctl set-volume:

sleep 2 && wpctl set-volume $(wpctl status | sed -n "s/^\s*\([0-9]\+\)\. VoidEngine\s*$/\1/p") 100%

So what’s going on here?

  • sleep 2: wait for 2 seconds
  • wpctl set-volume <id> 100%: set the volume of the stream with the specified <id> to 100%
  • $( ... ): run the command between the parenthesis and plug its output in this place
  • wpctl status: output a bunch of pipewire/wireplumber status information, but we are really only interested in the audio stream id of the game
  • sed -n "s/^[^0-9]*\([0-9]\+\)\. VoidEngine\s*$/\1/p":
    • -n: normally sed outputs everything you feed it, potentially modified. But we want only the one number from all of that input. So we silence output.
    • s/something/other thing/p: substitute something with other thing and print that.
    • ^\s*\([0-9]\+\)\. VoidEngine\s*$:
      • ^\s*: Beginning of the line (^), followed by a arbitrary number of whitespace characters
      • \([0-9]\+\)\. : One or more digits followed by a colon . (and a space). The digits are wrapped in a match group (). And everything is generously seasoned with escape characters \.
      • VoidEngine: the name of the process whose audio stream we are interested in. In the case of Dishonored 2, it is VoidEngine.
      • \s*$: arbitrary number of spaces and end of the line ($). This is relevant, because VoidEngine appears also in the Clients section of wpctl status, but we’re not interested in the client id of the game, we want the stream id. Luckily the line in the Clients section contains additional information after the process name, so by saying that we’re exclusively looking for whitespace after the process name, we exclude that line.
    • \1: insert match group 1 (which is the digits of the stream id)

Worked like a charm. But instead of playing, I wrote this blog entry. Time to go to bed.