mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
@@ -644,7 +644,7 @@ impl Client {
|
||||
// `try_start_clipboard` is called by all session when connection is established. (When handling peer info).
|
||||
// This function only create one thread with a loop, the loop is shared by all sessions.
|
||||
// After all sessions are end, the loop exists.
|
||||
//
|
||||
//
|
||||
// If clipboard update is detected, the text will be sent to all sessions by `send_text_clipboard_msg`.
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
fn try_start_clipboard(_ctx: Option<ClientClipboardContext>) {
|
||||
@@ -801,9 +801,17 @@ impl AudioHandler {
|
||||
let mut config: StreamConfig = config.into();
|
||||
config.channels = format0.channels as _;
|
||||
match sample_format {
|
||||
cpal::SampleFormat::F32 => self.build_output_stream::<f32>(&config, &device)?,
|
||||
cpal::SampleFormat::I8 => self.build_output_stream::<i8>(&config, &device)?,
|
||||
cpal::SampleFormat::I16 => self.build_output_stream::<i16>(&config, &device)?,
|
||||
cpal::SampleFormat::I32 => self.build_output_stream::<i32>(&config, &device)?,
|
||||
cpal::SampleFormat::I64 => self.build_output_stream::<i64>(&config, &device)?,
|
||||
cpal::SampleFormat::U8 => self.build_output_stream::<u8>(&config, &device)?,
|
||||
cpal::SampleFormat::U16 => self.build_output_stream::<u16>(&config, &device)?,
|
||||
cpal::SampleFormat::U32 => self.build_output_stream::<u32>(&config, &device)?,
|
||||
cpal::SampleFormat::U64 => self.build_output_stream::<u64>(&config, &device)?,
|
||||
cpal::SampleFormat::F32 => self.build_output_stream::<f32>(&config, &device)?,
|
||||
cpal::SampleFormat::F64 => self.build_output_stream::<f64>(&config, &device)?,
|
||||
f => bail!("unsupported audio format: {:?}", f),
|
||||
}
|
||||
self.sample_rate = (format0.sample_rate, config.sample_rate.0);
|
||||
Ok(())
|
||||
@@ -880,7 +888,7 @@ impl AudioHandler {
|
||||
|
||||
/// Build audio output stream for current device.
|
||||
#[cfg(not(any(target_os = "android", target_os = "linux")))]
|
||||
fn build_output_stream<T: cpal::Sample>(
|
||||
fn build_output_stream<T: cpal::Sample + cpal::SizedSample + cpal::FromSample<f32>>(
|
||||
&mut self,
|
||||
config: &StreamConfig,
|
||||
device: &Device,
|
||||
@@ -891,6 +899,7 @@ impl AudioHandler {
|
||||
};
|
||||
let audio_buffer = self.audio_buffer.0.clone();
|
||||
let ready = self.ready.clone();
|
||||
let timeout = None;
|
||||
let stream = device.build_output_stream(
|
||||
config,
|
||||
move |data: &mut [T], _: &_| {
|
||||
@@ -908,12 +917,13 @@ impl AudioHandler {
|
||||
let mut input = elems.into_iter();
|
||||
for sample in data.iter_mut() {
|
||||
*sample = match input.next() {
|
||||
Some(x) => T::from(&x),
|
||||
_ => T::from(&0.),
|
||||
Some(x) => T::from_sample(x),
|
||||
_ => T::from_sample(0.),
|
||||
};
|
||||
}
|
||||
},
|
||||
err_fn,
|
||||
timeout,
|
||||
)?;
|
||||
stream.play()?;
|
||||
self.audio_stream = Some(Box::new(stream));
|
||||
|
||||
@@ -104,7 +104,7 @@ mod cpal_impl {
|
||||
use super::*;
|
||||
use cpal::{
|
||||
traits::{DeviceTrait, HostTrait, StreamTrait},
|
||||
Device, Host, SupportedStreamConfig,
|
||||
BufferSize, Device, Host, InputCallbackInfo, StreamConfig, SupportedStreamConfig,
|
||||
};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
@@ -214,12 +214,9 @@ mod cpal_impl {
|
||||
}
|
||||
|
||||
fn play(sp: &GenericService) -> ResultType<(Box<dyn StreamTrait>, Arc<Message>)> {
|
||||
use cpal::SampleFormat::*;
|
||||
let (device, config) = get_device()?;
|
||||
let sp = sp.clone();
|
||||
let err_fn = move |err| {
|
||||
// too many UnknownErrno, will improve later
|
||||
log::trace!("an error occurred on stream: {}", err);
|
||||
};
|
||||
// Sample rate must be one of 8000, 12000, 16000, 24000, or 48000.
|
||||
let sample_rate_0 = config.sample_rate().0;
|
||||
let sample_rate = if sample_rate_0 < 12000 {
|
||||
@@ -233,6 +230,40 @@ mod cpal_impl {
|
||||
} else {
|
||||
48000
|
||||
};
|
||||
let stream = match config.sample_format() {
|
||||
I8 => build_input_stream::<i8>(device, &config, sp, sample_rate)?,
|
||||
I16 => build_input_stream::<i16>(device, &config, sp, sample_rate)?,
|
||||
I32 => build_input_stream::<i32>(device, &config, sp, sample_rate)?,
|
||||
I64 => build_input_stream::<i64>(device, &config, sp, sample_rate)?,
|
||||
U8 => build_input_stream::<u8>(device, &config, sp, sample_rate)?,
|
||||
U16 => build_input_stream::<u16>(device, &config, sp, sample_rate)?,
|
||||
U32 => build_input_stream::<u32>(device, &config, sp, sample_rate)?,
|
||||
U64 => build_input_stream::<u64>(device, &config, sp, sample_rate)?,
|
||||
F32 => build_input_stream::<f32>(device, &config, sp, sample_rate)?,
|
||||
F64 => build_input_stream::<f64>(device, &config, sp, sample_rate)?,
|
||||
f => bail!("unsupported audio format: {:?}", f),
|
||||
};
|
||||
stream.play()?;
|
||||
Ok((
|
||||
Box::new(stream),
|
||||
Arc::new(create_format_msg(sample_rate, config.channels())),
|
||||
))
|
||||
}
|
||||
|
||||
fn build_input_stream<T>(
|
||||
device: cpal::Device,
|
||||
config: &cpal::SupportedStreamConfig,
|
||||
sp: GenericService,
|
||||
sample_rate: u32,
|
||||
) -> ResultType<cpal::Stream>
|
||||
where
|
||||
T: cpal::SizedSample + dasp::sample::ToSample<f32>,
|
||||
{
|
||||
let err_fn = move |err| {
|
||||
// too many UnknownErrno, will improve later
|
||||
log::trace!("an error occurred on stream: {}", err);
|
||||
};
|
||||
let sample_rate_0 = config.sample_rate().0;
|
||||
log::debug!("Audio sample rate : {}", sample_rate);
|
||||
unsafe {
|
||||
AUDIO_ZERO_COUNT = 0;
|
||||
@@ -247,54 +278,34 @@ mod cpal_impl {
|
||||
// https://chromium.googlesource.com/chromium/deps/opus/+/1.1.1/include/opus.h
|
||||
let encode_len = sample_rate as usize * channels as usize / 100; // 10 ms
|
||||
INPUT_BUFFER.lock().unwrap().clear();
|
||||
let mut send_input_stream = move || {
|
||||
let mut lock = INPUT_BUFFER.lock().unwrap();
|
||||
while lock.len() >= encode_len {
|
||||
let frame: Vec<f32> = lock.drain(0..encode_len).collect();
|
||||
send(
|
||||
&frame,
|
||||
sample_rate_0,
|
||||
sample_rate,
|
||||
channels,
|
||||
&mut encoder,
|
||||
&sp,
|
||||
);
|
||||
}
|
||||
let timeout = None;
|
||||
let stream_config = StreamConfig {
|
||||
channels,
|
||||
sample_rate: config.sample_rate(),
|
||||
buffer_size: BufferSize::Default,
|
||||
};
|
||||
|
||||
let stream = match config.sample_format() {
|
||||
cpal::SampleFormat::F32 => device.build_input_stream(
|
||||
&config.into(),
|
||||
move |data, _: &_| {
|
||||
INPUT_BUFFER.lock().unwrap().extend(data);
|
||||
send_input_stream();
|
||||
},
|
||||
err_fn,
|
||||
)?,
|
||||
cpal::SampleFormat::I16 => device.build_input_stream(
|
||||
&config.into(),
|
||||
move |data: &[i16], _: &_| {
|
||||
let buffer: Vec<_> = data.iter().map(|s| cpal::Sample::to_f32(s)).collect();
|
||||
INPUT_BUFFER.lock().unwrap().extend(buffer);
|
||||
send_input_stream();
|
||||
},
|
||||
err_fn,
|
||||
)?,
|
||||
cpal::SampleFormat::U16 => device.build_input_stream(
|
||||
&config.into(),
|
||||
move |data: &[u16], _: &_| {
|
||||
let buffer: Vec<_> = data.iter().map(|s| cpal::Sample::to_f32(s)).collect();
|
||||
INPUT_BUFFER.lock().unwrap().extend(buffer);
|
||||
send_input_stream();
|
||||
},
|
||||
err_fn,
|
||||
)?,
|
||||
};
|
||||
stream.play()?;
|
||||
Ok((
|
||||
Box::new(stream),
|
||||
Arc::new(create_format_msg(sample_rate, channels)),
|
||||
))
|
||||
let stream = device.build_input_stream(
|
||||
&stream_config,
|
||||
move |data: &[T], _: &InputCallbackInfo| {
|
||||
let buffer: Vec<f32> = data.iter().map(|s| T::to_sample(*s)).collect();
|
||||
let mut lock = INPUT_BUFFER.lock().unwrap();
|
||||
lock.extend(buffer);
|
||||
while lock.len() >= encode_len {
|
||||
let frame: Vec<f32> = lock.drain(0..encode_len).collect();
|
||||
send(
|
||||
&frame,
|
||||
sample_rate_0,
|
||||
sample_rate,
|
||||
channels,
|
||||
&mut encoder,
|
||||
&sp,
|
||||
);
|
||||
}
|
||||
},
|
||||
err_fn,
|
||||
timeout,
|
||||
)?;
|
||||
Ok(stream)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user