tauri_plugin_tts/
models.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, Default, Deserialize, Serialize, PartialEq, Eq)]
5#[serde(rename_all = "lowercase")]
6pub enum QueueMode {
7 #[default]
9 Flush,
10 Add,
12}
13
14#[derive(Debug, Deserialize, Serialize)]
16#[serde(rename_all = "camelCase")]
17pub struct SpeakRequest {
18 pub text: String,
20 #[serde(default)]
22 pub language: Option<String>,
23 #[serde(default)]
25 pub voice_id: Option<String>,
26 #[serde(default = "default_rate")]
28 pub rate: f32,
29 #[serde(default = "default_pitch")]
31 pub pitch: f32,
32 #[serde(default = "default_volume")]
34 pub volume: f32,
35 #[serde(default)]
37 pub queue_mode: QueueMode,
38}
39
40fn default_rate() -> f32 {
41 1.0
42}
43fn default_pitch() -> f32 {
44 1.0
45}
46fn default_volume() -> f32 {
47 1.0
48}
49
50#[derive(Debug, Clone, Default, Deserialize, Serialize)]
52#[serde(rename_all = "camelCase")]
53pub struct SpeakResponse {
54 pub success: bool,
56 #[serde(skip_serializing_if = "Option::is_none")]
58 pub warning: Option<String>,
59}
60
61#[derive(Debug, Deserialize, Serialize)]
63#[serde(rename_all = "camelCase")]
64pub struct StopRequest {}
65
66#[derive(Debug, Clone, Default, Deserialize, Serialize)]
68#[serde(rename_all = "camelCase")]
69pub struct StopResponse {
70 pub success: bool,
71}
72
73#[derive(Debug, Clone, Deserialize, Serialize)]
75#[serde(rename_all = "camelCase")]
76pub struct Voice {
77 pub id: String,
79 pub name: String,
81 pub language: String,
83}
84
85#[derive(Debug, Deserialize, Serialize)]
87#[serde(rename_all = "camelCase")]
88pub struct GetVoicesRequest {
89 #[serde(default)]
91 pub language: Option<String>,
92}
93
94#[derive(Debug, Clone, Default, Deserialize, Serialize)]
96#[serde(rename_all = "camelCase")]
97pub struct GetVoicesResponse {
98 pub voices: Vec<Voice>,
99}
100
101#[derive(Debug, Deserialize, Serialize)]
103#[serde(rename_all = "camelCase")]
104pub struct IsSpeakingRequest {}
105
106#[derive(Debug, Clone, Default, Deserialize, Serialize)]
108#[serde(rename_all = "camelCase")]
109pub struct IsSpeakingResponse {
110 pub speaking: bool,
111}
112
113#[derive(Debug, Clone, Default, Deserialize, Serialize)]
115#[serde(rename_all = "camelCase")]
116pub struct PauseResumeResponse {
117 pub success: bool,
118 #[serde(skip_serializing_if = "Option::is_none")]
120 pub reason: Option<String>,
121}
122
123#[derive(Debug, Deserialize, Serialize)]
125#[serde(rename_all = "camelCase")]
126pub struct PreviewVoiceRequest {
127 pub voice_id: String,
129 #[serde(default)]
131 pub text: Option<String>,
132}
133
134impl PreviewVoiceRequest {
135 pub fn sample_text(&self) -> &str {
137 self.text
138 .as_deref()
139 .unwrap_or("Hello! This is a sample of how this voice sounds.")
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146
147 #[test]
148 fn test_speak_request_defaults() {
149 let json = r#"{"text": "Hello world"}"#;
150 let request: SpeakRequest = serde_json::from_str(json).unwrap();
151
152 assert_eq!(request.text, "Hello world");
153 assert!(request.language.is_none());
154 assert!(request.voice_id.is_none());
155 assert_eq!(request.rate, 1.0);
156 assert_eq!(request.pitch, 1.0);
157 assert_eq!(request.volume, 1.0);
158 }
159
160 #[test]
161 fn test_speak_request_full() {
162 let json = r#"{
163 "text": "Olá",
164 "language": "pt-BR",
165 "voiceId": "com.apple.voice.enhanced.pt-BR",
166 "rate": 0.8,
167 "pitch": 1.2,
168 "volume": 0.9
169 }"#;
170
171 let request: SpeakRequest = serde_json::from_str(json).unwrap();
172 assert_eq!(request.text, "Olá");
173 assert_eq!(request.language, Some("pt-BR".to_string()));
174 assert_eq!(
175 request.voice_id,
176 Some("com.apple.voice.enhanced.pt-BR".to_string())
177 );
178 assert_eq!(request.rate, 0.8);
179 assert_eq!(request.pitch, 1.2);
180 assert_eq!(request.volume, 0.9);
181 }
182
183 #[test]
184 fn test_voice_serialization() {
185 let voice = Voice {
186 id: "test-voice".to_string(),
187 name: "Test Voice".to_string(),
188 language: "en-US".to_string(),
189 };
190
191 let json = serde_json::to_string(&voice).unwrap();
192 assert!(json.contains("\"id\":\"test-voice\""));
193 assert!(json.contains("\"name\":\"Test Voice\""));
194 assert!(json.contains("\"language\":\"en-US\""));
195 }
196
197 #[test]
198 fn test_get_voices_request_optional_language() {
199 let json1 = r#"{}"#;
201 let request1: GetVoicesRequest = serde_json::from_str(json1).unwrap();
202 assert!(request1.language.is_none());
203
204 let json2 = r#"{"language": "en"}"#;
206 let request2: GetVoicesRequest = serde_json::from_str(json2).unwrap();
207 assert_eq!(request2.language, Some("en".to_string()));
208 }
209}