1use std::ffi::OsString;
2use std::ptr::null_mut;
3
4use windows as Windows;
5use Windows::Win32::Media::Speech::{ISpRecoResult, SPPHRASE_50, SPPR_ALL_ELEMENTS};
6
7use crate::com_util::{from_wide, out_to_ret, ComBox};
8use crate::Result;
9
10use super::SemanticTree;
11
12#[derive(Debug, PartialEq, Clone)]
14pub struct Phrase {
15 pub text: OsString,
17 pub semantics: Vec<SemanticTree>,
19}
20
21impl Phrase {
22 pub(crate) fn from_sapi(sapi_result: ISpRecoResult) -> Result<Self> {
24 let text = unsafe {
25 ComBox::from_raw(out_to_ret(|out| {
26 sapi_result.GetText(
27 SPPR_ALL_ELEMENTS.0 as u32,
28 SPPR_ALL_ELEMENTS.0 as u32,
29 true,
30 out,
31 null_mut(),
32 )
33 })?)
34 };
35 let phrase_info =
36 unsafe { ComBox::from_raw(sapi_result.GetPhrase()? as *const SPPHRASE_50) };
37 let first_prop = unsafe { (*phrase_info).as_ref() }
38 .and_then(|info| unsafe { info.pProperties.as_ref() });
39 Ok(Self {
40 text: unsafe { from_wide(&text) },
41 semantics: SemanticTree::from_sapi(first_prop),
42 })
43 }
44}