2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 using System.Collections.Generic;
20 using System.Runtime.InteropServices;
21 using static Interop.Tts;
23 namespace Tizen.Uix.Tts
26 /// Enumeration for States
57 /// Enumeration for TTS mode.
62 /// Default mode for normal application
72 /// Accessibiliity mode
78 /// Enum for Error values that can occur
83 /// Successful, No error
99 /// No answer from the STT service
107 /// Permission denied
111 /// STT NOT supported
123 /// No available engine
131 /// Audio policy blocked
137 /// Enumeration for Voice Types
142 /// Automatic Voice Type
163 /// You can use Text-To-Speech (TTS) API's to read sound data transformed by the engine from input texts.
164 /// 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.
166 public class TtsClient : IDisposable
168 private IntPtr _handle;
169 private event EventHandler<StateChangedEventArgs> _stateChanged;
170 private event EventHandler<UtteranceEventArgs> _utteranceStarted;
171 private event EventHandler<UtteranceEventArgs> _utteranceCompleted;
172 private event EventHandler<ErrorOccuredEventArgs> _errorOccured;
173 private event EventHandler<DefaultVoiceChangedEventArgs> _defaultVoiceChanged;
174 private event EventHandler<EngineChangedEventArgs> _engineChanged;
175 private bool disposedValue = false;
176 private Object thisLock = new Object();
177 private TtsStateChangedCB _stateDelegate;
178 private TtsUtteranceStartedCB _utteranceStartedResultDelegate;
179 private TtsUtteranceCompletedCB _utteranceCompletedResultDelegate;
180 private TtsErrorCB _errorDelegate;
181 private TtsDefaultVoiceChangedCB _voiceChangedDelegate;
182 private TtsEngineChangedCB _engineDelegate;
183 private TtsSupportedVoiceCB _supportedvoiceDelegate;
186 /// Constructor to create a TTS instance.
189 /// http://tizen.org/feature/speech.synthesis
191 /// <exception cref="InvalidOperationException">
192 /// This Exception can be due to the following reaons
194 /// 2. Operation Failed
195 /// 3. TTS Not Supported
196 /// 4. Engine Not Found
201 TtsError error = TtsCreate(out handle);
202 if (error != TtsError.None)
204 Log.Error(LogTag, "Create Failed with error " + error);
205 throw ExceptionFactory.CreateException(error);
212 /// Event to be invoked when TTS state changes.
214 public event EventHandler<StateChangedEventArgs> StateChanged
220 _stateDelegate = (IntPtr handle, State previous, State current, IntPtr userData) =>
222 StateChangedEventArgs args = new StateChangedEventArgs(previous, current);
223 _stateChanged?.Invoke(this, args);
225 TtsError error = TtsSetStateChangedCB(_handle, _stateDelegate, IntPtr.Zero);
226 if (error != TtsError.None)
228 Log.Error(LogTag, "Add StateChanged Failed with error " + error);
232 _stateChanged += value;
242 TtsError error = TtsUnsetStateChangedCB(_handle);
243 if (error != TtsError.None)
245 Log.Error(LogTag, "Remove StateChanged Failed with error " + error);
248 _stateChanged -= value;
255 /// Event to be invoked when the utterance starts.
257 public event EventHandler<UtteranceEventArgs> UtteranceStarted
263 _utteranceStartedResultDelegate = (IntPtr handle, int uttId, IntPtr userData) =>
265 UtteranceEventArgs args = new UtteranceEventArgs(uttId);
266 _utteranceStarted?.Invoke(this, args);
268 TtsError error = TtsSetUtteranceStartedCB(_handle, _utteranceStartedResultDelegate, IntPtr.Zero);
269 if (error != TtsError.None)
271 Log.Error(LogTag, "Add UtteranceStarted Failed with error " + error);
275 _utteranceStarted += value;
284 TtsError error = TtsUnsetUtteranceStartedCB(_handle);
285 if (error != TtsError.None)
287 Log.Error(LogTag, "Remove UtteranceStarted Failed with error " + error);
290 _utteranceStarted -= value;
296 /// Event to be invoked when the utterance completes.
298 public event EventHandler<UtteranceEventArgs> UtteranceCompleted
304 _utteranceCompletedResultDelegate = (IntPtr handle, int uttId, IntPtr userData) =>
306 UtteranceEventArgs args = new UtteranceEventArgs(uttId);
307 _utteranceCompleted?.Invoke(this, args);
309 TtsError error = TtsSetUtteranceCompletedCB(_handle, _utteranceCompletedResultDelegate, IntPtr.Zero);
310 if (error != TtsError.None)
312 Log.Error(LogTag, "Add UtteranceCompleted Failed with error " + error);
316 _utteranceCompleted += value;
325 TtsError error = TtsUnsetUtteranceCompletedCB(_handle);
326 if (error != TtsError.None)
328 Log.Error(LogTag, "Remove UtteranceCompleted Failed with error " + error);
331 _utteranceCompleted -= value;
337 /// Event to be invoked when an error occurs.
339 public event EventHandler<ErrorOccuredEventArgs> ErrorOccured
345 _errorDelegate = (IntPtr handle, int uttId, TtsError reason, IntPtr userData) =>
347 ErrorOccuredEventArgs args = new ErrorOccuredEventArgs(handle, uttId, reason);
348 _errorOccured?.Invoke(this, args);
350 TtsError error = TtsSetErrorCB(_handle, _errorDelegate, IntPtr.Zero);
351 if (error != TtsError.None)
353 Log.Error(LogTag, "Add ErrorOccured Failed with error " + error);
358 _errorOccured += value;
367 TtsError error = TtsUnsetErrorCB(_handle);
368 if (error != TtsError.None)
370 Log.Error(LogTag, "Remove ErrorOccured Failed with error " + error);
373 _errorOccured -= value;
379 /// Event to be invoked when an error occurs.
381 public event EventHandler<DefaultVoiceChangedEventArgs> DefaultVoiceChanged
387 _voiceChangedDelegate = (IntPtr handle, IntPtr previousLanguage, int previousVoiceType, IntPtr currentLanguage, int currentVoiceType, IntPtr userData) =>
389 string previousLanguageString = Marshal.PtrToStringAnsi(previousLanguage);
390 string currentLanguageString = Marshal.PtrToStringAnsi(currentLanguage);
391 DefaultVoiceChangedEventArgs args = new DefaultVoiceChangedEventArgs(previousLanguageString, previousVoiceType, currentLanguageString, currentVoiceType);
392 _defaultVoiceChanged?.Invoke(this, args);
394 TtsError error = TtsSetDefaultVoiceChangedCB(_handle, _voiceChangedDelegate, IntPtr.Zero);
395 if (error != TtsError.None)
397 Log.Error(LogTag, "Add DefaultVoiceChanged Failed with error " + error);
402 _defaultVoiceChanged += value;
412 TtsError error = TtsUnsetDefaultVoiceChangedCB(_handle);
413 if (error != TtsError.None)
415 Log.Error(LogTag, "Remove DefaultVoiceChanged Failed with error " + error);
418 _defaultVoiceChanged -= value;
424 /// Event to be invoked to detect engine change.
426 public event EventHandler<EngineChangedEventArgs> EngineChanged
432 _engineDelegate = (IntPtr handle, IntPtr engineId, IntPtr language, int voiceType, bool needCredential, IntPtr userData) =>
434 string engineIdString = Marshal.PtrToStringAnsi(engineId);
435 string languageString = Marshal.PtrToStringAnsi(language);
436 EngineChangedEventArgs args = new EngineChangedEventArgs(engineIdString, languageString, voiceType, needCredential);
437 _engineChanged?.Invoke(this, args);
439 TtsError error = TtsSetEngineChangedCB(_handle, _engineDelegate, IntPtr.Zero);
440 if (error != TtsError.None)
442 Log.Error(LogTag, "Add EngineChanged Failed with error " + error);
446 _engineChanged += value;
455 TtsError error = TtsUnsetEngineChangedCB(_handle);
456 if (error != TtsError.None)
458 Log.Error(LogTag, "Remove EngineChanged Failed with error " + error);
461 _engineChanged -= value;
467 /// Gets the default voice set by the user.
470 /// Default voice in TTS
473 /// Default Voice SupportedVoice value.
475 public SupportedVoice DefaultVoice
483 TtsError error = TtsGetDefaultVoice(_handle, out language, out voiceType);
484 if (error != TtsError.None)
486 Log.Error(LogTag, "DefaultVoice Failed with error " + error);
487 return new SupportedVoice();
490 return new SupportedVoice(language, voiceType);
496 /// Gets the maximum byte size for text.
499 /// Maximum byte size for text
502 /// Default Voice SupportedVoice value, 0 if unable to get the value
505 /// The State should be Ready
507 public uint GetMaxTextSize
514 TtsError error = TtsGetMaxTextSize(_handle, out maxTextSize);
515 if (error != TtsError.None)
517 Log.Error(LogTag, "MaxTextSize Failed with error " + error);
529 /// Gets the current TTS state.
532 /// Current state of TTS
535 /// Current TTS State value.
537 public State GetState
544 TtsError error = TtsGetState(_handle, out state);
545 if (error != TtsError.None)
547 Log.Error(LogTag, "CurrentState Failed with error " + error);
548 return State.Unavailable;
559 /// The TTS Mode can be set using this property
562 /// Current mode of TTS (default, screen-reader, notification)
567 /// <exception cref="InvalidOperationException">
568 /// This Exception can be due to the following reaons while setting the value
570 /// 2. Operation Failed
571 /// 3. TTS Not Supported
572 /// 4. Engine Not Found
575 /// State should be Created
577 public Mode CurrentMode
581 Mode mode = Mode.Default;
584 TtsError error = TtsGetMode(_handle, out mode);
585 if (error != TtsError.None)
587 Log.Error(LogTag, "Get Mode Failed with error " + error);
599 error = TtsSetMode(_handle, value);
602 if (error != TtsError.None)
604 Log.Error(LogTag, "Set Mode Failed with error " + error);
605 throw ExceptionFactory.CreateException(error);
611 /// Sets the app credential
613 /// <param name="credential">
614 /// The credential string
617 /// http://tizen.org/feature/speech.synthesis
619 /// <exception cref="InvalidOperationException">
620 /// This Exception can be due to the following reaons
621 /// 1. TTS Not Supported
624 /// <exception cref="ArgumentException">
625 /// This can happen if Improper value is provided while setting the value.
628 /// The State must be Created or Ready.
630 public void SetCredential(string credential)
634 TtsError error = TtsSetCredential(_handle, credential);
635 if (error != TtsError.None)
637 Tizen.Log.Error(LogTag, "SetCredential Failed with error " + error);
638 throw ExceptionFactory.CreateException(error);
644 /// Connects to the TTS service asynchronously.
647 /// http://tizen.org/feature/speech.synthesis
649 /// <exception cref="InvalidOperationException">
650 /// This Exception can be due to the following reasons
651 /// 1. TTS Not Supported
655 /// The State must be Created.
658 /// If this function is successful, the TTS state will be Ready
659 /// If this function is unsuccessful, ErrorOccured event will be invoked
661 public void Prepare()
665 TtsError error = TtsPrepare(_handle);
666 if (error != TtsError.None)
668 Log.Error(LogTag, "Prepare Failed with error " + error);
669 throw ExceptionFactory.CreateException(error);
675 /// Disconnects from the STT service.
678 /// http://tizen.org/feature/speech.synthesis
680 /// <exception cref="InvalidOperationException">
681 /// This Exception can be due to the following reasons
682 /// 1. TTS Not Supported
686 /// The State must be Ready.
689 /// If this function is successful, the TTS state will be Created
691 public void Unprepare()
695 TtsError error = TtsUnprepare(_handle);
696 if (error != TtsError.None)
698 Log.Error(LogTag, "Unprepare Failed with error " + error);
699 throw ExceptionFactory.CreateException(error);
705 /// Retrieves all supported voices of the current engine.
708 /// list of SupportedVoice.
711 /// http://tizen.org/feature/speech.synthesis
713 /// <exception cref="InvalidOperationException">
714 /// This Exception can be due to the following reasons
715 /// 1. TTS Not Supported
716 /// 2. Engine Not Found.
717 /// 3. Operation Failed.
719 public IEnumerable<SupportedVoice> GetSupportedVoices()
721 List<SupportedVoice> voicesList = new List<SupportedVoice>();
724 _supportedvoiceDelegate = (IntPtr handle, IntPtr language, int voiceType, IntPtr userData) =>
726 string lang = Marshal.PtrToStringAnsi(language);
727 SupportedVoice voice = new SupportedVoice(lang, voiceType);
728 voicesList.Add(voice);
731 TtsError error = TtsForeachSupportedVoices(_handle, _supportedvoiceDelegate, IntPtr.Zero);
732 if (error != TtsError.None)
734 Log.Error(LogTag, "GetSupportedVoices Failed with error " + error);
735 throw ExceptionFactory.CreateException(error);
744 /// Gets the private data from tts engine.
746 /// <param name="key">
750 /// The Data Corresponding to the Key provided
753 /// http://tizen.org/feature/speech.synthesis
755 /// <exception cref="InvalidOperationException">
756 /// This Exception can be due to the following reaons
757 /// 1. TTS Not Supported
759 /// 3. Engine Not found
760 /// 4. Operation Failure
763 /// The State must be Ready.
765 public string GetPrivateData(string key)
770 TtsError error = TtsGetPrivateData(_handle, key, out data);
771 if (error != TtsError.None)
773 Log.Error(LogTag, "GetPrivateData Failed with error " + error);
774 throw ExceptionFactory.CreateException(error);
783 /// Sets the private data to tts engine.
785 /// <param name="key">
788 /// <param name="data">
792 /// http://tizen.org/feature/speech.synthesis
794 /// <exception cref="InvalidOperationException">
795 /// This Exception can be due to the following reaons
796 /// 1. TTS Not Supported
798 /// 3. Engine Not found
799 /// 4. Operation Failure
801 /// <exception cref="ArgumentException">
802 /// This can happen if Improper value is provided while setting the value.
805 /// The State must be Ready.
807 public void SetPrivateData(string key, string data)
811 TtsError error = TtsSetPrivateData(_handle, key, data);
812 if (error != TtsError.None)
814 Log.Error(LogTag, "SetPrivateData Failed with error " + error);
815 throw ExceptionFactory.CreateException(error);
821 /// Gets the speed range.
824 /// The SpeedRange value
827 /// http://tizen.org/feature/speech.synthesis
829 /// <exception cref="InvalidOperationException">
830 /// This Exception can be due to the following reaons
831 /// 1. TTS Not Supported
833 /// 3. Operation Failure
836 /// The State must be Created.
838 public SpeedRange GetSpeedRange()
840 int min = 0, max = 0, normal = 0;
843 TtsError error = TtsGetSpeedRange(_handle, out min, out normal, out max);
844 if (error != TtsError.None)
846 Log.Error(LogTag, "GetSpeedRange Failed with error " + error);
847 throw ExceptionFactory.CreateException(error);
852 return new SpeedRange(min, normal, max);
856 /// Adds a text to the queue.
859 /// Locale MUST be set for utf8 text validation check.
861 /// <param name="text">
862 /// An input text based utf8
864 /// <param name="language">
865 /// The language selected from the SupportedVoice.Language Property obtained from GetSupportedVoices() (e.g. 'NULL'(Automatic), 'en_US')
867 /// <param name="voiceType">
868 /// The voice type selected from the SupportedVoice.VoiceType Property obtained from GetSupportedVoices()
870 /// <param name="speed">
871 /// A speaking speed (e.g.0 for Auto or the value from SpeedRange Property)
874 /// The utterance ID.
877 /// http://tizen.org/feature/speech.synthesis
879 /// <exception cref="InvalidOperationException">
880 /// This Exception can be due to the following reaons
881 /// 1. TTS Not Supported
883 /// 3. Operation Failure
885 /// 5. Permission Denied
887 /// <exception cref="ArgumentException">
888 /// This can happen if Improper value is provided.
891 /// The State must be Ready or Playing or Paused.
893 public int AddText(string text, string language, int voiceType, int speed)
898 TtsError error = TtsAddText(_handle, text, language, voiceType, speed, out id);
899 if (error != TtsError.None)
901 Log.Error(LogTag, "AddText Failed with error " + error);
902 throw ExceptionFactory.CreateException(error);
911 /// Starts synthesizing voice from the text and plays the synthesized audio data.
914 /// http://tizen.org/feature/speech.synthesis
916 /// <exception cref="InvalidOperationException">
917 /// This Exception can be due to the following reaons
918 /// 1. TTS Not Supported
920 /// 3. Operation Failure
921 /// 4. Out of Network
922 /// 5. Permission Denied
925 /// The State must be Ready or Paused.
928 /// If this function succeeds, the TTS state will be Playing.
934 TtsError error = TtsPlay(_handle);
935 if (error != TtsError.None)
937 Log.Error(LogTag, "Play Failed with error " + error);
938 throw ExceptionFactory.CreateException(error);
944 /// Stops playing the utterance and clears the queue.
947 /// http://tizen.org/feature/speech.synthesis
949 /// <exception cref="InvalidOperationException">
950 /// This Exception can be due to the following reaons
951 /// 1. TTS Not Supported
953 /// 3. Operation Failure
956 /// The State must be Ready or Playing or Paused.
959 /// If this function succeeds, the TTS state will be Ready.
960 /// This function will remove all text added via AddText() and synthesized sound data.
966 TtsError error = TtsStop(_handle);
967 if (error != TtsError.None)
969 Log.Error(LogTag, "Stop Failed with error " + error);
970 throw ExceptionFactory.CreateException(error);
976 /// Pauses the currently playing utterance.
979 /// http://tizen.org/feature/speech.synthesis
981 /// <exception cref="InvalidOperationException">
982 /// This Exception can be due to the following reaons
983 /// 1. TTS Not Supported
985 /// 3. Operation Failure
988 /// The State must be Playing.
991 /// If this function succeeds, the TTS state will be Paused.
997 TtsError error = TtsPause(_handle);
998 if (error != TtsError.None)
1000 Log.Error(LogTag, "Pause Failed with error " + error);
1001 throw ExceptionFactory.CreateException(error);
1007 /// Method to release resources
1009 public void Dispose()
1014 protected virtual void Dispose(bool disposing)
1020 TtsError error = TtsDestroy(_handle);
1021 if (error != TtsError.None)
1023 Log.Error(LogTag, "Destroy Failed with error " + error);
1027 disposedValue = true;