feat: wire MS-RDPEAI capture into Windows client and ActiveX - #1642
Conversation
There was a problem hiding this comment.
Pull request overview
Adds native audio playback hardening and end-to-end MS-RDPEAI microphone capture, including protocol, client, configuration, and ActiveX integration.
Changes:
- Stabilizes RDPSND negotiation and adds volume/Wave handling.
- Introduces the
ironrdp-rdpeaiprotocol crate and CPAL capture backend. - Wires audio capture through connector, client configuration, and ActiveX settings.
Reviewed changes
Copilot reviewed 32 out of 33 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
ffi/src/connector/config.rs |
Defaults capture off. |
crates/ironrdp/examples/screenshot.rs |
Updates connector configuration. |
crates/ironrdp-web/src/session.rs |
Defaults web capture off. |
crates/ironrdp-testsuite-extra/tests/e2e.rs |
Updates test configuration. |
crates/ironrdp-testsuite-extra/tests/client_config.rs |
Tests audio-mode mapping. |
crates/ironrdp-testsuite-core/tests/session/connection_activation.rs |
Updates session fixture. |
crates/ironrdp-testsuite-core/tests/rdpsnd/server.rs |
Updates format-matching tests. |
crates/ironrdp-testsuite-core/tests/rdpsnd/client.rs |
Expands playback negotiation tests. |
crates/ironrdp-testsuite-core/tests/connector/autodetect.rs |
Updates connector fixture. |
crates/ironrdp-rdpsnd/src/server.rs |
Reuses shared format matching. |
crates/ironrdp-rdpsnd/src/pdu/mod.rs |
Adds negotiation matching API. |
crates/ironrdp-rdpsnd/src/client.rs |
Stabilizes formats and Wave handling. |
crates/ironrdp-rdpsnd-native/src/lib.rs |
Exports capture backend. |
crates/ironrdp-rdpsnd-native/src/cpal.rs |
Adds formats and volume scaling. |
crates/ironrdp-rdpsnd-native/src/capture.rs |
Implements CPAL microphone capture. |
crates/ironrdp-rdpsnd-native/examples/cpal.rs |
Updates playback example. |
crates/ironrdp-rdpsnd-native/Cargo.toml |
Adds RDPEAI dependency. |
crates/ironrdp-rdpeai/src/pdu.rs |
Implements RDPEAI PDUs. |
crates/ironrdp-rdpeai/src/lib.rs |
Defines the new crate API. |
crates/ironrdp-rdpeai/src/client.rs |
Implements the capture state machine. |
crates/ironrdp-rdpeai/README.md |
Documents RDPEAI support. |
crates/ironrdp-rdpeai/Cargo.toml |
Defines the new crate. |
crates/ironrdp-connector/src/lib.rs |
Adds capture configuration. |
crates/ironrdp-connector/src/connection.rs |
Sets INFO_AUDIOCAPTURE. |
crates/ironrdp-client/src/rdp.rs |
Wires the capture DVC. |
crates/ironrdp-client/src/config.rs |
Adds capture builder settings. |
crates/ironrdp-client/Cargo.toml |
Extends the sound feature. |
crates/ironrdp-cfg/src/lib.rs |
Adds audiocapturemode. |
crates/ironrdp-activex/src/control.rs |
Maps ActiveX capture settings. |
crates/ironrdp-activex/README.md |
Documents audio behavior. |
Cargo.lock |
Locks the new crate. |
ARCHITECTURE.md |
Registers the RDPEAI crate. |
.agents/skills/commit-scope/SKILL.md |
Adds the RDPEAI commit scope. |
91cf87d to
6ab31f3
Compare
|
Addressed review feedback and split the XXL change into a stack:
Copilot findings (sink clear on restart, open handshake, packet bounds, FormatChange ack, dead fields, Formats allocation) are fixed on the tip. Please review #1645 first, then this PR once CI settles. Note LLM-assisted content (no human feedback). |
6ab31f3 to
d21adea
Compare
d21adea to
610dadd
Compare
610dadd to
c8f627f
Compare
c8f627f to
f15bc2c
Compare
f15bc2c to
3e5cc6c
Compare
7b92f5c to
8ba7f8e
Compare
3e5cc6c to
a97d40b
Compare
da1f0cc to
d44407b
Compare
f58b684 to
1f5fa15
Compare
d9f86d7 to
68728a8
Compare
971686e to
38896b4
Compare
Introduce the MS-RDPEAI client PDU and DVC state machine, wire CPAL microphone capture through ironrdp-client, advertise INFO_AUDIOCAPTURE, and map ActiveX AudioCaptureRedirectionMode into the connect path.
Address PR review findings: keep the capture sink across stream restarts, wait for CPAL startup before OpenReply, bound FramesPerPacket and packet sizes, and only confirm FormatChange after a successful set_format. Mark ironrdp-rdpeai unpublished with crate tests disabled and move unit coverage into ironrdp-testsuite-core. Drop the unrelated commit-scope skill edit from this branch.
Open uses the Open capture WAVEFORMATEX; FormatChange only updates encoding and must not restart CPAL or resize capture packets.
Reject Open/FormatChange when encode differs from the Open capture WAVEFORMATEX on the PCM-only backend, and require 16-bit capture to match the MS-RDPEAI Data PDU size contract. Put ironrdp-rdpeai behind a capture feature so playback-only consumers do not link AUDIO_INPUT.
Always confirm FormatChange for valid indices so servers do not hang. Restart capture when encode PCM params change, shorten Open stream-start wait, accept WAVE_FORMAT_EXTENSIBLE PCM, and reduce RT path locking. Document the optional capture feature packaging and add helper tests.
Keep ironrdp-testsuite-core free of extra-tier rdpsnd-native so architecture tier boundaries stay intact after MS-RDPEAI capture helpers land.
Re-add ironrdp-rdpeai edges for ironrdp-client and ironrdp-rdpsnd-native after rebasing capture onto master.
68728a8 to
02b204e
Compare
|
Marc-André Moreau (@mamoreau-devolutions) Much thanks for this! Finally I was able to record something using my microphone (but I had to make this change beforehand): diff --git a/crates/ironrdp-client/src/config.rs b/crates/ironrdp-client/src/config.rs
index 699e2932..a3fe2f34 100644
--- a/crates/ironrdp-client/src/config.rs
+++ b/crates/ironrdp-client/src/config.rs
@@ -291,7 +291,7 @@ impl Default for ChannelConfig {
#[cfg(feature = "sound")]
sound: true,
#[cfg(feature = "sound")]
- audio_capture: false,
+ audio_capture: true,
#[cfg(feature = "clipboard")]
clipboard: ClipboardType::Enable,
#[cfg(feature = "rdpdr")]Then in Windows/settings/audio I clicked to record a sample, then connected with But at the same time no idea why playback is not working (not even sure if it was before). I am using Arch with pulseaudio. It should work? |
I'm glad that it at least partially works for you, and we should revisit current command-line options to avoid the need to override the configuration like that. The pull request you're commenting on may contain cross-platform code but it's been only tested by wiring the platform-specific code on Windows. I haven't checked the status of platform-specific audio code on Linux, but my guess it may need a bit of love, but probably nothing an AI agent can't figure out. You're welcome to give it a try |
I'd be happy to take care of this one, so if possible, just leave it to me - it should be a pretty easy patch... So, just to summarize where I'm at with this so far, here’s what I know:
If I figure something out, I’ll probably open a new issue/PR with the changes to not mess with this PR discussion. I hope you're ok with mention you Marc-André Moreau (@mamoreau-devolutions) ? |
Yes just tag me on the PRs, I'll try to fast track them |
|
for the reference:
There is still one issue left. Microphone is available on the very first capture, not subsequent ones (probably device is closed or something like this) but I'll try to address this in separate PR... (Update: #1797) |
Add the client MS-RDPEAI capture path on top of hardened RDPSND playback: connector CFG + static channel wiring, CPAL PCM capture backend, ironrdp-client --audio-capture, and ActiveX AudioCaptureRedirectionMode.
PCM capture only accepts encode formats that match the Open capture stream, rejects non-16-bit capture (Data PDU size contract), and gates the capture backend behind ironrdp-rdpsnd-native/capture.
Depends on #1648 (playback).