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.
188 /// <exception cref="InvalidOperationException">
189 /// This Exception can be due to the following reaons
191 /// 2. Operation Failed
192 /// 3. TTS Not Supported
193 /// 4. Engine Not Found
198 TtsError error = TtsCreate(out handle);
199 if (error != TtsError.None)
201 Log.Error(LogTag, "Create Failed with error " + error);
202 throw ExceptionFactory.CreateException(error);
209 /// Event to be invoked when TTS state changes.
211 public event EventHandler<StateChangedEventArgs> StateChanged
217 _stateDelegate = (IntPtr handle, State previous, State current, IntPtr userData) =>
219 StateChangedEventArgs args = new StateChangedEventArgs(previous, current);
220 _stateChanged?.Invoke(this, args);
222 TtsError error = TtsSetStateChangedCB(_handle, _stateDelegate, IntPtr.Zero);
223 if (error != TtsError.None)
225 Log.Error(LogTag, "Add StateChanged Failed with error " + error);
229 _stateChanged += value;
239 TtsError error = TtsUnsetStateChangedCB(_handle);
240 if (error != TtsError.None)
242 Log.Error(LogTag, "Remove StateChanged Failed with error " + error);
245 _stateChanged -= value;
252 /// Event to be invoked when the utterance starts.
254 public event EventHandler<UtteranceEventArgs> UtteranceStarted
260 _utteranceStartedResultDelegate = (IntPtr handle, int uttId, IntPtr userData) =>
262 UtteranceEventArgs args = new UtteranceEventArgs(uttId);
263 _utteranceStarted?.Invoke(this, args);
265 TtsError error = TtsSetUtteranceStartedCB(_handle, _utteranceStartedResultDelegate, IntPtr.Zero);
266 if (error != TtsError.None)
268 Log.Error(LogTag, "Add UtteranceStarted Failed with error " + error);
272 _utteranceStarted += value;
281 TtsError error = TtsUnsetUtteranceStartedCB(_handle);
282 if (error != TtsError.None)
284 Log.Error(LogTag, "Remove UtteranceStarted Failed with error " + error);
287 _utteranceStarted -= value;
293 /// Event to be invoked when the utterance completes.
295 public event EventHandler<UtteranceEventArgs> UtteranceCompleted
301 _utteranceCompletedResultDelegate = (IntPtr handle, int uttId, IntPtr userData) =>
303 UtteranceEventArgs args = new UtteranceEventArgs(uttId);
304 _utteranceCompleted?.Invoke(this, args);
306 TtsError error = TtsSetUtteranceCompletedCB(_handle, _utteranceCompletedResultDelegate, IntPtr.Zero);
307 if (error != TtsError.None)
309 Log.Error(LogTag, "Add UtteranceCompleted Failed with error " + error);
313 _utteranceCompleted += value;
322 TtsError error = TtsUnsetUtteranceCompletedCB(_handle);
323 if (error != TtsError.None)
325 Log.Error(LogTag, "Remove UtteranceCompleted Failed with error " + error);
328 _utteranceCompleted -= value;
334 /// Event to be invoked when an error occurs.
336 public event EventHandler<ErrorOccuredEventArgs> ErrorOccured
342 _errorDelegate = (IntPtr handle, int uttId, TtsError reason, IntPtr userData) =>
344 ErrorOccuredEventArgs args = new ErrorOccuredEventArgs(handle, uttId, reason);
345 _errorOccured?.Invoke(this, args);
347 TtsError error = TtsSetErrorCB(_handle, _errorDelegate, IntPtr.Zero);
348 if (error != TtsError.None)
350 Log.Error(LogTag, "Add ErrorOccured Failed with error " + error);
355 _errorOccured += value;
364 TtsError error = TtsUnsetErrorCB(_handle);
365 if (error != TtsError.None)
367 Log.Error(LogTag, "Remove ErrorOccured Failed with error " + error);
370 _errorOccured -= value;
376 /// Event to be invoked when an error occurs.
378 public event EventHandler<DefaultVoiceChangedEventArgs> DefaultVoiceChanged
384 _voiceChangedDelegate = (IntPtr handle, IntPtr previousLanguage, int previousVoiceType, IntPtr currentLanguage, int currentVoiceType, IntPtr userData) =>
386 string previousLanguageString = Marshal.PtrToStringAnsi(previousLanguage);
387 string currentLanguageString = Marshal.PtrToStringAnsi(currentLanguage);
388 DefaultVoiceChangedEventArgs args = new DefaultVoiceChangedEventArgs(previousLanguageString, previousVoiceType, currentLanguageString, currentVoiceType);
389 _defaultVoiceChanged?.Invoke(this, args);
391 TtsError error = TtsSetDefaultVoiceChangedCB(_handle, _voiceChangedDelegate, IntPtr.Zero);
392 if (error != TtsError.None)
394 Log.Error(LogTag, "Add DefaultVoiceChanged Failed with error " + error);
399 _defaultVoiceChanged += value;
409 TtsError error = TtsUnsetDefaultVoiceChangedCB(_handle);
410 if (error != TtsError.None)
412 Log.Error(LogTag, "Remove DefaultVoiceChanged Failed with error " + error);
415 _defaultVoiceChanged -= value;
421 /// Event to be invoked to detect engine change.
423 public event EventHandler<EngineChangedEventArgs> EngineChanged
429 _engineDelegate = (IntPtr handle, IntPtr engineId, IntPtr language, int voiceType, bool needCredential, IntPtr userData) =>
431 string engineIdString = Marshal.PtrToStringAnsi(engineId);
432 string languageString = Marshal.PtrToStringAnsi(language);
433 EngineChangedEventArgs args = new EngineChangedEventArgs(engineIdString, languageString, voiceType, needCredential);
434 _engineChanged?.Invoke(this, args);
436 TtsError error = TtsSetEngineChangedCB(_handle, _engineDelegate, IntPtr.Zero);
437 if (error != TtsError.None)
439 Log.Error(LogTag, "Add EngineChanged Failed with error " + error);
443 _engineChanged += value;
452 TtsError error = TtsUnsetEngineChangedCB(_handle);
453 if (error != TtsError.None)
455 Log.Error(LogTag, "Remove EngineChanged Failed with error " + error);
458 _engineChanged -= value;
464 /// Gets the default voice set by the user.
467 /// Default Voice SupportedVoice value.
469 public SupportedVoice DefaultVoice
477 TtsError error = TtsGetDefaultVoice(_handle, out language, out voiceType);
478 if (error != TtsError.None)
480 Log.Error(LogTag, "DefaultVoice Failed with error " + error);
481 return new SupportedVoice();
484 return new SupportedVoice(language, voiceType);
490 /// Gets the maximum byte size for text.
493 /// Default Voice SupportedVoice value, 0 if unable to get the value
496 /// The State should be Ready
498 public uint GetMaxTextSize
505 TtsError error = TtsGetMaxTextSize(_handle, out maxTextSize);
506 if (error != TtsError.None)
508 Log.Error(LogTag, "MaxTextSize Failed with error " + error);
520 /// Gets the current TTS state.
523 /// Current TTS State value.
525 public State GetState
532 TtsError error = TtsGetState(_handle, out state);
533 if (error != TtsError.None)
535 Log.Error(LogTag, "CurrentState Failed with error " + error);
536 return State.Unavailable;
547 /// The TTS Mode can be set using this property
552 /// <exception cref="InvalidOperationException">
553 /// This Exception can be due to the following reaons while setting the value
555 /// 2. Operation Failed
556 /// 3. TTS Not Supported
557 /// 4. Engine Not Found
560 /// State should be Created
562 public Mode CurrentMode
566 Mode mode = Mode.Default;
569 TtsError error = TtsGetMode(_handle, out mode);
570 if (error != TtsError.None)
572 Log.Error(LogTag, "Get Mode Failed with error " + error);
584 error = TtsSetMode(_handle, value);
587 if (error != TtsError.None)
589 Log.Error(LogTag, "Set Mode Failed with error " + error);
590 throw ExceptionFactory.CreateException(error);
596 /// Sets the app credential
598 /// <param name="credential">
599 /// The credential string
601 /// <exception cref="InvalidOperationException">
602 /// This Exception can be due to the following reaons
603 /// 1. TTS Not Supported
606 /// <exception cref="ArgumentException">
607 /// This can happen if Improper value is provided while setting the value.
610 /// The State must be Created or Ready.
612 public void SetCredential(string credential)
616 TtsError error = TtsSetCredential(_handle, credential);
617 if (error != TtsError.None)
619 Tizen.Log.Error(LogTag, "SetCredential Failed with error " + error);
620 throw ExceptionFactory.CreateException(error);
626 /// Connects to the TTS service asynchronously.
628 /// <exception cref="InvalidOperationException">
629 /// This Exception can be due to the following reasons
630 /// 1. TTS Not Supported
634 /// The State must be Created.
637 /// If this function is successful, the TTS state will be Ready
638 /// If this function is unsuccessful, ErrorOccured event will be invoked
640 public void Prepare()
644 TtsError error = TtsPrepare(_handle);
645 if (error != TtsError.None)
647 Log.Error(LogTag, "Prepare Failed with error " + error);
648 throw ExceptionFactory.CreateException(error);
654 /// Disconnects from the STT service.
656 /// <exception cref="InvalidOperationException">
657 /// This Exception can be due to the following reasons
658 /// 1. TTS Not Supported
662 /// The State must be Ready.
665 /// If this function is successful, the TTS state will be Created
667 public void Unprepare()
671 TtsError error = TtsUnprepare(_handle);
672 if (error != TtsError.None)
674 Log.Error(LogTag, "Unprepare Failed with error " + error);
675 throw ExceptionFactory.CreateException(error);
681 /// Retrieves all supported voices of the current engine.
684 /// list of SupportedVoice.
686 /// <exception cref="InvalidOperationException">
687 /// This Exception can be due to the following reasons
688 /// 1. TTS Not Supported
689 /// 2. Engine Not Found.
690 /// 3. Operation Failed.
692 public IEnumerable<SupportedVoice> GetSupportedVoices()
694 List<SupportedVoice> voicesList = new List<SupportedVoice>();
697 _supportedvoiceDelegate = (IntPtr handle, IntPtr language, int voiceType, IntPtr userData) =>
699 string lang = Marshal.PtrToStringAnsi(language);
700 SupportedVoice voice = new SupportedVoice(lang, voiceType);
701 voicesList.Add(voice);
704 TtsError error = TtsForeachSupportedVoices(_handle, _supportedvoiceDelegate, IntPtr.Zero);
705 if (error != TtsError.None)
707 Log.Error(LogTag, "GetSupportedVoices Failed with error " + error);
708 throw ExceptionFactory.CreateException(error);
717 /// Gets the private data from tts engine.
719 /// <param name="key">
723 /// The Data Corresponding to the Key provided
725 /// <exception cref="InvalidOperationException">
726 /// This Exception can be due to the following reaons
727 /// 1. TTS Not Supported
729 /// 3. Engine Not found
730 /// 4. Operation Failure
733 /// The State must be Ready.
735 public string GetPrivateData(string key)
740 TtsError error = TtsGetPrivateData(_handle, key, out data);
741 if (error != TtsError.None)
743 Log.Error(LogTag, "GetPrivateData Failed with error " + error);
744 throw ExceptionFactory.CreateException(error);
753 /// Sets the private data to tts engine.
755 /// <param name="key">
758 /// <param name="data">
761 /// <exception cref="InvalidOperationException">
762 /// This Exception can be due to the following reaons
763 /// 1. TTS Not Supported
765 /// 3. Engine Not found
766 /// 4. Operation Failure
768 /// <exception cref="ArgumentException">
769 /// This can happen if Improper value is provided while setting the value.
772 /// The State must be Ready.
774 public void SetPrivateData(string key, string data)
778 TtsError error = TtsSetPrivateData(_handle, key, data);
779 if (error != TtsError.None)
781 Log.Error(LogTag, "SetPrivateData Failed with error " + error);
782 throw ExceptionFactory.CreateException(error);
788 /// Gets the speed range.
791 /// The SpeedRange value
793 /// <exception cref="InvalidOperationException">
794 /// This Exception can be due to the following reaons
795 /// 1. TTS Not Supported
797 /// 3. Operation Failure
800 /// The State must be Created.
802 public SpeedRange GetSpeedRange()
804 int min = 0, max = 0, normal = 0;
807 TtsError error = TtsGetSpeedRange(_handle, out min, out normal, out max);
808 if (error != TtsError.None)
810 Log.Error(LogTag, "GetSpeedRange Failed with error " + error);
811 throw ExceptionFactory.CreateException(error);
816 return new SpeedRange(min, normal, max);
820 /// Adds a text to the queue.
823 /// Locale MUST be set for utf8 text validation check.
825 /// <param name="text">
826 /// An input text based utf8
828 /// <param name="language">
829 /// The language selected from the SupportedVoice.Language Property obtained from GetSupportedVoices() (e.g. 'NULL'(Automatic), 'en_US')
831 /// <param name="voiceType">
832 /// The voice type selected from the SupportedVoice.VoiceType Property obtained from GetSupportedVoices()
834 /// <param name="speed">
835 /// A speaking speed (e.g.0 for Auto or the value from SpeedRange Property)
838 /// The utterance ID.
840 /// <exception cref="InvalidOperationException">
841 /// This Exception can be due to the following reaons
842 /// 1. TTS Not Supported
844 /// 3. Operation Failure
846 /// 5. Permission Denied
848 /// <exception cref="ArgumentException">
849 /// This can happen if Improper value is provided.
852 /// The State must be Ready or Playing or Paused.
854 public int AddText(string text, string language, int voiceType, int speed)
859 TtsError error = TtsAddText(_handle, text, language, voiceType, speed, out id);
860 if (error != TtsError.None)
862 Log.Error(LogTag, "AddText Failed with error " + error);
863 throw ExceptionFactory.CreateException(error);
872 /// Starts synthesizing voice from the text and plays the synthesized audio data.
874 /// <exception cref="InvalidOperationException">
875 /// This Exception can be due to the following reaons
876 /// 1. TTS Not Supported
878 /// 3. Operation Failure
879 /// 4. Out of Network
880 /// 5. Permission Denied
883 /// The State must be Ready or Paused.
886 /// If this function succeeds, the TTS state will be Playing.
892 TtsError error = TtsPlay(_handle);
893 if (error != TtsError.None)
895 Log.Error(LogTag, "Play Failed with error " + error);
896 throw ExceptionFactory.CreateException(error);
902 /// Stops playing the utterance and clears the queue.
904 /// <exception cref="InvalidOperationException">
905 /// This Exception can be due to the following reaons
906 /// 1. TTS Not Supported
908 /// 3. Operation Failure
911 /// The State must be Ready or Playing or Paused.
914 /// If this function succeeds, the TTS state will be Ready.
915 /// This function will remove all text added via AddText() and synthesized sound data.
921 TtsError error = TtsStop(_handle);
922 if (error != TtsError.None)
924 Log.Error(LogTag, "Stop Failed with error " + error);
925 throw ExceptionFactory.CreateException(error);
931 /// Pauses the currently playing utterance.
933 /// <exception cref="InvalidOperationException">
934 /// This Exception can be due to the following reaons
935 /// 1. TTS Not Supported
937 /// 3. Operation Failure
940 /// The State must be Playing.
943 /// If this function succeeds, the TTS state will be Paused.
949 TtsError error = TtsPause(_handle);
950 if (error != TtsError.None)
952 Log.Error(LogTag, "Pause Failed with error " + error);
953 throw ExceptionFactory.CreateException(error);
959 /// Method to release resources
961 public void Dispose()
966 protected virtual void Dispose(bool disposing)
972 TtsError error = TtsDestroy(_handle);
973 if (error != TtsError.None)
975 Log.Error(LogTag, "Destroy Failed with error " + error);
979 disposedValue = true;