Skip to content

Commit d5bc5d5

Browse files
committed
feat(rdp): add best_experience setting and improve audio redirection handling
1 parent 07b656d commit d5bc5d5

File tree

5 files changed

+151
-119
lines changed

5 files changed

+151
-119
lines changed

crates/audio/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,8 @@ impl AudioStats {
344344
/// so we will return 180.0 ms as a default value that is a bit less than initial expected RDP call rate.
345345
/// After that, it will be the actual mean interval.
346346
/// If sound is paused this value will grow a lot for the last calls, but it's acceptable
347-
/// in our use case, where we can use it to adjust "drift" on playback.
347+
/// in our use case, where we only use it to adjust "drift" on playback when latency is too high
348+
/// compared with this value.
348349
pub fn mean_calls_interval(&self) -> f32 {
349350
const MIN_EXPECTED_INTERVAL: f32 = 180.0;
350351
if self.time_between_play_calls.is_empty() {

crates/js/src/js_modules/rdp.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ struct RdpSettings {
5858
pub printer_redirection: Option<bool>,
5959
pub drives_to_redirect: Option<Vec<String>>,
6060
pub sound_latency_threshold: Option<u16>,
61+
pub best_experience: Option<bool>,
6162
}
6263

6364
impl Default for RdpSettings {
@@ -78,6 +79,7 @@ impl Default for RdpSettings {
7879
printer_redirection: None,
7980
drives_to_redirect: None,
8081
sound_latency_threshold: None,
82+
best_experience: None,
8183
}
8284
}
8385
}
@@ -129,6 +131,7 @@ fn start_rdp_fn(_: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<Js
129131
.drives_to_redirect
130132
.unwrap_or_else(|| vec!["all".to_string()]),
131133
sound_latency_threshold: rdp_settings.sound_latency_threshold,
134+
best_experience: rdp_settings.best_experience.unwrap_or(true),
132135
};
133136

134137
send_message(GuiMessage::ConnectRdp(settings));

crates/rdp/rdp/src/connection/builder.rs

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -63,21 +63,6 @@ impl Rdp {
6363
let user = CString::new(mut_self.config.settings.user.clone())?;
6464
let pass = CString::new(mut_self.config.settings.password.clone())?;
6565
let domain = CString::new(mut_self.config.settings.domain.clone())?;
66-
let drives_to_redirect = CString::new(
67-
mut_self
68-
.config
69-
.settings
70-
.drives_to_redirect
71-
.iter()
72-
.map(|s| match s.as_str() {
73-
"all" => "*",
74-
"DynamicDrives" => "DynamicDrives",
75-
other => other,
76-
})
77-
.collect::<Vec<&str>>()
78-
.join(";"),
79-
)
80-
.unwrap();
8166

8267
freerdp_settings_set_string(
8368
settings_ptr,
@@ -104,40 +89,6 @@ impl Rdp {
10489
FreeRDP_Settings_Keys_UInt32_FreeRDP_ServerPort,
10590
mut_self.config.settings.port,
10691
);
107-
freerdp_settings_set_bool(
108-
settings_ptr,
109-
FreeRDP_Settings_Keys_Bool_FreeRDP_IgnoreCertificate,
110-
!mut_self.config.settings.verify_cert as BOOL,
111-
);
112-
113-
// NLA setting
114-
freerdp_settings_set_bool(
115-
settings_ptr,
116-
FreeRDP_Settings_Keys_Bool_FreeRDP_NlaSecurity,
117-
mut_self.config.settings.use_nla as BOOL,
118-
);
119-
120-
let all_drives = mut_self
121-
.config
122-
.settings
123-
.drives_to_redirect
124-
.iter()
125-
.any(|s| s.as_str() == "all");
126-
let len_drives = mut_self.config.settings.drives_to_redirect.len();
127-
freerdp_settings_set_bool(
128-
settings_ptr,
129-
FreeRDP_Settings_Keys_Bool_FreeRDP_RedirectDrives,
130-
(len_drives != 0) as BOOL,
131-
);
132-
if !all_drives {
133-
// Remove "all" and, if any rameaining, use FreeRDP_RedirectDrives
134-
freerdp_settings_set_string(
135-
settings_ptr,
136-
FreeRDP_Settings_Keys_String_FreeRDP_DrivesToRedirect,
137-
drives_to_redirect.as_ptr(),
138-
);
139-
}
140-
14192
Ok(())
14293
}
14394
}

crates/rdp/rdp/src/connection/mod.rs

Lines changed: 143 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -93,26 +93,23 @@ impl Rdp {
9393
fn set_rdp_settings(&self) {
9494
#[cfg(debug_assertions)]
9595
self.debug_assert_instance();
96-
97-
if let Some(settings) = self.settings() {
98-
unsafe {
96+
unsafe {
97+
if let Some(settings) = self.settings() {
9998
// Set Falses first
100-
for i in [
99+
[
101100
FreeRDP_Settings_Keys_Bool_FreeRDP_FastPathInput,
102101
FreeRDP_Settings_Keys_Bool_FreeRDP_FastPathOutput,
103102
FreeRDP_Settings_Keys_Bool_FreeRDP_BitmapCompressionDisabled,
104103
FreeRDP_Settings_Keys_Bool_FreeRDP_RemoteConsoleAudio, // So audio is not played on server
105104
]
106105
.iter()
107-
{
106+
.for_each(|i| {
108107
freerdp_settings_set_bool(settings, *i, false.into());
109-
}
108+
});
110109
// Then Trues
111-
for i in [
110+
[
112111
FreeRDP_Settings_Keys_Bool_FreeRDP_GfxThinClient,
113112
FreeRDP_Settings_Keys_Bool_FreeRDP_GfxProgressive,
114-
FreeRDP_Settings_Keys_Bool_FreeRDP_AllowFontSmoothing,
115-
FreeRDP_Settings_Keys_Bool_FreeRDP_AllowDesktopComposition,
116113
FreeRDP_Settings_Keys_Bool_FreeRDP_AllowCacheWaitingList,
117114
FreeRDP_Settings_Keys_Bool_FreeRDP_DesktopResize,
118115
FreeRDP_Settings_Keys_Bool_FreeRDP_DynamicResolutionUpdate,
@@ -128,17 +125,18 @@ impl Rdp {
128125
FreeRDP_Settings_Keys_Bool_FreeRDP_GfxAVC444v2,
129126
FreeRDP_Settings_Keys_Bool_FreeRDP_GfxAVC444,
130127
FreeRDP_Settings_Keys_Bool_FreeRDP_GfxH264,
131-
// FreeRDP_Settings_Keys_Bool_FreeRDP_RemoteFxCodec,
128+
FreeRDP_Settings_Keys_Bool_FreeRDP_GfxProgressiveV2,
129+
//FreeRDP_Settings_Keys_Bool_FreeRDP_RemoteFxCodec,
132130
FreeRDP_Settings_Keys_Bool_FreeRDP_SupportGraphicsPipeline,
133131
]
134132
.iter()
135-
{
133+
.for_each(|i| {
136134
// Ignore the result, try with best effort
137135
freerdp_settings_set_bool(settings, *i, true.into());
138-
}
136+
});
139137

140138
// Set uint32 values
141-
for (i, v) in [
139+
[
142140
(FreeRDP_Settings_Keys_UInt32_FreeRDP_ColorDepth, 32),
143141
(
144142
FreeRDP_Settings_Keys_UInt32_FreeRDP_DesktopWidth,
@@ -155,19 +153,18 @@ impl Rdp {
155153
(FreeRDP_Settings_Keys_UInt32_FreeRDP_FrameAcknowledge, 0),
156154
]
157155
.iter()
158-
{
156+
.for_each(|(i, v)| {
159157
freerdp_settings_set_uint32(settings, *i, *v);
160-
}
161-
}
162-
163-
fn channels(
164-
settings: *mut rdpSettings,
165-
name: &str,
166-
channel: Option<&String>,
167-
add_static: bool,
168-
add_dynamic: bool,
169-
) {
170-
unsafe {
158+
});
159+
160+
// Audio redirection settings
161+
fn channels(
162+
settings: *mut rdpSettings,
163+
name: &str,
164+
channel: Option<&String>,
165+
add_static: bool,
166+
add_dynamic: bool,
167+
) {
171168
// Note: We can use the internal freerdp rdpsnd channel subsystems
172169

173170
let channel = if let Some(channel) = channel {
@@ -186,67 +183,144 @@ impl Rdp {
186183
let cchannel = std::ffi::CString::new(channel).unwrap();
187184
let channels: [*const std::os::raw::c_char; 2] =
188185
[cname.as_ptr(), cchannel.as_ptr()];
189-
if add_static {
190-
freerdp_client_add_static_channel(
191-
settings,
192-
channels.len(),
193-
channels.as_ptr(),
194-
);
195-
}
196-
if add_dynamic {
197-
freerdp_client_add_dynamic_channel(
198-
settings,
199-
channels.len(),
200-
channels.as_ptr(),
201-
);
186+
unsafe {
187+
if add_static {
188+
freerdp_client_add_static_channel(
189+
settings,
190+
channels.len(),
191+
channels.as_ptr(),
192+
);
193+
}
194+
if add_dynamic {
195+
freerdp_client_add_dynamic_channel(
196+
settings,
197+
channels.len(),
198+
channels.as_ptr(),
199+
);
200+
}
202201
}
203202
}
204-
}
205203

206-
// Sound redirection
207-
unsafe {
208-
// true-false = play on client
209-
// false-true = play on server
210-
// false-false = no audio
204+
if self.config.settings.audio_redirection {
205+
// Sound redirection
206+
// true-false = play on client
207+
// false-true = play on server
208+
// false-false = no audio
209+
freerdp_settings_set_bool(
210+
settings,
211+
FreeRDP_Settings_Keys_Bool_FreeRDP_AudioPlayback,
212+
true.into(),
213+
);
214+
freerdp_settings_set_bool(
215+
settings,
216+
FreeRDP_Settings_Keys_Bool_FreeRDP_RemoteConsoleAudio,
217+
false.into(), // Always false, we want audio on client
218+
);
219+
let channel = format!("sys:{}", crate::addins::RDPSND_SUBSYSTEM_CUSTOM);
220+
channels(settings, "rdpsnd", Some(&channel), true, true);
221+
// Default subsystem right now
222+
// channels(settings, "rdpsnd", None, true, true);
223+
}
224+
// Microphone redirection
225+
if self.config.settings.microphone_redirection {
226+
freerdp_settings_set_bool(
227+
settings,
228+
FreeRDP_Settings_Keys_Bool_FreeRDP_AudioCapture,
229+
true.into(),
230+
);
231+
channels(settings, "audin", None, false, true);
232+
}
233+
234+
// Set config settings for clipboard redirection
211235
freerdp_settings_set_bool(
212236
settings,
213-
FreeRDP_Settings_Keys_Bool_FreeRDP_AudioPlayback,
214-
true.into(),
237+
FreeRDP_Settings_Keys_Bool_FreeRDP_RedirectClipboard,
238+
self.config.settings.clipboard_redirection.into(),
215239
);
240+
241+
if self.config.settings.printer_redirection {
242+
freerdp_settings_set_bool(
243+
settings,
244+
FreeRDP_Settings_Keys_Bool_FreeRDP_RedirectPrinters,
245+
true.into(),
246+
);
247+
}
248+
216249
freerdp_settings_set_bool(
217250
settings,
218-
FreeRDP_Settings_Keys_Bool_FreeRDP_RemoteConsoleAudio,
219-
false.into(),
251+
FreeRDP_Settings_Keys_Bool_FreeRDP_IgnoreCertificate,
252+
(!self.config.settings.verify_cert).into(),
220253
);
221-
let channel = format!("sys:{}", crate::addins::RDPSND_SUBSYSTEM_CUSTOM);
222-
channels(settings, "rdpsnd", Some(&channel), true, true);
223-
// Default subsystem right now
224-
// channels(settings, "rdpsnd", None, true, true);
225-
}
226-
// Microphone redirection
227-
unsafe {
254+
255+
// NLA setting
228256
freerdp_settings_set_bool(
229257
settings,
230-
FreeRDP_Settings_Keys_Bool_FreeRDP_AudioCapture,
231-
true.into(),
258+
FreeRDP_Settings_Keys_Bool_FreeRDP_NlaSecurity,
259+
self.config.settings.use_nla.into(),
232260
);
233-
// TODO: Allow configuration of the audio capture device
234-
channels(settings, "audin", None, false, true);
235-
}
236261

237-
// Set config settings for clipboard redirection
238-
unsafe {
262+
let drives_to_redirect = std::ffi::CString::new(
263+
self.config
264+
.settings
265+
.drives_to_redirect
266+
.iter()
267+
.map(|s| match s.as_str() {
268+
"all" => "*",
269+
"DynamicDrives" => "DynamicDrives",
270+
other => other,
271+
})
272+
.collect::<Vec<&str>>()
273+
.join(";"),
274+
)
275+
.unwrap();
276+
277+
let all_drives = self
278+
.config
279+
.settings
280+
.drives_to_redirect
281+
.iter()
282+
.any(|s| s.as_str() == "all");
283+
let len_drives = self.config.settings.drives_to_redirect.len();
239284
freerdp_settings_set_bool(
240285
settings,
241-
FreeRDP_Settings_Keys_Bool_FreeRDP_RedirectClipboard,
242-
self.config.settings.clipboard_redirection.into(),
286+
FreeRDP_Settings_Keys_Bool_FreeRDP_RedirectDrives,
287+
(len_drives != 0) as BOOL,
243288
);
244-
}
289+
if !all_drives {
290+
// Remove "all" and, if any rameaining, use FreeRDP_RedirectDrives
291+
freerdp_settings_set_string(
292+
settings,
293+
FreeRDP_Settings_Keys_String_FreeRDP_DrivesToRedirect,
294+
drives_to_redirect.as_ptr(),
295+
);
296+
}
245297

246-
// Set perfromance flags from settings
247-
unsafe { freerdp_sys::freerdp_performance_flags_make(settings) };
248-
} else {
249-
log::debug!("Connection not built, cannot optimize settings.");
298+
if self.config.settings.best_experience {
299+
[
300+
FreeRDP_Settings_Keys_Bool_FreeRDP_DisableWallpaper,
301+
FreeRDP_Settings_Keys_Bool_FreeRDP_DisableFullWindowDrag,
302+
FreeRDP_Settings_Keys_Bool_FreeRDP_DisableMenuAnims,
303+
FreeRDP_Settings_Keys_Bool_FreeRDP_DisableThemes,
304+
]
305+
.iter()
306+
.for_each(|key| {
307+
freerdp_settings_set_bool(settings, *key, false.into());
308+
});
309+
[
310+
FreeRDP_Settings_Keys_Bool_FreeRDP_AllowFontSmoothing,
311+
FreeRDP_Settings_Keys_Bool_FreeRDP_AllowDesktopComposition,
312+
]
313+
.iter()
314+
.for_each(|key| {
315+
freerdp_settings_set_bool(settings, *key, true.into());
316+
});
317+
}
318+
319+
// Set perfromance flags from settings
320+
freerdp_sys::freerdp_performance_flags_make(settings);
321+
} else {
322+
log::debug!("Connection not built, cannot optimize settings.");
323+
}
250324
}
251325
}
252326

crates/rdp/rdp/src/settings.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ pub struct RdpSettings {
6464
pub drives_to_redirect: Vec<String>,
6565
#[zeroize(skip)]
6666
pub sound_latency_threshold: Option<u16>,
67+
#[zeroize(skip)]
68+
pub best_experience: bool,
6769
}
6870

6971
impl Default for RdpSettings {
@@ -83,6 +85,7 @@ impl Default for RdpSettings {
8385
printer_redirection: false,
8486
drives_to_redirect: vec!["all".to_string()], // By default, redirect all drives.
8587
sound_latency_threshold: None,
88+
best_experience: true,
8689
}
8790
}
8891
}

0 commit comments

Comments
 (0)