fix(audio): panic when pulseaudio channel is full
This commit is contained in:
parent
adc2c7e871
commit
7e61e8b829
1 changed files with 32 additions and 7 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright 2023 System76 <info@system76.com>
|
// Copyright 2023 System76 <info@system76.com>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use std::{cell::RefCell, rc::Rc, thread};
|
use std::{cell::RefCell, mem, rc::Rc, thread};
|
||||||
|
|
||||||
extern crate libpulse_binding as pulse;
|
extern crate libpulse_binding as pulse;
|
||||||
|
|
||||||
|
|
@ -153,9 +153,19 @@ pub struct Connection(mpsc::Sender<Message>);
|
||||||
|
|
||||||
impl Connection {
|
impl Connection {
|
||||||
pub fn send(&mut self, message: Message) {
|
pub fn send(&mut self, message: Message) {
|
||||||
self.0
|
if let Err(e) = self.0.try_send(message) {
|
||||||
.try_send(message)
|
match e {
|
||||||
.expect("Send message to PulseAudio server");
|
mpsc::error::TrySendError::Closed(_) => {
|
||||||
|
tracing::error!(
|
||||||
|
"Failed to send message: PulseAudio server communication closed"
|
||||||
|
);
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
mpsc::error::TrySendError::Full(_) => {
|
||||||
|
tracing::warn!("Failed to send message to PulseAudio server: channel is full")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -186,8 +196,8 @@ struct PulseHandle {
|
||||||
impl PulseHandle {
|
impl PulseHandle {
|
||||||
// Create pulse server thread, and bidirectional comms
|
// Create pulse server thread, and bidirectional comms
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let (to_pulse, mut to_pulse_recv) = tokio::sync::mpsc::channel(10);
|
let (to_pulse, mut to_pulse_recv) = tokio::sync::mpsc::channel(50);
|
||||||
let (from_pulse_send, from_pulse) = tokio::sync::mpsc::channel(10);
|
let (from_pulse_send, from_pulse) = tokio::sync::mpsc::channel(50);
|
||||||
|
|
||||||
// this thread should complete by pushing a completed message,
|
// this thread should complete by pushing a completed message,
|
||||||
// or fail message. This should never complete/fail without pushing
|
// or fail message. This should never complete/fail without pushing
|
||||||
|
|
@ -208,7 +218,22 @@ impl PulseHandle {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// This is where the we match messages from the GUI to pass to the pulse server
|
// This is where the we match messages from the GUI to pass to the pulse server
|
||||||
if let Some(msg) = to_pulse_recv.recv().await {
|
let mut msgs = Vec::new();
|
||||||
|
while let Ok(msg) = to_pulse_recv.try_recv() {
|
||||||
|
msgs.push(msg);
|
||||||
|
}
|
||||||
|
// deduplicate Messages that do not rely on response
|
||||||
|
// Reverse to retain the last element instead of the first
|
||||||
|
msgs.reverse();
|
||||||
|
msgs.dedup_by(|a, b| match a {
|
||||||
|
Message::SetSinkVolumeByName(..) | Message::SetSourceVolumeByName(..) => {
|
||||||
|
mem::discriminant(a) == mem::discriminant(b)
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
});
|
||||||
|
msgs.reverse();
|
||||||
|
|
||||||
|
for msg in msgs {
|
||||||
match msg {
|
match msg {
|
||||||
Message::GetDefaultSink => {
|
Message::GetDefaultSink => {
|
||||||
let server = match server.as_mut() {
|
let server = match server.as_mut() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue