1use std::collections::HashMap;
2use std::ops::Deref;
3use std::sync::{Arc, Mutex};
4
5use tokio::sync::oneshot::{channel, Receiver, Sender};
6
7use crate::tts::{EventfulSynthesizer, Speech, Synthesizer};
8use crate::Result;
9
10enum PendingSpeech {
11 Waiting(Sender<()>),
12 Finished,
13}
14
15#[cfg_attr(docsrs, doc(cfg(feature = "tokio-tts")))]
16pub struct AsyncSynthesizer {
18 base: EventfulSynthesizer,
19 pending_speeches: Arc<Mutex<HashMap<u32, PendingSpeech>>>,
20}
21
22impl AsyncSynthesizer {
23 pub fn new() -> Result<Self> {
25 let pending_speeches = Arc::new(Mutex::new(HashMap::<u32, PendingSpeech>::new()));
26 let handler = {
27 let pending_speeches = pending_speeches.clone();
28 move |id| {
29 let mut map = pending_speeches.lock().unwrap();
30 if let Some(PendingSpeech::Waiting(tx)) = map.remove(&id) {
31 let _ = tx.send(());
32 } else {
33 map.insert(id, PendingSpeech::Finished);
34 }
35 }
36 };
37 Ok(Self {
38 base: EventfulSynthesizer::new(handler)?,
39 pending_speeches,
40 })
41 }
42
43 pub async fn speak<'s, S: Into<Speech<'s>>>(&self, speech: S) -> Result<()> {
45 let id = self.base.speak(speech)?;
46 if let Some(rx) = self.awaiter_for_speech_id(id) {
47 let _ = rx.await;
48 }
49 Ok(())
50 }
51
52 pub fn speak_and_forget<'s, S: Into<Speech<'s>>>(&self, speech: S) -> Result<()> {
57 let id = self.base.speak(speech)?;
58 let _ = self.awaiter_for_speech_id(id);
59 Ok(())
60 }
61
62 fn awaiter_for_speech_id(&self, id: u32) -> Option<Receiver<()>> {
63 let mut map = self.pending_speeches.lock().unwrap();
64 if let Some(PendingSpeech::Finished) = map.remove(&id) {
65 return None;
66 }
67 let (tx, rx) = channel();
68 map.insert(id, PendingSpeech::Waiting(tx));
69 Some(rx)
70 }
71}
72
73impl Deref for AsyncSynthesizer {
74 type Target = Synthesizer;
75 fn deref(&self) -> &Self::Target {
76 &self.base
77 }
78}