mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-24 09:52:49 +08:00
fix(native): audio capture volume (#11240)
This commit is contained in:
@@ -524,10 +524,13 @@ async function getAllApps(): Promise<AppInfo[]> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const filteredApps = apps.filter(
|
const filteredApps = apps.filter((v): v is AppInfo => {
|
||||||
(v): v is AppInfo =>
|
return (
|
||||||
v !== null && !v.bundleIdentifier.startsWith('com.apple')
|
v !== null &&
|
||||||
);
|
(!v.bundleIdentifier.startsWith('com.apple') ||
|
||||||
|
v.bundleIdentifier === 'com.apple.Music')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
for (const app of filteredApps) {
|
for (const app of filteredApps) {
|
||||||
if (filteredApps.some(a => a.processId === app.processGroupId)) {
|
if (filteredApps.some(a => a.processId === app.processGroupId)) {
|
||||||
|
|||||||
@@ -98,12 +98,11 @@ impl InputAndOutputAudioBufferList {
|
|||||||
.max(processed_samples_output.len());
|
.max(processed_samples_output.len());
|
||||||
|
|
||||||
let mut mixed_samples = vec![0.0; mixed_samples_length];
|
let mut mixed_samples = vec![0.0; mixed_samples_length];
|
||||||
|
|
||||||
for (sample_index, mixed_sample) in mixed_samples.iter_mut().enumerate() {
|
for (sample_index, mixed_sample) in mixed_samples.iter_mut().enumerate() {
|
||||||
let sample_in = processed_samples_input.get(sample_index).unwrap_or(&0.0);
|
let sample_in = processed_samples_input.get(sample_index).unwrap_or(&0.0);
|
||||||
let sample_out = processed_samples_output.get(sample_index).unwrap_or(&0.0);
|
let sample_out = processed_samples_output.get(sample_index).unwrap_or(&0.0);
|
||||||
|
|
||||||
*mixed_sample = (sample_in + sample_out) / 2.0;
|
*mixed_sample = sample_in + sample_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(mixed_samples)
|
Ok(mixed_samples)
|
||||||
|
|||||||
@@ -18,12 +18,24 @@ impl ToCoreFoundation for CFString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToCoreFoundation for &CFString {
|
||||||
|
fn to_cf(&self) -> CFType {
|
||||||
|
self.as_CFType()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToCoreFoundation for String {
|
impl ToCoreFoundation for String {
|
||||||
fn to_cf(&self) -> CFType {
|
fn to_cf(&self) -> CFType {
|
||||||
CFString::new(self).as_CFType()
|
CFString::new(self).as_CFType()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToCoreFoundation for &str {
|
||||||
|
fn to_cf(&self) -> CFType {
|
||||||
|
CFString::new(self).as_CFType()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToCoreFoundation for bool {
|
impl ToCoreFoundation for bool {
|
||||||
fn to_cf(&self) -> CFType {
|
fn to_cf(&self) -> CFType {
|
||||||
if *self {
|
if *self {
|
||||||
|
|||||||
@@ -16,9 +16,8 @@ use core_foundation::{
|
|||||||
use coreaudio::sys::{
|
use coreaudio::sys::{
|
||||||
kAudioHardwarePropertyProcessObjectList, kAudioObjectPropertyElementMain,
|
kAudioHardwarePropertyProcessObjectList, kAudioObjectPropertyElementMain,
|
||||||
kAudioObjectPropertyScopeGlobal, kAudioObjectSystemObject, kAudioProcessPropertyBundleID,
|
kAudioObjectPropertyScopeGlobal, kAudioObjectSystemObject, kAudioProcessPropertyBundleID,
|
||||||
kAudioProcessPropertyIsRunning, kAudioProcessPropertyIsRunningInput, kAudioProcessPropertyPID,
|
kAudioProcessPropertyIsRunning, kAudioProcessPropertyPID, AudioObjectAddPropertyListenerBlock,
|
||||||
AudioObjectAddPropertyListenerBlock, AudioObjectID, AudioObjectPropertyAddress,
|
AudioObjectID, AudioObjectPropertyAddress, AudioObjectRemovePropertyListenerBlock,
|
||||||
AudioObjectRemovePropertyListenerBlock,
|
|
||||||
};
|
};
|
||||||
use libc;
|
use libc;
|
||||||
use napi::{
|
use napi::{
|
||||||
@@ -204,8 +203,8 @@ impl Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[napi(getter)]
|
#[napi(getter)]
|
||||||
pub fn name(&self) -> String {
|
pub fn name(&self) -> &str {
|
||||||
self.name.clone()
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
#[napi(getter)]
|
#[napi(getter)]
|
||||||
@@ -423,7 +422,7 @@ impl TappableApplication {
|
|||||||
pub fn get_is_running(&self) -> Result<bool> {
|
pub fn get_is_running(&self) -> Result<bool> {
|
||||||
// Use catch_unwind to prevent any panics
|
// Use catch_unwind to prevent any panics
|
||||||
let result = std::panic::catch_unwind(|| {
|
let result = std::panic::catch_unwind(|| {
|
||||||
match get_process_property(&self.object_id, kAudioProcessPropertyIsRunningInput) {
|
match get_process_property(&self.object_id, kAudioProcessPropertyIsRunning) {
|
||||||
Ok(is_running) => Ok(is_running),
|
Ok(is_running) => Ok(is_running),
|
||||||
Err(_) => Ok(false),
|
Err(_) => Ok(false),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use coreaudio::sys::{
|
|||||||
kAudioAggregateDeviceTapAutoStartKey, kAudioAggregateDeviceTapListKey,
|
kAudioAggregateDeviceTapAutoStartKey, kAudioAggregateDeviceTapListKey,
|
||||||
kAudioAggregateDeviceUIDKey, kAudioDevicePropertyNominalSampleRate, kAudioHardwareBadDeviceError,
|
kAudioAggregateDeviceUIDKey, kAudioDevicePropertyNominalSampleRate, kAudioHardwareBadDeviceError,
|
||||||
kAudioHardwareBadStreamError, kAudioHardwareNoError, kAudioHardwarePropertyDefaultInputDevice,
|
kAudioHardwareBadStreamError, kAudioHardwareNoError, kAudioHardwarePropertyDefaultInputDevice,
|
||||||
kAudioHardwarePropertyDefaultSystemOutputDevice, kAudioSubDeviceUIDKey, kAudioSubTapUIDKey,
|
kAudioHardwarePropertyDefaultOutputDevice, kAudioSubDeviceUIDKey, kAudioSubTapUIDKey,
|
||||||
AudioDeviceCreateIOProcIDWithBlock, AudioDeviceDestroyIOProcID, AudioDeviceIOProcID,
|
AudioDeviceCreateIOProcIDWithBlock, AudioDeviceDestroyIOProcID, AudioDeviceIOProcID,
|
||||||
AudioDeviceStart, AudioDeviceStop, AudioHardwareCreateAggregateDevice,
|
AudioDeviceStart, AudioDeviceStop, AudioHardwareCreateAggregateDevice,
|
||||||
AudioHardwareDestroyAggregateDevice, AudioObjectID, AudioTimeStamp, OSStatus,
|
AudioHardwareDestroyAggregateDevice, AudioObjectID, AudioTimeStamp, OSStatus,
|
||||||
@@ -31,7 +31,7 @@ use crate::{
|
|||||||
audio_buffer::InputAndOutputAudioBufferList,
|
audio_buffer::InputAndOutputAudioBufferList,
|
||||||
ca_tap_description::CATapDescription,
|
ca_tap_description::CATapDescription,
|
||||||
cf_types::CFDictionaryBuilder,
|
cf_types::CFDictionaryBuilder,
|
||||||
device::{get_device_audio_id, get_device_uid},
|
device::get_device_uid,
|
||||||
error::CoreAudioError,
|
error::CoreAudioError,
|
||||||
queue::create_audio_tap_queue,
|
queue::create_audio_tap_queue,
|
||||||
screen_capture_kit::TappableApplication,
|
screen_capture_kit::TappableApplication,
|
||||||
@@ -59,7 +59,7 @@ pub struct AggregateDevice {
|
|||||||
pub id: AudioObjectID,
|
pub id: AudioObjectID,
|
||||||
pub audio_stats: Option<AudioStats>,
|
pub audio_stats: Option<AudioStats>,
|
||||||
pub input_device_id: AudioObjectID,
|
pub input_device_id: AudioObjectID,
|
||||||
pub output_device_id: Option<AudioObjectID>,
|
pub output_device_id: AudioObjectID,
|
||||||
pub input_proc_id: Option<AudioDeviceIOProcID>,
|
pub input_proc_id: Option<AudioDeviceIOProcID>,
|
||||||
pub output_proc_id: Option<AudioDeviceIOProcID>,
|
pub output_proc_id: Option<AudioDeviceIOProcID>,
|
||||||
}
|
}
|
||||||
@@ -80,8 +80,15 @@ impl AggregateDevice {
|
|||||||
let (input_device_id, default_input_uid) =
|
let (input_device_id, default_input_uid) =
|
||||||
get_device_uid(kAudioHardwarePropertyDefaultInputDevice)?;
|
get_device_uid(kAudioHardwarePropertyDefaultInputDevice)?;
|
||||||
|
|
||||||
let description_dict =
|
// Get the default output device ID
|
||||||
Self::create_aggregate_description(tap_id, tap_description.get_uuid()?, default_input_uid)?;
|
let (output_device_id, output_device_uid) =
|
||||||
|
get_device_uid(kAudioHardwarePropertyDefaultOutputDevice)?;
|
||||||
|
let description_dict = Self::create_aggregate_description(
|
||||||
|
tap_id,
|
||||||
|
tap_description.get_uuid()?,
|
||||||
|
default_input_uid,
|
||||||
|
output_device_uid,
|
||||||
|
)?;
|
||||||
|
|
||||||
let mut aggregate_device_id: AudioObjectID = 0;
|
let mut aggregate_device_id: AudioObjectID = 0;
|
||||||
|
|
||||||
@@ -101,7 +108,7 @@ impl AggregateDevice {
|
|||||||
id: aggregate_device_id,
|
id: aggregate_device_id,
|
||||||
audio_stats: None,
|
audio_stats: None,
|
||||||
input_device_id,
|
input_device_id,
|
||||||
output_device_id: None,
|
output_device_id,
|
||||||
input_proc_id: None,
|
input_proc_id: None,
|
||||||
output_proc_id: None,
|
output_proc_id: None,
|
||||||
})
|
})
|
||||||
@@ -122,10 +129,15 @@ impl AggregateDevice {
|
|||||||
get_device_uid(kAudioHardwarePropertyDefaultInputDevice)?;
|
get_device_uid(kAudioHardwarePropertyDefaultInputDevice)?;
|
||||||
|
|
||||||
// Get the default output device ID
|
// Get the default output device ID
|
||||||
let output_device_id = get_device_audio_id(kAudioHardwarePropertyDefaultSystemOutputDevice)?;
|
let (output_device_id, output_device_uid) =
|
||||||
|
get_device_uid(kAudioHardwarePropertyDefaultOutputDevice)?;
|
||||||
|
|
||||||
let description_dict =
|
let description_dict = Self::create_aggregate_description(
|
||||||
Self::create_aggregate_description(tap_id, tap_description.get_uuid()?, default_input_uid)?;
|
tap_id,
|
||||||
|
tap_description.get_uuid()?,
|
||||||
|
default_input_uid,
|
||||||
|
output_device_uid,
|
||||||
|
)?;
|
||||||
|
|
||||||
let mut aggregate_device_id: AudioObjectID = 0;
|
let mut aggregate_device_id: AudioObjectID = 0;
|
||||||
|
|
||||||
@@ -147,7 +159,7 @@ impl AggregateDevice {
|
|||||||
id: aggregate_device_id,
|
id: aggregate_device_id,
|
||||||
audio_stats: None,
|
audio_stats: None,
|
||||||
input_device_id,
|
input_device_id,
|
||||||
output_device_id: Some(output_device_id),
|
output_device_id,
|
||||||
input_proc_id: None,
|
input_proc_id: None,
|
||||||
output_proc_id: None,
|
output_proc_id: None,
|
||||||
};
|
};
|
||||||
@@ -317,24 +329,21 @@ impl AggregateDevice {
|
|||||||
tap_id: AudioObjectID,
|
tap_id: AudioObjectID,
|
||||||
tap_uuid_string: ItemRef<CFString>,
|
tap_uuid_string: ItemRef<CFString>,
|
||||||
input_device_id: CFString,
|
input_device_id: CFString,
|
||||||
|
output_device_id: CFString,
|
||||||
) -> Result<CFDictionary<CFType, CFType>> {
|
) -> Result<CFDictionary<CFType, CFType>> {
|
||||||
let aggregate_device_name = CFString::new(&format!("Tap-{}", tap_id));
|
let aggregate_device_name = CFString::new(&format!("Tap-{}", tap_id));
|
||||||
let aggregate_device_uid: uuid::Uuid = CFUUID::new().into();
|
let aggregate_device_uid: uuid::Uuid = CFUUID::new().into();
|
||||||
let aggregate_device_uid_string = aggregate_device_uid.to_string();
|
let aggregate_device_uid_string = aggregate_device_uid.to_string();
|
||||||
|
|
||||||
let (_, output_device_uid) = get_device_uid(kAudioHardwarePropertyDefaultSystemOutputDevice)?;
|
let mut sub_device_input_dict = CFDictionaryBuilder::new();
|
||||||
|
sub_device_input_dict.add(kAudioSubDeviceUIDKey.as_slice(), &input_device_id);
|
||||||
let sub_device_input_dict = CFDictionary::from_CFType_pairs(&[(
|
|
||||||
cfstring_from_bytes_with_nul(kAudioSubDeviceUIDKey).as_CFType(),
|
|
||||||
input_device_id.as_CFType(),
|
|
||||||
)]);
|
|
||||||
|
|
||||||
let tap_device_dict = CFDictionary::from_CFType_pairs(&[(
|
let tap_device_dict = CFDictionary::from_CFType_pairs(&[(
|
||||||
cfstring_from_bytes_with_nul(kAudioSubTapUIDKey).as_CFType(),
|
cfstring_from_bytes_with_nul(kAudioSubTapUIDKey).as_CFType(),
|
||||||
tap_uuid_string.as_CFType(),
|
tap_uuid_string.as_CFType(),
|
||||||
)]);
|
)]);
|
||||||
|
|
||||||
let capture_device_list = vec![sub_device_input_dict];
|
let capture_device_list = vec![sub_device_input_dict.build()];
|
||||||
|
|
||||||
// Create the aggregate device description dictionary with a balanced
|
// Create the aggregate device description dictionary with a balanced
|
||||||
// configuration
|
// configuration
|
||||||
@@ -352,9 +361,10 @@ impl AggregateDevice {
|
|||||||
)
|
)
|
||||||
.add(
|
.add(
|
||||||
kAudioAggregateDeviceMainSubDeviceKey.as_slice(),
|
kAudioAggregateDeviceMainSubDeviceKey.as_slice(),
|
||||||
output_device_uid,
|
&output_device_id,
|
||||||
)
|
)
|
||||||
.add(kAudioAggregateDeviceIsPrivateKey.as_slice(), true)
|
.add(kAudioAggregateDeviceIsPrivateKey.as_slice(), true)
|
||||||
|
// can't be stacked because we're using a tap
|
||||||
.add(kAudioAggregateDeviceIsStackedKey.as_slice(), false)
|
.add(kAudioAggregateDeviceIsStackedKey.as_slice(), false)
|
||||||
.add(kAudioAggregateDeviceTapAutoStartKey.as_slice(), true)
|
.add(kAudioAggregateDeviceTapAutoStartKey.as_slice(), true)
|
||||||
.add(
|
.add(
|
||||||
@@ -381,7 +391,7 @@ pub struct AudioTapStream {
|
|||||||
stop_called: bool,
|
stop_called: bool,
|
||||||
audio_stats: AudioStats,
|
audio_stats: AudioStats,
|
||||||
input_device_id: AudioObjectID,
|
input_device_id: AudioObjectID,
|
||||||
output_device_id: Option<AudioObjectID>,
|
output_device_id: AudioObjectID,
|
||||||
input_proc_id: Option<AudioDeviceIOProcID>,
|
input_proc_id: Option<AudioDeviceIOProcID>,
|
||||||
output_proc_id: Option<AudioDeviceIOProcID>,
|
output_proc_id: Option<AudioDeviceIOProcID>,
|
||||||
}
|
}
|
||||||
@@ -408,11 +418,9 @@ impl AudioTapStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stop the output device if it was activated
|
// Stop the output device if it was activated
|
||||||
if let Some(output_id) = self.output_device_id {
|
if let Some(proc_id) = self.output_proc_id {
|
||||||
if let Some(proc_id) = self.output_proc_id {
|
let _ = unsafe { AudioDeviceStop(self.output_device_id, proc_id) };
|
||||||
let _ = unsafe { AudioDeviceStop(output_id, proc_id) };
|
let _ = unsafe { AudioDeviceDestroyIOProcID(self.output_device_id, proc_id) };
|
||||||
let _ = unsafe { AudioDeviceDestroyIOProcID(output_id, proc_id) };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy the main IO proc
|
// Destroy the main IO proc
|
||||||
|
|||||||
Reference in New Issue
Block a user