[Tts/Stt] Use thread lock only when add and remove event handler (#2782)
[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 STT 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         /// STT 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     };
159
160     /// <summary>
161     /// Enumeration for the voice types.
162     /// </summary>
163     /// <since_tizen> 3 </since_tizen>
164     public enum Voice
165     {
166         /// <summary>
167         /// The automatic voice type.
168         /// </summary>
169         /// <since_tizen> 3 </since_tizen>
170         Auto,
171
172         /// <summary>
173         /// The male voice type.
174         /// </summary>
175         /// <since_tizen> 3 </since_tizen>
176         Male,
177
178         /// <summary>
179         /// The female voice type.
180         /// </summary>
181         /// <since_tizen> 3 </since_tizen>
182         Female,
183
184         /// <summary>
185         /// The child voice type.
186         /// </summary>
187         /// <since_tizen> 3 </since_tizen>
188         Child
189     };
190
191     /// <summary>
192     /// You can use Text-To-Speech (TTS) API's to read sound data transformed by the engine from input texts.
193     /// 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.
194     /// </summary>
195     /// <since_tizen> 3 </since_tizen>
196     public class TtsClient : IDisposable
197     {
198         private IntPtr _handle;
199         private event EventHandler<StateChangedEventArgs> _stateChanged;
200         private event EventHandler<UtteranceEventArgs> _utteranceStarted;
201         private event EventHandler<UtteranceEventArgs> _utteranceCompleted;
202         private event EventHandler<ErrorOccurredEventArgs> _errorOccurred;
203         private event EventHandler<DefaultVoiceChangedEventArgs> _defaultVoiceChanged;
204         private event EventHandler<EngineChangedEventArgs> _engineChanged;
205         private bool disposedValue = false;
206         private readonly Object _stateChangedLock = new Object();
207         private readonly Object _utteranceStartedLock = new Object();
208         private readonly Object _utteranceCompletedLock = new Object();
209         private readonly Object _errorOccurredLock = new Object();
210         private readonly Object _defaultVoiceChangedLock = new Object();
211         private readonly Object _engineChangedLock = new Object();
212         private TtsStateChangedCB _stateDelegate;
213         private TtsUtteranceStartedCB _utteranceStartedResultDelegate;
214         private TtsUtteranceCompletedCB _utteranceCompletedResultDelegate;
215         private TtsErrorCB _errorDelegate;
216         private TtsDefaultVoiceChangedCB _voiceChangedDelegate;
217         private TtsEngineChangedCB _engineDelegate;
218         private TtsSupportedVoiceCB _supportedvoiceDelegate;
219
220         /// <summary>
221         /// Constructor to create a TTS instance.
222         /// </summary>
223         /// <since_tizen> 3 </since_tizen>
224         /// <feature>
225         /// http://tizen.org/feature/speech.synthesis
226         /// </feature>
227         /// <exception cref="InvalidOperationException">
228         /// This exception can be due to the following reasons:
229         /// 1. Operation Failed
230         /// 2. Engine Not Found
231         /// </exception>
232         /// <exception cref="OutOfMemoryException">This exception can be due to out Of memory.</exception>
233         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
234         public TtsClient()
235         {
236             IntPtr handle;
237             TtsError error = TtsCreate(out handle);
238             if (error != TtsError.None)
239             {
240                 Log.Error(LogTag, "Create Failed with error " + error);
241                 throw ExceptionFactory.CreateException(error);
242             }
243
244             _handle = handle;
245         }
246
247         /// <summary>
248         /// Destructor to destroy TtsClient handle.
249         /// </summary>
250         ~TtsClient()
251         {
252             Dispose(false);
253         }
254
255         /// <summary>
256         /// Event to be invoked when TTS state changes.
257         /// </summary>
258         /// <since_tizen> 3 </since_tizen>
259         public event EventHandler<StateChangedEventArgs> StateChanged
260         {
261             add
262             {
263                 lock (_stateChangedLock)
264                 {
265                     if (_stateChanged == null)
266                     {
267                         _stateDelegate = (IntPtr handle, State previous, State current, IntPtr userData) =>
268                         {
269                             StateChangedEventArgs args = new StateChangedEventArgs(previous, current);
270                             _stateChanged?.Invoke(this, args);
271                         };
272
273                         TtsError error = TtsSetStateChangedCB(_handle, _stateDelegate, IntPtr.Zero);
274                         if (error != TtsError.None)
275                         {
276                             Log.Error(LogTag, "Add StateChanged Failed with error " + error);
277                         }
278                     }
279                     _stateChanged += value;
280                 }
281
282             }
283
284             remove
285             {
286                 lock (_stateChangedLock)
287                 {
288                     _stateChanged -= value;
289                     if (_stateChanged == null)
290                     {
291                         TtsError error = TtsUnsetStateChangedCB(_handle);
292                         if (error != TtsError.None)
293                         {
294                             Log.Error(LogTag, "Remove StateChanged Failed with error " + error);
295                         }
296                     }
297                 }
298             }
299
300         }
301
302         /// <summary>
303         /// Event to be invoked when the utterance starts.
304         /// </summary>
305         /// <since_tizen> 3 </since_tizen>
306         public event EventHandler<UtteranceEventArgs> UtteranceStarted
307         {
308             add
309             {
310                 lock (_utteranceStartedLock)
311                 {
312                     if (_utteranceStarted == null)
313                     {
314                         _utteranceStartedResultDelegate = (IntPtr handle, int uttId, IntPtr userData) =>
315                         {
316                             UtteranceEventArgs args = new UtteranceEventArgs(uttId);
317                             _utteranceStarted?.Invoke(this, args);
318                         };
319
320                         TtsError error = TtsSetUtteranceStartedCB(_handle, _utteranceStartedResultDelegate, IntPtr.Zero);
321                         if (error != TtsError.None)
322                         {
323                             Log.Error(LogTag, "Add UtteranceStarted Failed with error " + error);
324                         }
325                     }
326                     _utteranceStarted += value;
327                 }
328             }
329
330             remove
331             {
332                 lock (_utteranceStartedLock)
333                 {
334                     _utteranceStarted -= value;
335                     if (_utteranceStarted == null)
336                     {
337                         TtsError error = TtsUnsetUtteranceStartedCB(_handle);
338                         if (error != TtsError.None)
339                         {
340                             Log.Error(LogTag, "Remove UtteranceStarted Failed with error " + error);
341                         }
342                     }
343                 }
344             }
345         }
346
347         /// <summary>
348         /// Event to be invoked when the utterance completes.
349         /// </summary>
350         /// <since_tizen> 3 </since_tizen>
351         public event EventHandler<UtteranceEventArgs> UtteranceCompleted
352         {
353             add
354             {
355                 lock (_utteranceCompletedLock)
356                 {
357                     if (_utteranceCompleted == null)
358                     {
359                         _utteranceCompletedResultDelegate = (IntPtr handle, int uttId, IntPtr userData) =>
360                         {
361                             UtteranceEventArgs args = new UtteranceEventArgs(uttId);
362                             _utteranceCompleted?.Invoke(this, args);
363                         };
364
365                         TtsError error = TtsSetUtteranceCompletedCB(_handle, _utteranceCompletedResultDelegate, IntPtr.Zero);
366                         if (error != TtsError.None)
367                         {
368                             Log.Error(LogTag, "Add UtteranceCompleted Failed with error " + error);
369                         }
370                     }
371                     _utteranceCompleted += value;
372                 }
373             }
374
375             remove
376             {
377                 lock (_utteranceCompletedLock)
378                 {
379                     _utteranceCompleted -= value;
380                     if (_utteranceCompleted == null)
381                     {
382                         TtsError error = TtsUnsetUtteranceCompletedCB(_handle);
383                         if (error != TtsError.None)
384                         {
385                             Log.Error(LogTag, "Remove UtteranceCompleted Failed with error " + error);
386                         }
387                     }
388                 }
389             }
390         }
391
392         /// <summary>
393         /// Event to be invoked when an error occurs.
394         /// </summary>
395         /// <since_tizen> 4 </since_tizen>
396         public event EventHandler<ErrorOccurredEventArgs> ErrorOccurred
397         {
398             add
399             {
400                 lock (_errorOccurredLock)
401                 {
402                     if (_errorOccurred == null)
403                     {
404                         _errorDelegate = (IntPtr handle, int uttId, TtsError reason, IntPtr userData) =>
405                         {
406                             ErrorOccurredEventArgs args = new ErrorOccurredEventArgs(handle, uttId, reason);
407                             _errorOccurred?.Invoke(this, args);
408                         };
409
410                         TtsError error = TtsSetErrorCB(_handle, _errorDelegate, IntPtr.Zero);
411                         if (error != TtsError.None)
412                         {
413                             Log.Error(LogTag, "Add ErrorOccurred Failed with error " + error);
414                         }
415                     }
416                     _errorOccurred += value;
417                 }
418             }
419
420             remove
421             {
422                 lock (_errorOccurredLock)
423                 {
424                     _errorOccurred -= value;
425                     if (_errorOccurred == null)
426                     {
427                         TtsError error = TtsUnsetErrorCB(_handle);
428                         if (error != TtsError.None)
429                         {
430                             Log.Error(LogTag, "Remove ErrorOccurred Failed with error " + error);
431                         }
432                     }
433                 }
434             }
435         }
436
437         /// <summary>
438         /// Event to be invoked when an error occurs.
439         /// </summary>
440         /// <since_tizen> 3 </since_tizen>
441         public event EventHandler<DefaultVoiceChangedEventArgs> DefaultVoiceChanged
442         {
443             add
444             {
445                 lock (_defaultVoiceChangedLock)
446                 {
447                     if (_defaultVoiceChanged == null)
448                     {
449                         _voiceChangedDelegate = (IntPtr handle, IntPtr previousLanguage, int previousVoiceType, IntPtr currentLanguage, int currentVoiceType, IntPtr userData) =>
450                         {
451                             string previousLanguageString = Marshal.PtrToStringAnsi(previousLanguage);
452                             string currentLanguageString = Marshal.PtrToStringAnsi(currentLanguage);
453                             DefaultVoiceChangedEventArgs args = new DefaultVoiceChangedEventArgs(previousLanguageString, previousVoiceType, currentLanguageString, currentVoiceType);
454                             _defaultVoiceChanged?.Invoke(this, args);
455                         };
456
457                         TtsError error = TtsSetDefaultVoiceChangedCB(_handle, _voiceChangedDelegate, IntPtr.Zero);
458                         if (error != TtsError.None)
459                         {
460                             Log.Error(LogTag, "Add DefaultVoiceChanged Failed with error " + error);
461                         }
462                     }
463                     _defaultVoiceChanged += value;
464                 }
465             }
466
467             remove
468             {
469                 lock (_defaultVoiceChangedLock)
470                 {
471                     _defaultVoiceChanged -= value;
472                     if (_defaultVoiceChanged == null)
473                     {
474                         TtsError error = TtsUnsetDefaultVoiceChangedCB(_handle);
475                         if (error != TtsError.None)
476                         {
477                             Log.Error(LogTag, "Remove DefaultVoiceChanged Failed with error " + error);
478                         }
479                     }
480                 }
481             }
482         }
483
484         /// <summary>
485         /// Event to be invoked to detect engine change.
486         /// </summary>
487         /// <since_tizen> 3 </since_tizen>
488         public event EventHandler<EngineChangedEventArgs> EngineChanged
489         {
490             add
491             {
492                 lock (_engineChangedLock)
493                 {
494                     if (_engineChanged == null)
495                     {
496                         _engineDelegate = (IntPtr handle, IntPtr engineId, IntPtr language, int voiceType, bool needCredential, IntPtr userData) =>
497                         {
498                             string engineIdString = Marshal.PtrToStringAnsi(engineId);
499                             string languageString = Marshal.PtrToStringAnsi(language);
500                             EngineChangedEventArgs args = new EngineChangedEventArgs(engineIdString, languageString, voiceType, needCredential);
501                             _engineChanged?.Invoke(this, args);
502                         };
503                         TtsError error = TtsSetEngineChangedCB(_handle, _engineDelegate, IntPtr.Zero);
504                         if (error != TtsError.None)
505                         {
506                             Log.Error(LogTag, "Add EngineChanged Failed with error " + error);
507                         }
508                     }
509                     _engineChanged += value;
510                 }
511             }
512
513             remove
514             {
515                 lock (_engineChangedLock)
516                 {
517                     _engineChanged -= value;
518                     if (_engineChanged == null)
519                     {
520                         TtsError error = TtsUnsetEngineChangedCB(_handle);
521                         if (error != TtsError.None)
522                         {
523                             Log.Error(LogTag, "Remove EngineChanged Failed with error " + error);
524                         }
525                     }
526                 }
527             }
528         }
529
530         /// <summary>
531         /// Gets the default voice set by the user.
532         /// </summary>
533         /// <since_tizen> 3 </since_tizen>
534         /// <value>
535         /// The default voice in TTS.
536         /// </value>
537         /// <returns>
538         /// The default voice SupportedVoice value.
539         /// </returns>
540         public SupportedVoice DefaultVoice
541         {
542             get
543             {
544                 string language;
545                 int voiceType;
546                 TtsError error = TtsGetDefaultVoice(_handle, out language, out voiceType);
547                 if (error != TtsError.None)
548                 {
549                     Log.Error(LogTag, "DefaultVoice Failed with error " + error);
550                     return new SupportedVoice();
551                 }
552
553                 return new SupportedVoice(language, voiceType);
554             }
555         }
556
557         /// <summary>
558         /// Gets the maximum byte size for text.
559         /// </summary>
560         /// <since_tizen> 3 </since_tizen>
561         /// <value>
562         /// The Maximum byte size for text.
563         /// </value>
564         /// <returns>
565         /// The Default Voice SupportedVoice value, 0 if unable to get the value.
566         /// </returns>
567         /// <pre>
568         /// The State should be ready.
569         /// </pre>
570         public uint MaxTextSize
571         {
572             get
573             {
574                 uint maxTextSize;
575                 TtsError error = TtsGetMaxTextSize(_handle, out maxTextSize);
576                 if (error != TtsError.None)
577                 {
578                     Log.Error(LogTag, "MaxTextSize Failed with error " + error);
579                     return 0;
580                 }
581
582                 return maxTextSize;
583             }
584
585         }
586
587         /// <summary>
588         /// Gets the current TTS state.
589         /// </summary>
590         /// <since_tizen> 3 </since_tizen>
591         /// <value>
592         /// The current state of TTS.
593         /// </value>
594         /// <returns>
595         /// Current TTS State value.
596         /// </returns>
597         public State CurrentState
598         {
599             get
600             {
601                 State state;
602                 TtsError error = TtsGetState(_handle, out state);
603                 if (error != TtsError.None)
604                 {
605                     Log.Error(LogTag, "CurrentState Failed with error " + error);
606                     return State.Unavailable;
607                 }
608
609                 return state;
610             }
611
612         }
613
614         /// <summary>
615         /// The TTS Mode can be set using this property.
616         /// </summary>
617         /// <since_tizen> 3 </since_tizen>
618         /// <value>
619         /// The current TTS mode (default, screen-reader, notification).
620         /// </value>
621         /// <returns>
622         /// The Mode value.
623         /// </returns>
624         /// <exception cref="InvalidOperationException">
625         /// This exception can be due to the following reasons while setting the value:
626         /// 1. Operation Failed
627         /// 2. Engine Not Found
628         /// </exception>
629         /// <exception cref="OutOfMemoryException">This exception can be due to out Of memory.</exception>
630         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
631         /// <pre>
632         /// The State should be created.
633         /// </pre>
634         public Mode CurrentMode
635         {
636             get
637             {
638                 Mode mode = Mode.Default;
639                 TtsError error = TtsGetMode(_handle, out mode);
640                 if (error != TtsError.None)
641                 {
642                     Log.Error(LogTag, "Get Mode Failed with error " + error);
643                     return Mode.Default;
644                 }
645
646                 return mode;
647             }
648             set
649             {
650                 TtsError error;
651                 error = TtsSetMode(_handle, value);
652
653                 if (error != TtsError.None)
654                 {
655                     Log.Error(LogTag, "Set Mode Failed with error " + error);
656                     throw ExceptionFactory.CreateException(error);
657                 }
658             }
659         }
660
661         /// <summary>
662         /// Sets the application credential.
663         /// </summary>
664         /// <since_tizen> 3 </since_tizen>
665         /// <param name="credential">.
666         /// The credential string.
667         /// </param>
668         /// <feature>
669         /// http://tizen.org/feature/speech.synthesis
670         /// </feature>
671         /// <exception cref="InvalidOperationException">This exception can be due to an invalid state.</exception>
672         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
673         /// <exception cref="ArgumentException">This exception can be due to improper value provided while setting the value.</exception>
674         /// <pre>
675         /// The State should be created or ready.
676         /// </pre>
677         public void SetCredential(string credential)
678         {
679             TtsError error = TtsSetCredential(_handle, credential);
680             if (error != TtsError.None)
681             {
682                 Tizen.Log.Error(LogTag, "SetCredential Failed with error " + error);
683                 throw ExceptionFactory.CreateException(error);
684             }
685         }
686
687         /// <summary>
688         /// Connects to the TTS service asynchronously.
689         /// </summary>
690         /// <since_tizen> 3 </since_tizen>
691         /// <feature>
692         /// http://tizen.org/feature/speech.synthesis
693         /// </feature>
694         /// <exception cref="InvalidOperationException">This exception can be due to an invalid state.</exception>
695         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
696         /// <pre>
697         /// The State must be Created.
698         /// </pre>
699         /// <post>
700         /// If this function is successful, the TTS state will be ready.
701         /// If this function is unsuccessful, ErrorOccurred event will be invoked.
702         /// </post>
703         public void Prepare()
704         {
705             TtsError error = TtsPrepare(_handle);
706             if (error != TtsError.None)
707             {
708                 Log.Error(LogTag, "Prepare Failed with error " + error);
709                 throw ExceptionFactory.CreateException(error);
710             }
711         }
712
713         /// <summary>
714         /// Disconnects from the STT service.
715         /// </summary>
716         /// <since_tizen> 3 </since_tizen>
717         /// <feature>
718         /// http://tizen.org/feature/speech.synthesis
719         /// </feature>
720         /// <exception cref="InvalidOperationException">This exception can be due to an invalid state.</exception>
721         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
722         /// <pre>
723         /// The state must be ready.
724         /// </pre>
725         /// <post>
726         /// If this function is successful, the TTS state will be created.
727         /// </post>
728         public void Unprepare()
729         {
730             TtsError error = TtsUnprepare(_handle);
731             if (error != TtsError.None)
732             {
733                 Log.Error(LogTag, "Unprepare Failed with error " + error);
734                 throw ExceptionFactory.CreateException(error);
735             }
736         }
737
738         /// <summary>
739         /// Retrieves all supported voices of the current engine.
740         /// </summary>
741         /// <since_tizen> 3 </since_tizen>
742         /// <returns>
743         /// The list of SupportedVoice.
744         /// </returns>
745         /// <feature>
746         /// http://tizen.org/feature/speech.synthesis
747         /// </feature>
748         /// <exception cref="InvalidOperationException">
749         /// This exception can be due to the following reasons:
750         /// 1. Engine Not Found
751         /// 2. Operation Failed
752         /// </exception>
753         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
754         public IEnumerable<SupportedVoice> GetSupportedVoices()
755         {
756             List<SupportedVoice> voicesList = new List<SupportedVoice>();
757
758             _supportedvoiceDelegate = (IntPtr handle, IntPtr language, int voiceType, IntPtr userData) =>
759             {
760                 string lang = Marshal.PtrToStringAnsi(language);
761                 SupportedVoice voice = new SupportedVoice(lang, voiceType);
762                 voicesList.Add(voice);
763                 return true;
764             };
765             TtsError error = TtsForeachSupportedVoices(_handle, _supportedvoiceDelegate, IntPtr.Zero);
766             if (error != TtsError.None)
767             {
768                 Log.Error(LogTag, "GetSupportedVoices Failed with error " + error);
769                 throw ExceptionFactory.CreateException(error);
770             }
771
772             return voicesList;
773         }
774
775         /// <summary>
776         /// Gets the private data from TTS engine.
777         /// </summary>
778         /// <since_tizen> 3 </since_tizen>
779         /// <param name="key">
780         /// The key string.
781         /// </param>
782         /// <returns>
783         /// The data corresponding to the provided key.
784         /// </returns>
785         /// <feature>
786         /// http://tizen.org/feature/speech.synthesis
787         /// </feature>
788         /// <exception cref="InvalidOperationException">
789         /// This exception can be due to the following reasons:
790         /// 1. Invalid State
791         /// 2. Engine Not found
792         /// 3. Operation Failure
793         /// </exception>
794         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
795         /// <pre>
796         /// The state must be ready.
797         /// </pre>
798         public string GetPrivateData(string key)
799         {
800             string data;
801             TtsError error = TtsGetPrivateData(_handle, key, out data);
802             if (error != TtsError.None)
803             {
804                 Log.Error(LogTag, "GetPrivateData Failed with error " + error);
805                 throw ExceptionFactory.CreateException(error);
806             }
807
808             return data;
809         }
810
811         /// <summary>
812         /// Sets the private data to tts engine.
813         /// </summary>
814         /// <since_tizen> 3 </since_tizen>
815         /// <param name="key">
816         /// The key string.
817         /// </param>
818         /// <param name="data">
819         /// The data string.
820         /// </param>
821         /// <feature>
822         /// http://tizen.org/feature/speech.synthesis
823         /// </feature>
824         /// <exception cref="InvalidOperationException">
825         /// This exception can be due to the following reasons:
826         /// 1. Invalid State
827         /// 2. Engine Not found
828         /// 3. Operation Failure
829         /// </exception>
830         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
831         /// <exception cref="ArgumentException">This exception can be due to improper value provided while setting the value.</exception>
832         /// <pre>
833         /// The state must be ready.
834         /// </pre>
835         public void SetPrivateData(string key, string data)
836         {
837             TtsError error = TtsSetPrivateData(_handle, key, data);
838             if (error != TtsError.None)
839             {
840                 Log.Error(LogTag, "SetPrivateData Failed with error " + error);
841                 throw ExceptionFactory.CreateException(error);
842             }
843         }
844
845         /// <summary>
846         /// Gets the speed range.
847         /// </summary>
848         /// <since_tizen> 3 </since_tizen>
849         /// <returns>
850         /// The SpeedRange value.
851         /// </returns>
852         /// <feature>
853         /// http://tizen.org/feature/speech.synthesis
854         /// </feature>
855         /// <exception cref="InvalidOperationException">
856         /// This exception can be due to the following reasons:
857         /// 1. Invalid State
858         /// 2. Operation Failure
859         /// </exception>
860         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
861         /// <pre>
862         /// The state must be created.
863         /// </pre>
864         public SpeedRange GetSpeedRange()
865         {
866             int min = 0, max = 0, normal = 0;
867             TtsError error = TtsGetSpeedRange(_handle, out min, out normal, out max);
868             if (error != TtsError.None)
869             {
870                 Log.Error(LogTag, "GetSpeedRange Failed with error " + error);
871                 throw ExceptionFactory.CreateException(error);
872             }
873
874             return new SpeedRange(min, normal, max);
875         }
876
877         /// <summary>
878         /// Adds a text to the queue.
879         /// </summary>
880         /// <since_tizen> 3 </since_tizen>
881         /// <remarks>
882         /// Locale MUST be set for UTF-8 text validation check.
883         /// </remarks>
884         /// <param name="text">
885         /// An input text based UTF-8.
886         /// </param>
887         /// <param name="language">
888         /// The language selected from the SupportedVoice.Language Property obtained from GetSupportedVoices()(e.g. 'NULL'(Automatic),'en_US').
889         /// </param>
890         /// <param name="voiceType">
891         /// The voice type selected from the SupportedVoice.VoiceType Property obtained from GetSupportedVoices().
892         /// </param>
893         /// <param name="speed">
894         /// A speaking speed (e.g.0 for Auto or the value from SpeedRange Property).
895         /// </param>
896         /// <returns>
897         /// The utterance ID.
898         /// </returns>
899         /// <feature>
900         /// http://tizen.org/feature/speech.synthesis
901         /// </feature>
902         /// <exception cref="InvalidOperationException">
903         /// This exception can be due to the following reasons:
904         /// 1. Invalid State
905         /// 2. Operation Failure
906         /// 3. Invalid Voice
907         /// </exception>
908         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
909         /// <exception cref="UnauthorizedAccessException">This exception can be due to permission denied.</exception>
910         /// <exception cref="ArgumentException">This exception can be due to improper value provided while setting the value.</exception>
911         /// <pre>
912         /// The state must be ready or playing or paused.
913         /// </pre>
914         public int AddText(string text, string language, int voiceType, int speed)
915         {
916             int id;
917             TtsError error = TtsAddText(_handle, text, language, voiceType, speed, out id);
918             if (error != TtsError.None)
919             {
920                 Log.Error(LogTag, "AddText Failed with error " + error);
921                 throw ExceptionFactory.CreateException(error);
922             }
923
924             return id;
925         }
926
927         /// <summary>
928         /// Starts synthesizing voice from the text and plays the synthesized audio data.
929         /// </summary>
930         /// <since_tizen> 3 </since_tizen>
931         /// <feature>
932         /// http://tizen.org/feature/speech.synthesis
933         /// </feature>
934         /// <exception cref="InvalidOperationException">
935         /// This exception can be due to the following reasons:
936         /// 1. Invalid State
937         /// 2. Operation Failure
938         /// 3. Out of Network
939         /// </exception>
940         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
941         /// <exception cref="UnauthorizedAccessException">This exception can be due to permission denied.</exception>
942         /// <pre>
943         /// The state must be ready or paused.
944         /// </pre>
945         /// <post>
946         /// If this function succeeds, the TTS state will be playing.
947         /// </post>
948         public void Play()
949         {
950             TtsError error = TtsPlay(_handle);
951             if (error != TtsError.None)
952             {
953                 Log.Error(LogTag, "Play Failed with error " + error);
954                 throw ExceptionFactory.CreateException(error);
955             }
956         }
957
958         /// <summary>
959         /// Stops playing the utterance and clears the queue.
960         /// </summary>
961         /// <since_tizen> 3 </since_tizen>
962         /// <feature>
963         /// http://tizen.org/feature/speech.synthesis
964         /// </feature>
965         /// <exception cref="InvalidOperationException">
966         /// This exception can be due to the following reasons:
967         /// 1. Invalid Stat
968         /// 2. Operation Failure
969         /// </exception>
970         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
971         /// <pre>
972         /// The state must be ready or playing or paused.
973         /// </pre>
974         /// <post>
975         /// If this function succeeds, the TTS state will be ready.
976         /// This function will remove all text added via AddText() and synthesized sound data.
977         /// </post>
978         public void Stop()
979         {
980             TtsError error = TtsStop(_handle);
981             if (error != TtsError.None)
982             {
983                 Log.Error(LogTag, "Stop Failed with error " + error);
984                 throw ExceptionFactory.CreateException(error);
985             }
986         }
987
988         /// <summary>
989         /// Pauses the currently playing utterance.
990         /// </summary>
991         /// <since_tizen> 3 </since_tizen>
992         /// <feature>
993         /// http://tizen.org/feature/speech.synthesis
994         /// </feature>
995         /// <exception cref="InvalidOperationException">
996         /// This exception can be due to the following reasons:
997         /// 1. Invalid State
998         /// 2. Operation Failure
999         /// </exception>
1000         /// <exception cref="NotSupportedException">This exception can be due to TTS not supported.</exception>
1001         /// <pre>
1002         /// The state must be playing.
1003         /// </pre>
1004         /// <post>
1005         /// If this function succeeds, the TTS state will be Paused.
1006         /// </post>
1007         public void Pause()
1008         {
1009             TtsError error = TtsPause(_handle);
1010             if (error != TtsError.None)
1011             {
1012                 Log.Error(LogTag, "Pause Failed with error " + error);
1013                 throw ExceptionFactory.CreateException(error);
1014             }
1015         }
1016
1017         /// <summary>
1018         /// Method to release resources.
1019         /// </summary>
1020         /// <since_tizen> 3 </since_tizen>
1021         public void Dispose()
1022         {
1023             Dispose(true);
1024             GC.SuppressFinalize(this);
1025         }
1026
1027         /// <summary>
1028         /// Method to release resources.
1029         /// </summary>
1030         /// <since_tizen> 3 </since_tizen>
1031         /// <param name="disposing">
1032         /// The boolean value for destoying tts handle.
1033         /// </param>
1034         protected virtual void Dispose(bool disposing)
1035         {
1036             if (!disposedValue)
1037             {
1038                 if (_handle != IntPtr.Zero)
1039                 {
1040                     TtsError error = TtsDestroy(_handle);
1041                     if (error != TtsError.None)
1042                     {
1043                         Log.Error(LogTag, "Destroy Failed with error " + error);
1044                     }
1045                     _handle = IntPtr.Zero;
1046                 }
1047
1048                 disposedValue = true;
1049             }
1050         }
1051     }
1052 }