Skip to content

Commit

Permalink
fix threading
Browse files Browse the repository at this point in the history
  • Loading branch information
HolbyFPV committed Nov 15, 2024
1 parent e581df1 commit 78d482d
Showing 1 changed file with 50 additions and 57 deletions.
107 changes: 50 additions & 57 deletions packages/desktop/src/providers/audio/audio_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use std::sync::{Arc, Mutex, OnceLock};

use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use tokio::sync::mpsc::{self, Sender};
use tokio::{
sync::mpsc::{self, Sender},
task,
};
use windows::Win32::{
Devices::FunctionDiscovery::PKEY_Device_FriendlyName,
Media::Audio::{
Expand Down Expand Up @@ -46,12 +49,24 @@ pub struct AudioProvider {
#[async_trait]
impl Provider for AudioProvider {
async fn run(&self, emit_result_tx: Sender<ProviderResult>) {
if let Err(err) = self.create_audio_manager(emit_result_tx.clone()) {
emit_result_tx
.send(Err(err).into())
.await
.expect("Error emitting media provider err.");
}
PROVIDER_TX
.set(emit_result_tx.clone())
.expect("Error setting provider tx in audio provider");

AUDIO_STATE
.set(Arc::new(Mutex::new(AudioOutput {
current_device: "n/a".to_string(),
volume: 0.0,
})))
.expect("Error setting initial audio state");

task::spawn_blocking(move || {
if let Err(err) = Self::create_audio_manager() {
emit_result_tx
.blocking_send(Err(err).into())
.expect("Error with media provider");
}
});
}
}

Expand All @@ -67,22 +82,7 @@ impl AudioProvider {
}
}

fn create_audio_manager(
&self,
emit_result_tx: Sender<ProviderResult>,
) -> anyhow::Result<()> {
PROVIDER_TX
.set(emit_result_tx.clone())
.expect("Error setting provider tx in focused window provider");

// todo do this at initialization
AUDIO_STATE
.set(Arc::new(Mutex::new(AudioOutput {
current_device: "n/a".to_string(),
volume: 0.0,
})))
.expect("Error setting initial state");

fn create_audio_manager() -> anyhow::Result<()> {
unsafe {
let _ = CoInitializeEx(None, COINIT_MULTITHREADED);

Expand Down Expand Up @@ -114,28 +114,22 @@ impl AudioProvider {
}
}

struct DeviceState {
volume_callbacks:
Arc<Mutex<Vec<(IAudioEndpointVolumeCallback, IAudioEndpointVolume)>>>,
}

#[derive(Clone)]
#[windows::core::implement(
IMMNotificationClient,
IAudioEndpointVolumeCallback
)]
struct MediaDeviceEventHandler {
enumerator: IMMDeviceEnumerator,
device_state: Arc<DeviceState>,
device_state:
Arc<Mutex<Vec<(IAudioEndpointVolumeCallback, IAudioEndpointVolume)>>>,
}

impl MediaDeviceEventHandler {
fn new(enumerator: IMMDeviceEnumerator) -> Self {
Self {
enumerator,
device_state: Arc::new(DeviceState {
volume_callbacks: Arc::new(Mutex::new(Vec::new())),
}),
device_state: Arc::new(Mutex::new(Vec::new())),
}
}

Expand All @@ -159,7 +153,6 @@ impl MediaDeviceEventHandler {
endpoint_volume.RegisterControlChangeNotify(&volume_callback)?;
self
.device_state
.volume_callbacks
.lock()
.unwrap()
.push((volume_callback, endpoint_volume));
Expand Down Expand Up @@ -187,6 +180,30 @@ impl IAudioEndpointVolumeCallback_Impl for MediaDeviceEventHandler_Impl {
}

impl IMMNotificationClient_Impl for MediaDeviceEventHandler_Impl {
fn OnDefaultDeviceChanged(
&self,
flow: EDataFlow,
role: ERole,
pwstrDefaultDeviceId: &PCWSTR,
) -> windows_core::Result<()> {
unsafe {
if flow == eRender && role == eMultimedia {
let device = self.enumerator.GetDevice(*pwstrDefaultDeviceId)?;
if let Ok(name) = MediaDeviceEventHandler::get_device_name(&device)
{
println!("Default device changed to: {}", name);
self.setup_volume_monitoring(&device)?;
if let Ok(mut output) = AUDIO_STATE.get().unwrap().lock() {
output.current_device = name;
}
AudioProvider::emit_volume();
}
}
}
Ok(())
}

// Unused fns, required for IMMNotificationClient_Impl
fn OnDeviceStateChanged(
&self,
pwstrDeviceId: &PCWSTR,
Expand Down Expand Up @@ -218,36 +235,12 @@ impl IMMNotificationClient_Impl for MediaDeviceEventHandler_Impl {
Ok(())
}

fn OnDefaultDeviceChanged(
&self,
flow: EDataFlow,
role: ERole,
pwstrDefaultDeviceId: &PCWSTR,
) -> windows_core::Result<()> {
unsafe {
if flow == eRender && role == eMultimedia {
let device = self.enumerator.GetDevice(*pwstrDefaultDeviceId)?;
if let Ok(name) = MediaDeviceEventHandler::get_device_name(&device)
{
println!("Default device changed to: {}", name);
self.setup_volume_monitoring(&device)?;
if let Ok(mut output) = AUDIO_STATE.get().unwrap().lock() {
output.current_device = name;
}
AudioProvider::emit_volume();
}
}
}
Ok(())
}

fn OnPropertyValueChanged(
&self,
pwstrDeviceId: &PCWSTR,
key: &windows::Win32::UI::Shell::PropertiesSystem::PROPERTYKEY,
) -> windows_core::Result<()> {
let device_id = unsafe { pwstrDeviceId.to_string()? };
println!("Property changed: {} - Key: {:?}", device_id, key);
Ok(())
}
}

0 comments on commit 78d482d

Please sign in to comment.