From 7e5c5b50e5a6dd6b9c1f265cfb1520db4319e739 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Tue, 31 Jan 2023 10:01:31 +0800 Subject: [PATCH] feat: set to default input device when in dual-way --- src/client/io_loop.rs | 10 +++++++-- src/common.rs | 44 +++++++++++++++++++++++++++++++++++++++- src/flutter_ffi.rs | 10 +++++++++ src/platform/linux.rs | 18 ++++++++++++++++ src/server/connection.rs | 7 ++++++- 5 files changed, 85 insertions(+), 4 deletions(-) diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index a284fdade..9117c8c5f 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -2,13 +2,14 @@ use crate::client::{ Client, CodecFormat, LoginConfigHandler, MediaData, MediaSender, QualityStatus, MILLI1, SEC30, SERVER_CLIPBOARD_ENABLED, SERVER_FILE_TRANSFER_ENABLED, SERVER_KEYBOARD_ENABLED, }; +use crate::common::{get_default_sound_input, set_sound_input}; #[cfg(not(any(target_os = "android", target_os = "ios")))] use crate::common::{check_clipboard, update_clipboard, ClipboardContext, CLIPBOARD_INTERVAL}; use crate::{audio_service, common, ConnInner, CLIENT_SERVER}; #[cfg(windows)] use clipboard::{cliprdr::CliprdrClientContext, ContextSend}; -use hbb_common::futures::channel::mpsc::unbounded; + use hbb_common::tokio::sync::mpsc::error::TryRecvError; use crate::server::Service; @@ -32,7 +33,7 @@ use hbb_common::tokio::{ }; use hbb_common::{allow_err, message_proto::*, sleep}; use hbb_common::{fs, log, Stream}; -use std::borrow::Borrow; + use std::collections::HashMap; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -270,6 +271,11 @@ impl Remote { if self.handler.is_file_transfer() || self.handler.is_port_forward() { return None; } + // Switch to default input device + let default_sound_device = get_default_sound_input(); + if let Some(device) = default_sound_device { + set_sound_input(device); + } // Create a channel to receive error or closed message let (tx, rx) = std::sync::mpsc::channel(); let (tx_audio_data, mut rx_audio_data) = hbb_common::tokio::sync::mpsc::unbounded_channel(); diff --git a/src/common.rs b/src/common.rs index c2d5a81f0..9cbc9b150 100644 --- a/src/common.rs +++ b/src/common.rs @@ -30,6 +30,8 @@ use hbb_common::{ // #[cfg(any(target_os = "android", target_os = "ios", feature = "cli"))] use hbb_common::{config::RENDEZVOUS_PORT, futures::future::join_all}; +use crate::ui_interface::{set_option, get_option}; + pub type NotifyMessageBox = fn(String, String, String, String) -> dyn Future; pub const CLIPBOARD_NAME: &'static str = "clipboard"; @@ -105,6 +107,46 @@ pub fn check_clipboard( None } +/// Set sound input device. +pub fn set_sound_input(device: String) { + let prior_device = get_option("audio-input".to_owned()); + if prior_device != device { + log::info!("switch to audio input device {}", device); + set_option("audio-input".to_owned(), device); + } else { + log::info!("audio input is already set to {}", device); + } +} + +/// Get system's default sound input device name. +#[inline] +#[cfg(not(any(target_os = "android", target_os = "ios")))] +pub fn get_default_sound_input() -> Option { + #[cfg(not(target_os = "linux"))] + { + use cpal::traits::{DeviceTrait, HostTrait}; + let host = cpal::default_host(); + let dev = host.default_input_device(); + return if let Some(dev) = dev { + match dev.name() { + Ok(name) => Some(name), + Err(_) => None, + } + } else { + None + }; + } + #[cfg(target_os = "linux")] + { + let input = crate::platform::linux::get_default_pa_source(); + return if let Some(input) = input { + Some(input.1) + } else { + None + }; + } +} + #[cfg(not(any(target_os = "android", target_os = "ios")))] pub fn update_clipboard(clipboard: Clipboard, old: Option<&Arc>>) { let content = if clipboard.compress { @@ -715,5 +757,5 @@ pub fn make_fd_to_json(id: i32, path: String, entries: &Vec) -> Strin #[cfg(test)] mod test_common { - use super::*; + } diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 10fd67fdd..31cb07c07 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -4,6 +4,9 @@ use std::str::FromStr; use flutter_rust_bridge::{StreamSink, SyncReturn, ZeroCopyBuffer}; use serde_json::json; +use crate::common::{is_keyboard_mode_supported, get_default_sound_input}; +use hbb_common::message_proto::KeyboardMode; +use hbb_common::ResultType; use hbb_common::{ config::{self, LocalConfig, ONLINE, PeerConfig}, fs, log, @@ -534,6 +537,13 @@ pub fn main_get_sound_inputs() -> Vec { vec![String::from("")] } +pub fn main_get_default_sound_input() -> Option { + #[cfg(not(any(target_os = "android", target_os = "ios")))] + return get_default_sound_input(); + #[cfg(any(target_os = "android", target_os = "ios"))] + String::from("") +} + pub fn main_get_hostname() -> SyncReturn { SyncReturn(crate::common::hostname()) } diff --git a/src/platform/linux.rs b/src/platform/linux.rs index ac3b32a49..8fa95ac90 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -534,6 +534,24 @@ pub fn get_pa_sources() -> Vec<(String, String)> { out } +pub fn get_default_pa_source() -> Option<(String, String)> { + use pulsectl::controllers::*; + match SourceController::create() { + Ok(mut handler) => { + if let Ok(dev) = handler.get_default_device() { + return Some(( + dev.name.unwrap_or("".to_owned()), + dev.description.unwrap_or("".to_owned()), + )); + } + } + Err(err) => { + log::error!("Failed to get_pa_source: {:?}", err); + } + } + None +} + pub fn lock_screen() { std::process::Command::new("xdg-screensaver") .arg("lock") diff --git a/src/server/connection.rs b/src/server/connection.rs index d5c2103b1..20cbe0f86 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -5,7 +5,7 @@ use crate::clipboard_file::*; use crate::common::update_clipboard; #[cfg(windows)] use crate::portable_service::client as portable_client; -use crate::{video_service, client::{MediaSender, start_audio_thread, LatencyController, MediaData}}; +use crate::{video_service, client::{MediaSender, start_audio_thread, LatencyController, MediaData}, common::{get_default_sound_input, set_sound_input}}; #[cfg(any(target_os = "android", target_os = "ios"))] use crate::{common::DEVICE_NAME, flutter::connection_manager::start_channel}; use crate::{ipc, VERSION}; @@ -1542,6 +1542,11 @@ impl Connection { }, Some(misc::Union::AudioFormat(format)) => { if !self.disable_audio { + // Switch to default input device + let default_sound_device = get_default_sound_input(); + if let Some(device) = default_sound_device { + set_sound_input(device); + } allow_err!(self.audio_sender.send(MediaData::AudioFormat(format))); } }