Skip to main content

speechd_module_sys/
types.rs

1use std::os::raw;
2
3use bitflags::bitflags;
4
5
6unsafe fn cstr_eq(a: *const raw::c_char, b: *const raw::c_char) -> bool {
7	if a.is_null() && b.is_null() {
8		true
9	} else if a.is_null() != b.is_null() {
10		false
11	} else {
12		unsafe { libc::strcmp(a, b) == 0 }
13	}
14}
15
16
17#[repr(C)]
18#[non_exhaustive]
19#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)]
20pub enum MessageType {
21	#[default]
22	Text = 0,
23	SoundIcon = 1,
24	Char = 2,
25	Key = 3,
26	Spell = 99,
27}
28
29
30/// Symbolic voice type
31///
32/// These values are approximations for human display, output modules are
33/// free to interpret their meanings in any way they consider sensible.
34#[repr(C)]
35#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)]
36pub enum VoiceType {
37	Male1 = 1,
38	Male2 = 2,
39	Male3 = 3,
40	Female1 = 4,
41	Female2 = 5,
42	Female3 = 6,
43	ChildMale = 7,
44	ChildFemale = 8,
45	#[default]
46	Unspecified = -1,
47}
48
49impl<'a> TryFrom<&'a str> for VoiceType {
50	type Error = ();
51
52	fn try_from(text: &'a str) -> Result<Self, ()> {
53		match text {
54			"male1" => Ok(Self::Male1),
55			"male2" => Ok(Self::Male2),
56			"male3" => Ok(Self::Male3),
57			"female1" => Ok(Self::Female1),
58			"female2" => Ok(Self::Female2),
59			"female3" => Ok(Self::Female3),
60			"child_male" => Ok(Self::ChildMale),
61			"child_female" => Ok(Self::ChildFemale),
62			"other" | "unspecified" | "non_binary" | "androgynous" | "agender" => Ok(Self::Unspecified),
63
64			_ => Err(()),
65		}
66	}
67}
68
69
70/// Punctuation verbosity mode
71///
72/// Which characters full under the [`Some`](Punctuation::Some) and
73/// [`Most`](Punctuation::Most) sets is ultimately up to each output module.
74/// For instance, `module_utils.c` defines “`~#$%^&*+=|<>[]_`” as a possible
75/// default set, but ultimately this should be made configurable or carefully
76/// trained for in your module.
77#[repr(u32)]
78#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)]
79pub enum Punctuation {
80	/// Speak all punctuation characters
81	All = 0,
82
83	/// Speak none of the punctuation characters
84	#[default]
85	None = 1,
86
87	/// Speak a smaller intermediate set of punctuation characters
88	Some = 2,
89
90	/// Speak a larger intermediate set of punctuation characters
91	Most = 3,
92}
93
94impl<'a> TryFrom<&'a str> for Punctuation {
95	type Error = ();
96
97	fn try_from(text: &'a str) -> Result<Self, ()> {
98		match text {
99			"none" => Ok(Self::None),
100			"all" => Ok(Self::All),
101			"some" => Ok(Self::Some),
102			"most" => Ok(Self::Most),
103
104			_ => Err(()),
105		}
106	}
107}
108
109
110/// Capital letter recognition
111///
112/// This settings only affect consecutive runs of capital letters (eg: “SSIP”),
113/// not words starting with a single capital letter (eg: “Berlin”).
114#[repr(C)]
115#[non_exhaustive]
116#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)]
117pub enum CapitalLetters {
118	/// Captial letter blocks should be pronounced as as other words
119	#[default]
120	None = 0,
121
122	/// Captial letter blocks should be spelled as individual letters
123	Spell = 1,
124
125	/// Captial letter blocks should have each letter prepended by the
126	/// “`capital`” sound icon (generally a short tick sound)
127	Icon = 2,
128}
129
130impl<'a> TryFrom<&'a str> for CapitalLetters {
131	type Error = ();
132
133	fn try_from(text: &'a str) -> Result<Self, ()> {
134		match text {
135			"none" => Ok(Self::None),
136			"spell" => Ok(Self::Spell),
137			"icon" => Ok(Self::Icon),
138
139			_ => Err(()),
140		}
141	}
142}
143
144
145/// Spelling mode enabled
146///
147/// Informational in the context of an output module, as speech dispatcher
148/// itself will perform the transformation of regular text into indiviual
149/// character spellings.
150#[repr(C)]
151#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)]
152pub enum Spelling {
153	#[default]
154	Off = 0,
155	On = 1,
156}
157
158impl<'a> TryFrom<&'a str> for Spelling {
159	type Error = ();
160
161	fn try_from(text: &'a str) -> Result<Self, ()> {
162		match text {
163			"on" => Ok(Self::On),
164			"off" => Ok(Self::Off),
165
166			_ => Err(()),
167		}
168	}
169}
170
171
172#[repr(C)]
173#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)]
174pub enum DataMode {
175	#[default]
176	Text = 0,
177	SSML = 1,
178}
179
180
181#[repr(C)]
182#[non_exhaustive]
183#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)]
184pub enum Priority {
185	Important = 1,
186	#[default]
187	Message = 2,
188	Text = 3,
189	Notification = 4,
190	Progress = 5,
191}
192
193impl<'a> TryFrom<&'a str> for Priority {
194	type Error = ();
195
196	fn try_from(text: &'a str) -> Result<Self, ()> {
197		match text {
198			"important" => Ok(Self::Important),
199			"message" => Ok(Self::Message),
200			"text" => Ok(Self::Text),
201			"notification" => Ok(Self::Notification),
202			"progress" => Ok(Self::Progress),
203
204			_ => Err(()),
205		}
206	}
207}
208
209
210bitflags! {
211	#[non_exhaustive]
212	#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
213	pub struct Notification: u32 {
214		const Begin      = 0b00000001;
215		const End        = 0b00000010;
216		const IndexMarks = 0b00000100;
217		const Cancel     = 0b00001000;
218		const Pause      = 0b00010000;
219		const Resume     = 0b00100000;
220		const All        = 0b00111111;
221	}
222}
223
224impl Default for Notification {
225	fn default() -> Self {
226		Notification::empty()
227	}
228}
229
230
231#[repr(C)]
232#[non_exhaustive]
233#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
234pub enum NotificationType {
235	Begin = 0,
236	End = 1,
237	IndexMark = 2,
238	Cancel = 3,
239	Pause = 4,
240	Resume = 5,
241}
242
243
244#[repr(C)]
245#[derive(Debug, Default, Eq)]
246pub struct Voice {
247	/// Name of the voice (id)
248	pub name: *const raw::c_char,
249
250	/// Subset of BCP-47
251	///
252	/// A 2/3-letter ISO language code, possibly followed by a hyphen and a
253	/// 2/3-letter ISO region code (e.g.: `en-US`).
254	pub language: *const raw::c_char,
255
256	/// Custom string describing dialect and other properties
257	pub variant: *const raw::c_char,
258}
259
260impl PartialEq for Voice {
261	fn eq(&self, other: &Self) -> bool {
262		(unsafe { cstr_eq(self.name, other.name) }) &&
263		(unsafe { cstr_eq(self.language, other.language) }) &&
264		(unsafe { cstr_eq(self.variant, other.variant) })
265	}
266}
267
268
269#[repr(C)]
270#[derive(Debug, Default, PartialEq, Eq)]
271pub struct MsgSettings {
272	pub rate: raw::c_int,
273	pub pitch: raw::c_int,
274	pub pitch_range: raw::c_int,
275	pub volume: raw::c_int,
276	pub punctuation_mode: Punctuation,
277	pub spelling_mode: Spelling,
278	pub cap_let_recogn: CapitalLetters,
279	pub voice_type: VoiceType,
280	pub voice: Voice,
281}