Move from `StrResult` to `anyhow::Result` (#1739)
* Add `ToAny`, `ToCon` and `AnyhowToCon` * Remove all current tracing macros and add `bail_con!()`
This commit is contained in:
parent
586a262850
commit
3bb47fa433
|
@ -246,6 +246,7 @@ dependencies = [
|
|||
name = "alvr_common"
|
||||
version = "21.0.0-dev00"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"backtrace",
|
||||
"glam",
|
||||
"log",
|
||||
|
@ -529,6 +530,9 @@ name = "anyhow"
|
|||
version = "1.0.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "app_dirs2"
|
||||
|
|
|
@ -5,10 +5,11 @@ mod windows;
|
|||
pub use crate::windows::*;
|
||||
|
||||
use alvr_common::{
|
||||
anyhow::{self, anyhow, bail, Context, Result},
|
||||
info,
|
||||
once_cell::sync::Lazy,
|
||||
parking_lot::{Mutex, RwLock},
|
||||
prelude::*,
|
||||
RelaxedAtomic,
|
||||
ConnectionError, RelaxedAtomic, ToAny,
|
||||
};
|
||||
use alvr_session::{
|
||||
AudioBufferingConfig, CustomAudioDeviceConfig, LinuxAudioBackend, MicrophoneDevicesConfig,
|
||||
|
@ -38,49 +39,41 @@ static VIRTUAL_MICROPHONE_PAIRS: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
|
|||
.collect()
|
||||
});
|
||||
|
||||
fn device_from_custom_config(host: &Host, config: &CustomAudioDeviceConfig) -> StrResult<Device> {
|
||||
fn device_from_custom_config(host: &Host, config: &CustomAudioDeviceConfig) -> Result<Device> {
|
||||
Ok(match config {
|
||||
CustomAudioDeviceConfig::NameSubstring(name_substring) => host
|
||||
.devices()
|
||||
.map_err(err!())?
|
||||
.devices()?
|
||||
.find(|d| {
|
||||
d.name()
|
||||
.map(|name| name.to_lowercase().contains(&name_substring.to_lowercase()))
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.ok_or_else(|| {
|
||||
.with_context(|| {
|
||||
format!("Cannot find audio device which name contains \"{name_substring}\"")
|
||||
})?,
|
||||
CustomAudioDeviceConfig::Index(index) => host
|
||||
.devices()
|
||||
.map_err(err!())?
|
||||
.devices()?
|
||||
.nth(*index)
|
||||
.ok_or_else(|| format!("Cannot find audio device at index {index}"))?,
|
||||
.with_context(|| format!("Cannot find audio device at index {index}"))?,
|
||||
})
|
||||
}
|
||||
|
||||
fn microphone_pair_from_sink_name(host: &Host, sink_name: &str) -> StrResult<(Device, Device)> {
|
||||
fn microphone_pair_from_sink_name(host: &Host, sink_name: &str) -> Result<(Device, Device)> {
|
||||
let sink = host
|
||||
.output_devices()
|
||||
.map_err(err!())?
|
||||
.output_devices()?
|
||||
.find(|d| d.name().unwrap_or_default().contains(sink_name))
|
||||
.ok_or_else(|| {
|
||||
"VB-CABLE or Voice Meeter not found. Please install or reinstall either one".to_owned()
|
||||
})?;
|
||||
.context("VB-CABLE or Voice Meeter not found. Please install or reinstall either one")?;
|
||||
|
||||
if let Some(source_name) = VIRTUAL_MICROPHONE_PAIRS.get(sink_name) {
|
||||
Ok((
|
||||
sink,
|
||||
host.input_devices()
|
||||
.map_err(err!())?
|
||||
host.input_devices()?
|
||||
.find(|d| {
|
||||
d.name()
|
||||
.map(|name| name.contains(source_name))
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.ok_or_else(|| {
|
||||
"Matching output microphone not found. Did you rename it?".to_owned()
|
||||
})?,
|
||||
.context("Matching output microphone not found. Did you rename it?")?,
|
||||
))
|
||||
} else {
|
||||
unreachable!("Invalid argument")
|
||||
|
@ -98,7 +91,7 @@ impl AudioDevice {
|
|||
pub fn new_output(
|
||||
linux_backend: Option<LinuxAudioBackend>,
|
||||
config: Option<&CustomAudioDeviceConfig>,
|
||||
) -> StrResult<Self> {
|
||||
) -> Result<Self> {
|
||||
#[cfg(target_os = "linux")]
|
||||
let host = match linux_backend {
|
||||
Some(LinuxAudioBackend::Alsa) => cpal::host_from_id(cpal::HostId::Alsa).unwrap(),
|
||||
|
@ -111,7 +104,7 @@ impl AudioDevice {
|
|||
let device = match config {
|
||||
None => host
|
||||
.default_output_device()
|
||||
.ok_or_else(|| "No output audio device found".to_owned())?,
|
||||
.context("No output audio device found")?,
|
||||
Some(config) => device_from_custom_config(&host, config)?,
|
||||
};
|
||||
|
||||
|
@ -121,13 +114,13 @@ impl AudioDevice {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn new_input(config: Option<CustomAudioDeviceConfig>) -> StrResult<Self> {
|
||||
pub fn new_input(config: Option<CustomAudioDeviceConfig>) -> Result<Self> {
|
||||
let host = cpal::default_host();
|
||||
|
||||
let device = match config {
|
||||
None => host
|
||||
.default_input_device()
|
||||
.ok_or_else(|| "No input audio device found".to_owned())?,
|
||||
.context("No input audio device found")?,
|
||||
Some(config) => device_from_custom_config(&host, &config)?,
|
||||
};
|
||||
|
||||
|
@ -141,7 +134,7 @@ impl AudioDevice {
|
|||
pub fn new_virtual_microphone_pair(
|
||||
linux_backend: Option<LinuxAudioBackend>,
|
||||
config: MicrophoneDevicesConfig,
|
||||
) -> StrResult<(Self, Self)> {
|
||||
) -> Result<(Self, Self)> {
|
||||
#[cfg(target_os = "linux")]
|
||||
let host = match linux_backend {
|
||||
Some(LinuxAudioBackend::Alsa) => cpal::host_from_id(cpal::HostId::Alsa).unwrap(),
|
||||
|
@ -153,7 +146,7 @@ impl AudioDevice {
|
|||
|
||||
let (sink, source) = match config {
|
||||
MicrophoneDevicesConfig::Automatic => {
|
||||
let mut pair = Err(String::new());
|
||||
let mut pair = Err(anyhow!("No microphones found"));
|
||||
for sink_name in VIRTUAL_MICROPHONE_PAIRS.keys() {
|
||||
pair = microphone_pair_from_sink_name(&host, sink_name);
|
||||
if pair.is_ok() {
|
||||
|
@ -193,13 +186,12 @@ impl AudioDevice {
|
|||
))
|
||||
}
|
||||
|
||||
pub fn input_sample_rate(&self) -> StrResult<u32> {
|
||||
pub fn input_sample_rate(&self) -> Result<u32> {
|
||||
let config = self
|
||||
.inner
|
||||
.default_input_config()
|
||||
// On Windows, loopback devices are not recognized as input devices. Use output config.
|
||||
.or_else(|_| self.inner.default_output_config())
|
||||
.map_err(err!())?;
|
||||
.or_else(|_| self.inner.default_output_config())?;
|
||||
|
||||
Ok(config.sample_rate().0)
|
||||
}
|
||||
|
@ -213,11 +205,10 @@ pub fn is_same_device(device1: &AudioDevice, device2: &AudioDevice) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum AudioRecordState {
|
||||
Recording,
|
||||
ShouldStop,
|
||||
Err(String),
|
||||
Err(Option<anyhow::Error>),
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
|
@ -227,17 +218,16 @@ pub fn record_audio_blocking(
|
|||
device: &AudioDevice,
|
||||
channels_count: u16,
|
||||
mute: bool,
|
||||
) -> StrResult {
|
||||
) -> Result<()> {
|
||||
let config = device
|
||||
.inner
|
||||
.default_input_config()
|
||||
// On Windows, loopback devices are not recognized as input devices. Use output config.
|
||||
.or_else(|_| device.inner.default_output_config())
|
||||
.map_err(err!())?;
|
||||
.or_else(|_| device.inner.default_output_config())?;
|
||||
|
||||
if config.channels() > 2 {
|
||||
// todo: handle more than 2 channels
|
||||
return fmt_e!(
|
||||
bail!(
|
||||
"Audio devices with more than 2 channels are not supported. {}",
|
||||
"Please turn off surround audio."
|
||||
);
|
||||
|
@ -251,70 +241,67 @@ pub fn record_audio_blocking(
|
|||
|
||||
let state = Arc::new(Mutex::new(AudioRecordState::Recording));
|
||||
|
||||
let stream = device
|
||||
.inner
|
||||
.build_input_stream_raw(
|
||||
&stream_config,
|
||||
config.sample_format(),
|
||||
{
|
||||
let state = Arc::clone(&state);
|
||||
let runtime = Arc::clone(&runtime);
|
||||
move |data, _| {
|
||||
let data = if config.sample_format() == SampleFormat::F32 {
|
||||
data.bytes()
|
||||
.chunks_exact(4)
|
||||
.flat_map(|b| {
|
||||
f32::from_ne_bytes([b[0], b[1], b[2], b[3]])
|
||||
.to_sample::<i16>()
|
||||
.to_ne_bytes()
|
||||
.to_vec()
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
data.bytes().to_vec()
|
||||
};
|
||||
let stream = device.inner.build_input_stream_raw(
|
||||
&stream_config,
|
||||
config.sample_format(),
|
||||
{
|
||||
let state = Arc::clone(&state);
|
||||
let runtime = Arc::clone(&runtime);
|
||||
move |data, _| {
|
||||
let data = if config.sample_format() == SampleFormat::F32 {
|
||||
data.bytes()
|
||||
.chunks_exact(4)
|
||||
.flat_map(|b| {
|
||||
f32::from_ne_bytes([b[0], b[1], b[2], b[3]])
|
||||
.to_sample::<i16>()
|
||||
.to_ne_bytes()
|
||||
.to_vec()
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
data.bytes().to_vec()
|
||||
};
|
||||
|
||||
let data = if config.channels() == 1 && channels_count == 2 {
|
||||
data.chunks_exact(2)
|
||||
.flat_map(|c| vec![c[0], c[1], c[0], c[1]])
|
||||
.collect()
|
||||
} else if config.channels() == 2 && channels_count == 1 {
|
||||
data.chunks_exact(4)
|
||||
.flat_map(|c| vec![c[0], c[1]])
|
||||
.collect()
|
||||
} else {
|
||||
data
|
||||
};
|
||||
let data = if config.channels() == 1 && channels_count == 2 {
|
||||
data.chunks_exact(2)
|
||||
.flat_map(|c| vec![c[0], c[1], c[0], c[1]])
|
||||
.collect()
|
||||
} else if config.channels() == 2 && channels_count == 1 {
|
||||
data.chunks_exact(4)
|
||||
.flat_map(|c| vec![c[0], c[1]])
|
||||
.collect()
|
||||
} else {
|
||||
data
|
||||
};
|
||||
|
||||
if let Some(runtime) = &*runtime.read() {
|
||||
sender.send(runtime, &(), data).ok();
|
||||
} else {
|
||||
*state.lock() = AudioRecordState::ShouldStop;
|
||||
}
|
||||
if let Some(runtime) = &*runtime.read() {
|
||||
sender.send(runtime, &(), data).ok();
|
||||
} else {
|
||||
*state.lock() = AudioRecordState::ShouldStop;
|
||||
}
|
||||
},
|
||||
{
|
||||
let state = Arc::clone(&state);
|
||||
move |e| *state.lock() = AudioRecordState::Err(e.to_string())
|
||||
},
|
||||
None,
|
||||
)
|
||||
.map_err(err!())?;
|
||||
}
|
||||
},
|
||||
{
|
||||
let state = Arc::clone(&state);
|
||||
move |e| *state.lock() = AudioRecordState::Err(Some(e.into()))
|
||||
},
|
||||
None,
|
||||
)?;
|
||||
|
||||
#[cfg(windows)]
|
||||
if mute && device.is_output {
|
||||
crate::windows::set_mute_windows_device(device, true).ok();
|
||||
}
|
||||
|
||||
let mut res = stream.play().map_err(err!());
|
||||
let mut res = stream.play().to_any();
|
||||
|
||||
if res.is_ok() {
|
||||
while matches!(*state.lock(), AudioRecordState::Recording) && runtime.read().is_some() {
|
||||
thread::sleep(Duration::from_millis(500))
|
||||
}
|
||||
|
||||
if let AudioRecordState::Err(e) = state.lock().clone() {
|
||||
res = Err(e);
|
||||
if let AudioRecordState::Err(e) = &mut *state.lock() {
|
||||
res = Err(e.take().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,14 +354,14 @@ pub fn receive_samples_loop(
|
|||
channels_count: usize,
|
||||
batch_frames_count: usize,
|
||||
average_buffer_frames_count: usize,
|
||||
) -> StrResult {
|
||||
) -> Result<()> {
|
||||
let mut receiver_buffer = ReceiverBuffer::new();
|
||||
let mut recovery_sample_buffer = vec![];
|
||||
while running.value() {
|
||||
match receiver.recv_buffer(Duration::from_millis(500), &mut receiver_buffer) {
|
||||
Ok(true) => (),
|
||||
Ok(false) | Err(ConnectionError::Timeout) => continue,
|
||||
Err(ConnectionError::Other(e)) => return fmt_e!("{e}"),
|
||||
Err(ConnectionError::Other(e)) => return Err(e),
|
||||
};
|
||||
|
||||
let (_, packet) = receiver_buffer.get()?;
|
||||
|
@ -519,7 +506,7 @@ pub fn play_audio_loop(
|
|||
sample_rate: u32,
|
||||
config: AudioBufferingConfig,
|
||||
receiver: StreamReceiver<()>,
|
||||
) -> StrResult {
|
||||
) -> Result<()> {
|
||||
// Size of a chunk of frames. It corresponds to the duration if a fade-in/out in frames.
|
||||
let batch_frames_count = sample_rate as usize * config.batch_ms as usize / 1000;
|
||||
|
||||
|
@ -529,18 +516,16 @@ pub fn play_audio_loop(
|
|||
|
||||
let sample_buffer = Arc::new(Mutex::new(VecDeque::new()));
|
||||
|
||||
let (_stream, handle) = OutputStream::try_from_device(&device.inner).map_err(err!())?;
|
||||
let (_stream, handle) = OutputStream::try_from_device(&device.inner)?;
|
||||
|
||||
handle
|
||||
.play_raw(StreamingSource {
|
||||
sample_buffer: Arc::clone(&sample_buffer),
|
||||
current_batch: vec![],
|
||||
current_batch_cursor: 0,
|
||||
channels_count: channels_count as _,
|
||||
sample_rate,
|
||||
batch_frames_count,
|
||||
})
|
||||
.map_err(err!())?;
|
||||
handle.play_raw(StreamingSource {
|
||||
sample_buffer: Arc::clone(&sample_buffer),
|
||||
current_batch: vec![],
|
||||
current_batch_cursor: 0,
|
||||
channels_count: channels_count as _,
|
||||
sample_rate,
|
||||
batch_frames_count,
|
||||
})?;
|
||||
|
||||
receive_samples_loop(
|
||||
running,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::AudioDevice;
|
||||
use alvr_common::prelude::*;
|
||||
use alvr_common::anyhow::{bail, Result};
|
||||
use rodio::DeviceTrait;
|
||||
|
||||
fn get_windows_device(device: &AudioDevice) -> StrResult<windows::Win32::Media::Audio::IMMDevice> {
|
||||
fn get_windows_device(device: &AudioDevice) -> Result<windows::Win32::Media::Audio::IMMDevice> {
|
||||
use widestring::U16CStr;
|
||||
use windows::Win32::{
|
||||
Devices::FunctionDiscovery::PKEY_Device_FriendlyName,
|
||||
|
@ -10,54 +10,49 @@ fn get_windows_device(device: &AudioDevice) -> StrResult<windows::Win32::Media::
|
|||
System::Com::{self, CLSCTX_ALL, COINIT_MULTITHREADED, STGM_READ},
|
||||
};
|
||||
|
||||
let device_name = device.inner.name().map_err(err!())?;
|
||||
let device_name = device.inner.name()?;
|
||||
|
||||
unsafe {
|
||||
// This will fail the second time is called, ignore the error
|
||||
Com::CoInitializeEx(None, COINIT_MULTITHREADED).ok();
|
||||
|
||||
let imm_device_enumerator: IMMDeviceEnumerator =
|
||||
Com::CoCreateInstance(&MMDeviceEnumerator, None, CLSCTX_ALL).map_err(err!())?;
|
||||
Com::CoCreateInstance(&MMDeviceEnumerator, None, CLSCTX_ALL)?;
|
||||
|
||||
let imm_device_collection = imm_device_enumerator
|
||||
.EnumAudioEndpoints(eAll, DEVICE_STATE_ACTIVE)
|
||||
.map_err(err!())?;
|
||||
let imm_device_collection =
|
||||
imm_device_enumerator.EnumAudioEndpoints(eAll, DEVICE_STATE_ACTIVE)?;
|
||||
|
||||
let count = imm_device_collection.GetCount().map_err(err!())?;
|
||||
let count = imm_device_collection.GetCount()?;
|
||||
|
||||
for i in 0..count {
|
||||
let imm_device = imm_device_collection.Item(i).map_err(err!())?;
|
||||
let imm_device = imm_device_collection.Item(i)?;
|
||||
|
||||
let property_store = imm_device.OpenPropertyStore(STGM_READ).map_err(err!())?;
|
||||
let property_store = imm_device.OpenPropertyStore(STGM_READ)?;
|
||||
|
||||
let mut prop_variant = property_store
|
||||
.GetValue(&PKEY_Device_FriendlyName)
|
||||
.map_err(err!())?;
|
||||
let mut prop_variant = property_store.GetValue(&PKEY_Device_FriendlyName)?;
|
||||
let utf16_name =
|
||||
U16CStr::from_ptr_str(prop_variant.Anonymous.Anonymous.Anonymous.pwszVal.0);
|
||||
Com::StructuredStorage::PropVariantClear(&mut prop_variant).map_err(err!())?;
|
||||
Com::StructuredStorage::PropVariantClear(&mut prop_variant)?;
|
||||
|
||||
let imm_device_name = utf16_name.to_string().map_err(err!())?;
|
||||
let imm_device_name = utf16_name.to_string()?;
|
||||
if imm_device_name == device_name {
|
||||
return Ok(imm_device);
|
||||
}
|
||||
}
|
||||
|
||||
fmt_e!("No device found with specified name")
|
||||
bail!("No device found with specified name")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_windows_device_id(device: &AudioDevice) -> StrResult<String> {
|
||||
pub fn get_windows_device_id(device: &AudioDevice) -> Result<String> {
|
||||
use widestring::U16CStr;
|
||||
use windows::Win32::System::Com;
|
||||
|
||||
unsafe {
|
||||
let imm_device = get_windows_device(device)?;
|
||||
|
||||
let id_str_ptr = imm_device.GetId().map_err(err!())?;
|
||||
let id_str = U16CStr::from_ptr_str(id_str_ptr.0)
|
||||
.to_string()
|
||||
.map_err(err!())?;
|
||||
let id_str_ptr = imm_device.GetId()?;
|
||||
let id_str = U16CStr::from_ptr_str(id_str_ptr.0).to_string()?;
|
||||
Com::CoTaskMemFree(Some(id_str_ptr.0 as _));
|
||||
|
||||
Ok(id_str)
|
||||
|
@ -65,7 +60,7 @@ pub fn get_windows_device_id(device: &AudioDevice) -> StrResult<String> {
|
|||
}
|
||||
|
||||
// device must be an output device
|
||||
pub fn set_mute_windows_device(device: &AudioDevice, mute: bool) -> StrResult {
|
||||
pub fn set_mute_windows_device(device: &AudioDevice, mute: bool) -> Result<()> {
|
||||
use windows::{
|
||||
core::GUID,
|
||||
Win32::{Media::Audio::Endpoints::IAudioEndpointVolume, System::Com::CLSCTX_ALL},
|
||||
|
@ -74,13 +69,9 @@ pub fn set_mute_windows_device(device: &AudioDevice, mute: bool) -> StrResult {
|
|||
unsafe {
|
||||
let imm_device = get_windows_device(device)?;
|
||||
|
||||
let endpoint_volume = imm_device
|
||||
.Activate::<IAudioEndpointVolume>(CLSCTX_ALL, None)
|
||||
.map_err(err!())?;
|
||||
let endpoint_volume = imm_device.Activate::<IAudioEndpointVolume>(CLSCTX_ALL, None)?;
|
||||
|
||||
endpoint_volume
|
||||
.SetMute(mute, &GUID::zeroed())
|
||||
.map_err(err!())?;
|
||||
endpoint_volume.SetMute(mute, &GUID::zeroed())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use alvr_audio::{AudioDevice, AudioRecordState};
|
||||
use alvr_common::{
|
||||
anyhow::{bail, Result},
|
||||
parking_lot::{Mutex, RwLock},
|
||||
prelude::*,
|
||||
RelaxedAtomic,
|
||||
RelaxedAtomic, ToAny,
|
||||
};
|
||||
use alvr_session::AudioBufferingConfig;
|
||||
use alvr_sockets::{StreamReceiver, StreamSender};
|
||||
|
@ -46,7 +46,7 @@ impl AudioInputCallback for RecorderCallback {
|
|||
}
|
||||
|
||||
fn on_error_before_close(&mut self, _: &mut dyn AudioInputStreamSafe, error: oboe::Error) {
|
||||
*self.state.lock() = AudioRecordState::Err(error.to_string());
|
||||
*self.state.lock() = AudioRecordState::Err(Some(error.into()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ pub fn record_audio_blocking(
|
|||
device: &AudioDevice,
|
||||
channels_count: u16,
|
||||
mute: bool,
|
||||
) -> StrResult {
|
||||
) -> Result<()> {
|
||||
let sample_rate = device.input_sample_rate()?;
|
||||
|
||||
let state = Arc::new(Mutex::new(AudioRecordState::Recording));
|
||||
|
@ -77,18 +77,17 @@ pub fn record_audio_blocking(
|
|||
sender,
|
||||
state: Arc::clone(&state),
|
||||
})
|
||||
.open_stream()
|
||||
.map_err(err!())?;
|
||||
.open_stream()?;
|
||||
|
||||
let mut res = stream.start().map_err(err!());
|
||||
let mut res = stream.start().to_any();
|
||||
|
||||
if res.is_ok() {
|
||||
while matches!(*state.lock(), AudioRecordState::Recording) && runtime.read().is_some() {
|
||||
thread::sleep(Duration::from_millis(500))
|
||||
}
|
||||
|
||||
if let AudioRecordState::Err(e) = state.lock().clone() {
|
||||
res = Err(e);
|
||||
if let AudioRecordState::Err(e) = &mut *state.lock() {
|
||||
res = Err(e.take().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,11 +131,11 @@ pub fn play_audio_loop(
|
|||
sample_rate: u32,
|
||||
config: AudioBufferingConfig,
|
||||
receiver: StreamReceiver<()>,
|
||||
) -> StrResult {
|
||||
) -> Result<()> {
|
||||
// the client sends invalid sample rates sometimes, and we crash if we try and use one
|
||||
// (batch_frames_count ends up zero and the audio callback gets confused)
|
||||
if sample_rate < 8000 {
|
||||
return fmt_e!("Invalid audio sample rate");
|
||||
bail!("Invalid audio sample rate");
|
||||
}
|
||||
|
||||
let batch_frames_count = sample_rate as usize * config.batch_ms as usize / 1000;
|
||||
|
@ -159,10 +158,9 @@ pub fn play_audio_loop(
|
|||
sample_buffer: Arc::clone(&sample_buffer),
|
||||
batch_frames_count,
|
||||
})
|
||||
.open_stream()
|
||||
.map_err(err!())?;
|
||||
.open_stream()?;
|
||||
|
||||
stream.start().map_err(err!())?;
|
||||
stream.start()?;
|
||||
|
||||
alvr_audio::receive_samples_loop(
|
||||
running,
|
||||
|
|
|
@ -3,11 +3,12 @@ use crate::{
|
|||
ClientCoreEvent,
|
||||
};
|
||||
use alvr_common::{
|
||||
debug, error,
|
||||
glam::{Quat, UVec2, Vec2, Vec3},
|
||||
info,
|
||||
once_cell::sync::Lazy,
|
||||
parking_lot::Mutex,
|
||||
prelude::*,
|
||||
DeviceMotion, Fov, Pose,
|
||||
warn, DeviceMotion, Fov, Pose,
|
||||
};
|
||||
use alvr_packets::{ButtonEntry, ButtonValue, Tracking};
|
||||
use alvr_session::{CodecType, FoveatedRenderingConfig};
|
||||
|
|
|
@ -10,11 +10,12 @@ use crate::{
|
|||
};
|
||||
use alvr_audio::AudioDevice;
|
||||
use alvr_common::{
|
||||
debug, error,
|
||||
glam::UVec2,
|
||||
info,
|
||||
once_cell::sync::Lazy,
|
||||
parking_lot::{Mutex, RwLock},
|
||||
prelude::*,
|
||||
ALVR_VERSION,
|
||||
warn, AnyhowToCon, ConResult, ConnectionError, ToCon, ALVR_VERSION,
|
||||
};
|
||||
use alvr_packets::{
|
||||
ClientConnectionResult, ClientControlPacket, ClientStatistics, Haptics, ServerControlPacket,
|
||||
|
@ -119,12 +120,12 @@ fn connection_pipeline(
|
|||
.worker_threads(2)
|
||||
.enable_all()
|
||||
.build()
|
||||
.map_err(to_con_e!())?;
|
||||
.to_con()?;
|
||||
|
||||
let (mut proto_control_socket, server_ip) = {
|
||||
let config = Config::load();
|
||||
let announcer_socket = AnnouncerSocket::new(&config.hostname).map_err(to_con_e!())?;
|
||||
let listener_socket = alvr_sockets::get_server_listener(&runtime).map_err(to_con_e!())?;
|
||||
let announcer_socket = AnnouncerSocket::new(&config.hostname).to_con()?;
|
||||
let listener_socket = alvr_sockets::get_server_listener(&runtime).to_con()?;
|
||||
|
||||
loop {
|
||||
if !IS_ALIVE.value() {
|
||||
|
@ -183,22 +184,20 @@ fn connection_pipeline(
|
|||
}),
|
||||
},
|
||||
)
|
||||
.map_err(to_con_e!())?;
|
||||
let config_packet = proto_control_socket
|
||||
.recv::<StreamConfigPacket>(&runtime, Duration::from_secs(1))
|
||||
.map_err(to_con_e!())?;
|
||||
.to_con()?;
|
||||
let config_packet =
|
||||
proto_control_socket.recv::<StreamConfigPacket>(&runtime, Duration::from_secs(1))?;
|
||||
|
||||
let settings = {
|
||||
let mut session_desc = SessionConfig::default();
|
||||
session_desc
|
||||
.merge_from_json(&json::from_str(&config_packet.session).map_err(to_con_e!())?)
|
||||
.map_err(to_con_e!())?;
|
||||
.merge_from_json(&json::from_str(&config_packet.session).to_con()?)
|
||||
.to_con()?;
|
||||
session_desc.to_settings()
|
||||
};
|
||||
|
||||
let negotiated_config =
|
||||
json::from_str::<HashMap<String, json::Value>>(&config_packet.negotiated)
|
||||
.map_err(to_con_e!())?;
|
||||
json::from_str::<HashMap<String, json::Value>>(&config_packet.negotiated).to_con()?;
|
||||
|
||||
let view_resolution = negotiated_config
|
||||
.get("view_resolution")
|
||||
|
@ -260,7 +259,7 @@ fn connection_pipeline(
|
|||
settings.connection.client_send_buffer_bytes,
|
||||
settings.connection.client_recv_buffer_bytes,
|
||||
)
|
||||
.map_err(to_con_e!())?;
|
||||
.to_con()?;
|
||||
|
||||
if let Err(e) = control_sender.send(&runtime, &ClientControlPacket::StreamReady) {
|
||||
info!("Server disconnected. Cause: {e}");
|
||||
|
@ -347,7 +346,7 @@ fn connection_pipeline(
|
|||
});
|
||||
|
||||
let game_audio_thread = if let Switch::Enabled(config) = settings.audio.game_audio {
|
||||
let device = AudioDevice::new_output(None, None).map_err(to_con_e!())?;
|
||||
let device = AudioDevice::new_output(None, None).to_con()?;
|
||||
|
||||
thread::spawn(move || {
|
||||
alvr_common::show_err(audio::play_audio_loop(
|
||||
|
@ -364,7 +363,7 @@ fn connection_pipeline(
|
|||
};
|
||||
|
||||
let microphone_thread = if matches!(settings.audio.microphone, Switch::Enabled(_)) {
|
||||
let device = AudioDevice::new_input(None).map_err(to_con_e!())?;
|
||||
let device = AudioDevice::new_input(None).to_con()?;
|
||||
|
||||
let microphone_sender = stream_socket.request_stream(AUDIO);
|
||||
|
||||
|
|
|
@ -4,9 +4,6 @@ use alvr_packets::DecoderInitializationConfig;
|
|||
use alvr_session::{CodecType, MediacodecDataType};
|
||||
use std::time::Duration;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
use alvr_common::prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DecoderInitConfig {
|
||||
pub codec: CodecType,
|
||||
|
@ -80,7 +77,10 @@ pub fn push_nal(timestamp: Duration, nal: &[u8]) -> bool {
|
|||
} else {
|
||||
#[cfg(target_os = "android")]
|
||||
if let Some(decoder) = &*DECODER_ENQUEUER.lock() {
|
||||
matches!(show_err(decoder.push_frame_nal(timestamp, nal)), Some(true))
|
||||
matches!(
|
||||
alvr_common::show_err(decoder.push_frame_nal(timestamp, nal)),
|
||||
Some(true)
|
||||
)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
|
|
@ -25,10 +25,10 @@ pub use logging_backend::init_logging;
|
|||
pub use platform::try_get_permission;
|
||||
|
||||
use alvr_common::{
|
||||
error,
|
||||
glam::{UVec2, Vec2},
|
||||
once_cell::sync::Lazy,
|
||||
parking_lot::Mutex,
|
||||
prelude::*,
|
||||
Fov, RelaxedAtomic,
|
||||
};
|
||||
use alvr_packets::{BatteryPacket, ButtonEntry, ClientControlPacket, Tracking, ViewsConfig};
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use crate::decoder::DecoderInitConfig;
|
||||
use alvr_common::{
|
||||
anyhow::{bail, Result},
|
||||
error, info,
|
||||
once_cell::sync::Lazy,
|
||||
parking_lot::{Condvar, Mutex},
|
||||
prelude::*,
|
||||
RelaxedAtomic,
|
||||
warn, RelaxedAtomic,
|
||||
};
|
||||
use alvr_session::{CodecType, MediacodecDataType};
|
||||
use jni::{
|
||||
|
@ -306,7 +307,7 @@ unsafe impl Send for VideoDecoderEnqueuer {}
|
|||
|
||||
impl VideoDecoderEnqueuer {
|
||||
// Block until the buffer has been written or timeout is reached. Returns false if timeout.
|
||||
pub fn push_frame_nal(&self, timestamp: Duration, data: &[u8]) -> StrResult<bool> {
|
||||
pub fn push_frame_nal(&self, timestamp: Duration, data: &[u8]) -> Result<bool> {
|
||||
let Some(decoder) = &*self.inner.lock() else {
|
||||
// This might happen only during destruction
|
||||
return Ok(false);
|
||||
|
@ -325,14 +326,12 @@ impl VideoDecoderEnqueuer {
|
|||
// NB: the function expects the timestamp in micros, but nanos is used to have
|
||||
// complete precision, so when converted back to Duration it can compare correctly
|
||||
// to other Durations
|
||||
decoder
|
||||
.queue_input_buffer(buffer, 0, data.len(), timestamp.as_nanos() as _, 0)
|
||||
.map_err(err!())?;
|
||||
decoder.queue_input_buffer(buffer, 0, data.len(), timestamp.as_nanos() as _, 0)?;
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
Ok(DequeuedInputBufferResult::TryAgainLater) => Ok(false),
|
||||
Err(e) => fmt_e!("{e}"),
|
||||
Err(e) => bail!("{e}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -410,7 +409,7 @@ pub fn video_decoder_split(
|
|||
config: DecoderInitConfig,
|
||||
csd_0: Vec<u8>,
|
||||
dequeued_frame_callback: impl Fn(Duration) + Send + 'static,
|
||||
) -> StrResult<(VideoDecoderEnqueuer, VideoDecoderDequeuer)> {
|
||||
) -> Result<(VideoDecoderEnqueuer, VideoDecoderDequeuer)> {
|
||||
let running = Arc::new(RelaxedAtomic::new(true));
|
||||
let decoder_enqueuer = Arc::new(Mutex::new(None::<SharedMediaCodec>));
|
||||
let decoder_ready_notifier = Arc::new(Condvar::new());
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use alvr_common::{StrResult, *};
|
||||
use alvr_common::{anyhow::Result, ALVR_NAME};
|
||||
use alvr_sockets::{CONTROL_PORT, LOCAL_IP};
|
||||
use std::net::{Ipv4Addr, UdpSocket};
|
||||
|
||||
|
@ -8,9 +8,9 @@ pub struct AnnouncerSocket {
|
|||
}
|
||||
|
||||
impl AnnouncerSocket {
|
||||
pub fn new(hostname: &str) -> StrResult<Self> {
|
||||
let socket = UdpSocket::bind((LOCAL_IP, CONTROL_PORT)).map_err(err!())?;
|
||||
socket.set_broadcast(true).map_err(err!())?;
|
||||
pub fn new(hostname: &str) -> Result<Self> {
|
||||
let socket = UdpSocket::bind((LOCAL_IP, CONTROL_PORT))?;
|
||||
socket.set_broadcast(true)?;
|
||||
|
||||
let mut packet = [0; 56];
|
||||
packet[0..ALVR_NAME.len()].copy_from_slice(ALVR_NAME.as_bytes());
|
||||
|
@ -20,10 +20,10 @@ impl AnnouncerSocket {
|
|||
Ok(Self { socket, packet })
|
||||
}
|
||||
|
||||
pub fn broadcast(&self) -> StrResult {
|
||||
pub fn broadcast(&self) -> Result<()> {
|
||||
self.socket
|
||||
.send_to(&self.packet, (Ipv4Addr::BROADCAST, CONTROL_PORT))
|
||||
.map_err(err!())?;
|
||||
.send_to(&self.packet, (Ipv4Addr::BROADCAST, CONTROL_PORT))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use alvr_common::prelude::*;
|
||||
use alvr_common::{error, info};
|
||||
use app_dirs2::{AppDataType, AppInfo};
|
||||
use rand::Rng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
|
|
@ -2,10 +2,11 @@ mod interaction;
|
|||
|
||||
use alvr_client_core::{opengl::RenderViewInput, ClientCoreEvent};
|
||||
use alvr_common::{
|
||||
error,
|
||||
glam::{Quat, UVec2, Vec2, Vec3},
|
||||
prelude::*,
|
||||
info,
|
||||
settings_schema::Switch,
|
||||
DeviceMotion, Fov, Pose, RelaxedAtomic, HEAD_ID, LEFT_HAND_ID, RIGHT_HAND_ID,
|
||||
warn, DeviceMotion, Fov, Pose, RelaxedAtomic, HEAD_ID, LEFT_HAND_ID, RIGHT_HAND_ID,
|
||||
};
|
||||
use alvr_packets::{FaceData, Tracking};
|
||||
use alvr_session::ClientsideFoveationMode;
|
||||
|
|
|
@ -7,6 +7,7 @@ authors.workspace = true
|
|||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
anyhow = { version = "1", features = ["backtrace"] }
|
||||
backtrace = "0.3"
|
||||
glam = { version = "0.24", features = ["serde"] }
|
||||
log = "0.4"
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
use anyhow::Result;
|
||||
use std::{error::Error, fmt::Display};
|
||||
|
||||
pub enum ConnectionError {
|
||||
Timeout,
|
||||
Other(anyhow::Error),
|
||||
}
|
||||
|
||||
impl Display for ConnectionError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
ConnectionError::Timeout => write!(f, "Timeout"),
|
||||
ConnectionError::Other(s) => write!(f, "{}", s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type ConResult<T = ()> = Result<T, ConnectionError>;
|
||||
|
||||
pub fn timeout<T>() -> ConResult<T> {
|
||||
Err(ConnectionError::Timeout)
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! con_bail {
|
||||
($($args:tt)+) => {
|
||||
return Err(alvr_common::ConnectionError::Other(alvr_common::anyhow::anyhow!($($args)+)))
|
||||
};
|
||||
}
|
||||
|
||||
pub trait ToCon<T> {
|
||||
fn to_con(self) -> ConResult<T>;
|
||||
}
|
||||
|
||||
impl<T> ToCon<T> for Option<T> {
|
||||
fn to_con(self) -> ConResult<T> {
|
||||
match self {
|
||||
Some(value) => Ok(value),
|
||||
None => Err(ConnectionError::Other(anyhow::anyhow!("Unexpected None"))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E: Error + Send + Sync + 'static> ToCon<T> for Result<T, E> {
|
||||
fn to_con(self) -> ConResult<T> {
|
||||
match self {
|
||||
Ok(value) => Ok(value),
|
||||
Err(e) => Err(ConnectionError::Other(e.into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AnyhowToCon<T> {
|
||||
fn to_con(self) -> ConResult<T>;
|
||||
}
|
||||
|
||||
impl<T> AnyhowToCon<T> for Result<T, anyhow::Error> {
|
||||
fn to_con(self) -> ConResult<T> {
|
||||
match self {
|
||||
Ok(value) => Ok(value),
|
||||
Err(e) => Err(ConnectionError::Other(e)),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +1,13 @@
|
|||
mod average;
|
||||
mod connection_result;
|
||||
mod logging;
|
||||
mod paths;
|
||||
mod primitives;
|
||||
mod version;
|
||||
|
||||
use std::{
|
||||
fmt::Display,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
|
||||
pub mod prelude {
|
||||
pub use crate::{
|
||||
con_e, con_fmt_e, enone, err, err_dbg, fmt_e, logging::*, timeout, to_con_e, ConResult,
|
||||
ConnectionError, StrResult,
|
||||
};
|
||||
pub use log::{debug, error, info, warn};
|
||||
}
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
pub use anyhow;
|
||||
pub use log;
|
||||
pub use once_cell;
|
||||
pub use parking_lot;
|
||||
|
@ -24,6 +15,8 @@ pub use semver;
|
|||
pub use settings_schema;
|
||||
|
||||
pub use average::*;
|
||||
pub use connection_result::*;
|
||||
pub use log::{debug, error, info, warn};
|
||||
pub use logging::*;
|
||||
pub use paths::*;
|
||||
pub use primitives::*;
|
||||
|
@ -31,26 +24,6 @@ pub use version::*;
|
|||
|
||||
pub const ALVR_NAME: &str = "ALVR";
|
||||
|
||||
pub type StrResult<T = ()> = Result<T, String>;
|
||||
|
||||
pub enum ConnectionError {
|
||||
Timeout,
|
||||
Other(String),
|
||||
}
|
||||
impl Display for ConnectionError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
ConnectionError::Timeout => write!(f, "Timeout"),
|
||||
ConnectionError::Other(s) => write!(f, "{}", s),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub type ConResult<T = ()> = Result<T, ConnectionError>;
|
||||
|
||||
pub fn timeout<T>() -> ConResult<T> {
|
||||
Err(ConnectionError::Timeout)
|
||||
}
|
||||
|
||||
// Simple wrapper for AtomicBool when using Ordering::Relaxed. Deref cannot be implemented (cannot
|
||||
// return local reference)
|
||||
pub struct RelaxedAtomic(AtomicBool);
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use anyhow::Result;
|
||||
use backtrace::Backtrace;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use settings_schema::SettingsSchema;
|
||||
use std::{fmt::Display, future::Future};
|
||||
use std::{error::Error, fmt::Display};
|
||||
|
||||
#[derive(
|
||||
SettingsSchema, Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord,
|
||||
|
@ -134,63 +135,24 @@ pub fn show_err_blocking<T, E: Display>(res: Result<T, E>) -> Option<T> {
|
|||
res.map_err(|e| show_e_block(e, true)).ok()
|
||||
}
|
||||
|
||||
pub async fn show_err_async<T, E: Display>(
|
||||
future_res: impl Future<Output = Result<T, E>>,
|
||||
) -> Option<T> {
|
||||
show_err(future_res.await)
|
||||
pub trait ToAny<T> {
|
||||
fn to_any(self) -> Result<T>;
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! fmt_e {
|
||||
($($args:tt)+) => {
|
||||
Err(format!($($args)+))
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! err {
|
||||
() => {
|
||||
|e| format!("At {}:{}: {e}", file!(), line!())
|
||||
};
|
||||
}
|
||||
|
||||
// trace_err variant for errors that do not implement fmt::Display
|
||||
#[macro_export]
|
||||
macro_rules! err_dbg {
|
||||
() => {
|
||||
|e| format!("At {}:{}: {e:?}", file!(), line!())
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! enone {
|
||||
() => {
|
||||
|| format!("At {}:{}", file!(), line!())
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! con_fmt_e {
|
||||
($($args:tt)+) => {
|
||||
Err(ConnectionError::Other(format!($($args)+)))
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! con_e {
|
||||
() => {
|
||||
|e| match e {
|
||||
ConnectionError::Timeout => ConnectionError::Timeout,
|
||||
ConnectionError::Other(e) => {
|
||||
ConnectionError::Other(format!("At {}:{}: {e}", file!(), line!()))
|
||||
}
|
||||
impl<T> ToAny<T> for Option<T> {
|
||||
fn to_any(self) -> Result<T> {
|
||||
match self {
|
||||
Some(value) => Ok(value),
|
||||
None => Err(anyhow::anyhow!("Unexpected None")),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! to_con_e {
|
||||
() => {
|
||||
|e| ConnectionError::Other(format!("At {}:{}: {e}", file!(), line!()))
|
||||
};
|
||||
impl<T, E: Error + Send + Sync + 'static> ToAny<T> for Result<T, E> {
|
||||
fn to_any(self) -> Result<T> {
|
||||
match self {
|
||||
Ok(value) => Ok(value),
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use alvr_common::{parking_lot::Mutex, prelude::*, RelaxedAtomic};
|
||||
use alvr_common::{debug, error, info, parking_lot::Mutex, warn, RelaxedAtomic};
|
||||
use alvr_events::{Event, EventType};
|
||||
use alvr_packets::ServerRequest;
|
||||
use alvr_server_io::ServerDataManager;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::data_sources;
|
||||
use alvr_common::{once_cell::sync::Lazy, parking_lot::Mutex, prelude::*};
|
||||
use alvr_common::{debug, once_cell::sync::Lazy, parking_lot::Mutex};
|
||||
use alvr_filesystem as afs;
|
||||
use alvr_session::{DriverLaunchAction, DriversBackup};
|
||||
use std::{
|
||||
|
@ -32,7 +32,7 @@ pub fn is_steamvr_running() -> bool {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn maybe_wrap_vrcompositor_launcher() -> StrResult {
|
||||
pub fn maybe_wrap_vrcompositor_launcher() -> alvr_common::anyhow::Result<()> {
|
||||
use std::fs;
|
||||
|
||||
let steamvr_bin_dir = alvr_server_io::steamvr_root_dir()?
|
||||
|
@ -42,17 +42,16 @@ pub fn maybe_wrap_vrcompositor_launcher() -> StrResult {
|
|||
|
||||
// In case of SteamVR update, vrcompositor will be restored
|
||||
if fs::read_link(&launcher_path).is_ok() {
|
||||
fs::remove_file(&launcher_path).map_err(err!())?; // recreate the link
|
||||
fs::remove_file(&launcher_path)?; // recreate the link
|
||||
} else {
|
||||
fs::rename(&launcher_path, steamvr_bin_dir.join("vrcompositor.real")).map_err(err!())?;
|
||||
fs::rename(&launcher_path, steamvr_bin_dir.join("vrcompositor.real"))?;
|
||||
}
|
||||
|
||||
std::os::unix::fs::symlink(
|
||||
afs::filesystem_layout_from_dashboard_exe(&env::current_exe().unwrap())
|
||||
.vrcompositor_wrapper(),
|
||||
&launcher_path,
|
||||
)
|
||||
.map_err(err!())?;
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -138,7 +137,7 @@ impl Launcher {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
show_err(maybe_wrap_vrcompositor_launcher());
|
||||
alvr_common::show_err(maybe_wrap_vrcompositor_launcher());
|
||||
|
||||
if !is_steamvr_running() {
|
||||
debug!("SteamVR is dead. Launching...");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use alvr_common::{prelude::*, DeviceMotion, Pose};
|
||||
use alvr_common::{info, DeviceMotion, LogEntry, Pose};
|
||||
use alvr_packets::{AudioDevicesList, ButtonValue};
|
||||
use alvr_session::SessionConfig;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
|
|
@ -11,12 +11,14 @@ use crate::{
|
|||
};
|
||||
use alvr_audio::AudioDevice;
|
||||
use alvr_common::{
|
||||
con_bail, debug, error,
|
||||
glam::{UVec2, Vec2},
|
||||
info,
|
||||
once_cell::sync::Lazy,
|
||||
parking_lot::{Mutex, RwLock},
|
||||
prelude::*,
|
||||
settings_schema::Switch,
|
||||
RelaxedAtomic, DEVICE_ID_TO_PATH, HEAD_ID, LEFT_HAND_ID, RIGHT_HAND_ID,
|
||||
warn, AnyhowToCon, ConResult, ConnectionError, RelaxedAtomic, ToCon, DEVICE_ID_TO_PATH,
|
||||
HEAD_ID, LEFT_HAND_ID, RIGHT_HAND_ID,
|
||||
};
|
||||
use alvr_events::{ButtonEvent, EventType, HapticsEvent, TrackingEvent};
|
||||
use alvr_packets::{
|
||||
|
@ -306,7 +308,7 @@ pub fn handshake_loop() {
|
|||
}
|
||||
|
||||
fn try_connect(mut client_ips: HashMap<IpAddr, String>) -> ConResult {
|
||||
let runtime = Runtime::new().map_err(to_con_e!())?;
|
||||
let runtime = Runtime::new().to_con()?;
|
||||
|
||||
let (mut proto_socket, client_ip) = ProtoControlSocket::connect_to(
|
||||
&runtime,
|
||||
|
@ -366,9 +368,7 @@ fn try_connect(mut client_ips: HashMap<IpAddr, String>) -> ConResult {
|
|||
display_name,
|
||||
streaming_capabilities,
|
||||
..
|
||||
} = proto_socket
|
||||
.recv(&runtime, Duration::from_secs(1))
|
||||
.map_err(to_con_e!())?
|
||||
} = proto_socket.recv(&runtime, Duration::from_secs(1))?
|
||||
{
|
||||
SERVER_DATA_MANAGER.write().update_client_list(
|
||||
client_hostname.clone(),
|
||||
|
@ -394,7 +394,7 @@ fn try_connect(mut client_ips: HashMap<IpAddr, String>) -> ConResult {
|
|||
let streaming_caps = if let Some(streaming_caps) = maybe_streaming_caps {
|
||||
streaming_caps
|
||||
} else {
|
||||
return con_fmt_e!("Only streaming clients are supported for now");
|
||||
con_bail!("Only streaming clients are supported for now");
|
||||
};
|
||||
|
||||
let settings = SERVER_DATA_MANAGER.read().settings().clone();
|
||||
|
@ -447,38 +447,37 @@ fn try_connect(mut client_ips: HashMap<IpAddr, String>) -> ConResult {
|
|||
warn!("Chosen refresh rate not supported. Using {fps}Hz");
|
||||
}
|
||||
|
||||
let game_audio_sample_rate = if let Switch::Enabled(game_audio_config) =
|
||||
&settings.audio.game_audio
|
||||
{
|
||||
let game_audio_device = AudioDevice::new_output(
|
||||
Some(settings.audio.linux_backend),
|
||||
game_audio_config.device.as_ref(),
|
||||
)
|
||||
.map_err(to_con_e!())?;
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
if let Switch::Enabled(microphone_desc) = &settings.audio.microphone {
|
||||
let (sink, source) = AudioDevice::new_virtual_microphone_pair(
|
||||
let game_audio_sample_rate =
|
||||
if let Switch::Enabled(game_audio_config) = &settings.audio.game_audio {
|
||||
let game_audio_device = AudioDevice::new_output(
|
||||
Some(settings.audio.linux_backend),
|
||||
microphone_desc.devices.clone(),
|
||||
game_audio_config.device.as_ref(),
|
||||
)
|
||||
.map_err(to_con_e!())?;
|
||||
if alvr_audio::is_same_device(&game_audio_device, &sink)
|
||||
|| alvr_audio::is_same_device(&game_audio_device, &source)
|
||||
{
|
||||
return con_fmt_e!("Game audio and microphone cannot point to the same device!");
|
||||
}
|
||||
}
|
||||
.to_con()?;
|
||||
|
||||
game_audio_device.input_sample_rate().map_err(to_con_e!())?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
if let Switch::Enabled(microphone_desc) = &settings.audio.microphone {
|
||||
let (sink, source) = AudioDevice::new_virtual_microphone_pair(
|
||||
Some(settings.audio.linux_backend),
|
||||
microphone_desc.devices.clone(),
|
||||
)
|
||||
.to_con()?;
|
||||
if alvr_audio::is_same_device(&game_audio_device, &sink)
|
||||
|| alvr_audio::is_same_device(&game_audio_device, &source)
|
||||
{
|
||||
con_bail!("Game audio and microphone cannot point to the same device!");
|
||||
}
|
||||
}
|
||||
|
||||
game_audio_device.input_sample_rate().to_con()?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let client_config = StreamConfigPacket {
|
||||
session: {
|
||||
let session = SERVER_DATA_MANAGER.read().session().clone();
|
||||
serde_json::to_string(&session).map_err(to_con_e!())?
|
||||
serde_json::to_string(&session).to_con()?
|
||||
},
|
||||
negotiated: serde_json::json!({
|
||||
"view_resolution": stream_view_resolution,
|
||||
|
@ -487,9 +486,7 @@ fn try_connect(mut client_ips: HashMap<IpAddr, String>) -> ConResult {
|
|||
})
|
||||
.to_string(),
|
||||
};
|
||||
proto_socket
|
||||
.send(&runtime, &client_config)
|
||||
.map_err(to_con_e!())?;
|
||||
proto_socket.send(&runtime, &client_config).to_con()?;
|
||||
|
||||
let (mut control_sender, mut control_receiver) = proto_socket.split();
|
||||
|
||||
|
@ -512,15 +509,15 @@ fn try_connect(mut client_ips: HashMap<IpAddr, String>) -> ConResult {
|
|||
|
||||
control_sender
|
||||
.send(&runtime, &ServerControlPacket::StartStream)
|
||||
.map_err(to_con_e!())?;
|
||||
.to_con()?;
|
||||
|
||||
match control_receiver.recv(&runtime, Duration::from_secs(1)) {
|
||||
Ok(ClientControlPacket::StreamReady) => (),
|
||||
Ok(_) => {
|
||||
return con_fmt_e!("Got unexpected packet waiting for stream ack");
|
||||
con_bail!("Got unexpected packet waiting for stream ack");
|
||||
}
|
||||
Err(e) => {
|
||||
return con_fmt_e!("Error while waiting for stream ack: {e}");
|
||||
con_bail!("Error while waiting for stream ack: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -545,8 +542,7 @@ fn try_connect(mut client_ips: HashMap<IpAddr, String>) -> ConResult {
|
|||
settings.connection.server_send_buffer_bytes,
|
||||
settings.connection.server_recv_buffer_bytes,
|
||||
settings.connection.packet_size as _,
|
||||
)
|
||||
.map_err(to_con_e!())?;
|
||||
)?;
|
||||
|
||||
let mut video_sender = stream_socket.request_stream(VIDEO);
|
||||
let game_audio_sender = stream_socket.request_stream(AUDIO);
|
||||
|
@ -648,7 +644,7 @@ fn try_connect(mut client_ips: HashMap<IpAddr, String>) -> ConResult {
|
|||
Some(settings.audio.linux_backend),
|
||||
config.devices,
|
||||
)
|
||||
.map_err(to_con_e!())?;
|
||||
.to_con()?;
|
||||
|
||||
#[cfg(windows)]
|
||||
if let Ok(id) = alvr_audio::get_windows_device_id(&source) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use alvr_common::{glam::EulerRot, prelude::*};
|
||||
use alvr_common::{anyhow::Result, glam::EulerRot};
|
||||
use alvr_packets::FaceData;
|
||||
use alvr_session::FaceTrackingSinkConfig;
|
||||
use bytes::{BufMut, BytesMut};
|
||||
|
@ -16,16 +16,14 @@ pub struct FaceTrackingSink {
|
|||
}
|
||||
|
||||
impl FaceTrackingSink {
|
||||
pub fn new(config: FaceTrackingSinkConfig, local_osc_port: u16) -> StrResult<Self> {
|
||||
pub fn new(config: FaceTrackingSinkConfig, local_osc_port: u16) -> Result<Self> {
|
||||
let port = match config {
|
||||
FaceTrackingSinkConfig::VrchatEyeOsc { port } => port,
|
||||
FaceTrackingSinkConfig::VrcFaceTracking => VRCFT_PORT,
|
||||
};
|
||||
|
||||
let socket = UdpSocket::bind(format!("127.0.0.1:{local_osc_port}")).map_err(err!())?;
|
||||
socket
|
||||
.connect(format!("127.0.0.1:{port}"))
|
||||
.map_err(err!())?;
|
||||
let socket = UdpSocket::bind(format!("127.0.0.1:{local_osc_port}"))?;
|
||||
socket.connect(format!("127.0.0.1:{port}"))?;
|
||||
|
||||
Ok(Self {
|
||||
config,
|
||||
|
|
|
@ -23,11 +23,11 @@ mod bindings {
|
|||
use bindings::*;
|
||||
|
||||
use alvr_common::{
|
||||
error,
|
||||
glam::Quat,
|
||||
log,
|
||||
once_cell::sync::Lazy,
|
||||
parking_lot::{Mutex, RwLock},
|
||||
prelude::*,
|
||||
};
|
||||
use alvr_events::EventType;
|
||||
use alvr_filesystem::{self as afs, Layout};
|
||||
|
@ -51,7 +51,9 @@ use sysinfo::{ProcessRefreshKind, RefreshKind, SystemExt};
|
|||
use tokio::{runtime::Runtime, sync::broadcast};
|
||||
|
||||
static FILESYSTEM_LAYOUT: Lazy<Layout> = Lazy::new(|| {
|
||||
afs::filesystem_layout_from_openvr_driver_root_dir(&alvr_server_io::get_driver_dir().unwrap())
|
||||
afs::filesystem_layout_from_openvr_driver_root_dir(
|
||||
&alvr_server_io::get_driver_dir_from_registered().unwrap(),
|
||||
)
|
||||
});
|
||||
static SERVER_DATA_MANAGER: Lazy<RwLock<ServerDataManager>> =
|
||||
Lazy::new(|| RwLock::new(ServerDataManager::new(&FILESYSTEM_LAYOUT.session())));
|
||||
|
@ -226,9 +228,7 @@ fn init() {
|
|||
logging_backend::init_logging(events_sender.clone());
|
||||
|
||||
if let Some(runtime) = WEBSERVER_RUNTIME.lock().as_mut() {
|
||||
runtime.spawn(alvr_common::show_err_async(web_server::web_server(
|
||||
events_sender,
|
||||
)));
|
||||
runtime.spawn(async { alvr_common::show_err(web_server::web_server(events_sender).await) });
|
||||
}
|
||||
|
||||
SERVER_DATA_MANAGER.write().clean_client_list();
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// todo: add more emulation modes
|
||||
|
||||
use crate::{FfiOpenvrProperty, FfiOpenvrPropertyValue, SERVER_DATA_MANAGER};
|
||||
use alvr_common::{prelude::*, settings_schema::Switch, HEAD_ID, LEFT_HAND_ID, RIGHT_HAND_ID};
|
||||
use alvr_common::{info, settings_schema::Switch, HEAD_ID, LEFT_HAND_ID, RIGHT_HAND_ID};
|
||||
use alvr_session::{
|
||||
ControllersEmulationMode, HeadsetEmulationMode, OpenvrPropValue,
|
||||
OpenvrPropertyKey::{self, *},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use alvr_common::{prelude::*, StrResult, ALVR_NAME};
|
||||
use alvr_common::{anyhow::Result, con_bail, ConResult, ToCon, ALVR_NAME};
|
||||
use alvr_sockets::{CONTROL_PORT, HANDSHAKE_PACKET_SIZE_BYTES, LOCAL_IP};
|
||||
use std::{
|
||||
io::ErrorKind,
|
||||
|
@ -12,11 +12,9 @@ pub struct WelcomeSocket {
|
|||
}
|
||||
|
||||
impl WelcomeSocket {
|
||||
pub fn new(read_timeout: Duration) -> StrResult<Self> {
|
||||
let socket = UdpSocket::bind((LOCAL_IP, CONTROL_PORT)).map_err(err!())?;
|
||||
socket
|
||||
.set_read_timeout(Some(read_timeout))
|
||||
.map_err(err!())?;
|
||||
pub fn new(read_timeout: Duration) -> Result<Self> {
|
||||
let socket = UdpSocket::bind((LOCAL_IP, CONTROL_PORT))?;
|
||||
socket.set_read_timeout(Some(read_timeout))?;
|
||||
|
||||
Ok(Self {
|
||||
socket,
|
||||
|
@ -30,9 +28,9 @@ impl WelcomeSocket {
|
|||
Ok(pair) => pair,
|
||||
Err(e) => {
|
||||
if matches!(e.kind(), ErrorKind::TimedOut | ErrorKind::WouldBlock) {
|
||||
return timeout();
|
||||
return alvr_common::timeout();
|
||||
} else {
|
||||
return con_fmt_e!("{e}");
|
||||
con_bail!("{e}");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -46,14 +44,14 @@ impl WelcomeSocket {
|
|||
let received_protocol_id = u64::from_le_bytes(protocol_id_bytes);
|
||||
|
||||
if received_protocol_id != alvr_common::protocol_id() {
|
||||
return con_fmt_e!("Found incompatible client! Upgrade or downgrade\nExpected protocol ID {}, Found {received_protocol_id}",
|
||||
con_bail!("Found incompatible client! Upgrade or downgrade\nExpected protocol ID {}, Found {received_protocol_id}",
|
||||
alvr_common::protocol_id());
|
||||
}
|
||||
|
||||
let mut hostname_bytes = [0; 32];
|
||||
hostname_bytes.copy_from_slice(&self.buffer[24..56]);
|
||||
let hostname = std::str::from_utf8(&hostname_bytes)
|
||||
.map_err(to_con_e!())?
|
||||
.to_con()?
|
||||
.trim_end_matches('\x00')
|
||||
.to_owned();
|
||||
|
||||
|
@ -61,11 +59,11 @@ impl WelcomeSocket {
|
|||
} else if &self.buffer[..16] == b"\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00ALVR"
|
||||
|| &self.buffer[..5] == b"\x01ALVR"
|
||||
{
|
||||
con_fmt_e!("Found old client. Please upgrade")
|
||||
con_bail!("Found old client. Please upgrade")
|
||||
} else {
|
||||
// Unexpected packet.
|
||||
// Note: no need to check for v12 and v13, not found in the wild anymore
|
||||
con_fmt_e!("Found unrelated packet during discovery")
|
||||
con_bail!("Found unrelated packet during discovery")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,10 @@ use crate::{
|
|||
connection::ClientDisconnectRequest, DECODER_CONFIG, DISCONNECT_CLIENT_NOTIFIER,
|
||||
FILESYSTEM_LAYOUT, SERVER_DATA_MANAGER, VIDEO_MIRROR_SENDER, VIDEO_RECORDING_FILE,
|
||||
};
|
||||
use alvr_common::{log, prelude::*};
|
||||
use alvr_common::{
|
||||
anyhow::{self, Result},
|
||||
error, info, log, warn,
|
||||
};
|
||||
use alvr_events::{Event, EventType};
|
||||
use alvr_packets::{ClientListAction, ServerRequest};
|
||||
use alvr_session::ConnectionState;
|
||||
|
@ -22,28 +25,21 @@ use tokio_util::codec::{BytesCodec, FramedRead};
|
|||
|
||||
pub const WS_BROADCAST_CAPACITY: usize = 256;
|
||||
|
||||
fn reply(code: StatusCode) -> StrResult<Response<Body>> {
|
||||
Response::builder()
|
||||
.status(code)
|
||||
.body(Body::empty())
|
||||
.map_err(err!())
|
||||
fn reply(code: StatusCode) -> Result<Response<Body>> {
|
||||
Ok(Response::builder().status(code).body(Body::empty())?)
|
||||
}
|
||||
|
||||
async fn from_request_body<T: DeserializeOwned>(request: Request<Body>) -> StrResult<T> {
|
||||
json::from_reader(
|
||||
hyper::body::aggregate(request)
|
||||
.await
|
||||
.map_err(err!())?
|
||||
.reader(),
|
||||
)
|
||||
.map_err(err!())
|
||||
async fn from_request_body<T: DeserializeOwned>(request: Request<Body>) -> Result<T> {
|
||||
Ok(json::from_reader(
|
||||
hyper::body::aggregate(request).await?.reader(),
|
||||
)?)
|
||||
}
|
||||
|
||||
async fn websocket<T: Clone + Send + 'static>(
|
||||
request: Request<Body>,
|
||||
sender: broadcast::Sender<T>,
|
||||
message_builder: impl Fn(T) -> protocol::Message + Send + Sync + 'static,
|
||||
) -> StrResult<Response<Body>> {
|
||||
) -> Result<Response<Body>> {
|
||||
if let Some(key) = request.headers().typed_get::<headers::SecWebsocketKey>() {
|
||||
tokio::spawn(async move {
|
||||
match hyper::upgrade::on(request).await {
|
||||
|
@ -79,8 +75,7 @@ async fn websocket<T: Clone + Send + 'static>(
|
|||
|
||||
let mut response = Response::builder()
|
||||
.status(StatusCode::SWITCHING_PROTOCOLS)
|
||||
.body(Body::empty())
|
||||
.map_err(err!())?;
|
||||
.body(Body::empty())?;
|
||||
|
||||
let h = response.headers_mut();
|
||||
h.typed_insert(headers::Upgrade::websocket());
|
||||
|
@ -96,7 +91,7 @@ async fn websocket<T: Clone + Send + 'static>(
|
|||
async fn http_api(
|
||||
request: Request<Body>,
|
||||
events_sender: broadcast::Sender<Event>,
|
||||
) -> StrResult<Response<Body>> {
|
||||
) -> Result<Response<Body>> {
|
||||
let mut response = match request.uri().path() {
|
||||
// New unified requests
|
||||
"/api/dashboard-request" => {
|
||||
|
@ -251,9 +246,7 @@ async fn http_api(
|
|||
builder = builder.header(CONTENT_TYPE, "application/wasm");
|
||||
}
|
||||
|
||||
builder
|
||||
.body(Body::wrap_stream(FramedRead::new(file, BytesCodec::new())))
|
||||
.map_err(err!())?
|
||||
builder.body(Body::wrap_stream(FramedRead::new(file, BytesCodec::new())))?
|
||||
} else {
|
||||
reply(StatusCode::NOT_FOUND)?
|
||||
}
|
||||
|
@ -263,7 +256,7 @@ async fn http_api(
|
|||
|
||||
response.headers_mut().insert(
|
||||
CACHE_CONTROL,
|
||||
HeaderValue::from_str("no-cache, no-store, must-revalidate").map_err(err!())?,
|
||||
HeaderValue::from_str("no-cache, no-store, must-revalidate")?,
|
||||
);
|
||||
response
|
||||
.headers_mut()
|
||||
|
@ -272,7 +265,7 @@ async fn http_api(
|
|||
Ok(response)
|
||||
}
|
||||
|
||||
pub async fn web_server(events_sender: broadcast::Sender<Event>) -> StrResult {
|
||||
pub async fn web_server(events_sender: broadcast::Sender<Event>) -> Result<()> {
|
||||
let web_server_port = SERVER_DATA_MANAGER
|
||||
.read()
|
||||
.settings()
|
||||
|
@ -282,7 +275,7 @@ pub async fn web_server(events_sender: broadcast::Sender<Event>) -> StrResult {
|
|||
let service = service::make_service_fn(|_| {
|
||||
let events_sender = events_sender.clone();
|
||||
async move {
|
||||
StrResult::Ok(service::service_fn(move |request| {
|
||||
Ok::<_, anyhow::Error>(service::service_fn(move |request| {
|
||||
let events_sender = events_sender.clone();
|
||||
async move {
|
||||
let res = http_api(request, events_sender).await;
|
||||
|
@ -296,11 +289,10 @@ pub async fn web_server(events_sender: broadcast::Sender<Event>) -> StrResult {
|
|||
}
|
||||
});
|
||||
|
||||
hyper::Server::bind(&SocketAddr::new(
|
||||
Ok(hyper::Server::bind(&SocketAddr::new(
|
||||
"0.0.0.0".parse().unwrap(),
|
||||
web_server_port,
|
||||
))
|
||||
.serve(service)
|
||||
.await
|
||||
.map_err(err!())
|
||||
.await?)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,10 @@ pub use firewall::*;
|
|||
pub use openvr_drivers::*;
|
||||
pub use openvrpaths::*;
|
||||
|
||||
use alvr_common::prelude::*;
|
||||
use alvr_common::{
|
||||
anyhow::{bail, Result},
|
||||
error, info,
|
||||
};
|
||||
use alvr_events::EventType;
|
||||
use alvr_packets::{AudioDevicesList, ClientListAction, GpuVendor, PathSegment, PathValuePair};
|
||||
use alvr_session::{ClientConnectionConfig, ConnectionState, SessionConfig, Settings};
|
||||
|
@ -20,8 +23,10 @@ use std::{
|
|||
};
|
||||
use wgpu::AdapterInfo;
|
||||
|
||||
fn save_session(session: &SessionConfig, path: &Path) -> StrResult {
|
||||
fs::write(path, json::to_string_pretty(session).map_err(err!())?).map_err(err!())
|
||||
fn save_session(session: &SessionConfig, path: &Path) -> Result<()> {
|
||||
fs::write(path, json::to_string_pretty(session)?)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// SessionConfig wrapper that saves session.json on destruction.
|
||||
|
@ -155,7 +160,7 @@ impl ServerDataManager {
|
|||
}
|
||||
|
||||
// Note: "value" can be any session subtree, in json format.
|
||||
pub fn set_values(&mut self, descs: Vec<PathValuePair>) -> StrResult {
|
||||
pub fn set_values(&mut self, descs: Vec<PathValuePair>) -> Result<()> {
|
||||
let mut session_json = serde_json::to_value(self.session.clone()).unwrap();
|
||||
|
||||
for desc in descs {
|
||||
|
@ -166,22 +171,14 @@ impl ServerDataManager {
|
|||
if let Some(name) = session_ref.get_mut(name) {
|
||||
name
|
||||
} else {
|
||||
return fmt_e!(
|
||||
"From path {:?}: segment \"{}\" not found",
|
||||
desc.path,
|
||||
name
|
||||
);
|
||||
bail!("From path {:?}: segment \"{name}\" not found", desc.path);
|
||||
}
|
||||
}
|
||||
PathSegment::Index(index) => {
|
||||
if let Some(index) = session_ref.get_mut(index) {
|
||||
index
|
||||
} else {
|
||||
return fmt_e!(
|
||||
"From path {:?}: segment [{}] not found",
|
||||
desc.path,
|
||||
index
|
||||
);
|
||||
bail!("From path {:?}: segment [{index}] not found", desc.path);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -190,7 +187,7 @@ impl ServerDataManager {
|
|||
}
|
||||
|
||||
// session_json has been updated
|
||||
self.session = serde_json::from_value(session_json).map_err(err!())?;
|
||||
self.session = serde_json::from_value(session_json)?;
|
||||
self.settings = self.session.to_settings();
|
||||
|
||||
save_session(&self.session, &self.session_path).unwrap();
|
||||
|
@ -327,24 +324,21 @@ impl ServerDataManager {
|
|||
}
|
||||
|
||||
#[cfg_attr(not(target_os = "linux"), allow(unused_variables))]
|
||||
pub fn get_audio_devices_list(&self) -> StrResult<AudioDevicesList> {
|
||||
pub fn get_audio_devices_list(&self) -> Result<AudioDevicesList> {
|
||||
#[cfg(target_os = "linux")]
|
||||
let host = match self.session.to_settings().audio.linux_backend {
|
||||
alvr_session::LinuxAudioBackend::Alsa => cpal::host_from_id(cpal::HostId::Alsa),
|
||||
alvr_session::LinuxAudioBackend::Jack => cpal::host_from_id(cpal::HostId::Jack),
|
||||
}
|
||||
.map_err(err!())?;
|
||||
alvr_session::LinuxAudioBackend::Alsa => cpal::host_from_id(cpal::HostId::Alsa)?,
|
||||
alvr_session::LinuxAudioBackend::Jack => cpal::host_from_id(cpal::HostId::Jack)?,
|
||||
};
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
let host = cpal::default_host();
|
||||
|
||||
let output = host
|
||||
.output_devices()
|
||||
.map_err(err!())?
|
||||
.output_devices()?
|
||||
.filter_map(|d| d.name().ok())
|
||||
.collect::<Vec<_>>();
|
||||
let input = host
|
||||
.input_devices()
|
||||
.map_err(err!())?
|
||||
.input_devices()?
|
||||
.filter_map(|d| d.name().ok())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
use crate::openvrpaths;
|
||||
use alvr_common::prelude::*;
|
||||
use alvr_common::{
|
||||
anyhow::{bail, Result},
|
||||
ToAny,
|
||||
};
|
||||
use serde_json as json;
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
|
@ -7,19 +10,17 @@ use std::{
|
|||
path::PathBuf,
|
||||
};
|
||||
|
||||
pub fn get_registered_drivers() -> StrResult<Vec<PathBuf>> {
|
||||
pub fn get_registered_drivers() -> Result<Vec<PathBuf>> {
|
||||
Ok(openvrpaths::from_openvr_paths(
|
||||
openvrpaths::load_openvr_paths_json()?
|
||||
.get_mut("external_drivers")
|
||||
.ok_or_else(enone!())?,
|
||||
.to_any()?,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn driver_registration(driver_paths: &[PathBuf], register: bool) -> StrResult {
|
||||
pub fn driver_registration(driver_paths: &[PathBuf], register: bool) -> Result<()> {
|
||||
let mut openvr_paths_json = openvrpaths::load_openvr_paths_json()?;
|
||||
let paths_json_ref = openvr_paths_json
|
||||
.get_mut("external_drivers")
|
||||
.ok_or_else(enone!())?;
|
||||
let paths_json_ref = openvr_paths_json.get_mut("external_drivers").to_any()?;
|
||||
|
||||
let mut paths: HashSet<_> = openvrpaths::from_openvr_paths(paths_json_ref)
|
||||
.into_iter()
|
||||
|
@ -40,25 +41,22 @@ pub fn driver_registration(driver_paths: &[PathBuf], register: bool) -> StrResul
|
|||
openvrpaths::save_openvr_paths_json(&openvr_paths_json)
|
||||
}
|
||||
|
||||
fn get_driver_dir_from_registered() -> StrResult<PathBuf> {
|
||||
pub fn get_driver_dir_from_registered() -> Result<PathBuf> {
|
||||
for dir in get_registered_drivers()? {
|
||||
let maybe_driver_name = || -> StrResult<_> {
|
||||
let manifest_string =
|
||||
fs::read_to_string(dir.join("driver.vrdrivermanifest")).map_err(err!())?;
|
||||
let maybe_driver_name = || -> Result<_> {
|
||||
let manifest_string = fs::read_to_string(dir.join("driver.vrdrivermanifest"))?;
|
||||
let mut manifest_map =
|
||||
json::from_str::<HashMap<String, json::Value>>(&manifest_string).map_err(err!())?;
|
||||
json::from_str::<HashMap<String, json::Value>>(&manifest_string)?;
|
||||
|
||||
manifest_map.remove("name").ok_or_else(enone!())
|
||||
manifest_map.remove("name").to_any()
|
||||
}();
|
||||
|
||||
if maybe_driver_name == Ok(json::Value::String("alvr_server".to_owned())) {
|
||||
return Ok(dir);
|
||||
if let Ok(json::Value::String(str)) = maybe_driver_name {
|
||||
if str == "alvr_server" {
|
||||
return Ok(dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt_e!("ALVR driver path not registered")
|
||||
}
|
||||
|
||||
pub fn get_driver_dir() -> StrResult<PathBuf> {
|
||||
get_driver_dir_from_registered()
|
||||
.map_err(|e| format!("ALVR driver path not stored and not registered ({e})"))
|
||||
bail!("ALVR driver path not registered")
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use alvr_common::prelude::*;
|
||||
use alvr_common::{
|
||||
anyhow::{bail, Result},
|
||||
ToAny,
|
||||
};
|
||||
use encoding_rs_io::DecodeReaderBytes;
|
||||
use serde_json as json;
|
||||
use std::{
|
||||
|
@ -7,37 +10,39 @@ use std::{
|
|||
path::PathBuf,
|
||||
};
|
||||
|
||||
fn openvr_source_file_path() -> StrResult<PathBuf> {
|
||||
fn openvr_source_file_path() -> Result<PathBuf> {
|
||||
let path = if cfg!(windows) {
|
||||
dirs::cache_dir()
|
||||
} else {
|
||||
dirs::config_dir()
|
||||
}
|
||||
.ok_or_else(enone!())?
|
||||
.to_any()?
|
||||
.join("openvr/openvrpaths.vrpath");
|
||||
|
||||
if path.exists() {
|
||||
Ok(path)
|
||||
} else {
|
||||
fmt_e!("{} does not exist", path.to_string_lossy())
|
||||
bail!("{} does not exist", path.to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn load_openvr_paths_json() -> StrResult<json::Value> {
|
||||
let file = File::open(openvr_source_file_path()?).map_err(err!())?;
|
||||
pub(crate) fn load_openvr_paths_json() -> Result<json::Value> {
|
||||
let file = File::open(openvr_source_file_path()?)?;
|
||||
|
||||
let mut file_content_decoded = String::new();
|
||||
DecodeReaderBytes::new(&file)
|
||||
.read_to_string(&mut file_content_decoded)
|
||||
.map_err(err!())?;
|
||||
DecodeReaderBytes::new(&file).read_to_string(&mut file_content_decoded)?;
|
||||
|
||||
json::from_str(&file_content_decoded).map_err(err!())
|
||||
let value = json::from_str(&file_content_decoded)?;
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub(crate) fn save_openvr_paths_json(openvr_paths: &json::Value) -> StrResult {
|
||||
let file_content = json::to_string_pretty(openvr_paths).map_err(err!())?;
|
||||
pub(crate) fn save_openvr_paths_json(openvr_paths: &json::Value) -> Result<()> {
|
||||
let file_content = json::to_string_pretty(openvr_paths)?;
|
||||
|
||||
fs::write(openvr_source_file_path()?, file_content).map_err(err!())
|
||||
fs::write(openvr_source_file_path()?, file_content)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn from_openvr_paths(paths: &json::Value) -> Vec<std::path::PathBuf> {
|
||||
|
@ -63,15 +68,12 @@ pub(crate) fn to_openvr_paths(paths: &[PathBuf]) -> json::Value {
|
|||
json::Value::Array(paths_vec)
|
||||
}
|
||||
|
||||
fn get_single_openvr_path(path_type: &str) -> StrResult<PathBuf> {
|
||||
fn get_single_openvr_path(path_type: &str) -> Result<PathBuf> {
|
||||
let openvr_paths_json = load_openvr_paths_json()?;
|
||||
let paths_json = openvr_paths_json.get(path_type).ok_or_else(enone!())?;
|
||||
from_openvr_paths(paths_json)
|
||||
.get(0)
|
||||
.cloned()
|
||||
.ok_or_else(enone!())
|
||||
let paths_json = openvr_paths_json.get(path_type).to_any()?;
|
||||
from_openvr_paths(paths_json).get(0).cloned().to_any()
|
||||
}
|
||||
|
||||
pub fn steamvr_root_dir() -> StrResult<PathBuf> {
|
||||
pub fn steamvr_root_dir() -> Result<PathBuf> {
|
||||
get_single_openvr_path("runtime")
|
||||
}
|
||||
|
|
|
@ -3,7 +3,11 @@ mod settings;
|
|||
pub use settings::*;
|
||||
pub use settings_schema;
|
||||
|
||||
use alvr_common::{prelude::*, semver::Version, ALVR_VERSION};
|
||||
use alvr_common::{
|
||||
anyhow::{bail, Result},
|
||||
semver::Version,
|
||||
ToAny, ALVR_VERSION,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json as json;
|
||||
use settings_schema::{NumberType, SchemaNode};
|
||||
|
@ -159,7 +163,7 @@ impl SessionConfig {
|
|||
// deserialization will fail if the type of values does not match. Because of this,
|
||||
// `session_settings` must be handled separately to do a better job of retrieving data using the
|
||||
// settings schema.
|
||||
pub fn merge_from_json(&mut self, json_value: &json::Value) -> StrResult {
|
||||
pub fn merge_from_json(&mut self, json_value: &json::Value) -> Result<()> {
|
||||
const SESSION_SETTINGS_STR: &str = "session_settings";
|
||||
|
||||
if let Ok(session_desc) = json::from_value(json_value.clone()) {
|
||||
|
@ -167,15 +171,16 @@ impl SessionConfig {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
let old_session_json = json::to_value(&self).map_err(err!())?;
|
||||
let old_session_fields = old_session_json.as_object().ok_or_else(enone!())?;
|
||||
// Note: unwrap is safe because current session is expected to serialize correctly
|
||||
let old_session_json = json::to_value(&self).unwrap();
|
||||
let old_session_fields = old_session_json.as_object().unwrap();
|
||||
|
||||
let maybe_session_settings_json =
|
||||
json_value
|
||||
.get(SESSION_SETTINGS_STR)
|
||||
.map(|new_session_settings_json| {
|
||||
extrapolate_session_settings_from_session_settings(
|
||||
&old_session_json[SESSION_SETTINGS_STR],
|
||||
&old_session_fields[SESSION_SETTINGS_STR],
|
||||
new_session_settings_json,
|
||||
&Settings::schema(settings::session_settings_default()),
|
||||
)
|
||||
|
@ -196,7 +201,9 @@ impl SessionConfig {
|
|||
let mut session_desc_mut =
|
||||
json::from_value::<SessionConfig>(json::Value::Object(new_fields)).unwrap_or_default();
|
||||
|
||||
match json::from_value::<SessionSettings>(maybe_session_settings_json.ok_or_else(enone!())?)
|
||||
match maybe_session_settings_json
|
||||
.to_any()
|
||||
.and_then(|s| serde_json::from_value::<SessionSettings>(s).map_err(|e| e.into()))
|
||||
{
|
||||
Ok(session_settings) => {
|
||||
session_desc_mut.session_settings = session_settings;
|
||||
|
@ -206,7 +213,7 @@ impl SessionConfig {
|
|||
Err(e) => {
|
||||
*self = session_desc_mut;
|
||||
|
||||
fmt_e!("Error while deserializing extrapolated session settings: {e}")
|
||||
bail!("Error while deserializing extrapolated session settings: {e}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::{Ldc, CONTROL_PORT, LOCAL_IP};
|
||||
use alvr_common::prelude::*;
|
||||
use alvr_common::{anyhow::Result, ConResult, ToCon};
|
||||
use bytes::Bytes;
|
||||
use futures::{
|
||||
stream::{SplitSink, SplitStream},
|
||||
|
@ -20,11 +20,11 @@ pub struct ControlSocketSender<T> {
|
|||
}
|
||||
|
||||
impl<S: Serialize> ControlSocketSender<S> {
|
||||
pub fn send(&mut self, runtime: &Runtime, packet: &S) -> StrResult {
|
||||
let packet_bytes = bincode::serialize(packet).map_err(err!())?;
|
||||
runtime
|
||||
.block_on(self.inner.send(packet_bytes.into()))
|
||||
.map_err(err!())
|
||||
pub fn send(&mut self, runtime: &Runtime, packet: &S) -> Result<()> {
|
||||
let packet_bytes = bincode::serialize(packet)?;
|
||||
runtime.block_on(self.inner.send(packet_bytes.into()))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,20 +37,18 @@ impl<R: DeserializeOwned> ControlSocketReceiver<R> {
|
|||
pub fn recv(&mut self, runtime: &Runtime, timeout: Duration) -> ConResult<R> {
|
||||
let packet_bytes = runtime.block_on(async {
|
||||
tokio::select! {
|
||||
res = self.inner.next() => {
|
||||
res.map(|p| p.map_err(to_con_e!())).ok_or_else(enone!()).map_err(to_con_e!())
|
||||
}
|
||||
res = self.inner.next() => res.map(|p| p.to_con()).to_con(),
|
||||
_ = time::sleep(timeout) => alvr_common::timeout(),
|
||||
}
|
||||
})??;
|
||||
bincode::deserialize(&packet_bytes).map_err(to_con_e!())
|
||||
bincode::deserialize(&packet_bytes).to_con()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_server_listener(runtime: &Runtime) -> StrResult<TcpListener> {
|
||||
runtime
|
||||
.block_on(TcpListener::bind((LOCAL_IP, CONTROL_PORT)))
|
||||
.map_err(err!())
|
||||
pub fn get_server_listener(runtime: &Runtime) -> Result<TcpListener> {
|
||||
let listener = runtime.block_on(TcpListener::bind((LOCAL_IP, CONTROL_PORT)))?;
|
||||
|
||||
Ok(listener)
|
||||
}
|
||||
|
||||
// Proto-control-socket that can send and receive any packet. After the split, only the packets of
|
||||
|
@ -78,7 +76,7 @@ impl ProtoControlSocket {
|
|||
.collect::<Vec<_>>();
|
||||
runtime.block_on(async {
|
||||
tokio::select! {
|
||||
res = TcpStream::connect(client_addresses.as_slice()) => res.map_err(to_con_e!()),
|
||||
res = TcpStream::connect(client_addresses.as_slice()) => res.to_con(),
|
||||
_ = time::sleep(timeout) => alvr_common::timeout(),
|
||||
}
|
||||
})?
|
||||
|
@ -86,7 +84,7 @@ impl ProtoControlSocket {
|
|||
PeerType::Server(listener) => {
|
||||
let (socket, _) = runtime.block_on(async {
|
||||
tokio::select! {
|
||||
res = listener.accept() => res.map_err(to_con_e!()),
|
||||
res = listener.accept() => res.to_con(),
|
||||
_ = time::sleep(timeout) => alvr_common::timeout(),
|
||||
}
|
||||
})?;
|
||||
|
@ -94,18 +92,17 @@ impl ProtoControlSocket {
|
|||
}
|
||||
};
|
||||
|
||||
socket.set_nodelay(true).map_err(to_con_e!())?;
|
||||
let peer_ip = socket.peer_addr().map_err(to_con_e!())?.ip();
|
||||
socket.set_nodelay(true).to_con()?;
|
||||
let peer_ip = socket.peer_addr().to_con()?.ip();
|
||||
let socket = Framed::new(socket, Ldc::new());
|
||||
|
||||
Ok((Self { inner: socket }, peer_ip))
|
||||
}
|
||||
|
||||
pub fn send<S: Serialize>(&mut self, runtime: &Runtime, packet: &S) -> StrResult {
|
||||
let packet_bytes = bincode::serialize(packet).map_err(err!())?;
|
||||
runtime
|
||||
.block_on(self.inner.send(packet_bytes.into()))
|
||||
.map_err(err!())
|
||||
pub fn send<S: Serialize>(&mut self, runtime: &Runtime, packet: &S) -> Result<()> {
|
||||
runtime.block_on(self.inner.send(bincode::serialize(packet)?.into()))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn recv<R: DeserializeOwned>(
|
||||
|
@ -116,14 +113,13 @@ impl ProtoControlSocket {
|
|||
let packet_bytes = runtime
|
||||
.block_on(async {
|
||||
tokio::select! {
|
||||
res = self.inner.next() => res.map(|p| p.map_err(to_con_e!())),
|
||||
res = self.inner.next() => res.map(|p| p.to_con()),
|
||||
_ = time::sleep(timeout) => Some(alvr_common::timeout()),
|
||||
}
|
||||
})
|
||||
.ok_or_else(enone!())
|
||||
.map_err(to_con_e!())??;
|
||||
.to_con()??;
|
||||
|
||||
bincode::deserialize(&packet_bytes).map_err(to_con_e!())
|
||||
bincode::deserialize(&packet_bytes).to_con()
|
||||
}
|
||||
|
||||
pub fn split<S: Serialize, R: DeserializeOwned>(
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
mod tcp;
|
||||
mod udp;
|
||||
|
||||
use alvr_common::prelude::*;
|
||||
use alvr_common::{anyhow::Result, con_bail, debug, error, info, AnyhowToCon, ConResult};
|
||||
use alvr_session::{SocketBufferSize, SocketProtocol};
|
||||
use bytes::{Buf, BufMut, BytesMut};
|
||||
use futures::SinkExt;
|
||||
|
@ -28,11 +28,11 @@ pub fn set_socket_buffers(
|
|||
socket: &socket2::Socket,
|
||||
send_buffer_bytes: SocketBufferSize,
|
||||
recv_buffer_bytes: SocketBufferSize,
|
||||
) -> StrResult {
|
||||
) -> Result<()> {
|
||||
info!(
|
||||
"Initial socket buffer size: send: {}B, recv: {}B",
|
||||
socket.send_buffer_size().map_err(err!())?,
|
||||
socket.recv_buffer_size().map_err(err!())?
|
||||
socket.send_buffer_size()?,
|
||||
socket.recv_buffer_size()?
|
||||
);
|
||||
|
||||
{
|
||||
|
@ -48,7 +48,7 @@ pub fn set_socket_buffers(
|
|||
} else {
|
||||
info!(
|
||||
"Set socket send buffer succeeded: {}",
|
||||
socket.send_buffer_size().map_err(err!())?
|
||||
socket.send_buffer_size()?
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ pub fn set_socket_buffers(
|
|||
} else {
|
||||
info!(
|
||||
"Set socket recv buffer succeeded: {}",
|
||||
socket.recv_buffer_size().map_err(err!())?
|
||||
socket.recv_buffer_size()?
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -124,38 +124,34 @@ pub struct StreamSender<T> {
|
|||
}
|
||||
|
||||
impl<T: Serialize> StreamSender<T> {
|
||||
fn send_buffer(&self, runtime: &Runtime, buffer: BytesMut) -> StrResult {
|
||||
fn send_buffer(&self, runtime: &Runtime, buffer: BytesMut) -> Result<()> {
|
||||
match &self.socket {
|
||||
StreamSendSocket::Udp(socket) => runtime
|
||||
.block_on(
|
||||
socket
|
||||
.inner
|
||||
.lock()
|
||||
.feed((buffer.freeze(), socket.peer_addr)),
|
||||
)
|
||||
.map_err(err!()),
|
||||
StreamSendSocket::Tcp(socket) => runtime
|
||||
.block_on(socket.lock().feed(buffer.freeze()))
|
||||
.map_err(err!()),
|
||||
StreamSendSocket::Udp(socket) => Ok(runtime.block_on(
|
||||
socket
|
||||
.inner
|
||||
.lock()
|
||||
.feed((buffer.freeze(), socket.peer_addr)),
|
||||
)?),
|
||||
StreamSendSocket::Tcp(socket) => {
|
||||
Ok(runtime.block_on(socket.lock().feed(buffer.freeze()))?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send(&mut self, runtime: &Runtime, header: &T, payload_buffer: Vec<u8>) -> StrResult {
|
||||
pub fn send(&mut self, runtime: &Runtime, header: &T, payload_buffer: Vec<u8>) -> Result<()> {
|
||||
// packet layout:
|
||||
// [ 2B (stream ID) | 4B (packet index) | 4B (packet shard count) | 4B (shard index)]
|
||||
// this escluses length delimited coding, which is handled by the TCP backend
|
||||
const OFFSET: usize = 2 + 4 + 4 + 4;
|
||||
let max_shard_data_size = self.max_packet_size - OFFSET;
|
||||
|
||||
let header_size = bincode::serialized_size(header).map_err(err!()).unwrap() as usize;
|
||||
let header_size = bincode::serialized_size(header).unwrap() as usize;
|
||||
self.header_buffer.clear();
|
||||
if self.header_buffer.capacity() < header_size {
|
||||
// If the buffer is empty, with this call we request a capacity of "header_size".
|
||||
self.header_buffer.reserve(header_size);
|
||||
}
|
||||
bincode::serialize_into(&mut self.header_buffer, header)
|
||||
.map_err(err!())
|
||||
.unwrap();
|
||||
bincode::serialize_into(&mut self.header_buffer, header).unwrap();
|
||||
let header_shards = self.header_buffer.chunks(max_shard_data_size);
|
||||
|
||||
let payload_shards = payload_buffer.chunks(max_shard_data_size);
|
||||
|
@ -175,13 +171,8 @@ impl<T: Serialize> StreamSender<T> {
|
|||
}
|
||||
|
||||
match &self.socket {
|
||||
StreamSendSocket::Udp(socket) => runtime
|
||||
.block_on(socket.inner.lock().flush())
|
||||
.map_err(err!())?,
|
||||
|
||||
StreamSendSocket::Tcp(socket) => {
|
||||
runtime.block_on(socket.lock().flush()).map_err(err!())?
|
||||
}
|
||||
StreamSendSocket::Udp(socket) => runtime.block_on(socket.inner.lock().flush())?,
|
||||
StreamSendSocket::Tcp(socket) => runtime.block_on(socket.lock().flush())?,
|
||||
}
|
||||
|
||||
self.next_packet_index += 1;
|
||||
|
@ -212,9 +203,9 @@ impl<T> ReceiverBuffer<T> {
|
|||
}
|
||||
|
||||
impl<T: DeserializeOwned> ReceiverBuffer<T> {
|
||||
pub fn get(&self) -> StrResult<(T, &[u8])> {
|
||||
pub fn get(&self) -> Result<(T, &[u8])> {
|
||||
let mut data: &[u8] = &self.inner;
|
||||
let header = bincode::deserialize_from(&mut data).map_err(err!())?;
|
||||
let header = bincode::deserialize_from(&mut data)?;
|
||||
|
||||
Ok((header, data))
|
||||
}
|
||||
|
@ -240,7 +231,7 @@ impl<T: DeserializeOwned> StreamReceiver<T> {
|
|||
let mut shard = match self.receiver.recv_timeout(timeout) {
|
||||
Ok(shard) => Ok(shard),
|
||||
Err(RecvTimeoutError::Timeout) => alvr_common::timeout(),
|
||||
Err(RecvTimeoutError::Disconnected) => con_fmt_e!("Disconnected"),
|
||||
Err(RecvTimeoutError::Disconnected) => con_bail!("Disconnected"),
|
||||
}?;
|
||||
let shard_packet_index = shard.get_u32();
|
||||
let shards_count = shard.get_u32() as usize;
|
||||
|
@ -299,7 +290,7 @@ impl<T: DeserializeOwned> StreamReceiver<T> {
|
|||
|
||||
loop {
|
||||
if self.recv_buffer(timeout, &mut buffer)? {
|
||||
return Ok(buffer.get().map_err(to_con_e!())?.0);
|
||||
return Ok(buffer.get().to_con()?.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -317,7 +308,7 @@ impl StreamSocketBuilder {
|
|||
stream_socket_config: SocketProtocol,
|
||||
send_buffer_bytes: SocketBufferSize,
|
||||
recv_buffer_bytes: SocketBufferSize,
|
||||
) -> StrResult<Self> {
|
||||
) -> Result<Self> {
|
||||
Ok(match stream_socket_config {
|
||||
SocketProtocol::Udp => StreamSocketBuilder::Udp(udp::bind(
|
||||
runtime,
|
||||
|
@ -383,8 +374,8 @@ impl StreamSocketBuilder {
|
|||
) -> ConResult<StreamSocket> {
|
||||
let (send_socket, receive_socket) = match protocol {
|
||||
SocketProtocol::Udp => {
|
||||
let socket = udp::bind(runtime, port, send_buffer_bytes, recv_buffer_bytes)
|
||||
.map_err(to_con_e!())?;
|
||||
let socket =
|
||||
udp::bind(runtime, port, send_buffer_bytes, recv_buffer_bytes).to_con()?;
|
||||
let (send_socket, receive_socket) = udp::connect(socket, client_ip, port);
|
||||
|
||||
(
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{Ldc, LOCAL_IP};
|
||||
use alvr_common::{parking_lot::Mutex, prelude::*};
|
||||
use alvr_common::{anyhow::Result, con_bail, parking_lot::Mutex, ConResult, ToCon};
|
||||
use alvr_session::SocketBufferSize;
|
||||
use bytes::{Buf, Bytes, BytesMut};
|
||||
use futures::{
|
||||
|
@ -27,16 +27,16 @@ pub fn bind(
|
|||
port: u16,
|
||||
send_buffer_bytes: SocketBufferSize,
|
||||
recv_buffer_bytes: SocketBufferSize,
|
||||
) -> StrResult<TcpListener> {
|
||||
let socket = runtime
|
||||
.block_on(TcpListener::bind((LOCAL_IP, port)))
|
||||
.map_err(err!())?;
|
||||
let socket = socket2::Socket::from(socket.into_std().map_err(err!())?);
|
||||
) -> Result<TcpListener> {
|
||||
let socket = runtime.block_on(TcpListener::bind((LOCAL_IP, port)))?;
|
||||
let socket = socket2::Socket::from(socket.into_std()?);
|
||||
|
||||
super::set_socket_buffers(&socket, send_buffer_bytes, recv_buffer_bytes).ok();
|
||||
|
||||
let _tokio_guard = runtime.enter();
|
||||
TcpListener::from_std(socket.into()).map_err(err!())
|
||||
let socket = TcpListener::from_std(socket.into())?;
|
||||
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
pub fn accept_from_server(
|
||||
|
@ -47,16 +47,16 @@ pub fn accept_from_server(
|
|||
) -> ConResult<(TcpStreamSendSocket, TcpStreamReceiveSocket)> {
|
||||
let (socket, server_address) = runtime.block_on(async {
|
||||
tokio::select! {
|
||||
res = listener.accept() => res.map_err(to_con_e!()),
|
||||
res = listener.accept() => res.to_con(),
|
||||
_ = time::sleep(timeout) => alvr_common::timeout(),
|
||||
}
|
||||
})?;
|
||||
|
||||
if server_address.ip() != server_ip {
|
||||
return con_fmt_e!("Connected to wrong client: {server_address} != {server_ip}");
|
||||
con_bail!("Connected to wrong client: {server_address} != {server_ip}");
|
||||
}
|
||||
|
||||
socket.set_nodelay(true).map_err(to_con_e!())?;
|
||||
socket.set_nodelay(true).to_con()?;
|
||||
let socket = Framed::new(socket, Ldc::new());
|
||||
let (send_socket, receive_socket) = socket.split();
|
||||
|
||||
|
@ -73,20 +73,20 @@ pub fn connect_to_client(
|
|||
) -> ConResult<(TcpStreamSendSocket, TcpStreamReceiveSocket)> {
|
||||
let socket = runtime.block_on(async {
|
||||
tokio::select! {
|
||||
res = TcpStream::connect((client_ip, port)) => res.map_err(to_con_e!()),
|
||||
res = TcpStream::connect((client_ip, port)) => res.to_con(),
|
||||
_ = time::sleep(timeout) => alvr_common::timeout(),
|
||||
}
|
||||
})?;
|
||||
|
||||
let socket = socket2::Socket::from(socket.into_std().map_err(to_con_e!())?);
|
||||
let socket = socket2::Socket::from(socket.into_std().to_con()?);
|
||||
|
||||
super::set_socket_buffers(&socket, send_buffer_bytes, recv_buffer_bytes).ok();
|
||||
|
||||
let socket = {
|
||||
let _tokio_guard = runtime.enter();
|
||||
TcpStream::from_std(socket.into()).map_err(to_con_e!())?
|
||||
TcpStream::from_std(socket.into()).to_con()?
|
||||
};
|
||||
socket.set_nodelay(true).map_err(to_con_e!())?;
|
||||
socket.set_nodelay(true).to_con()?;
|
||||
let socket = Framed::new(socket, Ldc::new());
|
||||
let (send_socket, receive_socket) = socket.split();
|
||||
|
||||
|
@ -101,7 +101,7 @@ pub fn recv(
|
|||
) -> ConResult {
|
||||
if let Some(maybe_packet) = runtime.block_on(async {
|
||||
tokio::select! {
|
||||
res = socket.next() => res.map(|p| p.map_err(to_con_e!())),
|
||||
res = socket.next() => res.map(|p| p.to_con()),
|
||||
_ = time::sleep(timeout) => Some(alvr_common::timeout()),
|
||||
}
|
||||
}) {
|
||||
|
@ -109,11 +109,11 @@ pub fn recv(
|
|||
|
||||
let stream_id = packet.get_u16();
|
||||
if let Some(enqueuer) = packet_enqueuers.get_mut(&stream_id) {
|
||||
enqueuer.send(packet).map_err(to_con_e!())?;
|
||||
enqueuer.send(packet).to_con()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
con_fmt_e!("Socket closed")
|
||||
con_bail!("Socket closed")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{Ldc, LOCAL_IP};
|
||||
use alvr_common::{parking_lot::Mutex, prelude::*};
|
||||
use alvr_common::{anyhow::Result, con_bail, parking_lot::Mutex, ConResult, ToCon};
|
||||
use alvr_session::SocketBufferSize;
|
||||
use bytes::{Buf, Bytes, BytesMut};
|
||||
use futures::{
|
||||
|
@ -36,16 +36,16 @@ pub fn bind(
|
|||
port: u16,
|
||||
send_buffer_bytes: SocketBufferSize,
|
||||
recv_buffer_bytes: SocketBufferSize,
|
||||
) -> StrResult<UdpSocket> {
|
||||
let socket = runtime
|
||||
.block_on(UdpSocket::bind((LOCAL_IP, port)))
|
||||
.map_err(err!())?;
|
||||
let socket = socket2::Socket::from(socket.into_std().map_err(err!())?);
|
||||
) -> Result<UdpSocket> {
|
||||
let socket = runtime.block_on(UdpSocket::bind((LOCAL_IP, port)))?;
|
||||
let socket = socket2::Socket::from(socket.into_std()?);
|
||||
|
||||
super::set_socket_buffers(&socket, send_buffer_bytes, recv_buffer_bytes).ok();
|
||||
|
||||
let _tokio_guard = runtime.enter();
|
||||
UdpSocket::from_std(socket.into()).map_err(err!())
|
||||
let socket = UdpSocket::from_std(socket.into())?;
|
||||
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
pub fn connect(
|
||||
|
@ -77,11 +77,11 @@ pub fn recv(
|
|||
) -> ConResult {
|
||||
if let Some(maybe_packet) = runtime.block_on(async {
|
||||
tokio::select! {
|
||||
res = socket.inner.next() => res.map(|p| p.map_err(to_con_e!())),
|
||||
res = socket.inner.next() => res.map(|p| p.to_con()),
|
||||
_ = time::sleep(timeout) => Some(alvr_common::timeout()),
|
||||
}
|
||||
}) {
|
||||
let (mut packet_bytes, address) = maybe_packet.map_err(to_con_e!())?;
|
||||
let (mut packet_bytes, address) = maybe_packet?;
|
||||
|
||||
if address != socket.peer_addr {
|
||||
// Non fatal
|
||||
|
@ -90,11 +90,11 @@ pub fn recv(
|
|||
|
||||
let stream_id = packet_bytes.get_u16();
|
||||
if let Some(enqueuer) = packet_enqueuers.get_mut(&stream_id) {
|
||||
enqueuer.send(packet_bytes).map_err(to_con_e!())?;
|
||||
enqueuer.send(packet_bytes).to_con()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
con_fmt_e!("Socket closed")
|
||||
con_bail!("Socket closed")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue