refactor: replace all rust Result with anyhow::Result (#103)

This commit is contained in:
Tarasov Aleksandr
2026-05-15 19:32:26 +03:00
committed by GitHub
parent 9b70bcd69d
commit dc1ecc81ea
12 changed files with 72 additions and 72 deletions
Generated
+1
View File
@@ -3097,6 +3097,7 @@ checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5"
name = "pwsp" name = "pwsp"
version = "1.8.1" version = "1.8.1"
dependencies = [ dependencies = [
"anyhow",
"async-trait", "async-trait",
"clap", "clap",
"dirs", "dirs",
+1
View File
@@ -28,6 +28,7 @@ clap = { version = "4.6.1", default-features = false, features = [
] } ] }
dirs = "6.0.0" dirs = "6.0.0"
itertools = "0.14.0" itertools = "0.14.0"
anyhow = "1.0.102"
rodio = { git = "https://github.com/arabianq/rodio.git", rev = "1a08f281c352622bd82b87b8731585245802d9cf", default-features = false, features = [ rodio = { git = "https://github.com/arabianq/rodio.git", rev = "1a08f281c352622bd82b87b8731585245802d9cf", default-features = false, features = [
"symphonia-all", "symphonia-all",
+4 -5
View File
@@ -1,9 +1,10 @@
use anyhow::{Result, anyhow};
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use pwsp::{ use pwsp::{
types::socket::Request, types::socket::Request,
utils::daemon::{make_request, wait_for_daemon}, utils::daemon::{make_request, wait_for_daemon},
}; };
use std::{error::Error, path::PathBuf}; use std::path::PathBuf;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(version, about, long_about = None)] #[command(version, about, long_about = None)]
@@ -146,7 +147,7 @@ enum SetCommands {
} }
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> { async fn main() -> Result<()> {
let cli = Cli::parse(); let cli = Cli::parse();
wait_for_daemon().await?; wait_for_daemon().await?;
@@ -204,9 +205,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
}, },
}; };
let response = make_request(request) let response = make_request(request).await.map_err(|e| anyhow!(e))?;
.await
.map_err(|e| e as Box<dyn Error>)?;
println!("{} : {}", response.status, response.message); println!("{} : {}", response.status, response.message);
Ok(()) Ok(())
+5 -4
View File
@@ -1,3 +1,4 @@
use anyhow::{Result, anyhow};
use pwsp::{ use pwsp::{
types::socket::{MAX_MESSAGE_SIZE, Request, Response}, types::socket::{MAX_MESSAGE_SIZE, Request, Response},
utils::{ utils::{
@@ -11,7 +12,7 @@ use pwsp::{
}, },
}; };
use std::os::unix::fs::PermissionsExt; use std::os::unix::fs::PermissionsExt;
use std::{error::Error, fs, time::Duration}; use std::{fs, time::Duration};
use tokio::{ use tokio::{
io::{AsyncReadExt, AsyncWriteExt}, io::{AsyncReadExt, AsyncWriteExt},
net::UnixListener, net::UnixListener,
@@ -19,11 +20,11 @@ use tokio::{
}; };
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> { async fn main() -> Result<()> {
create_runtime_dir()?; create_runtime_dir()?;
if is_daemon_running()? { if is_daemon_running()? {
return Err("Another instance is already running.".into()); return Err(anyhow!("Another instance is already running."));
} }
get_daemon_config(); // Initialize daemon config get_daemon_config(); // Initialize daemon config
@@ -76,7 +77,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
Ok(()) Ok(())
} }
async fn commands_loop(listener: UnixListener) -> Result<(), Box<dyn Error>> { async fn commands_loop(listener: UnixListener) -> Result<()> {
loop { loop {
let (mut stream, _addr) = listener.accept().await?; let (mut stream, _addr) = listener.accept().await?;
+5 -9
View File
@@ -2,6 +2,7 @@ mod draw;
mod input; mod input;
mod update; mod update;
use anyhow::{Result, anyhow};
use eframe::{HardwareAcceleration, NativeOptions, icon_data::from_png_bytes, run_native}; use eframe::{HardwareAcceleration, NativeOptions, icon_data::from_png_bytes, run_native};
use egui::{Context, FontData, FontDefinitions, FontFamily, FontTweak, Vec2, ViewportBuilder}; use egui::{Context, FontData, FontDefinitions, FontFamily, FontTweak, Vec2, ViewportBuilder};
use itertools::Itertools; use itertools::Itertools;
@@ -20,7 +21,6 @@ use pwsp::{
}; };
use rfd::FileDialog; use rfd::FileDialog;
use std::{ use std::{
error::Error,
fs, fs,
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::{Arc, Mutex}, sync::{Arc, Mutex},
@@ -198,11 +198,7 @@ impl SoundpadGui {
} }
} }
fn add_font( fn add_font(font_name: &str, font_bytes: &[u8], fonts: &mut FontDefinitions) -> Result<()> {
font_name: &str,
font_bytes: &[u8],
fonts: &mut FontDefinitions,
) -> Result<(), Box<dyn Error>> {
let font_data = FontData::from_owned(font_bytes.to_vec()).tweak(FontTweak { let font_data = FontData::from_owned(font_bytes.to_vec()).tweak(FontTweak {
scale: 1.0, scale: 1.0,
hinting_override: Some(true), hinting_override: Some(true),
@@ -227,7 +223,7 @@ fn add_font(
Ok(()) Ok(())
} }
fn load_system_fonts(fonts: &mut FontDefinitions) -> Result<(), Box<dyn Error>> { fn load_system_fonts(fonts: &mut FontDefinitions) -> Result<()> {
let (_, en_sans) = find_for_locale("en", FontStyle::Sans); let (_, en_sans) = find_for_locale("en", FontStyle::Sans);
let (_, en_serif) = find_for_locale("en", FontStyle::Serif); let (_, en_serif) = find_for_locale("en", FontStyle::Serif);
let (_, ja_sans) = find_for_locale("ja", FontStyle::Sans); let (_, ja_sans) = find_for_locale("ja", FontStyle::Sans);
@@ -246,7 +242,7 @@ fn load_system_fonts(fonts: &mut FontDefinitions) -> Result<(), Box<dyn Error>>
Ok(()) Ok(())
} }
pub async fn run() -> Result<(), Box<dyn Error>> { pub async fn run() -> Result<()> {
const ICON: &[u8] = include_bytes!("../../assets/icon.png"); const ICON: &[u8] = include_bytes!("../../assets/icon.png");
let options = NativeOptions { let options = NativeOptions {
@@ -283,6 +279,6 @@ pub async fn run() -> Result<(), Box<dyn Error>> {
} }
Ok(()) Ok(())
} }
Err(e) => Err(e.into()), Err(e) => Err(anyhow!(e.to_string())),
} }
} }
+2 -2
View File
@@ -1,8 +1,8 @@
mod gui; mod gui;
use std::error::Error; use anyhow::Result;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> { async fn main() -> Result<()> {
gui::run().await gui::run().await
} }
+14 -17
View File
@@ -5,6 +5,7 @@ use crate::{
pipewire::{create_link, get_device, link_player_to_virtual_mic}, pipewire::{create_link, get_device, link_player_to_virtual_mic},
}, },
}; };
use anyhow::{Result, anyhow};
use rodio::{Decoder, DeviceSinkBuilder, MixerDeviceSink, Player, Source}; use rodio::{Decoder, DeviceSinkBuilder, MixerDeviceSink, Player, Source};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{ use std::{
@@ -65,7 +66,7 @@ pub struct AudioPlayer {
} }
impl AudioPlayer { impl AudioPlayer {
pub async fn new() -> Result<Self, Box<dyn Error>> { pub async fn new() -> Result<Self> {
let daemon_config = get_daemon_config(); let daemon_config = get_daemon_config();
let default_volume = daemon_config.default_volume.unwrap_or(1.0); let default_volume = daemon_config.default_volume.unwrap_or(1.0);
@@ -88,7 +89,7 @@ impl AudioPlayer {
Ok(audio_player) Ok(audio_player)
} }
fn ensure_stream(&mut self) -> Result<&MixerDeviceSink, Box<dyn Error>> { fn ensure_stream(&mut self) -> Result<&MixerDeviceSink> {
if self.stream_handle.is_none() { if self.stream_handle.is_none() {
let mut sink = DeviceSinkBuilder::open_default_sink()?; let mut sink = DeviceSinkBuilder::open_default_sink()?;
sink.log_on_drop(false); sink.log_on_drop(false);
@@ -126,7 +127,7 @@ impl AudioPlayer {
} }
} }
async fn link_player(&mut self) -> Result<(), Box<dyn Error>> { async fn link_player(&mut self) -> Result<()> {
if self.player_link_sender.is_some() { if self.player_link_sender.is_some() {
return Ok(()); return Ok(());
} }
@@ -140,7 +141,7 @@ impl AudioPlayer {
} }
} }
async fn link_devices(&mut self) -> Result<(), Box<dyn Error>> { async fn link_devices(&mut self) -> Result<()> {
self.abort_link_thread(); self.abort_link_thread();
let input_device; let input_device;
@@ -289,7 +290,7 @@ impl AudioPlayer {
0.0 0.0
} }
pub fn seek(&mut self, position: f32, id: Option<u32>) -> Result<(), Box<dyn Error>> { pub fn seek(&mut self, position: f32, id: Option<u32>) -> Result<()> {
let position = if position < 0.0 { 0.0 } else { position }; let position = if position < 0.0 { 0.0 } else { position };
if let Some(id) = id { if let Some(id) = id {
@@ -305,22 +306,18 @@ impl AudioPlayer {
Ok(()) Ok(())
} }
pub fn get_duration(&mut self, id: Option<u32>) -> Result<f32, Box<dyn Error>> { pub fn get_duration(&mut self, id: Option<u32>) -> Result<f32> {
if let Some(id) = id { if let Some(id) = id {
if let Some(sound) = self.tracks.get(&id) { if let Some(sound) = self.tracks.get(&id) {
return sound.duration.ok_or("Unknown duration".into()); return sound.duration.ok_or(anyhow!("Unknown duration"));
} }
} else if let Some(sound) = self.tracks.values().last() { } else if let Some(sound) = self.tracks.values().last() {
return sound.duration.ok_or("Unknown duration".into()); return sound.duration.ok_or(anyhow!("Unknown duration"));
} }
Err("No track playing".into()) Err(anyhow!("No track playing"))
} }
pub async fn play( pub async fn play(&mut self, file_path: &Path, concurrent: bool) -> Result<u32> {
&mut self,
file_path: &Path,
concurrent: bool,
) -> Result<u32, Box<dyn Error>> {
let path_buf = file_path.to_path_buf(); let path_buf = file_path.to_path_buf();
let decoder_result = let decoder_result =
@@ -369,7 +366,7 @@ impl AudioPlayer {
Ok(id) Ok(id)
} }
Err(err) => Err(err as Box<dyn Error>), Err(err) => Err(anyhow!(err)),
} }
} }
@@ -472,11 +469,11 @@ impl AudioPlayer {
} }
} }
pub async fn set_current_input_device(&mut self, name: &str) -> Result<(), Box<dyn Error>> { pub async fn set_current_input_device(&mut self, name: &str) -> Result<()> {
let input_device = get_device(name).await?; let input_device = get_device(name).await?;
if input_device.device_type != DeviceType::Input { if input_device.device_type != DeviceType::Input {
return Err("Selected device is not an input device".into()); return Err(anyhow!("Selected device is not an input device"));
} }
self.input_device_name = Some(name.to_string()); self.input_device_name = Some(name.to_string());
+9 -8
View File
@@ -1,6 +1,7 @@
use crate::{types::socket::Request, utils::config::get_config_path}; use crate::{types::socket::Request, utils::config::get_config_path};
use anyhow::Result;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{collections::HashMap, error::Error, fs, path::PathBuf}; use std::{collections::HashMap, fs, path::PathBuf};
#[derive(Default, Clone, Serialize, Deserialize)] #[derive(Default, Clone, Serialize, Deserialize)]
#[serde(default)] #[serde(default)]
@@ -10,7 +11,7 @@ pub struct DaemonConfig {
} }
impl DaemonConfig { impl DaemonConfig {
pub fn save_to_file(&self) -> Result<(), Box<dyn Error>> { pub fn save_to_file(&self) -> Result<()> {
let config_path = get_config_path()?.join("daemon.json"); let config_path = get_config_path()?.join("daemon.json");
if let Some(config_dir) = config_path.parent() if let Some(config_dir) = config_path.parent()
@@ -24,7 +25,7 @@ impl DaemonConfig {
Ok(()) Ok(())
} }
pub fn load_from_file() -> Result<DaemonConfig, Box<dyn Error>> { pub fn load_from_file() -> Result<DaemonConfig> {
let config_path = get_config_path()?.join("daemon.json"); let config_path = get_config_path()?.join("daemon.json");
let bytes = fs::read(config_path)?; let bytes = fs::read(config_path)?;
match serde_json::from_slice::<DaemonConfig>(&bytes) { match serde_json::from_slice::<DaemonConfig>(&bytes) {
@@ -65,7 +66,7 @@ impl Default for GuiConfig {
} }
impl GuiConfig { impl GuiConfig {
pub fn save_to_file(&mut self) -> Result<(), Box<dyn Error>> { pub fn save_to_file(&mut self) -> Result<()> {
let config_path = get_config_path()?.join("gui.json"); let config_path = get_config_path()?.join("gui.json");
if let Some(config_dir) = config_path.parent() if let Some(config_dir) = config_path.parent()
@@ -84,7 +85,7 @@ impl GuiConfig {
Ok(()) Ok(())
} }
pub fn load_from_file() -> Result<GuiConfig, Box<dyn Error>> { pub fn load_from_file() -> Result<GuiConfig> {
let config_path = get_config_path()?.join("gui.json"); let config_path = get_config_path()?.join("gui.json");
let bytes = fs::read(config_path)?; let bytes = fs::read(config_path)?;
match serde_json::from_slice::<GuiConfig>(&bytes) { match serde_json::from_slice::<GuiConfig>(&bytes) {
@@ -108,11 +109,11 @@ pub struct HotkeyConfig {
} }
impl HotkeyConfig { impl HotkeyConfig {
pub fn config_path() -> Result<PathBuf, Box<dyn Error>> { pub fn config_path() -> Result<PathBuf> {
Ok(get_config_path()?.join("hotkeys.json")) Ok(get_config_path()?.join("hotkeys.json"))
} }
pub fn load() -> Result<HotkeyConfig, Box<dyn Error>> { pub fn load() -> Result<HotkeyConfig> {
let path = Self::config_path()?; let path = Self::config_path()?;
if !path.exists() { if !path.exists() {
return Ok(HotkeyConfig::default()); return Ok(HotkeyConfig::default());
@@ -124,7 +125,7 @@ impl HotkeyConfig {
} }
} }
pub fn save(&self) -> Result<(), Box<dyn Error>> { pub fn save(&self) -> Result<()> {
let path = Self::config_path()?; let path = Self::config_path()?;
if let Some(dir) = path.parent() if let Some(dir) = path.parent()
&& !dir.exists() && !dir.exists()
+3 -2
View File
@@ -1,6 +1,7 @@
use std::{error::Error, path::PathBuf}; use anyhow::Result;
use std::path::PathBuf;
pub fn get_config_path() -> Result<PathBuf, Box<dyn Error>> { pub fn get_config_path() -> Result<PathBuf> {
let config_path = dirs::config_dir().expect("Failed to obtain config dir"); let config_path = dirs::config_dir().expect("Failed to obtain config dir");
Ok(config_path.join("pwsp")) Ok(config_path.join("pwsp"))
} }
+4 -3
View File
@@ -4,6 +4,7 @@ use crate::types::{
socket::{MAX_MESSAGE_SIZE, Request, Response}, socket::{MAX_MESSAGE_SIZE, Request, Response},
}; };
use anyhow::Result;
use std::os::unix::fs::PermissionsExt; use std::os::unix::fs::PermissionsExt;
use std::path::PathBuf; use std::path::PathBuf;
use std::{error::Error, fs}; use std::{error::Error, fs};
@@ -40,7 +41,7 @@ pub fn get_runtime_dir() -> PathBuf {
dirs::runtime_dir().unwrap_or(PathBuf::from("/run/pwsp")) dirs::runtime_dir().unwrap_or(PathBuf::from("/run/pwsp"))
} }
pub fn create_runtime_dir() -> Result<(), Box<dyn Error>> { pub fn create_runtime_dir() -> Result<()> {
let runtime_dir = get_runtime_dir(); let runtime_dir = get_runtime_dir();
if !runtime_dir.exists() { if !runtime_dir.exists() {
fs::create_dir_all(&runtime_dir)?; fs::create_dir_all(&runtime_dir)?;
@@ -50,7 +51,7 @@ pub fn create_runtime_dir() -> Result<(), Box<dyn Error>> {
Ok(()) Ok(())
} }
pub fn is_daemon_running() -> Result<bool, Box<dyn Error>> { pub fn is_daemon_running() -> Result<bool> {
let lock_file = fs::File::create(get_runtime_dir().join("daemon.lock"))?; let lock_file = fs::File::create(get_runtime_dir().join("daemon.lock"))?;
match lock_file.try_lock() { match lock_file.try_lock() {
Ok(_) => Ok(false), Ok(_) => Ok(false),
@@ -58,7 +59,7 @@ pub fn is_daemon_running() -> Result<bool, Box<dyn Error>> {
} }
} }
pub async fn wait_for_daemon() -> Result<(), Box<dyn Error>> { pub async fn wait_for_daemon() -> Result<()> {
if is_daemon_running()? { if is_daemon_running()? {
return Ok(()); return Ok(());
} }
+3 -3
View File
@@ -7,8 +7,8 @@ use crate::{
}, },
utils::daemon::{is_daemon_running, make_request}, utils::daemon::{is_daemon_running, make_request},
}; };
use anyhow::{Result, anyhow};
use std::{ use std::{
error::Error,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
time::Instant, time::Instant,
}; };
@@ -22,11 +22,11 @@ pub fn get_gui_config() -> GuiConfig {
}) })
} }
pub fn make_request_sync(request: Request) -> Result<Response, Box<dyn Error>> { pub fn make_request_sync(request: Request) -> Result<Response> {
tokio::task::block_in_place(|| { tokio::task::block_in_place(|| {
tokio::runtime::Handle::current() tokio::runtime::Handle::current()
.block_on(make_request(request)) .block_on(make_request(request))
.map_err(|e| e as Box<dyn Error>) .map_err(|e| anyhow!(e))
}) })
} }
+21 -19
View File
@@ -1,9 +1,10 @@
use crate::types::pipewire::{AudioDevice, DeviceType, Port, Terminate}; use crate::types::pipewire::{AudioDevice, DeviceType, Port, Terminate};
use anyhow::{Result, anyhow};
use pipewire::{ use pipewire::{
context::ContextRc, link::Link, main_loop::MainLoopRc, properties::properties, context::ContextRc, link::Link, main_loop::MainLoopRc, properties::properties,
registry::GlobalObject, spa::utils::dict::DictRef, registry::GlobalObject, spa::utils::dict::DictRef,
}; };
use std::{collections::HashMap, error::Error, thread}; use std::{collections::HashMap, thread};
use tokio::{ use tokio::{
sync::mpsc, sync::mpsc,
time::{Duration, timeout}, time::{Duration, timeout},
@@ -142,7 +143,7 @@ async fn pw_get_global_objects_thread(
main_loop.run(); main_loop.run();
} }
pub async fn get_all_devices() -> Result<(Vec<AudioDevice>, Vec<AudioDevice>), Box<dyn Error>> { pub async fn get_all_devices() -> Result<(Vec<AudioDevice>, Vec<AudioDevice>)> {
// Channels to communicate with pipewire thread // Channels to communicate with pipewire thread
let (main_sender, mut main_receiver) = mpsc::channel(10); let (main_sender, mut main_receiver) = mpsc::channel(10);
let (pw_sender, pw_receiver) = pipewire::channel::channel(); let (pw_sender, pw_receiver) = pipewire::channel::channel();
@@ -155,7 +156,7 @@ pub async fn get_all_devices() -> Result<(Vec<AudioDevice>, Vec<AudioDevice>), B
// Wait for initialization to complete // Wait for initialization to complete
if let Err(e) = init_receiver.recv()? { if let Err(e) = init_receiver.recv()? {
return Err(e.into()); return Err(anyhow!(e));
} }
let mut input_devices: HashMap<u32, AudioDevice> = HashMap::new(); let mut input_devices: HashMap<u32, AudioDevice> = HashMap::new();
@@ -238,7 +239,7 @@ pub async fn get_all_devices() -> Result<(Vec<AudioDevice>, Vec<AudioDevice>), B
} }
} }
pub async fn get_device(device_name: &str) -> Result<AudioDevice, Box<dyn Error>> { pub async fn get_device(device_name: &str) -> Result<AudioDevice> {
let (input_devices, output_devices) = get_all_devices().await?; let (input_devices, output_devices) = get_all_devices().await?;
input_devices input_devices
@@ -250,10 +251,10 @@ pub async fn get_device(device_name: &str) -> Result<AudioDevice, Box<dyn Error>
|| device.name.contains(device_name) || device.name.contains(device_name)
|| device.nick.contains(device_name) || device.nick.contains(device_name)
}) })
.ok_or_else(|| "Device not found".into()) .ok_or_else(|| anyhow!("Device not found"))
} }
pub fn create_virtual_mic() -> Result<pipewire::channel::Sender<Terminate>, Box<dyn Error>> { pub fn create_virtual_mic() -> Result<pipewire::channel::Sender<Terminate>> {
let (pw_sender, pw_receiver) = pipewire::channel::channel::<Terminate>(); let (pw_sender, pw_receiver) = pipewire::channel::channel::<Terminate>();
let (init_sender, init_receiver) = std::sync::mpsc::sync_channel(0); let (init_sender, init_receiver) = std::sync::mpsc::sync_channel(0);
@@ -305,45 +306,46 @@ pub fn create_virtual_mic() -> Result<pipewire::channel::Sender<Terminate>, Box<
}); });
if let Err(e) = init_receiver.recv()? { if let Err(e) = init_receiver.recv()? {
return Err(e.into()); return Err(anyhow!(e));
} }
Ok(pw_sender) Ok(pw_sender)
} }
pub async fn link_player_to_virtual_mic() pub async fn link_player_to_virtual_mic() -> Result<pipewire::channel::Sender<Terminate>> {
-> Result<pipewire::channel::Sender<Terminate>, Box<dyn Error>> {
let pwsp_daemon_output = match get_device("pwsp-daemon").await { let pwsp_daemon_output = match get_device("pwsp-daemon").await {
Ok(device) => device, Ok(device) => device,
Err(_) => { Err(_) => {
return Err( return Err(anyhow!(
"Could not find alsa_playback.pwsp-daemon device, skipping device linking".into(), "Could not find alsa_playback.pwsp-daemon device, skipping device linking"
); ));
} }
}; };
let pwsp_daemon_input = match get_device("pwsp-virtual-mic").await { let pwsp_daemon_input = match get_device("pwsp-virtual-mic").await {
Ok(device) => device, Ok(device) => device,
Err(_) => { Err(_) => {
return Err("Could not find pwsp-virtual-mic device, skipping device linking".into()); return Err(anyhow!(
"Could not find pwsp-virtual-mic device, skipping device linking"
));
} }
}; };
let output_fl = match pwsp_daemon_output.output_fl { let output_fl = match pwsp_daemon_output.output_fl {
Some(port) => port, Some(port) => port,
None => return Err("Failed to get pwsp-daemon output_fl".into()), None => return Err(anyhow!("Failed to get pwsp-daemon output_fl")),
}; };
let output_fr = match pwsp_daemon_output.output_fr { let output_fr = match pwsp_daemon_output.output_fr {
Some(port) => port, Some(port) => port,
None => return Err("Failed to get pwsp-daemon output_fr".into()), None => return Err(anyhow!("Failed to get pwsp-daemon output_fr")),
}; };
let input_fl = match pwsp_daemon_input.input_fl { let input_fl = match pwsp_daemon_input.input_fl {
Some(port) => port, Some(port) => port,
None => return Err("Failed to get pwsp-virtual-mic input_fl".into()), None => return Err(anyhow!("Failed to get pwsp-virtual-mic input_fl")),
}; };
let input_fr = match pwsp_daemon_input.input_fr { let input_fr = match pwsp_daemon_input.input_fr {
Some(port) => port, Some(port) => port,
None => return Err("Failed to get pwsp-virtual-mic input_fr".into()), None => return Err(anyhow!("Failed to get pwsp-virtual-mic input_fr")),
}; };
create_link(output_fl, output_fr, input_fl, input_fr) create_link(output_fl, output_fr, input_fl, input_fr)
@@ -354,7 +356,7 @@ pub fn create_link(
output_fr: Port, output_fr: Port,
input_fl: Port, input_fl: Port,
input_fr: Port, input_fr: Port,
) -> Result<pipewire::channel::Sender<Terminate>, Box<dyn Error>> { ) -> Result<pipewire::channel::Sender<Terminate>> {
let (pw_sender, pw_receiver) = pipewire::channel::channel::<Terminate>(); let (pw_sender, pw_receiver) = pipewire::channel::channel::<Terminate>();
let (init_sender, init_receiver) = std::sync::mpsc::sync_channel(0); let (init_sender, init_receiver) = std::sync::mpsc::sync_channel(0);
@@ -419,7 +421,7 @@ pub fn create_link(
}); });
if let Err(e) = init_receiver.recv()? { if let Err(e) = init_receiver.recv()? {
return Err(e.into()); return Err(anyhow!(e));
} }
Ok(pw_sender) Ok(pw_sender)