mirror of
https://github.com/arabianq/pipewire-soundpad.git
synced 2026-04-28 06:21:23 +00:00
Fix daemon autostart issue caused by sync pipewire retry loop (#43)
At boot time, PipeWire takes some time to register the `pwsp-daemon` and `pwsp-virtual-mic` devices. Previously, the daemon's retry loop for `link_player_to_virtual_mic()` was synchronous and limited to 5 attempts (1.5 seconds total). This caused systemd autostarts to fail with a code 1 if the devices were not yet available. This change replaces the synchronous wait with an asynchronous `tokio::spawn` task. It will retry the link attempt up to 60 times with a 1-second delay without blocking the startup of the rest of the daemon. This prevents it from exiting abruptly during autostart. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
6114b9a7f8
commit
f01a0e656c
+12
-5
@@ -31,16 +31,20 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
eprintln!("Failed to initialize audio player: {}", err);
|
eprintln!("Failed to initialize audio player: {}", err);
|
||||||
} // Initialize audio player
|
} // Initialize audio player
|
||||||
|
|
||||||
let max_retries = 5;
|
tokio::spawn(async {
|
||||||
|
let max_retries = 60;
|
||||||
for i in 0..=max_retries {
|
for i in 0..=max_retries {
|
||||||
match link_player_to_virtual_mic().await {
|
match link_player_to_virtual_mic().await {
|
||||||
Ok(_) => break,
|
Ok(_) => {
|
||||||
|
println!("Successfully linked player to virtual mic.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
Err(e) => println!("{e}\t{i}/{max_retries}"),
|
Err(e) => println!("{e}\t{i}/{max_retries}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep(Duration::from_millis(300 * i)).await;
|
sleep(Duration::from_millis(1000)).await;
|
||||||
}
|
}
|
||||||
link_player_to_virtual_mic().await?;
|
});
|
||||||
|
|
||||||
let runtime_dir = get_runtime_dir();
|
let runtime_dir = get_runtime_dir();
|
||||||
|
|
||||||
@@ -97,7 +101,10 @@ async fn commands_loop(listener: UnixListener) -> Result<(), Box<dyn Error>> {
|
|||||||
let request_len = u32::from_le_bytes(len_bytes) as usize;
|
let request_len = u32::from_le_bytes(len_bytes) as usize;
|
||||||
|
|
||||||
if request_len > 10 * 1024 * 1024 {
|
if request_len > 10 * 1024 * 1024 {
|
||||||
eprintln!("Failed to read message from client: request too large ({} bytes)!", request_len);
|
eprintln!(
|
||||||
|
"Failed to read message from client: request too large ({} bytes)!",
|
||||||
|
request_len
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -86,7 +86,8 @@ impl SoundpadGui {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|cd| dirs.iter().position(|x| x == cd));
|
.and_then(|cd| dirs.iter().position(|x| x == cd));
|
||||||
|
|
||||||
let new_dir_index = match (current_dir_index, arrow_up_pressed, arrow_down_pressed) {
|
let new_dir_index =
|
||||||
|
match (current_dir_index, arrow_up_pressed, arrow_down_pressed) {
|
||||||
(Some(i), true, false) => (i + dirs.len() - 1) % dirs.len(),
|
(Some(i), true, false) => (i + dirs.len() - 1) % dirs.len(),
|
||||||
(Some(i), false, true) => (i + 1) % dirs.len(),
|
(Some(i), false, true) => (i + 1) % dirs.len(),
|
||||||
(Some(i), true, true) => i,
|
(Some(i), true, true) => i,
|
||||||
@@ -109,7 +110,8 @@ impl SoundpadGui {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|f| files.iter().position(|x| x == f));
|
.and_then(|f| files.iter().position(|x| x == f));
|
||||||
|
|
||||||
let new_files_index = match (current_files_index, arrow_up_pressed, arrow_down_pressed) {
|
let new_files_index =
|
||||||
|
match (current_files_index, arrow_up_pressed, arrow_down_pressed) {
|
||||||
(Some(i), true, false) => (i + files.len() - 1) % files.len(),
|
(Some(i), true, false) => (i + files.len() - 1) % files.len(),
|
||||||
(Some(i), false, true) => (i + 1) % files.len(),
|
(Some(i), false, true) => (i + 1) % files.len(),
|
||||||
(Some(i), true, true) => i,
|
(Some(i), true, true) => i,
|
||||||
|
|||||||
+8
-2
@@ -58,7 +58,10 @@ impl SoundpadGui {
|
|||||||
|
|
||||||
pub fn play_toggle(&mut self) {
|
pub fn play_toggle(&mut self) {
|
||||||
let (new_state, request) = {
|
let (new_state, request) = {
|
||||||
let guard = self.audio_player_state_shared.lock().unwrap_or_else(|e| e.into_inner());
|
let guard = self
|
||||||
|
.audio_player_state_shared
|
||||||
|
.lock()
|
||||||
|
.unwrap_or_else(|e| e.into_inner());
|
||||||
match guard.state {
|
match guard.state {
|
||||||
PlayerState::Playing => (Some(PlayerState::Paused), Some(Request::pause(None))),
|
PlayerState::Playing => (Some(PlayerState::Paused), Some(Request::pause(None))),
|
||||||
PlayerState::Paused => (Some(PlayerState::Playing), Some(Request::resume(None))),
|
PlayerState::Paused => (Some(PlayerState::Playing), Some(Request::resume(None))),
|
||||||
@@ -71,7 +74,10 @@ impl SoundpadGui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(state) = new_state {
|
if let Some(state) = new_state {
|
||||||
let mut guard = self.audio_player_state_shared.lock().unwrap_or_else(|e| e.into_inner());
|
let mut guard = self
|
||||||
|
.audio_player_state_shared
|
||||||
|
.lock()
|
||||||
|
.unwrap_or_else(|e| e.into_inner());
|
||||||
guard.new_state = Some(state.clone());
|
guard.new_state = Some(state.clone());
|
||||||
guard.state = state;
|
guard.state = state;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -77,7 +77,10 @@ impl App for SoundpadGui {
|
|||||||
|
|
||||||
// Sync audio player state
|
// Sync audio player state
|
||||||
{
|
{
|
||||||
let guard = self.audio_player_state_shared.lock().unwrap_or_else(|e| e.into_inner());
|
let guard = self
|
||||||
|
.audio_player_state_shared
|
||||||
|
.lock()
|
||||||
|
.unwrap_or_else(|e| e.into_inner());
|
||||||
self.audio_player_state = guard.clone();
|
self.audio_player_state = guard.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -280,13 +280,15 @@ impl AudioPlayer {
|
|||||||
) -> Result<u32, Box<dyn Error>> {
|
) -> Result<u32, Box<dyn Error>> {
|
||||||
let path_buf = file_path.to_path_buf();
|
let path_buf = file_path.to_path_buf();
|
||||||
|
|
||||||
let decoder_result = tokio::task::spawn_blocking(move || -> Result<_, Box<dyn Error + Send + Sync>> {
|
let decoder_result =
|
||||||
|
tokio::task::spawn_blocking(move || -> Result<_, Box<dyn Error + Send + Sync>> {
|
||||||
if !path_buf.exists() {
|
if !path_buf.exists() {
|
||||||
return Err(format!("File does not exist: {}", path_buf.display()).into());
|
return Err(format!("File does not exist: {}", path_buf.display()).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let file = fs::File::open(&path_buf)?;
|
let file = fs::File::open(&path_buf)?;
|
||||||
let decoder = Decoder::try_from(file).map_err(|e| Box::new(e) as Box<dyn Error + Send + Sync>)?;
|
let decoder = Decoder::try_from(file)
|
||||||
|
.map_err(|e| Box::new(e) as Box<dyn Error + Send + Sync>)?;
|
||||||
Ok(decoder)
|
Ok(decoder)
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|||||||
Reference in New Issue
Block a user