[Tts][TCSACR-497] Add new API for service state information (#4488)
[platform/core/csapi/tizenfx.git] / src / Tizen.Uix.Tts / Tizen.Uix.Tts / TtsClient.cs
1 /*
2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18 using System;
19 using System.Collections.Generic;
20 using System.Runtime.InteropServices;
21 using static Interop.Tts;
22
23 namespace Tizen.Uix.Tts
24 {
25     /// <summary>
26     /// Enumeration for the states.
27     /// </summary>
28     /// <since_tizen> 3 </since_tizen>
29     public enum State
30     {
31         /// <summary>
32         ///  Created state.
33         /// </summary>
34         /// <since_tizen> 3 </since_tizen>
35         Created = 0,
36
37         /// <summary>
38         /// Ready state.
39         /// </summary>
40         /// <since_tizen> 3 </since_tizen>
41         Ready = 1,
42
43         /// <summary>
44         /// Playing state.
45         /// </summary>
46         /// <since_tizen> 3 </since_tizen>
47         Playing = 2,
48
49         /// <summary>
50         /// Paused state.
51         /// </summary>
52         /// <since_tizen> 3 </since_tizen>
53         Paused = 3,
54
55         /// <summary>
56         /// Unavailable state.
57         /// </summary>
58         /// <since_tizen> 3 </since_tizen>
59         Unavailable
60     };
61
62     /// <summary>
63     /// Enumeration for TTS mode.
64     /// </summary>
65     /// <since_tizen> 3 </since_tizen>
66     public enum Mode
67     {
68         /// <summary>
69         /// Default mode for normal application.
70         /// </summary>
71         /// <since_tizen> 3 </since_tizen>
72         Default = 0,
73
74         /// <summary>
75         /// Notification mode.
76         /// </summary>
77         /// <since_tizen> 3 </since_tizen>
78         Notification = 1,
79
80         /// <summary>
81         /// Accessibility mode.
82         /// </summary>
83         /// <since_tizen> 3 </since_tizen>
84         ScreenReader = 2
85     };
86
87     /// <summary>
88     /// Enumeration for error values that can occur.
89     /// </summary>
90     /// <since_tizen> 3 </since_tizen>
91     public enum Error
92     {
93         /// <summary>
94         /// Successful, no error.
95         /// </summary>
96         /// <since_tizen> 3 </since_tizen>
97         None,
98         /// <summary>
99         /// Out of memory.
100         /// </summary>
101         /// <since_tizen> 3 </since_tizen>
102         OutOfMemory,
103         /// <summary>
104         /// I/O error.
105         /// </summary>
106         /// <since_tizen> 3 </since_tizen>
107         IoError,
108         /// <summary>
109         /// Invalid parameter.
110         /// </summary>
111         /// <since_tizen> 3 </since_tizen>
112         InvalidParameter,
113         /// <summary>
114         /// No answer from the TTS service.
115         /// </summary>
116         /// <since_tizen> 3 </since_tizen>
117         TimedOut,
118         /// <summary>
119         /// Network is down.
120         /// </summary>
121         /// <since_tizen> 3 </since_tizen>
122         OutOfNetwork,
123         /// <summary>
124         /// Permission denied.
125         /// </summary>
126         /// <since_tizen> 3 </since_tizen>
127         PermissionDenied,
128         /// <summary>
129         /// TTS not supported.
130         /// </summary>
131         /// <since_tizen> 3 </since_tizen>
132         NotSupported,
133         /// <summary>
134         /// Invalid state.
135         /// </summary>
136         /// <since_tizen> 3 </since_tizen>
137         InvalidState,
138         /// <summary>
139         /// Invalid voice.
140         /// </summary>
141         /// <since_tizen> 3 </since_tizen>
142         InvalidVoice,
143         /// <summary>
144         /// No available engine.
145         /// </summary>
146         /// <since_tizen> 3 </since_tizen>
147         EngineNotFound,
148         /// <summary>
149         /// Operation failed.
150         /// </summary>
151         /// <since_tizen> 3 </since_tizen>
152         OperationFailed,
153         /// <summary>
154         /// Audio policy blocked.
155         /// </summary>
156         /// <since_tizen> 3 </since_tizen>
157         AudioPolicyBlocked,
158         /// <summary>
159         /// Not supported feature of current engine.
160         /// </summary>
161         /// <since_tizen> 10 </since_tizen>
162         NotSupportedFeature,
163         /// <summary>
164         /// Service reset.
165         /// </summary>
166         /// <since_tizen> 10 </since_tizen>
167         ServiceReset,
168         /// <summary>
169         /// Screen reader off.
170         /// </summary>
171         /// <since_tizen> 10 </since_tizen>
172         ScreenReaderOff
173     };
174
175     /// <summary>
176     /// Enumeration for the voice types.
177     /// </summary>
178     /// <since_tizen> 3 </since_tizen>
179     public enum Voice
180     {
181         /// <summary>
182         /// The automatic voice type.
183         /// </summary>
184         /// <since_tizen> 3 </since_tizen>
185         Auto,
186
187         /// <summary>
188         /// The male voice type.
189         /// </summary>
190         /// <since_tizen> 3 </since_tizen>
191         Male,
192
193         /// <summary>
194         /// The female voice type.
195         /// </summary>
196         /// <since_tizen> 3 </since_tizen>
197         Female,
198
199         /// <summary>
200         /// The child voice type.
201         /// </summary>
202         /// <since_tizen> 3 </since_tizen>
203         Child
204     };
205
206     /// <summary>
207     /// Enumeration for the states of TTS service.
208     /// </summary>
209     /// <since_tizen> 10 </since_tizen>
210     public enum ServiceState
211     {
212         /// <summary>
213         /// Ready state.
214         /// </summary>
215         Ready = 0,
216
217         /// <summary>
218         /// Synthesizing state.
219         /// </summary>
220         Synthesizing = 1,
221
222         /// <summary>
223         /// Playing state.
224         /// </summary>
225         Playing = 2,
226
227         /// <summary>
228         /// Unavailable state.
229         /// </summary>
230         Unavailable
231     };
232
233     /// <summary>
234     /// You can use Text-To-Speech (TTS) API's to read sound data transformed by the engine from input texts.
235     /// Applications can add input-text to queue for reading continuously and control the player that can play, pause, and stop sound data synthesized from text.
236     /// </summary>
237     /// <since_tizen> 3 </since_tizen>
238     public class TtsClient : IDisposable
239     {
240         private IntPtr _handle;
241         private event EventHandler<StateChangedEventArgs> _stateChanged;
242         private event EventHandler<UtteranceEventArgs> _utteranceStarted;
243         private event EventHandler<UtteranceEventArgs> _utteranceCompleted;
244         private event EventHandler<ErrorOccurredEventArgs> _errorOccurred;
245         private event EventHandler<DefaultVoiceChangedEventArgs> _defaultVoiceChanged;
246         private event EventHandler<EngineChangedEventArgs> _engineChanged;
247         private event EventHandler<ScreenReaderChangedEventArgs> _screenReaderChanged;
248         private event EventHandler<ServiceStateChangedEventArgs> _serviceStateChanged;
249         private bool disposedValue = false;
250         private readonly Object _stateChangedLock = new Object();
251         private readonly Object _utteranceStartedLock = new Object();
252         private readonly Object _utteranceCompletedLock = new Object();
253         private readonly Object _errorOccurredLock = new Object();
254         private readonly Object _defaultVoiceChangedLock = new Object();
255         private readonly Object _engineChangedLock = new Object();
256         private readonly Object _screenReaderChangedLock = new Object();
257         private readonly Object _serviceStateChangedLock = new Object();
258         private TtsStateChangedCB _stateDelegate;
259         private TtsUtteranceStartedCB _utteranceStartedResultDelegate;
260         private TtsUtteranceCompletedCB _utteranceCompletedResultDelegate;
261         private TtsErrorCB _errorDelegate;
262         private TtsDefaultVoiceChangedCB _voiceChangedDelegate;
263         private TtsEngineChangedCB _engineDelegate;
264         private TtsScreenReaderChangedCB _screenReaderDelegate;
265         private TtsServiceStateChangedCB _serviceStateDelegate;
266         private TtsSupportedVoiceCB _supportedvoiceDelegate;
267
268         /// <summary>
269         /// Constructor to create a TTS instance.
270         /// </summary>
271         /// <since_tizen> 3 </since_tizen>
272         /// <feature>
273         /// http://tizen.org/feature/speech.synthesis
274         /// </feature>
275         /// <exception cref="InvalidOperationException">
276         /// This exception can be due to the following reasons:
277         /// 1. Operation Failed
278         /// 2. Engine Not Found
279         /// </exception>
280         /// <exception cref="OutOfMemoryException">This exception can be due to out Of memory.</exception>
281         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
282         public TtsClient()
283         {
284             IntPtr handle;
285             TtsError error = TtsCreate(out handle);
286             if (error != TtsError.None)
287             {
288                 Log.Error(LogTag, "Create Failed with error " + error);
289                 throw ExceptionFactory.CreateException(error);
290             }
291
292             _handle = handle;
293         }
294
295         /// <summary>
296         /// Destructor to destroy TtsClient handle.
297         /// </summary>
298         ~TtsClient()
299         {
300             Dispose(false);
301         }
302
303         /// <summary>
304         /// Event to be invoked when TTS state changes.
305         /// </summary>
306         /// <since_tizen> 3 </since_tizen>
307         public event EventHandler<StateChangedEventArgs> StateChanged
308         {
309             add
310             {
311                 lock (_stateChangedLock)
312                 {
313                     if (_stateChanged == null)
314                     {
315                         _stateDelegate = (IntPtr handle, State previous, State current, IntPtr userData) =>
316                         {
317                             StateChangedEventArgs args = new StateChangedEventArgs(previous, current);
318                             _stateChanged?.Invoke(this, args);
319                         };
320
321                         TtsError error = TtsSetStateChangedCB(_handle, _stateDelegate, IntPtr.Zero);
322                         if (error != TtsError.None)
323                         {
324                             Log.Error(LogTag, "Add StateChanged Failed with error " + error);
325                         }
326                     }
327                     _stateChanged += value;
328                 }
329
330             }
331
332             remove
333             {
334                 lock (_stateChangedLock)
335                 {
336                     _stateChanged -= value;
337                     if (_stateChanged == null)
338                     {
339                         TtsError error = TtsUnsetStateChangedCB(_handle);
340                         if (error != TtsError.None)
341                         {
342                             Log.Error(LogTag, "Remove StateChanged Failed with error " + error);
343                         }
344                     }
345                 }
346             }
347
348         }
349
350         /// <summary>
351         /// Event to be invoked when the utterance starts.
352         /// </summary>
353         /// <since_tizen> 3 </since_tizen>
354         public event EventHandler<UtteranceEventArgs> UtteranceStarted
355         {
356             add
357             {
358                 lock (_utteranceStartedLock)
359                 {
360                     if (_utteranceStarted == null)
361                     {
362                         _utteranceStartedResultDelegate = (IntPtr handle, int uttId, IntPtr userData) =>
363                         {
364                             UtteranceEventArgs args = new UtteranceEventArgs(uttId);
365                             _utteranceStarted?.Invoke(this, args);
366                         };
367
368                         TtsError error = TtsSetUtteranceStartedCB(_handle, _utteranceStartedResultDelegate, IntPtr.Zero);
369                         if (error != TtsError.None)
370                         {
371                             Log.Error(LogTag, "Add UtteranceStarted Failed with error " + error);
372                         }
373                     }
374                     _utteranceStarted += value;
375                 }
376             }
377
378             remove
379             {
380                 lock (_utteranceStartedLock)
381                 {
382                     _utteranceStarted -= value;
383                     if (_utteranceStarted == null)
384                     {
385                         TtsError error = TtsUnsetUtteranceStartedCB(_handle);
386                         if (error != TtsError.None)
387                         {
388                             Log.Error(LogTag, "Remove UtteranceStarted Failed with error " + error);
389                         }
390                     }
391                 }
392             }
393         }
394
395         /// <summary>
396         /// Event to be invoked when the utterance completes.
397         /// </summary>
398         /// <since_tizen> 3 </since_tizen>
399         public event EventHandler<UtteranceEventArgs> UtteranceCompleted
400         {
401             add
402             {
403                 lock (_utteranceCompletedLock)
404                 {
405                     if (_utteranceCompleted == null)
406                     {
407                         _utteranceCompletedResultDelegate = (IntPtr handle, int uttId, IntPtr userData) =>
408                         {
409                             UtteranceEventArgs args = new UtteranceEventArgs(uttId);
410                             _utteranceCompleted?.Invoke(this, args);
411                         };
412
413                         TtsError error = TtsSetUtteranceCompletedCB(_handle, _utteranceCompletedResultDelegate, IntPtr.Zero);
414                         if (error != TtsError.None)
415                         {
416                             Log.Error(LogTag, "Add UtteranceCompleted Failed with error " + error);
417                         }
418                     }
419                     _utteranceCompleted += value;
420                 }
421             }
422
423             remove
424             {
425                 lock (_utteranceCompletedLock)
426                 {
427                     _utteranceCompleted -= value;
428                     if (_utteranceCompleted == null)
429                     {
430                         TtsError error = TtsUnsetUtteranceCompletedCB(_handle);
431                         if (error != TtsError.None)
432                         {
433                             Log.Error(LogTag, "Remove UtteranceCompleted Failed with error " + error);
434                         }
435                     }
436                 }
437             }
438         }
439
440         /// <summary>
441         /// Event to be invoked when an error occurs.
442         /// </summary>
443         /// <since_tizen> 4 </since_tizen>
444         public event EventHandler<ErrorOccurredEventArgs> ErrorOccurred
445         {
446             add
447             {
448                 lock (_errorOccurredLock)
449                 {
450                     if (_errorOccurred == null)
451                     {
452                         _errorDelegate = (IntPtr handle, int uttId, TtsError reason, IntPtr userData) =>
453                         {
454                             ErrorOccurredEventArgs args = new ErrorOccurredEventArgs(handle, uttId, reason);
455                             _errorOccurred?.Invoke(this, args);
456                         };
457
458                         TtsError error = TtsSetErrorCB(_handle, _errorDelegate, IntPtr.Zero);
459                         if (error != TtsError.None)
460                         {
461                             Log.Error(LogTag, "Add ErrorOccurred Failed with error " + error);
462                         }
463                     }
464                     _errorOccurred += value;
465                 }
466             }
467
468             remove
469             {
470                 lock (_errorOccurredLock)
471                 {
472                     _errorOccurred -= value;
473                     if (_errorOccurred == null)
474                     {
475                         TtsError error = TtsUnsetErrorCB(_handle);
476                         if (error != TtsError.None)
477                         {
478                             Log.Error(LogTag, "Remove ErrorOccurred Failed with error " + error);
479                         }
480                     }
481                 }
482             }
483         }
484
485         /// <summary>
486         /// Event to be invoked when an error occurs.
487         /// </summary>
488         /// <since_tizen> 3 </since_tizen>
489         public event EventHandler<DefaultVoiceChangedEventArgs> DefaultVoiceChanged
490         {
491             add
492             {
493                 lock (_defaultVoiceChangedLock)
494                 {
495                     if (_defaultVoiceChanged == null)
496                     {
497                         _voiceChangedDelegate = (IntPtr handle, IntPtr previousLanguage, int previousVoiceType, IntPtr currentLanguage, int currentVoiceType, IntPtr userData) =>
498                         {
499                             string previousLanguageString = Marshal.PtrToStringAnsi(previousLanguage);
500                             string currentLanguageString = Marshal.PtrToStringAnsi(currentLanguage);
501                             DefaultVoiceChangedEventArgs args = new DefaultVoiceChangedEventArgs(previousLanguageString, previousVoiceType, currentLanguageString, currentVoiceType);
502                             _defaultVoiceChanged?.Invoke(this, args);
503                         };
504
505                         TtsError error = TtsSetDefaultVoiceChangedCB(_handle, _voiceChangedDelegate, IntPtr.Zero);
506                         if (error != TtsError.None)
507                         {
508                             Log.Error(LogTag, "Add DefaultVoiceChanged Failed with error " + error);
509                         }
510                     }
511                     _defaultVoiceChanged += value;
512                 }
513             }
514
515             remove
516             {
517                 lock (_defaultVoiceChangedLock)
518                 {
519                     _defaultVoiceChanged -= value;
520                     if (_defaultVoiceChanged == null)
521                     {
522                         TtsError error = TtsUnsetDefaultVoiceChangedCB(_handle);
523                         if (error != TtsError.None)
524                         {
525                             Log.Error(LogTag, "Remove DefaultVoiceChanged Failed with error " + error);
526                         }
527                     }
528                 }
529             }
530         }
531
532         /// <summary>
533         /// Event to be invoked to detect engine change.
534         /// </summary>
535         /// <since_tizen> 3 </since_tizen>
536         public event EventHandler<EngineChangedEventArgs> EngineChanged
537         {
538             add
539             {
540                 lock (_engineChangedLock)
541                 {
542                     if (_engineChanged == null)
543                     {
544                         _engineDelegate = (IntPtr handle, IntPtr engineId, IntPtr language, int voiceType, bool needCredential, IntPtr userData) =>
545                         {
546                             string engineIdString = Marshal.PtrToStringAnsi(engineId);
547                             string languageString = Marshal.PtrToStringAnsi(language);
548                             EngineChangedEventArgs args = new EngineChangedEventArgs(engineIdString, languageString, voiceType, needCredential);
549                             _engineChanged?.Invoke(this, args);
550                         };
551                         TtsError error = TtsSetEngineChangedCB(_handle, _engineDelegate, IntPtr.Zero);
552                         if (error != TtsError.None)
553                         {
554                             Log.Error(LogTag, "Add EngineChanged Failed with error " + error);
555                         }
556                     }
557                     _engineChanged += value;
558                 }
559             }
560
561             remove
562             {
563                 lock (_engineChangedLock)
564                 {
565                     _engineChanged -= value;
566                     if (_engineChanged == null)
567                     {
568                         TtsError error = TtsUnsetEngineChangedCB(_handle);
569                         if (error != TtsError.None)
570                         {
571                             Log.Error(LogTag, "Remove EngineChanged Failed with error " + error);
572                         }
573                     }
574                 }
575             }
576         }
577
578         /// <summary>
579         /// Event to be invoked to detect screen reader status change.
580         /// </summary>
581         /// <since_tizen> 9 </since_tizen>
582         public event EventHandler<ScreenReaderChangedEventArgs> ScreenReaderChanged
583         {
584             add
585             {
586                 lock (_screenReaderChangedLock)
587                 {
588                     if (_screenReaderChanged == null)
589                     {
590                         _screenReaderDelegate = (IntPtr handle, bool isOn, IntPtr userData) =>
591                         {
592                             ScreenReaderChangedEventArgs args = new ScreenReaderChangedEventArgs(isOn);
593                             _screenReaderChanged?.Invoke(this, args);
594                         };
595                         TtsError error = TtsSetScreenReaderChangedCB(_handle, _screenReaderDelegate, IntPtr.Zero);
596                         if (error != TtsError.None)
597                         {
598                             Log.Error(LogTag, "Add ScreenReaderChanged Failed with error " + error);
599                         }
600                     }
601                     _screenReaderChanged += value;
602                 }
603             }
604
605             remove
606             {
607                 lock (_screenReaderChangedLock)
608                 {
609                     _screenReaderChanged -= value;
610                     if (_screenReaderChanged == null)
611                     {
612                         TtsError error = TtsUnsetScreenReaderChangedCB(_handle);
613                         if (error != TtsError.None)
614                         {
615                             Log.Error(LogTag, "Remove ScreenReaderChanged Failed with error " + error);
616                         }
617                     }
618                 }
619             }
620         }
621
622         /// <summary>
623         /// Event to be invoked when the state of TTS service changes.
624         /// </summary>
625         /// <since_tizen> 10 </since_tizen>
626         public event EventHandler<ServiceStateChangedEventArgs> ServiceStateChanged
627         {
628             add
629             {
630                 lock (_serviceStateChangedLock)
631                 {
632                     if (_serviceStateChanged == null)
633                     {
634                         _serviceStateDelegate = (IntPtr handle, ServiceState previous, ServiceState current, IntPtr userData) =>
635                         {
636                             ServiceStateChangedEventArgs args = new ServiceStateChangedEventArgs(previous, current);
637                             _serviceStateChanged?.Invoke(this, args);
638                         };
639
640                         TtsError error = TtsSetServiceStateChangedCB(_handle, _serviceStateDelegate, IntPtr.Zero);
641                         if (error != TtsError.None)
642                         {
643                             Log.Error(LogTag, "Add ServiceStateChanged Failed with error " + error);
644                         }
645                     }
646                     _serviceStateChanged += value;
647                 }
648             }
649
650             remove
651             {
652                 lock (_serviceStateChangedLock)
653                 {
654                     _serviceStateChanged -= value;
655                     if (_serviceStateChanged == null)
656                     {
657                         TtsError error = TtsUnsetStateChangedCB(_handle);
658                         if (error != TtsError.None)
659                         {
660                             Log.Error(LogTag, "Remove ServiceStateChanged Failed with error " + error);
661                         }
662                     }
663                 }
664             }
665         }
666
667         /// <summary>
668         /// Gets the default voice set by the user.
669         /// </summary>
670         /// <since_tizen> 3 </since_tizen>
671         /// <value>
672         /// The default voice in TTS.
673         /// </value>
674         /// <returns>
675         /// The default voice SupportedVoice value.
676         /// </returns>
677         public SupportedVoice DefaultVoice
678         {
679             get
680             {
681                 string language;
682                 int voiceType;
683                 TtsError error = TtsGetDefaultVoice(_handle, out language, out voiceType);
684                 if (error != TtsError.None)
685                 {
686                     Log.Error(LogTag, "DefaultVoice Failed with error " + error);
687                     return new SupportedVoice();
688                 }
689
690                 return new SupportedVoice(language, voiceType);
691             }
692         }
693
694         /// <summary>
695         /// Gets the maximum byte size for text.
696         /// </summary>
697         /// <since_tizen> 3 </since_tizen>
698         /// <value>
699         /// The Maximum byte size for text.
700         /// </value>
701         /// <returns>
702         /// The Default Voice SupportedVoice value, 0 if unable to get the value.
703         /// </returns>
704         /// <pre>
705         /// The Client must be in the <see cref="State.Ready"/> state.
706         /// </pre>
707         public uint MaxTextSize
708         {
709             get
710             {
711                 uint maxTextSize;
712                 TtsError error = TtsGetMaxTextSize(_handle, out maxTextSize);
713                 if (error != TtsError.None)
714                 {
715                     Log.Error(LogTag, "MaxTextSize Failed with error " + error);
716                     return 0;
717                 }
718
719                 return maxTextSize;
720             }
721
722         }
723
724         /// <summary>
725         /// Gets the current TTS state.
726         /// </summary>
727         /// <since_tizen> 3 </since_tizen>
728         /// <value>
729         /// The current state of TTS.
730         /// </value>
731         /// <returns>
732         /// Current TTS State value.
733         /// </returns>
734         public State CurrentState
735         {
736             get
737             {
738                 State state;
739                 TtsError error = TtsGetState(_handle, out state);
740                 if (error != TtsError.None)
741                 {
742                     Log.Error(LogTag, "CurrentState Failed with error " + error);
743                     return State.Unavailable;
744                 }
745
746                 return state;
747             }
748
749         }
750
751         /// <summary>
752         /// Gets the current state of TTS service.
753         /// </summary>
754         /// <value>
755         /// The current state of TTS service.
756         /// </value>
757         /// <since_tizen> 10 </since_tizen>
758         public ServiceState CurrentServiceState
759         {
760             get
761             {
762                 ServiceState state;
763                 TtsError error = TtsGetServiceState(_handle, out state);
764                 if (error != TtsError.None)
765                 {
766                     Log.Error(LogTag, "CurrentServiceState Failed with error " + error);
767                     return ServiceState.Unavailable;
768                 }
769
770                 return state;
771             }
772         }
773
774         /// <summary>
775         /// The TTS Mode can be set using this property.
776         /// </summary>
777         /// <since_tizen> 3 </since_tizen>
778         /// <value>
779         /// The current TTS mode (default, screen-reader, notification).
780         /// </value>
781         /// <returns>
782         /// The Mode value.
783         /// </returns>
784         /// <exception cref="InvalidOperationException">
785         /// This exception can be due to the following reasons while setting the value:
786         /// 1. Operation Failed
787         /// 2. Engine Not Found
788         /// </exception>
789         /// <exception cref="OutOfMemoryException">This exception can be due to out Of memory.</exception>
790         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
791         /// <pre>
792         /// The Client must be in the <see cref="State.Created"/> state.
793         /// </pre>
794         public Mode CurrentMode
795         {
796             get
797             {
798                 Mode mode = Mode.Default;
799                 TtsError error = TtsGetMode(_handle, out mode);
800                 if (error != TtsError.None)
801                 {
802                     Log.Error(LogTag, "Get Mode Failed with error " + error);
803                     return Mode.Default;
804                 }
805
806                 return mode;
807             }
808             set
809             {
810                 TtsError error;
811                 error = TtsSetMode(_handle, value);
812
813                 if (error != TtsError.None)
814                 {
815                     Log.Error(LogTag, "Set Mode Failed with error " + error);
816                     throw ExceptionFactory.CreateException(error);
817                 }
818             }
819         }
820
821         /// <summary>
822         /// Gets the current status of screen reader.
823         /// </summary>
824         /// <since_tizen> 9 </since_tizen>
825         /// <value>
826         /// The current status of screen reader.
827         /// </value>
828         /// <returns>
829         /// Boolean value whether screen reader is on or off.
830         /// </returns>
831         /// <feature>
832         /// http://tizen.org/feature/speech.synthesis
833         /// </feature>
834         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
835         public bool IsScreenReaderOn
836         {
837             get
838             {
839                 bool isOn = true;
840                 TtsError error = TtsCheckScreenReaderOn(_handle, out isOn);
841                 if (error != TtsError.None)
842                 {
843                     Log.Error(LogTag, "Fail to check screen reader on with error " + error);
844                     return false;
845                 }
846
847                 return isOn;
848             }
849         }
850
851         /// <summary>
852         /// Sets the application credential.
853         /// </summary>
854         /// <since_tizen> 3 </since_tizen>
855         /// <param name="credential">.
856         /// The credential string.
857         /// </param>
858         /// <feature>
859         /// http://tizen.org/feature/speech.synthesis
860         /// </feature>
861         /// <exception cref="InvalidOperationException">This exception can be due to an invalid state.</exception>
862         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
863         /// <exception cref="ArgumentException">This exception can be due to improper value provided while setting the value.</exception>
864         /// <pre>
865         /// The Client must be in the <see cref="State.Created"/> or <see cref="State.Ready"/> state.
866         /// </pre>
867         public void SetCredential(string credential)
868         {
869             TtsError error = TtsSetCredential(_handle, credential);
870             if (error != TtsError.None)
871             {
872                 Tizen.Log.Error(LogTag, "SetCredential Failed with error " + error);
873                 throw ExceptionFactory.CreateException(error);
874             }
875         }
876
877         /// <summary>
878         /// Connects to the TTS service asynchronously.
879         /// </summary>
880         /// <since_tizen> 3 </since_tizen>
881         /// <feature>
882         /// http://tizen.org/feature/speech.synthesis
883         /// </feature>
884         /// <exception cref="InvalidOperationException">
885         /// This exception can be due to the following reasons while setting the value:
886         /// 1. Invalid state
887         /// 2. Screen reader off
888         /// </exception>
889         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
890         /// <pre>
891         /// The Client must be in the <see cref="State.Created"/> state.
892         /// </pre>
893         /// <post>
894         /// If this function is successful, the Client will be in the <see cref="State.Ready"/> state.
895         /// If this function is unsuccessful, ErrorOccurred event will be invoked.
896         /// </post>
897         public void Prepare()
898         {
899             TtsError error = TtsPrepare(_handle);
900             if (error != TtsError.None)
901             {
902                 Log.Error(LogTag, "Prepare Failed with error " + error);
903                 throw ExceptionFactory.CreateException(error);
904             }
905         }
906
907         /// <summary>
908         /// Disconnects from the TTS service.
909         /// </summary>
910         /// <since_tizen> 3 </since_tizen>
911         /// <feature>
912         /// http://tizen.org/feature/speech.synthesis
913         /// </feature>
914         /// <exception cref="InvalidOperationException">This exception can be due to an invalid state.</exception>
915         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
916         /// <pre>
917         /// The Client must be in the <see cref="State.Ready"/> state.
918         /// </pre>
919         /// <post>
920         /// If this function is successful, the Client will be in the <see cref="State.Created"/> state.
921         /// </post>
922         public void Unprepare()
923         {
924             TtsError error = TtsUnprepare(_handle);
925             if (error != TtsError.None)
926             {
927                 Log.Error(LogTag, "Unprepare Failed with error " + error);
928                 throw ExceptionFactory.CreateException(error);
929             }
930         }
931
932         /// <summary>
933         /// Retrieves all supported voices of the current engine.
934         /// </summary>
935         /// <since_tizen> 3 </since_tizen>
936         /// <returns>
937         /// The list of SupportedVoice.
938         /// </returns>
939         /// <feature>
940         /// http://tizen.org/feature/speech.synthesis
941         /// </feature>
942         /// <exception cref="InvalidOperationException">
943         /// This exception can be due to the following reasons:
944         /// 1. Engine Not Found
945         /// 2. Operation Failed
946         /// </exception>
947         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
948         public IEnumerable<SupportedVoice> GetSupportedVoices()
949         {
950             List<SupportedVoice> voicesList = new List<SupportedVoice>();
951
952             _supportedvoiceDelegate = (IntPtr handle, IntPtr language, int voiceType, IntPtr userData) =>
953             {
954                 string lang = Marshal.PtrToStringAnsi(language);
955                 SupportedVoice voice = new SupportedVoice(lang, voiceType);
956                 voicesList.Add(voice);
957                 return true;
958             };
959             TtsError error = TtsForeachSupportedVoices(_handle, _supportedvoiceDelegate, IntPtr.Zero);
960             if (error != TtsError.None)
961             {
962                 Log.Error(LogTag, "GetSupportedVoices Failed with error " + error);
963                 throw ExceptionFactory.CreateException(error);
964             }
965
966             return voicesList;
967         }
968
969         /// <summary>
970         /// Gets the private data from TTS engine.
971         /// </summary>
972         /// <since_tizen> 3 </since_tizen>
973         /// <param name="key">
974         /// The key string.
975         /// </param>
976         /// <returns>
977         /// The data corresponding to the provided key.
978         /// </returns>
979         /// <feature>
980         /// http://tizen.org/feature/speech.synthesis
981         /// </feature>
982         /// <exception cref="InvalidOperationException">
983         /// This exception can be due to the following reasons:
984         /// 1. Invalid State
985         /// 2. Engine Not found
986         /// 3. Operation Failure
987         /// </exception>
988         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
989         /// <pre>
990         /// The Client must be in the <see cref="State.Ready"/> state.
991         /// </pre>
992         public string GetPrivateData(string key)
993         {
994             string data;
995             TtsError error = TtsGetPrivateData(_handle, key, out data);
996             if (error != TtsError.None)
997             {
998                 Log.Error(LogTag, "GetPrivateData Failed with error " + error);
999                 throw ExceptionFactory.CreateException(error);
1000             }
1001
1002             return data;
1003         }
1004
1005         /// <summary>
1006         /// Sets the private data to tts engine.
1007         /// </summary>
1008         /// <since_tizen> 3 </since_tizen>
1009         /// <param name="key">
1010         /// The key string.
1011         /// </param>
1012         /// <param name="data">
1013         /// The data string.
1014         /// </param>
1015         /// <feature>
1016         /// http://tizen.org/feature/speech.synthesis
1017         /// </feature>
1018         /// <exception cref="InvalidOperationException">
1019         /// This exception can be due to the following reasons:
1020         /// 1. Invalid State
1021         /// 2. Engine Not found
1022         /// 3. Operation Failure
1023         /// </exception>
1024         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
1025         /// <exception cref="ArgumentException">This exception can be due to improper value provided while setting the value.</exception>
1026         /// <pre>
1027         /// The Client must be in the <see cref="State.Ready"/> state.
1028         /// </pre>
1029         public void SetPrivateData(string key, string data)
1030         {
1031             TtsError error = TtsSetPrivateData(_handle, key, data);
1032             if (error != TtsError.None)
1033             {
1034                 Log.Error(LogTag, "SetPrivateData Failed with error " + error);
1035                 throw ExceptionFactory.CreateException(error);
1036             }
1037         }
1038
1039         /// <summary>
1040         /// Gets the speed range.
1041         /// </summary>
1042         /// <since_tizen> 3 </since_tizen>
1043         /// <returns>
1044         /// The SpeedRange value.
1045         /// </returns>
1046         /// <feature>
1047         /// http://tizen.org/feature/speech.synthesis
1048         /// </feature>
1049         /// <exception cref="InvalidOperationException">
1050         /// This exception can be due to the following reasons:
1051         /// 1. Invalid State
1052         /// 2. Operation Failure
1053         /// </exception>
1054         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
1055         /// <pre>
1056         /// The Client must be in the <see cref="State.Created"/> state.
1057         /// </pre>
1058         public SpeedRange GetSpeedRange()
1059         {
1060             int min = 0, max = 0, normal = 0;
1061             TtsError error = TtsGetSpeedRange(_handle, out min, out normal, out max);
1062             if (error != TtsError.None)
1063             {
1064                 Log.Error(LogTag, "GetSpeedRange Failed with error " + error);
1065                 throw ExceptionFactory.CreateException(error);
1066             }
1067
1068             return new SpeedRange(min, normal, max);
1069         }
1070
1071         /// <summary>
1072         /// Adds a text to the queue.
1073         /// </summary>
1074         /// <since_tizen> 3 </since_tizen>
1075         /// <remarks>
1076         /// Locale MUST be set for text validation check.
1077         /// </remarks>
1078         /// <param name="text">
1079         /// An input text.
1080         /// </param>
1081         /// <param name="language">
1082         /// The language selected from the SupportedVoice.Language Property obtained from GetSupportedVoices()(e.g. 'NULL'(Automatic),'en_US').
1083         /// </param>
1084         /// <param name="voiceType">
1085         /// The voice type selected from the SupportedVoice.VoiceType Property obtained from GetSupportedVoices().
1086         /// </param>
1087         /// <param name="speed">
1088         /// A speaking speed (e.g.0 for Auto or the value from SpeedRange Property).
1089         /// </param>
1090         /// <returns>
1091         /// The utterance ID.
1092         /// </returns>
1093         /// <feature>
1094         /// http://tizen.org/feature/speech.synthesis
1095         /// </feature>
1096         /// <exception cref="InvalidOperationException">
1097         /// This exception can be due to the following reasons:
1098         /// 1. Invalid State
1099         /// 2. Operation Failure
1100         /// 3. Invalid Voice
1101         /// 4. Screen reader off
1102         /// </exception>
1103         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
1104         /// <exception cref="UnauthorizedAccessException">This exception can be due to permission denied.</exception>
1105         /// <exception cref="ArgumentException">This exception can be due to improper value provided while setting the value.</exception>
1106         /// <pre>
1107         /// The Client must be in the <see cref="State.Ready"/>, <see cref="State.Playing"/>, or <see cref="State.Paused"/> state.
1108         /// </pre>
1109         public int AddText(string text, string language, int voiceType, int speed)
1110         {
1111             int id;
1112             TtsError error = TtsAddText(_handle, text, language, voiceType, speed, out id);
1113             if (error != TtsError.None)
1114             {
1115                 Log.Error(LogTag, "AddText Failed with error " + error);
1116                 throw ExceptionFactory.CreateException(error);
1117             }
1118
1119             return id;
1120         }
1121
1122         /// <summary>
1123         /// Starts synthesizing voice from the text and plays the synthesized audio data.
1124         /// </summary>
1125         /// <since_tizen> 3 </since_tizen>
1126         /// <feature>
1127         /// http://tizen.org/feature/speech.synthesis
1128         /// </feature>
1129         /// <exception cref="InvalidOperationException">
1130         /// This exception can be due to the following reasons:
1131         /// 1. Invalid State
1132         /// 2. Operation Failure
1133         /// 3. Out of Network
1134         /// 4. Screen reader off
1135         /// </exception>
1136         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
1137         /// <exception cref="UnauthorizedAccessException">This exception can be due to permission denied.</exception>
1138         /// <pre>
1139         /// The Client must be in the <see cref="State.Ready"/> or <see cref="State.Paused"/> state.
1140         /// </pre>
1141         /// <post>
1142         /// If this function succeeds, the Client will be in the <see cref="State.Playing"/> state.
1143         /// </post>
1144         public void Play()
1145         {
1146             TtsError error = TtsPlay(_handle);
1147             if (error != TtsError.None)
1148             {
1149                 Log.Error(LogTag, "Play Failed with error " + error);
1150                 throw ExceptionFactory.CreateException(error);
1151             }
1152         }
1153
1154         /// <summary>
1155         /// Stops playing the utterance and clears the queue.
1156         /// </summary>
1157         /// <since_tizen> 3 </since_tizen>
1158         /// <feature>
1159         /// http://tizen.org/feature/speech.synthesis
1160         /// </feature>
1161         /// <exception cref="InvalidOperationException">
1162         /// This exception can be due to the following reasons:
1163         /// 1. Invalid Stat
1164         /// 2. Operation Failure
1165         /// 3. Screen reader off
1166         /// </exception>
1167         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
1168         /// <pre>
1169         /// The Client must be in the <see cref="State.Ready"/>, <see cref="State.Playing"/>, or <see cref="State.Paused"/> state.
1170         /// </pre>
1171         /// <post>
1172         /// If this function succeeds, the Client will be in the <see cref="State.Ready"/> state.
1173         /// This function will remove all text added via AddText() and synthesized sound data.
1174         /// </post>
1175         public void Stop()
1176         {
1177             TtsError error = TtsStop(_handle);
1178             if (error != TtsError.None)
1179             {
1180                 Log.Error(LogTag, "Stop Failed with error " + error);
1181                 throw ExceptionFactory.CreateException(error);
1182             }
1183         }
1184
1185         /// <summary>
1186         /// Pauses the currently playing utterance.
1187         /// </summary>
1188         /// <since_tizen> 3 </since_tizen>
1189         /// <feature>
1190         /// http://tizen.org/feature/speech.synthesis
1191         /// </feature>
1192         /// <exception cref="InvalidOperationException">
1193         /// This exception can be due to the following reasons:
1194         /// 1. Invalid State
1195         /// 2. Operation Failure
1196         /// 3. Screen reader off
1197         /// </exception>
1198         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
1199         /// <pre>
1200         /// The Client must be in the <see cref="State.Playing"/> state.
1201         /// </pre>
1202         /// <post>
1203         /// If this function succeeds, the Client will be in the <see cref="State.Paused"/> state.
1204         /// </post>
1205         public void Pause()
1206         {
1207             TtsError error = TtsPause(_handle);
1208             if (error != TtsError.None)
1209             {
1210                 Log.Error(LogTag, "Pause Failed with error " + error);
1211                 throw ExceptionFactory.CreateException(error);
1212             }
1213         }
1214
1215         /// <summary>
1216         /// Repeats the last added text.
1217         /// </summary>
1218         /// <since_tizen> 10 </since_tizen>
1219         /// <returns>
1220         /// The RepeatedText instance which stores the text to repeat and its utterance ID.
1221         /// </returns>
1222         /// <feature>
1223         /// http://tizen.org/feature/speech.synthesis
1224         /// </feature>
1225         /// <exception cref="InvalidOperationException">
1226         /// This exception can be due to the following reasons:
1227         /// 1. Invalid State
1228         /// 2. Operation Failure
1229         /// 3. Screen reader off
1230         /// </exception>
1231         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
1232         /// <pre>
1233         /// The Client must be in the <see cref="State.Ready"/> state.
1234         /// </pre>
1235         /// <post>
1236         /// If this function succeeds, the Client will be in the <see cref="State.Playing"/> state.
1237         /// </post>
1238         public RepeatedText Repeat()
1239         {
1240             TtsError error = TtsRepeat(_handle, out string text, out int uttId);
1241             if (error != TtsError.None)
1242             {
1243                 Log.Error(LogTag, "Repeat Failed with error " + error);
1244                 throw ExceptionFactory.CreateException(error);
1245             }
1246
1247             return new RepeatedText(text, uttId);
1248         }
1249
1250         /// <summary>
1251         /// Method to release resources.
1252         /// </summary>
1253         /// <since_tizen> 3 </since_tizen>
1254         public void Dispose()
1255         {
1256             Dispose(true);
1257             GC.SuppressFinalize(this);
1258         }
1259
1260         /// <summary>
1261         /// Method to release resources.
1262         /// </summary>
1263         /// <since_tizen> 3 </since_tizen>
1264         /// <param name="disposing">
1265         /// The boolean value for destoying tts handle.
1266         /// </param>
1267         protected virtual void Dispose(bool disposing)
1268         {
1269             if (!disposedValue)
1270             {
1271                 if (_handle != IntPtr.Zero)
1272                 {
1273                     TtsError error = TtsDestroy(_handle);
1274                     if (error != TtsError.None)
1275                     {
1276                         Log.Error(LogTag, "Destroy Failed with error " + error);
1277                     }
1278                     _handle = IntPtr.Zero;
1279                 }
1280
1281                 disposedValue = true;
1282             }
1283         }
1284     }
1285 }