Skip to main content

sapi_lite/stt/context/
event.rs

1use std::ops::Deref;
2
3use windows as Windows;
4use Windows::core::Interface;
5
6use crate::event::{Event, EventSink, EventSource};
7use crate::stt::{Phrase, Recognizer};
8use crate::Result;
9
10use super::Context;
11
12/// The handler [`EventfulContext`] will call.
13pub trait EventHandler: Sync {
14    /// Called when the engine has successfully recognized a phrase.
15    fn on_recognition(&self, phrase: Phrase);
16}
17
18impl<F: Fn(Phrase) + Sync> EventHandler for F {
19    fn on_recognition(&self, phrase: Phrase) {
20        self(phrase)
21    }
22}
23
24/// A recognition context that calls the supplied event handler every time the engine recognizes a
25/// phrase in it.
26pub struct EventfulContext {
27    base: Context,
28}
29
30impl EventfulContext {
31    /// Creates a new recognition context for the given recognizer, configured to call the given
32    /// handler whenever a phrase from this context is recognized.
33    pub fn new<E: EventHandler + 'static>(recognizer: &Recognizer, handler: E) -> Result<Self> {
34        let intf = unsafe { recognizer.intf.CreateRecoContext() }?;
35        EventSink::new(EventSource::from_sapi(intf.cast()?), move |event| {
36            if let Event::Recognition(result) = event {
37                let phrase = Phrase::from_sapi(result)?;
38                handler.on_recognition(phrase);
39            }
40            Ok(())
41        })
42        .install(None)?;
43        Ok(Self {
44            base: Context::new(intf, recognizer.pauser.clone()),
45        })
46    }
47}
48
49impl Deref for EventfulContext {
50    type Target = Context;
51    fn deref(&self) -> &Self::Target {
52        &self.base
53    }
54}