Fix virtual mic audio linking (#62)

* Fix virtual mic audio linking by managing it in AudioPlayer lifecycle

- Moved `link_player_to_virtual_mic` to `src/utils/pipewire.rs` and updated it to return a termination sender.
- Added `player_link_sender` to `AudioPlayer` to manage the PipeWire link between the daemon and the virtual mic.
- Integrated linking logic into `AudioPlayer::play` and `AudioPlayer::update` to ensure the link is established when audio starts playing.
- Ensured the link is terminated in `AudioPlayer::drop_stream` when the audio sink is closed.
- Removed redundant and potentially failing startup linking loop from the daemon.
- Fixed log spam by ensuring `link_player` is only attempted when necessary and errors are handled gracefully.
- Maintained compatibility with stable Rust by avoiding unstable features.

Co-authored-by: arabianq <55220741+arabianq@users.noreply.github.com>

* small refactor

* refactor

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
This commit is contained in:
Tarasov Aleksandr
2026-04-17 14:24:58 +03:00
committed by GitHub
parent 5c4b8f4b45
commit 2a8fcca06b
5 changed files with 97 additions and 76 deletions
+2 -21
View File
@@ -1,10 +1,10 @@
use pwsp::{
types::socket::{Request, Response, MAX_MESSAGE_SIZE},
types::socket::{MAX_MESSAGE_SIZE, Request, Response},
utils::{
commands::parse_command,
daemon::{
create_runtime_dir, get_audio_player, get_daemon_config, get_runtime_dir,
is_daemon_running, link_player_to_virtual_mic,
is_daemon_running,
},
global_hotkeys::start_global_hotkey_listener,
pipewire::create_virtual_mic,
@@ -32,25 +32,6 @@ async fn main() -> Result<(), Box<dyn Error>> {
eprintln!("Failed to initialize audio player: {}", err);
} // Initialize audio player
tokio::spawn(async {
let max_retries = 60;
for i in 0..=max_retries {
match link_player_to_virtual_mic().await {
Ok(_) => {
println!("Successfully linked player to virtual mic.");
break;
}
Err(e) => {
if i == 0 || i == max_retries {
eprintln!("{e} (attempt {i}/{max_retries})");
}
}
}
sleep(Duration::from_millis(1000)).await;
}
});
tokio::spawn(async {
start_global_hotkey_listener().await;
});