feat: macos, audio, loopback (#10025)

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou
2024-11-23 18:41:27 +08:00
committed by GitHub
parent 02b046bdbf
commit 0973f51df9
9 changed files with 105 additions and 21 deletions

View File

@@ -837,7 +837,7 @@ async fn check_software_update_() -> hbb_common::ResultType<()> {
let _ = crate::flutter::push_global_event(crate::flutter::APP_TYPE_MAIN, data);
}
}
*SOFTWARE_UPDATE_URL.lock().unwrap() = response_url;
*SOFTWARE_UPDATE_URL.lock().unwrap() = response_url;
}
Ok(())
}

View File

@@ -774,13 +774,6 @@ pub fn main_get_sound_inputs() -> Vec<String> {
vec![String::from("")]
}
pub fn main_get_default_sound_input() -> Option<String> {
#[cfg(not(any(target_os = "android", target_os = "ios")))]
return get_default_sound_input();
#[cfg(any(target_os = "android", target_os = "ios"))]
None
}
pub fn main_get_login_device_info() -> SyncReturn<String> {
SyncReturn(get_login_device_info_json())
}
@@ -2317,6 +2310,16 @@ pub fn session_request_new_display_init_msgs(session_id: SessionID, display: usi
}
}
pub fn main_audio_support_loopback() -> SyncReturn<bool> {
#[cfg(target_os = "windows")]
let is_surpport = true;
#[cfg(feature = "screencapturekit")]
let is_surpport = crate::audio_service::is_screen_capture_kit_available();
#[cfg(not(any(target_os = "windows", feature = "screencapturekit")))]
let is_surpport = false;
SyncReturn(is_surpport)
}
#[cfg(target_os = "android")]
pub mod server_side {
use hbb_common::{config, log};

View File

@@ -156,6 +156,14 @@ mod pa_impl {
}
}
#[inline]
#[cfg(feature = "screencapturekit")]
pub fn is_screen_capture_kit_available() -> bool {
cpal::available_hosts()
.iter()
.any(|host| *host == cpal::HostId::ScreenCaptureKit)
}
#[cfg(not(any(target_os = "linux", target_os = "android")))]
mod cpal_impl {
use self::service::{Reset, ServiceSwap};
@@ -170,6 +178,11 @@ mod cpal_impl {
static ref INPUT_BUFFER: Arc<Mutex<std::collections::VecDeque<f32>>> = Default::default();
}
#[cfg(feature = "screencapturekit")]
lazy_static::lazy_static! {
static ref HOST_SCREEN_CAPTURE_KIT: Result<Host, cpal::HostUnavailable> = cpal::host_from_id(cpal::HostId::ScreenCaptureKit);
}
#[derive(Default)]
pub struct State {
stream: Option<(Box<dyn StreamTrait>, Arc<Message>)>,
@@ -246,6 +259,27 @@ mod cpal_impl {
send_f32(&data, encoder, sp);
}
#[cfg(feature = "screencapturekit")]
fn get_device() -> ResultType<(Device, SupportedStreamConfig)> {
let audio_input = super::get_audio_input();
if !audio_input.is_empty() {
return get_audio_input(&audio_input);
}
if !is_screen_capture_kit_available() {
return get_audio_input("");
}
let device = HOST_SCREEN_CAPTURE_KIT
.as_ref()?
.default_input_device()
.with_context(|| "Failed to get default input device for loopback")?;
let format = device
.default_input_config()
.map_err(|e| anyhow!(e))
.with_context(|| "Failed to get input output format")?;
log::info!("Default input format: {:?}", format);
Ok((device, format))
}
#[cfg(windows)]
fn get_device() -> ResultType<(Device, SupportedStreamConfig)> {
let audio_input = super::get_audio_input();
@@ -267,7 +301,7 @@ mod cpal_impl {
Ok((device, format))
}
#[cfg(not(windows))]
#[cfg(not(any(windows, feature = "screencapturekit")))]
fn get_device() -> ResultType<(Device, SupportedStreamConfig)> {
let audio_input = super::get_audio_input();
get_audio_input(&audio_input)
@@ -275,7 +309,20 @@ mod cpal_impl {
fn get_audio_input(audio_input: &str) -> ResultType<(Device, SupportedStreamConfig)> {
let mut device = None;
if !audio_input.is_empty() {
#[cfg(feature = "screencapturekit")]
if !audio_input.is_empty() && is_screen_capture_kit_available() {
for d in HOST_SCREEN_CAPTURE_KIT
.as_ref()?
.devices()
.with_context(|| "Failed to get audio devices")?
{
if d.name().unwrap_or("".to_owned()) == audio_input {
device = Some(d);
break;
}
}
}
if device.is_none() && !audio_input.is_empty() {
for d in HOST
.devices()
.with_context(|| "Failed to get audio devices")?

View File

@@ -321,6 +321,8 @@ pub fn get_sound_inputs() -> Vec<String> {
fn get_sound_inputs_() -> Vec<String> {
let mut out = Vec::new();
use cpal::traits::{DeviceTrait, HostTrait};
// Do not use `cpal::host_from_id(cpal::HostId::ScreenCaptureKit)` for feature = "screencapturekit"
// Because we explicitly handle the "System Sound" device.
let host = cpal::default_host();
if let Ok(devices) = host.devices() {
for device in devices {