feat(host): emit desktop audio exclusion status events
This commit is contained in:
+33
-4
@@ -15,6 +15,7 @@ use super::observer::Readiness;
|
||||
use super::observer::adapter::RegistryObserverHandle;
|
||||
use super::owned_thread::OwnedThread;
|
||||
use super::taint::snapshot::{GlobalId, Serial};
|
||||
use crate::common::output::AudioExclusionEvent;
|
||||
use crate::repair::plan as repair_plan;
|
||||
use anyhow::{Context, Result, bail};
|
||||
use pipewire::proxy::ProxyT;
|
||||
@@ -143,8 +144,10 @@ pub(super) struct AudioGraphOwner {
|
||||
/// `Routing` remains a separate type in `host::audio`.
|
||||
pub(super) struct BareCaptureSink {
|
||||
// Drop order is load-bearing: close the fan-out observer connection (and
|
||||
// therefore every non-lingering link) before the sink-owning connection.
|
||||
// therefore every non-lingering link), then detach the status task, before
|
||||
// the sink-owning connection.
|
||||
fanout: Option<RegistryObserverHandle>,
|
||||
status_forwarder: Option<tokio::task::JoinHandle<()>>,
|
||||
graph_owner: Option<AudioGraphOwner>,
|
||||
monitor_name: String,
|
||||
}
|
||||
@@ -156,21 +159,34 @@ impl BareCaptureSink {
|
||||
.await
|
||||
.context("failed to start the bare connection-owned capture sink")?;
|
||||
let identity = graph_owner.identity().clone();
|
||||
let fanout = RegistryObserverHandle::spawn_with_mutation_sink(
|
||||
Box::new(FanoutController::new(
|
||||
let (status_tx, status_rx) = mpsc::unbounded_channel();
|
||||
let status_forwarder = tokio::spawn(forward_audio_exclusion_status(status_rx));
|
||||
let fanout = match RegistryObserverHandle::spawn_with_mutation_sink(
|
||||
Box::new(FanoutController::with_status_sender(
|
||||
Serial(identity.serial),
|
||||
AecConfig::Off,
|
||||
status_tx,
|
||||
)),
|
||||
health,
|
||||
)
|
||||
.context("failed to start the desktop-excluding fan-out observer")?;
|
||||
.context("failed to start the desktop-excluding fan-out observer")
|
||||
{
|
||||
Ok(fanout) => fanout,
|
||||
Err(error) => {
|
||||
let _ = status_forwarder.await;
|
||||
graph_owner.shutdown().await;
|
||||
return Err(error);
|
||||
}
|
||||
};
|
||||
if let Err(error) = wait_for_fanout_ready(&fanout, &identity).await {
|
||||
drop(fanout);
|
||||
let _ = status_forwarder.await;
|
||||
graph_owner.shutdown().await;
|
||||
return Err(error).context("desktop-excluding fan-out did not become ready");
|
||||
}
|
||||
Ok(Self {
|
||||
fanout: Some(fanout),
|
||||
status_forwarder: Some(status_forwarder),
|
||||
graph_owner: Some(graph_owner),
|
||||
monitor_name: identity.monitor_name,
|
||||
})
|
||||
@@ -193,6 +209,11 @@ impl BareCaptureSink {
|
||||
if let Some(fanout) = self.fanout.take() {
|
||||
drop(fanout);
|
||||
}
|
||||
if let Some(status_forwarder) = self.status_forwarder.take()
|
||||
&& let Err(error) = status_forwarder.await
|
||||
{
|
||||
tracing::warn!(%error, "audio fan-out: status forwarder task failed");
|
||||
}
|
||||
if let Some(graph_owner) = self.graph_owner.take()
|
||||
&& !graph_owner.shutdown().await
|
||||
{
|
||||
@@ -201,6 +222,14 @@ impl BareCaptureSink {
|
||||
}
|
||||
}
|
||||
|
||||
async fn forward_audio_exclusion_status(
|
||||
mut status_rx: mpsc::UnboundedReceiver<AudioExclusionEvent>,
|
||||
) {
|
||||
while let Some(event) = status_rx.recv().await {
|
||||
event.emit();
|
||||
}
|
||||
}
|
||||
|
||||
async fn wait_for_fanout_ready(
|
||||
observer: &RegistryObserverHandle,
|
||||
identity: &SinkIdentity,
|
||||
|
||||
Reference in New Issue
Block a user