ssip_client/
client.rs

1// ssip-client -- Speech Dispatcher client in Rust
2// Copyright (c) 2021-2022 Laurent Pelecq
3//
4// Licensed under the Apache License, Version 2.0
5// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
6// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. All files in the project carrying such notice may not be copied,
8// modified, or distributed except according to those terms.
9
10use std::io::{self, Read, Write};
11
12use crate::constants::*;
13use crate::protocol::{
14    flush_lines, parse_event_id, parse_single_integer, parse_single_value, parse_typed_lines,
15    write_lines,
16};
17use crate::types::*;
18
19// Trick to have common implementation for std and mio streams..
20#[cfg(all(not(feature = "async-mio"), unix))]
21pub use std::os::unix::io::AsRawFd as Source;
22
23#[cfg(feature = "async-mio")]
24pub use mio::event::Source;
25
26/// Convert boolean to ON or OFF
27fn on_off(value: bool) -> &'static str {
28    if value {
29        "on"
30    } else {
31        "off"
32    }
33}
34
35#[derive(Debug, Clone)]
36/// Request for SSIP server.
37pub enum Request {
38    SetName(ClientName),
39    // Speech related requests
40    Speak,
41    SendLine(String),
42    SendLines(Vec<String>),
43    SpeakChar(char),
44    SpeakKey(KeyName),
45    // Flow control
46    Stop(MessageScope),
47    Cancel(MessageScope),
48    Pause(MessageScope),
49    Resume(MessageScope),
50    // Setter and getter
51    SetPriority(Priority),
52    SetDebug(bool),
53    SetOutputModule(ClientScope, String),
54    GetOutputModule,
55    ListOutputModules,
56    SetLanguage(ClientScope, String),
57    GetLanguage,
58    SetSsmlMode(bool),
59    SetPunctuationMode(ClientScope, PunctuationMode),
60    SetSpelling(ClientScope, bool),
61    SetCapitalLettersRecognitionMode(ClientScope, CapitalLettersRecognitionMode),
62    SetVoiceType(ClientScope, String),
63    GetVoiceType,
64    ListVoiceTypes,
65    SetSynthesisVoice(ClientScope, String),
66    ListSynthesisVoices,
67    SetRate(ClientScope, i8),
68    GetRate,
69    SetPitch(ClientScope, i8),
70    GetPitch,
71    SetVolume(ClientScope, i8),
72    GetVolume,
73    SetPauseContext(ClientScope, u32),
74    SetNotification(NotificationType, bool),
75    // Blocks
76    Begin,
77    End,
78    // History
79    SetHistory(ClientScope, bool),
80    HistoryGetClients,
81    HistoryGetClientId,
82    HistoryGetClientMsgs(ClientScope, u32, u32),
83    HistoryGetLastMsgId,
84    HistoryGetMsg(MessageId),
85    HistoryCursorGet,
86    HistoryCursorSet(ClientScope, HistoryPosition),
87    HistoryCursorMove(CursorDirection),
88    HistorySpeak(MessageId),
89    HistorySort(SortDirection, SortKey),
90    HistorySetShortMsgLength(u32),
91    HistorySetMsgTypeOrdering(Vec<Ordering>),
92    HistorySearch(ClientScope, String),
93    // Misc.
94    Quit,
95}
96
97impl Request {
98    /// Return true if the request are data.
99    ///
100    /// After a `Speak` has been sent, when the client receives `OK_RECEIVING_DATA`, the
101    /// next request must be `Request::SendLine` or `Request::SendLines`.
102    pub fn is_data(&self) -> bool {
103        matches!(self, Request::SendLine(_) | Request::SendLines(_))
104    }
105}
106
107#[derive(Debug)]
108/// Response from SSIP server.
109pub enum Response {
110    LanguageSet,                                     // 201
111    PrioritySet,                                     // 202
112    RateSet,                                         // 203
113    PitchSet,                                        // 204
114    PunctuationSet,                                  // 205
115    CapLetRecognSet,                                 // 206
116    SpellingSet,                                     // 207
117    ClientNameSet,                                   // 208
118    VoiceSet,                                        // 209
119    Stopped,                                         // 210
120    Paused,                                          // 211
121    Resumed,                                         // 212
122    Canceled,                                        // 213
123    TableSet,                                        // 215
124    OutputModuleSet,                                 // 216
125    PauseContextSet,                                 // 217
126    VolumeSet,                                       // 218
127    SsmlModeSet,                                     // 219
128    NotificationSet,                                 // 220
129    PitchRangeSet,                                   // 263
130    DebugSet,                                        // 262
131    HistoryCurSetFirst,                              // 220
132    HistoryCurSetLast,                               // 221
133    HistoryCurSetPos,                                // 222
134    HistoryCurMoveFor,                               // 223
135    HistoryCurMoveBack,                              // 224
136    MessageQueued,                                   // 225,
137    SoundIconQueued,                                 // 226
138    MessageCanceled,                                 // 227
139    ReceivingData,                                   // 230
140    Bye,                                             // 231
141    HistoryClientListSent(Vec<HistoryClientStatus>), // 240
142    HistoryMsgsListSent(Vec<String>),                // 241
143    HistoryLastMsg(String),                          // 242
144    HistoryCurPosRet(String),                        // 243
145    TableListSent(Vec<String>),                      // 244
146    HistoryClientIdSent(ClientId),                   // 245
147    MessageTextSent,                                 // 246
148    HelpSent(Vec<String>),                           // 248
149    VoicesListSent(Vec<SynthesisVoice>),             // 249
150    OutputModulesListSent(Vec<String>),              // 250
151    Get(String),                                     // 251
152    InsideBlock,                                     // 260
153    OutsideBlock,                                    // 261
154    NotImplemented,                                  // 299
155    EventIndexMark(EventId, String),                 // 700
156    EventBegin(EventId),                             // 701
157    EventEnd(EventId),                               // 702
158    EventCanceled(EventId),                          // 703
159    EventPaused(EventId),                            // 704
160    EventResumed(EventId),                           // 705
161}
162
163macro_rules! send_one_line {
164    ($self:expr, $fmt:expr, $( $arg:expr ),+) => {
165        flush_lines(&mut $self.output, &[format!($fmt, $( $arg ),+).as_str()])
166    };
167    ($self:expr, $fmt:expr) => {
168        flush_lines(&mut $self.output, &[$fmt])
169    }
170}
171
172macro_rules! send_toggle {
173    ($output:expr, $fmt:expr, $val:expr) => {
174        send_one_line!($output, $fmt, on_off($val))
175    };
176    ($output:expr, $fmt:expr, $arg:expr, $val:expr) => {
177        send_one_line!($output, $fmt, $arg, on_off($val))
178    };
179}
180
181macro_rules! send_range {
182    ($output:expr, $fmt:expr, $scope:expr, $val:expr) => {
183        send_one_line!(
184            $output,
185            $fmt,
186            $scope,
187            std::cmp::max(-100, std::cmp::min(100, $val))
188        )
189    };
190}
191
192/// SSIP client on generic stream
193///
194/// There are two ways to send requests and receive responses:
195/// * Either with the generic [`Client::send`] and [`Client::receive`]
196/// * Or with the specific methods such as [`Client::set_rate`], ..., [`Client::get_rate`], ...
197#[derive(Debug)]
198pub struct Client<S: Read + Write + Source> {
199    input: io::BufReader<S>,
200    output: io::BufWriter<S>,
201}
202
203impl<S: Read + Write + Source> Client<S> {
204    /// Create a SSIP client on the reader and writer.
205    pub(crate) fn new(input: io::BufReader<S>, output: io::BufWriter<S>) -> Self {
206        // https://stackoverflow.com/questions/58467659/how-to-store-tcpstream-with-bufreader-and-bufwriter-in-a-data-structure
207        Self { input, output }
208    }
209
210    /// Flush output buf writer
211    fn flush(&mut self) -> ClientResult<&mut Self> {
212        self.output.flush()?;
213        Ok(self)
214    }
215
216    #[cfg(all(not(feature = "async-mio"), unix))]
217    /// Input source for the non-blocking API based on `poll`.
218    pub(crate) fn input_source(&self) -> &S {
219        self.input.get_ref()
220    }
221
222    #[cfg(all(not(feature = "async-mio"), unix))]
223    /// Output source for the non-blocking API based on `poll`.
224    pub(crate) fn output_source(&self) -> &S {
225        self.output.get_ref()
226    }
227
228    /// Send lines of text (terminated by a single dot).
229    pub fn send_lines(&mut self, lines: &[String]) -> ClientResult<&mut Self> {
230        const END_OF_DATA: [&str; 1] = ["."];
231        write_lines(
232            &mut self.output,
233            lines
234                .iter()
235                .map(|s| s.as_str())
236                .collect::<Vec<&str>>()
237                .as_slice(),
238        )?;
239        flush_lines(&mut self.output, &END_OF_DATA)?;
240        Ok(self)
241    }
242
243    /// Send one line of text (terminated by a single dot).
244    pub fn send_line(&mut self, line: &str) -> ClientResult<&mut Self> {
245        const END_OF_DATA: &str = ".";
246        flush_lines(&mut self.output, &[line, END_OF_DATA])?;
247        Ok(self)
248    }
249
250    /// Send a request
251    pub fn send(&mut self, request: Request) -> ClientResult<&mut Self> {
252        match request {
253            Request::SetName(client_name) => send_one_line!(
254                self,
255                "SET self CLIENT_NAME {}:{}:{}",
256                client_name.user,
257                client_name.application,
258                client_name.component
259            ),
260            Request::Speak => send_one_line!(self, "SPEAK"),
261            Request::SendLine(line) => self.send_line(&line).map(|_| ()),
262            Request::SendLines(lines) => self.send_lines(&lines).map(|_| ()),
263            Request::SpeakChar(ch) => send_one_line!(self, "CHAR {}", ch),
264            Request::SpeakKey(key) => send_one_line!(self, "KEY {}", key),
265            Request::Stop(scope) => send_one_line!(self, "STOP {}", scope),
266            Request::Cancel(scope) => send_one_line!(self, "CANCEL {}", scope),
267            Request::Pause(scope) => send_one_line!(self, "PAUSE {}", scope),
268            Request::Resume(scope) => send_one_line!(self, "RESUME {}", scope),
269            Request::SetPriority(prio) => send_one_line!(self, "SET self PRIORITY {}", prio),
270            Request::SetDebug(value) => send_toggle!(self, "SET all DEBUG {}", value),
271            Request::SetOutputModule(scope, value) => {
272                send_one_line!(self, "SET {} OUTPUT_MODULE {}", scope, value)
273            }
274            Request::GetOutputModule => send_one_line!(self, "GET OUTPUT_MODULE"),
275            Request::ListOutputModules => send_one_line!(self, "LIST OUTPUT_MODULES"),
276            Request::SetLanguage(scope, lang) => {
277                send_one_line!(self, "SET {} LANGUAGE {}", scope, lang)
278            }
279            Request::GetLanguage => send_one_line!(self, "GET LANGUAGE"),
280            Request::SetSsmlMode(value) => send_toggle!(self, "SET self SSML_MODE {}", value),
281            Request::SetPunctuationMode(scope, mode) => {
282                send_one_line!(self, "SET {} PUNCTUATION {}", scope, mode)
283            }
284            Request::SetSpelling(scope, value) => {
285                send_toggle!(self, "SET {} SPELLING {}", scope, value)
286            }
287            Request::SetCapitalLettersRecognitionMode(scope, mode) => {
288                send_one_line!(self, "SET {} CAP_LET_RECOGN {}", scope, mode)
289            }
290            Request::SetVoiceType(scope, value) => {
291                send_one_line!(self, "SET {} VOICE_TYPE {}", scope, value)
292            }
293            Request::GetVoiceType => send_one_line!(self, "GET VOICE_TYPE"),
294            Request::ListVoiceTypes => send_one_line!(self, "LIST VOICES"),
295            Request::SetSynthesisVoice(scope, value) => {
296                send_one_line!(self, "SET {} SYNTHESIS_VOICE {}", scope, value)
297            }
298            Request::ListSynthesisVoices => send_one_line!(self, "LIST SYNTHESIS_VOICES"),
299            Request::SetRate(scope, value) => send_range!(self, "SET {} RATE {}", scope, value),
300            Request::GetRate => send_one_line!(self, "GET RATE"),
301            Request::SetPitch(scope, value) => send_range!(self, "SET {} PITCH {}", scope, value),
302            Request::GetPitch => send_one_line!(self, "GET PITCH"),
303            Request::SetVolume(scope, value) => {
304                send_range!(self, "SET {} VOLUME {}", scope, value)
305            }
306            Request::GetVolume => send_one_line!(self, "GET VOLUME"),
307            Request::SetPauseContext(scope, value) => {
308                send_one_line!(self, "SET {} PAUSE_CONTEXT {}", scope, value)
309            }
310            Request::SetHistory(scope, value) => {
311                send_toggle!(self, "SET {} HISTORY {}", scope, value)
312            }
313            Request::SetNotification(ntype, value) => {
314                send_toggle!(self, "SET self NOTIFICATION {} {}", ntype, value)
315            }
316            Request::Begin => send_one_line!(self, "BLOCK BEGIN"),
317            Request::End => send_one_line!(self, "BLOCK END"),
318            Request::HistoryGetClients => send_one_line!(self, "HISTORY GET CLIENT_LIST"),
319            Request::HistoryGetClientId => send_one_line!(self, "HISTORY GET CLIENT_ID"),
320            Request::HistoryGetClientMsgs(scope, start, number) => send_one_line!(
321                self,
322                "HISTORY GET CLIENT_MESSAGES {} {}_{}",
323                scope,
324                start,
325                number
326            ),
327            Request::HistoryGetLastMsgId => send_one_line!(self, "HISTORY GET LAST"),
328            Request::HistoryGetMsg(id) => send_one_line!(self, "HISTORY GET MESSAGE {}", id),
329            Request::HistoryCursorGet => send_one_line!(self, "HISTORY CURSOR GET"),
330            Request::HistoryCursorSet(scope, pos) => {
331                send_one_line!(self, "HISTORY CURSOR SET {} {}", scope, pos)
332            }
333            Request::HistoryCursorMove(direction) => {
334                send_one_line!(self, "HISTORY CURSOR {}", direction)
335            }
336            Request::HistorySpeak(id) => send_one_line!(self, "HISTORY SAY {}", id),
337            Request::HistorySort(direction, key) => {
338                send_one_line!(self, "HISTORY SORT {} {}", direction, key)
339            }
340            Request::HistorySetShortMsgLength(length) => {
341                send_one_line!(self, "HISTORY SET SHORT_MESSAGE_LENGTH {}", length)
342            }
343            Request::HistorySetMsgTypeOrdering(ordering) => {
344                send_one_line!(
345                    self,
346                    "HISTORY SET MESSAGE_TYPE_ORDERING \"{}\"",
347                    ordering
348                        .iter()
349                        .map(|x| x.to_string())
350                        .collect::<Vec<String>>()
351                        .join(" ")
352                )
353            }
354            Request::HistorySearch(scope, condition) => {
355                send_one_line!(self, "HISTORY SEARCH {} \"{}\"", scope, condition)
356            }
357            Request::Quit => send_one_line!(self, "QUIT"),
358        }?;
359        Ok(self)
360    }
361
362    /// Set the client name. It must be the first call on startup.
363    pub fn set_client_name(&mut self, client_name: ClientName) -> ClientResult<&mut Self> {
364        self.send(Request::SetName(client_name))
365    }
366
367    /// Initiate communitation to send text to speak
368    pub fn speak(&mut self) -> ClientResult<&mut Self> {
369        self.send(Request::Speak)
370    }
371
372    /// Speak a char
373    pub fn speak_char(&mut self, ch: char) -> ClientResult<&mut Self> {
374        self.send(Request::SpeakChar(ch))
375    }
376
377    /// Speak a symbolic key name
378    pub fn speak_key(&mut self, key_name: KeyName) -> ClientResult<&mut Self> {
379        self.send(Request::SpeakKey(key_name))
380    }
381
382    /// Stop current message
383    pub fn stop(&mut self, scope: MessageScope) -> ClientResult<&mut Self> {
384        self.send(Request::Stop(scope))
385    }
386
387    /// Cancel current message
388    pub fn cancel(&mut self, scope: MessageScope) -> ClientResult<&mut Self> {
389        self.send(Request::Cancel(scope))
390    }
391
392    /// Pause current message
393    pub fn pause(&mut self, scope: MessageScope) -> ClientResult<&mut Self> {
394        self.send(Request::Pause(scope))
395    }
396
397    /// Resume current message
398    pub fn resume(&mut self, scope: MessageScope) -> ClientResult<&mut Self> {
399        self.send(Request::Resume(scope))
400    }
401
402    /// Set message priority
403    pub fn set_priority(&mut self, prio: Priority) -> ClientResult<&mut Self> {
404        self.send(Request::SetPriority(prio))
405    }
406
407    /// Set debug mode. Return the log location
408    pub fn set_debug(&mut self, value: bool) -> ClientResult<&mut Self> {
409        self.send(Request::SetDebug(value))
410    }
411
412    /// Set output module
413    pub fn set_output_module(
414        &mut self,
415        scope: ClientScope,
416        value: &str,
417    ) -> ClientResult<&mut Self> {
418        self.send(Request::SetOutputModule(scope, value.to_string()))
419    }
420
421    /// Get the current output module
422    pub fn get_output_module(&mut self) -> ClientResult<&mut Self> {
423        self.send(Request::GetOutputModule)
424    }
425
426    /// List the available output modules
427    pub fn list_output_modules(&mut self) -> ClientResult<&mut Self> {
428        self.send(Request::ListOutputModules)
429    }
430
431    /// Set language code
432    pub fn set_language(&mut self, scope: ClientScope, value: &str) -> ClientResult<&mut Self> {
433        self.send(Request::SetLanguage(scope, value.to_string()))
434    }
435
436    /// Get the current language
437    pub fn get_language(&mut self) -> ClientResult<&mut Self> {
438        self.send(Request::GetLanguage)
439    }
440
441    /// Set SSML mode (Speech Synthesis Markup Language)
442    pub fn set_ssml_mode(&mut self, mode: bool) -> ClientResult<&mut Self> {
443        self.send(Request::SetSsmlMode(mode))
444    }
445
446    /// Set punctuation mode
447    pub fn set_punctuation_mode(
448        &mut self,
449        scope: ClientScope,
450        mode: PunctuationMode,
451    ) -> ClientResult<&mut Self> {
452        self.send(Request::SetPunctuationMode(scope, mode))
453    }
454
455    /// Set spelling on or off
456    pub fn set_spelling(&mut self, scope: ClientScope, value: bool) -> ClientResult<&mut Self> {
457        self.send(Request::SetSpelling(scope, value))
458    }
459
460    /// Set capital letters recognition mode
461    pub fn set_capital_letter_recogn(
462        &mut self,
463        scope: ClientScope,
464        mode: CapitalLettersRecognitionMode,
465    ) -> ClientResult<&mut Self> {
466        self.send(Request::SetCapitalLettersRecognitionMode(scope, mode))
467    }
468
469    /// Set the voice type (MALE1, FEMALE1, …)
470    pub fn set_voice_type(&mut self, scope: ClientScope, value: &str) -> ClientResult<&mut Self> {
471        self.send(Request::SetVoiceType(scope, value.to_string()))
472    }
473
474    /// Get the current pre-defined voice
475    pub fn get_voice_type(&mut self) -> ClientResult<&mut Self> {
476        self.send(Request::GetVoiceType)
477    }
478
479    /// List the available symbolic voice names
480    pub fn list_voice_types(&mut self) -> ClientResult<&mut Self> {
481        self.send(Request::ListVoiceTypes)
482    }
483
484    /// Set the voice
485    pub fn set_synthesis_voice(
486        &mut self,
487        scope: ClientScope,
488        value: &str,
489    ) -> ClientResult<&mut Self> {
490        self.send(Request::SetSynthesisVoice(scope, value.to_string()))
491    }
492
493    /// Lists the available voices for the current synthesizer
494    pub fn list_synthesis_voices(&mut self) -> ClientResult<&mut Self> {
495        self.send(Request::ListSynthesisVoices)
496    }
497
498    /// Set the rate of speech. n is an integer value within the range from -100 to 100, lower values meaning slower speech.
499    pub fn set_rate(&mut self, scope: ClientScope, value: i8) -> ClientResult<&mut Self> {
500        self.send(Request::SetRate(scope, value))
501    }
502
503    /// Get the current rate of speech.
504    pub fn get_rate(&mut self) -> ClientResult<&mut Self> {
505        self.send(Request::GetRate)
506    }
507
508    /// Set the pitch of speech. n is an integer value within the range from -100 to 100.
509    pub fn set_pitch(&mut self, scope: ClientScope, value: i8) -> ClientResult<&mut Self> {
510        self.send(Request::SetPitch(scope, value))
511    }
512
513    /// Get the current pitch value.
514    pub fn get_pitch(&mut self) -> ClientResult<&mut Self> {
515        self.send(Request::GetPitch)
516    }
517
518    /// Set the volume of speech. n is an integer value within the range from -100 to 100.
519    pub fn set_volume(&mut self, scope: ClientScope, value: i8) -> ClientResult<&mut Self> {
520        self.send(Request::SetVolume(scope, value))
521    }
522
523    /// Get the current volume.
524    pub fn get_volume(&mut self) -> ClientResult<&mut Self> {
525        self.send(Request::GetVolume)
526    }
527
528    /// Set the number of (more or less) sentences that should be repeated after a previously paused text is resumed.
529    pub fn set_pause_context(&mut self, scope: ClientScope, value: u32) -> ClientResult<&mut Self> {
530        self.send(Request::SetPauseContext(scope, value))
531    }
532
533    /// Enable notification events
534    pub fn set_notification(
535        &mut self,
536        ntype: NotificationType,
537        value: bool,
538    ) -> ClientResult<&mut Self> {
539        self.send(Request::SetNotification(ntype, value))
540    }
541
542    /// Open a block
543    pub fn block_begin(&mut self) -> ClientResult<&mut Self> {
544        self.send(Request::Begin)
545    }
546
547    /// End a block
548    pub fn block_end(&mut self) -> ClientResult<&mut Self> {
549        self.send(Request::End)
550    }
551
552    /// Enable or disable history of received messages.
553    pub fn set_history(&mut self, scope: ClientScope, value: bool) -> ClientResult<&mut Self> {
554        self.send(Request::SetHistory(scope, value))
555    }
556
557    /// Get clients in history.
558    pub fn history_get_clients(&mut self) -> ClientResult<&mut Self> {
559        self.send(Request::HistoryGetClients)
560    }
561
562    /// Get client id in the history.
563    pub fn history_get_client_id(&mut self) -> ClientResult<&mut Self> {
564        self.send(Request::HistoryGetClientId)
565    }
566
567    /// Get last message said.
568    pub fn history_get_last(&mut self) -> ClientResult<&mut Self> {
569        self.send(Request::HistoryGetLastMsgId)
570    }
571
572    /// Get a range of client messages.
573    pub fn history_get_client_messages(
574        &mut self,
575        scope: ClientScope,
576        start: u32,
577        number: u32,
578    ) -> ClientResult<&mut Self> {
579        self.send(Request::HistoryGetClientMsgs(scope, start, number))
580    }
581
582    /// Get the id of the last message sent by the client.
583    pub fn history_get_last_message_id(&mut self) -> ClientResult<&mut Self> {
584        self.send(Request::HistoryGetLastMsgId)
585    }
586
587    /// Return the text of an history message.
588    pub fn history_get_message(&mut self, msg_id: MessageId) -> ClientResult<&mut Self> {
589        self.send(Request::HistoryGetMsg(msg_id))
590    }
591
592    /// Get the id of the message the history cursor is pointing to.
593    pub fn history_get_cursor(&mut self) -> ClientResult<&mut Self> {
594        self.send(Request::HistoryCursorGet)
595    }
596
597    /// Set the history cursor position.
598    pub fn history_set_cursor(
599        &mut self,
600        scope: ClientScope,
601        pos: HistoryPosition,
602    ) -> ClientResult<&mut Self> {
603        self.send(Request::HistoryCursorSet(scope, pos))
604    }
605
606    /// Move the cursor position backward or forward.
607    pub fn history_move_cursor(&mut self, direction: CursorDirection) -> ClientResult<&mut Self> {
608        self.send(Request::HistoryCursorMove(direction))
609    }
610
611    /// Speak the message from history.
612    pub fn history_speak(&mut self, msg_id: MessageId) -> ClientResult<&mut Self> {
613        self.send(Request::HistorySpeak(msg_id))
614    }
615
616    /// Sort messages in history.
617    pub fn history_sort(
618        &mut self,
619        direction: SortDirection,
620        key: SortKey,
621    ) -> ClientResult<&mut Self> {
622        self.send(Request::HistorySort(direction, key))
623    }
624
625    /// Set the maximum length of short versions of history messages.
626    pub fn history_set_short_message_length(&mut self, length: u32) -> ClientResult<&mut Self> {
627        self.send(Request::HistorySetShortMsgLength(length))
628    }
629
630    /// Set the ordering of the message types, from the minimum to the maximum.
631    pub fn history_set_ordering(&mut self, ordering: Vec<Ordering>) -> ClientResult<&mut Self> {
632        self.send(Request::HistorySetMsgTypeOrdering(ordering))
633    }
634
635    /// Search in message history.
636    pub fn history_search(
637        &mut self,
638        scope: ClientScope,
639        condition: &str,
640    ) -> ClientResult<&mut Self> {
641        self.send(Request::HistorySearch(scope, condition.to_string()))
642    }
643
644    /// Close the connection
645    pub fn quit(&mut self) -> ClientResult<&mut Self> {
646        self.send(Request::Quit)
647    }
648
649    /// Receive answer from server
650    fn receive_answer(&mut self, lines: &mut Vec<String>) -> ClientStatus {
651        crate::protocol::receive_answer(&mut self.input, Some(lines))
652    }
653
654    /// Receive one response.
655    pub fn receive(&mut self) -> ClientResult<Response> {
656        const MSG_CURSOR_SET_FIRST: &str = "OK CURSOR SET FIRST";
657        let mut lines = Vec::new();
658        let status = self.receive_answer(&mut lines)?;
659        match status.code {
660            OK_LANGUAGE_SET => Ok(Response::LanguageSet),
661            OK_PRIORITY_SET => Ok(Response::PrioritySet),
662            OK_RATE_SET => Ok(Response::RateSet),
663            OK_PITCH_SET => Ok(Response::PitchSet),
664            OK_PUNCTUATION_SET => Ok(Response::PunctuationSet),
665            OK_CAP_LET_RECOGN_SET => Ok(Response::CapLetRecognSet),
666            OK_SPELLING_SET => Ok(Response::SpellingSet),
667            OK_CLIENT_NAME_SET => Ok(Response::ClientNameSet),
668            OK_VOICE_SET => Ok(Response::VoiceSet),
669            OK_STOPPED => Ok(Response::Stopped),
670            OK_PAUSED => Ok(Response::Paused),
671            OK_RESUMED => Ok(Response::Resumed),
672            OK_CANCELED => Ok(Response::Canceled),
673            OK_TABLE_SET => Ok(Response::TableSet),
674            OK_OUTPUT_MODULE_SET => Ok(Response::OutputModuleSet),
675            OK_PAUSE_CONTEXT_SET => Ok(Response::PauseContextSet),
676            OK_VOLUME_SET => Ok(Response::VolumeSet),
677            OK_SSML_MODE_SET => Ok(Response::SsmlModeSet),
678            // Warning OK_CUR_SET_FIRST == OK_NOTIFICATION_SET == 220. Matching message to make the difference
679            OK_NOTIFICATION_SET => {
680                if status.message == MSG_CURSOR_SET_FIRST {
681                    //OK_CUR_SET_FIRST => Ok(Response::HistoryCurSetFirst)
682                    Ok(Response::HistoryCurSetFirst)
683                } else {
684                    Ok(Response::NotificationSet)
685                }
686            }
687            OK_CUR_SET_LAST => Ok(Response::HistoryCurSetLast),
688            OK_CUR_SET_POS => Ok(Response::HistoryCurSetPos),
689            OK_PITCH_RANGE_SET => Ok(Response::PitchRangeSet),
690            OK_DEBUG_SET => Ok(Response::DebugSet),
691            OK_CUR_MOV_FOR => Ok(Response::HistoryCurMoveFor),
692            OK_CUR_MOV_BACK => Ok(Response::HistoryCurMoveBack),
693            OK_MESSAGE_QUEUED => Ok(Response::MessageQueued),
694            OK_SND_ICON_QUEUED => Ok(Response::SoundIconQueued),
695            OK_MSG_CANCELED => Ok(Response::MessageCanceled),
696            OK_RECEIVING_DATA => Ok(Response::ReceivingData),
697            OK_BYE => Ok(Response::Bye),
698            OK_CLIENTS_LIST_SENT => Ok(Response::HistoryClientListSent(parse_typed_lines::<
699                HistoryClientStatus,
700            >(&lines)?)),
701            OK_MSGS_LIST_SENT => Ok(Response::HistoryMsgsListSent(lines)),
702            OK_LAST_MSG => Ok(Response::HistoryLastMsg(parse_single_value(&lines)?)),
703            OK_CUR_POS_RET => Ok(Response::HistoryCurPosRet(parse_single_value(&lines)?)),
704            OK_TABLE_LIST_SENT => Ok(Response::TableListSent(lines)),
705            OK_CLIENT_ID_SENT => Ok(Response::HistoryClientIdSent(parse_single_integer(&lines)?)),
706            OK_MSG_TEXT_SENT => Ok(Response::MessageTextSent),
707            OK_HELP_SENT => Ok(Response::HelpSent(lines)),
708            OK_VOICES_LIST_SENT => Ok(Response::VoicesListSent(
709                parse_typed_lines::<SynthesisVoice>(&lines)?,
710            )),
711            OK_OUTPUT_MODULES_LIST_SENT => Ok(Response::OutputModulesListSent(lines)),
712            OK_GET => Ok(Response::Get(parse_single_value(&lines)?)),
713            OK_INSIDE_BLOCK => Ok(Response::InsideBlock),
714            OK_OUTSIDE_BLOCK => Ok(Response::OutsideBlock),
715            OK_NOT_IMPLEMENTED => Ok(Response::NotImplemented),
716            EVENT_INDEX_MARK => match lines.len() {
717                0..=2 => Err(ClientError::TooFewLines),
718                3 => Ok(Response::EventIndexMark(
719                    parse_event_id(&lines)?,
720                    lines[2].to_owned(),
721                )),
722                _ => Err(ClientError::TooManyLines),
723            },
724            EVENT_BEGIN => Ok(Response::EventBegin(parse_event_id(&lines)?)),
725            EVENT_END => Ok(Response::EventEnd(parse_event_id(&lines)?)),
726            EVENT_CANCELED => Ok(Response::EventCanceled(parse_event_id(&lines)?)),
727            EVENT_PAUSED => Ok(Response::EventPaused(parse_event_id(&lines)?)),
728            EVENT_RESUMED => Ok(Response::EventResumed(parse_event_id(&lines)?)),
729            _ => panic!("error should have been caught earlier"),
730        }
731    }
732
733    /// Check status of answer, discard lines.
734    pub fn check_status(&mut self, expected_code: ReturnCode) -> ClientResult<&mut Self> {
735        crate::protocol::receive_answer(&mut self.input, None).and_then(|status| {
736            if status.code == expected_code {
737                Ok(self)
738            } else {
739                Err(ClientError::UnexpectedStatus(status.code))
740            }
741        })
742    }
743
744    /// Receive lines
745    pub fn receive_lines(&mut self, expected_code: ReturnCode) -> ClientResult<Vec<String>> {
746        let mut lines = Vec::new();
747        let status = self.receive_answer(&mut lines)?;
748        if status.code == expected_code {
749            Ok(lines)
750        } else {
751            Err(ClientError::UnexpectedStatus(status.code))
752        }
753    }
754
755    /// Receive a single string
756    pub fn receive_string(&mut self, expected_code: ReturnCode) -> ClientResult<String> {
757        self.receive_lines(expected_code)
758            .and_then(|lines| parse_single_value(&lines))
759    }
760
761    /// Receive signed 8-bit integer
762    pub fn receive_i8(&mut self) -> ClientResult<u8> {
763        self.receive_string(OK_GET).and_then(|s| {
764            s.parse()
765                .map_err(|_| ClientError::invalid_data("invalid signed integer"))
766        })
767    }
768
769    /// Receive unsigned 8-bit integer
770    pub fn receive_u8(&mut self) -> ClientResult<u8> {
771        self.receive_string(OK_GET).and_then(|s| {
772            s.parse()
773                .map_err(|_| ClientError::invalid_data("invalid unsigned 8-bit integer"))
774        })
775    }
776
777    /// Receive cursor pos
778    pub fn receive_cursor_pos(&mut self) -> ClientResult<u16> {
779        self.receive_string(OK_CUR_POS_RET).and_then(|s| {
780            s.parse()
781                .map_err(|_| ClientError::invalid_data("invalid unsigned 16-bit integer"))
782        })
783    }
784
785    /// Receive message id
786    pub fn receive_message_id(&mut self) -> ClientResult<MessageId> {
787        let mut lines = Vec::new();
788        match self.receive_answer(&mut lines)?.code {
789            OK_MESSAGE_QUEUED | OK_LAST_MSG => Ok(parse_single_integer(&lines)?),
790            _ => Err(ClientError::invalid_data("not a message id")),
791        }
792    }
793
794    /// Receive client id
795    pub fn receive_client_id(&mut self) -> ClientResult<ClientId> {
796        self.receive_string(OK_CLIENT_ID_SENT).and_then(|s| {
797            s.parse()
798                .map_err(|_| ClientError::invalid_data("invalid client id"))
799        })
800    }
801
802    /// Receive a list of synthesis voices
803    pub fn receive_synthesis_voices(&mut self) -> ClientResult<Vec<SynthesisVoice>> {
804        self.receive_lines(OK_VOICES_LIST_SENT)
805            .and_then(|lines| parse_typed_lines::<SynthesisVoice>(&lines))
806    }
807
808    /// Receive a notification
809    pub fn receive_event(&mut self) -> ClientResult<Event> {
810        let mut lines = Vec::new();
811        crate::protocol::receive_answer(&mut self.input, Some(&mut lines)).and_then(|status| {
812            if lines.len() < 2 {
813                Err(ClientError::unexpected_eof("event truncated"))
814            } else {
815                let message = &lines[0];
816                let client = &lines[1];
817                match status.code {
818                    700 => {
819                        if lines.len() != 3 {
820                            Err(ClientError::unexpected_eof("index markevent truncated"))
821                        } else {
822                            let mark = lines[3].to_owned();
823                            Ok(Event::index_mark(mark, message, client))
824                        }
825                    }
826                    701 => Ok(Event::begin(message, client)),
827                    702 => Ok(Event::end(message, client)),
828                    703 => Ok(Event::cancel(message, client)),
829                    704 => Ok(Event::pause(message, client)),
830                    705 => Ok(Event::resume(message, client)),
831                    _ => Err(ClientError::invalid_data("wrong status code for event")),
832                }
833            }
834        })
835    }
836
837    /// Receive a list of client status from history.
838    pub fn receive_history_clients(&mut self) -> ClientResult<Vec<HistoryClientStatus>> {
839        self.receive_lines(OK_CLIENTS_LIST_SENT)
840            .and_then(|lines| parse_typed_lines::<HistoryClientStatus>(&lines))
841    }
842
843    /// Check the result of `set_client_name`.
844    pub fn check_client_name_set(&mut self) -> ClientResult<&mut Self> {
845        self.check_status(OK_CLIENT_NAME_SET)
846    }
847
848    /// Check if server accept data.
849    pub fn check_receiving_data(&mut self) -> ClientResult<&mut Self> {
850        self.check_status(OK_RECEIVING_DATA)
851    }
852
853    /// Register the socket for polling.
854    #[cfg(feature = "async-mio")]
855    pub fn register(
856        &mut self,
857        poll: &mio::Poll,
858        input_token: mio::Token,
859        output_token: mio::Token,
860    ) -> io::Result<()> {
861        poll.registry()
862            .register(self.input.get_mut(), input_token, mio::Interest::READABLE)?;
863        poll.registry()
864            .register(self.output.get_mut(), output_token, mio::Interest::WRITABLE)?;
865        Ok(())
866    }
867}
868
869impl<S: Read + Write + Source> Drop for Client<S> {
870    fn drop(&mut self) {
871        let _ = self.flush();
872    }
873}
874
875#[cfg(test)]
876mod test {
877
878    use super::Request;
879
880    #[test]
881    fn test_is_data() {
882        assert!(Request::SendLine("".to_owned()).is_data());
883        assert!(Request::SendLines(vec![]).is_data());
884        assert!(!Request::Speak.is_data());
885        assert!(!Request::SpeakChar('a').is_data());
886    }
887}