Skip to content

Replace PulseAudio with PipeWire/WirePlumber audio stack in WSLg - #1418

Open
Hengqian Ling (linghengqian) wants to merge 3 commits into
microsoft:mainfrom
linghengqian:pa-remove
Open

Hengqian Ling (linghengqian) wants to merge 3 commits into
microsoft:mainfrom
linghengqian:pa-remove

Conversation

@linghengqian

Copy link
Copy Markdown

@linghengqian

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

@benhillis

Copy link
Copy Markdown
Member

Triage note (2026-05): Thanks for the substantial work — replacing PulseAudio with PipeWire/WirePlumber is squarely on the roadmap (tracked in #290, with 40+ reactions) and we want to land this. A few things will hold the merge button:

  1. We need to validate audio behavior end-to-end against current RDP audio playback and capture paths. The pipewire-wslg-rdp.patch and pipewire-rdp-module.c carry the equivalent of the existing PulseAudio RDP module — verifying parity (sample rates, latency, capture devices, mute/volume integration with Windows) is the bulk of the review.
  2. cgmanifest.json will need entries for PipeWire / WirePlumber so Component Governance is happy.
  3. An internal buddy build through the full Azure Pipelines flow before merge.

Not asking for changes yet — just setting expectations. If you want to chip away at (1) and (2) preemptively that would help.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm glad Microsoft is willing to take on this work, especially since I don't actually have an Azure account to test the corresponding CI files. Should I close this PR?

@iarna

Rebecca Turner (iarna) commented Jul 18, 2026 •

Copy link
Copy Markdown

especially since I don't actually have an Azure account to test the corresponding CI files

They were suggesting that a microsofty would need to do the full run through, which is why they suggested you could, if you wanted, look at 1 and 2.

They seem to be saying they're gonna do the work to land this one way or the other, so that would imply that no, you should not close it.

(Obviously, as neither a member of this project, nor an MS employee, I'm not speaking for anyone here, just hopefully clarifying things.)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure whether I should resolve the merge conflicts; even if I did, I wouldn't be able to register for an account on https://www.azure.cn/ as an individual to test the CI, as accounts there require corporate registration.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Native modules cannot currently load through pulse.cmd, and several real-time socket and startup issues can prevent or stall audio.

14 open findings
What changed in this PR

Replaces WSLg’s PulseAudio implementation with PipeWire, WirePlumber, and PulseAudio compatibility support, addressing #290.

Changes:

  • Builds and launches the PipeWire audio stack.
  • Adds custom PipeWire RDP sink/source modules and configuration.
  • Updates build metadata and documentation.
File Description
WSLGd/​main.cpp Launches and monitors the new audio stack.
samples/​container/​Containers.md Updates container audio guidance.
README.md Documents PipeWire architecture and verification.
Microsoft.WSLg.nuspec Updates package description.
Dockerfile Builds and packages PipeWire and WirePlumber.
CONTRIBUTING.md Updates build prerequisites and arguments.
config/​pipewire.conf Configures the PipeWire daemon.
config/​pipewire-wslg-rdp.patch Adds RDP modules to PipeWire’s build.
config/​pipewire-rdp-module.c Implements RDP audio bridging.
config/​pipewire-pulse.conf Configures PulseAudio compatibility.
config/​BUILD.md Updates manual build instructions.
cgmanifest.json Registers new dependencies.
build-and-export.sh Supplies new dependency revisions.
.github/​ISSUE_TEMPLATE/​bug_report.yml Updates requested audio logs.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread WSLGd/main.cpp Resolved
Comment thread WSLGd/main.cpp Resolved
Comment thread config/pipewire-pulse.conf Resolved
Comment thread config/pipewire-rdp-module.c Resolved
Comment thread config/pipewire-rdp-module.c Resolved
Comment thread config/pipewire-rdp-module.c Resolved
Comment thread config/pipewire-rdp-module.c Resolved
Comment thread config/pipewire-rdp-module.c Resolved
Comment thread .github/ISSUE_TEMPLATE/bug_report.yml Resolved
Comment thread README.md Resolved

Copilot AI left a comment

Copy link
Copy Markdown

Comment thread config/pipewire-rdp-module.c Resolved
Comment thread config/pipewire-rdp-module.c Resolved
Comment thread config/pipewire-rdp-module.c Resolved
Comment thread config/pipewire-rdp-module.c Resolved
linghengqian

This comment was marked as outdated.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread config/pipewire-rdp-module.c Resolved
Comment thread config/pipewire-rdp-module.c Resolved
Comment thread config/pipewire-rdp-module.c Resolved
Comment thread Dockerfile Resolved
Comment thread config/pipewire-rdp-module.c Resolved
Comment thread config/pipewire.conf Resolved
Comment thread README.md Resolved

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread config/pipewire-rdp-module.c Resolved
Comment thread config/pipewire-rdp-module.c Resolved
Comment thread config/pipewire-rdp-module.c Resolved
Comment thread config/pipewire-rdp-module.c Resolved
Copilot AI balanced review requested due to automatic review settings October 9, 2026 13:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The RDP module has incorrect latency reporting, unsafe core reconnection lifecycle handling, and possible microphone frame corruption after overflow.

3 open findings
4 resolved since last review

🧠 Review effort: Balanced

Comment thread config/pipewire-rdp-module.c Resolved
Comment thread config/pipewire-rdp-module.c Resolved
Comment thread config/pipewire-rdp-module.c Resolved

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Latency publication, configurable RDP socket paths, and native socket access have unresolved functional regressions.

0 open findings

3 resolved since last review
Previously missed (4)

In code that hasn't changed since last review

Medium severity Preserve PULSE_AUDIO_RDP_SINK endpoint override

config/​pipewire-pulse.conf:36

This hardcoded path bypasses the existing PULSE_AUDIO_RDP_SINK override set by WSLGd and configurable through .wslgconfig; the former PulseAudio RDP module read that environment variable. Private/test deployments that redirect Weston's sink socket will now keep connecting to /mnt/wslg/PulseAudioRDPSink. Preserve the environment fallback in the new module and avoid overriding it here.

Medium severity Preserve PULSE_AUDIO_RDP_SOURCE endpoint override

config/​pipewire-pulse.conf:47

This likewise bypasses the existing PULSE_AUDIO_RDP_SOURCE override set by WSLGd and configurable through .wslgconfig; the former source module consumed that variable. Any deployment using a redirected microphone socket will silently connect to the default path instead. Preserve the environment fallback in the module rather than fixing the endpoint in this config.

Medium severity Defer stream parameter updates to the main loop

config/​pipewire-rdp-module.c:616

pw_stream_update_params() is called from the RT/data-loop process callback, but PipeWire 1.4.10 enforces that this API runs on the stream's main loop (ensure_loop(impl->main_loop, return -EIO)). The update therefore fails, and published_seq is still advanced, so the measured RDP transport latency is never published or retried. Defer the parameter update to the main-loop timer and only mark the sequence published after a successful call.

Medium severity Configure native PipeWire socket access permissions

config/​pipewire.conf:27

The native pipewire-0 socket is created without explicit permissions, so protocol-native leaves its mode to the process umask; unlike the Pulse socket (which PipeWire chmods to 0777), it is not connectable by user-distro accounts whose UID differs from the fixed wslg UID 1000. That prevents the native PipeWire/JACK/Flatpak use case motivating this migration for such accounts. Configure socket ownership/mode and the matching access policy explicitly for projected user-distro access.

🧠 Review effort: Balanced

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a closer look

  • I’ve reviewed it and don’t see any issues; I tested it locally using that Dockerfile in rootless Docker.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

audio-redirection enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

use Pipewire instead of PA

5 participants