fix: stabilize multi-account chat handling

This commit is contained in:
Mikhail Kilin
2026-05-17 04:06:19 +03:00
parent 1208aa5afb
commit 42884d174e
22 changed files with 471 additions and 203 deletions

View File

@@ -1,7 +1,7 @@
//! Audio playback module for voice messages.
//!
//! Provides:
//! - AudioPlayer: rodio-based playback with play/pause/stop/volume controls
//! - AudioPlayer: ffplay-based playback with play/pause/seek controls
//! - VoiceCache: LRU cache for downloaded OGG voice files
pub mod cache;

View File

@@ -23,12 +23,15 @@ pub struct AudioPlayer {
impl AudioPlayer {
/// Creates a new AudioPlayer
pub fn new() -> Result<Self, String> {
Command::new("which")
let ffplay_check = Command::new("which")
.arg("ffplay")
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.output()
.map_err(|_| "ffplay not found (install ffmpeg)".to_string())?;
if !ffplay_check.status.success() {
return Err("ffplay not found (install ffmpeg)".to_string());
}
Ok(Self {
current_pid: Arc::new(Mutex::new(None)),
@@ -48,44 +51,48 @@ impl AudioPlayer {
self.stop();
let path_owned = path.as_ref().to_path_buf();
*self.current_path.lock().unwrap() = Some(path_owned.clone());
*self.starting.lock().unwrap() = true;
let current_pid = self.current_pid.clone();
let paused = self.paused.clone();
let starting = self.starting.clone();
std::thread::spawn(move || {
let mut cmd = Command::new("ffplay");
cmd.arg("-nodisp")
.arg("-autoexit")
.arg("-loglevel")
.arg("quiet");
let mut cmd = Command::new("ffplay");
cmd.arg("-nodisp")
.arg("-autoexit")
.arg("-loglevel")
.arg("quiet");
if start_secs > 0.0 {
cmd.arg("-ss").arg(format!("{:.1}", start_secs));
if start_secs > 0.0 {
cmd.arg("-ss").arg(format!("{:.1}", start_secs));
}
let mut child = match cmd
.arg(&path_owned)
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.spawn()
{
Ok(child) => child,
Err(e) => {
*self.starting.lock().unwrap() = false;
return Err(format!("failed to start ffplay: {}", e));
}
};
if let Ok(mut child) = cmd
.arg(&path_owned)
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.spawn()
{
let pid = child.id();
*current_pid.lock().unwrap() = Some(pid);
let pid = child.id();
*self.current_path.lock().unwrap() = Some(path_owned);
*current_pid.lock().unwrap() = Some(pid);
*paused.lock().unwrap() = false;
*starting.lock().unwrap() = false;
std::thread::spawn(move || {
let _ = child.wait();
// Обнуляем только если это наш pid (новый play мог уже заменить его)
let mut pid_guard = current_pid.lock().unwrap();
if *pid_guard == Some(pid) {
*pid_guard = None;
*paused.lock().unwrap() = false;
*starting.lock().unwrap() = false;
let _ = child.wait();
// Обнуляем только если это наш pid (новый play мог уже заменить его)
let mut pid_guard = current_pid.lock().unwrap();
if *pid_guard == Some(pid) {
*pid_guard = None;
*paused.lock().unwrap() = false;
}
} else {
*starting.lock().unwrap() = false;
}
});