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.
18 using System.Runtime.InteropServices;
19 using static Interop.TtsEngine;
21 namespace Tizen.Uix.TtsEngine
24 /// Enumeration for audio type.
29 /// Signed 16-bit audio type
33 /// Unsigned 8-bit audio type
43 /// Enumeration for result.
45 public enum ResultEvent
48 /// Event when the voice synthesis is failed
52 /// Event when the sound data is first data by callback function
56 /// Event when the next sound data exist, not first and not last
60 /// Event when the sound data is last data or sound data is only one result
66 /// Enumeration for Voice Type
75 /// female voice type.
79 /// child's voice type.
85 /// Enum for Error values that can occur
90 /// Successful, No error
92 None = ErrorCode.None,
96 OutOfMemory = ErrorCode.OutOfMemory,
100 IoError = ErrorCode.IoError,
102 /// Invalid parameter
104 InvalidParameter = ErrorCode.InvalidParameter,
106 /// Network down(Out of network)
108 NetworkDown = ErrorCode.NetworkDown,
112 InvalidState = ErrorCode.InvalidState,
116 InvalidVoice = ErrorCode.InvalidVoice,
120 OperationFailed = ErrorCode.OperationFailed,
122 /// Not supported feature of current engine
124 NotSupportedFeature = ErrorCode.NotSupportedFeature,
128 NotSupported = ErrorCode.NotSupported,
130 /// Permission denied
132 PermissionDenied = ErrorCode.PermissionDenied
136 /// This Class represents the Tts Engine which has to be inherited to make the engine.
138 public abstract class Engine
140 private CallbackStructGCHandle _callbackStructGCHandle = new CallbackStructGCHandle();
141 private PrivateDataSetCb _privateDataSetCb;
142 private Action<string> _privateDatacallback;
143 private PrivateDataRequestedCb _privateDataRequestedCb;
144 private OutAction<string> _privateDataRequestedCallback;
145 private static Engine _engine;
146 private IntPtr _structIntPtrHandle;
149 /// An Action with 2 Input Parameter returning a Error
151 /// <typeparam name="T">Generic Type for Parameter 1</typeparam>
152 /// <param name="a">The Input Parameter 1</param>
153 /// <param name="b">The Input Parameter 2</param>
154 /// <returns>Error Value</returns>
155 public delegate Error Action<T>(T a, T b);
158 /// An Action with 2 Out Parameter returning a Error
160 /// <typeparam name="T">Generic Type for Parameter 1</typeparam>
161 /// <param name="a">The Input Parameter 1</param>
162 /// <param name="b">The Input Parameter 2</param>
163 /// <returns>Error Value</returns>
164 public delegate Error OutAction<T>(T a, out T b);
167 /// Called when TTS engine informs the engine service user about whole supported language and voice type list.
168 /// This callback function is implemented by the engine service user.Therefore, the engine developer does NOT have to implement this callback function.
171 /// This callback function is called by ForEachSupportedVoices() to inform the whole supported voice list. userData must be transferred from ForEachSupportedVoices().
173 /// <param name="language">The language is specified as an ISO 3166 alpha-2 two-letter country code followed by ISO 639-1 for the two-letter language code.
174 /// For example, "ko_KR" for Korean, "en_US" for American English</param>
175 /// <param name="type">The voice type</param>
176 /// <param name="userData">The user data passed from ForEachSupportedVoices()</param>
177 /// <returns>true to continue with the next iteration of the loop false to break out of the loop</returns>
178 /// <precondition>ForEachSupportedVoices() will invoke this callback function.</precondition>
179 public delegate bool SupportedVoice(string language, VoiceType type, IntPtr userData);
182 /// Called when the engine service user starts to synthesize a voice, asynchronously.
185 /// In this callback function, TTS engine must transfer the synthesized result to the engine service user using SendResult().
186 /// Also, if TTS engine needs the application's credential, it can set the credential granted to the application.
188 /// <param name="language">The language is specified as an ISO 3166 alpha-2 two-letter country code followed by ISO 639-1 for the two-letter language code.
189 /// For example, "ko_KR" for Korean, "en_US" for American English</param>
190 /// <param name="type">The voice type</param>
191 /// <param name="text">Texts</param>
192 /// <param name="speed">The speed of speaking</param>
193 /// <param name="appid">The Application ID</param>
194 /// <param name="credential">The credential granted to the application</param>
195 /// <param name="userData">The user data which must be passed to SendResult() function</param>
197 /// Following Error Codes can be returned
200 /// 3. InvalidParameter
202 /// 5. OperationFailed
204 /// 7. PermissionDenied
206 /// <postcondition>This function invokes SendResult()</postcondition>
207 public abstract Error StartSynthesis(string language, int type, string text, int speed, string appid, string credential, IntPtr userData);
210 /// Called when the engine service user requests the basic information of TTS engine.
213 /// The allocated engineUuid, engineName, and engineSetting will be released internally.
214 /// In order to upload the engine at Tizen Appstore, both a service app and a ui app are necessary.
215 /// Therefore, engineSetting must be transferred to the engine service user.
217 /// <param name="engineUuid">UUID of engine</param>
218 /// <param name="engineName">Name of engine</param>
219 /// <param name="engineSetting">The engine setting application(ui app)'s app ID</param>
220 /// <param name="useNetwork">The status for using network</param>
222 /// Following Error Codes can be returned
226 public abstract Error GetInformation(out string engineUuid, out string engineName, out string engineSetting, out bool useNetwork);
229 /// Called when the engine service user initializes TTS engine.
232 /// Following Error Codes can be returned
235 /// 3. NotSupportedFeature
236 /// 4. PermissionDenied
238 public abstract Error Initialize();
241 /// Called when the engine service user deinitializes TTS engine.
244 /// NOTE that the engine may be terminated automatically. When this callback function is invoked, the release of resources is necessary.
247 /// Following Error Codes can be returned
251 public abstract Error Deinitialize();
254 /// Called when the engine service user gets the whole supported voice list.
257 /// In this function, the engine service user's callback function 'SupportedVoice()' is invoked repeatedly for getting all supported voices,
258 /// and userData must be transferred to 'SupportedVoice()'. If 'SupportedVoice()' returns false, it should be stopped to call 'SupportedVoice()'.</remarks>
259 /// <param name="callback">The callback function</param>
260 /// <param name="userData">The user data which must be passed to SupportedVoice()</param>
262 /// Following Error Codes can be returned
264 /// 2. OperationFailed
266 /// <postcondition>This callback function invokes SupportedVoice() repeatedly for getting all supported voices.</postcondition>
267 public abstract Error ForEachSupportedVoices(SupportedVoice callback, IntPtr userData);
270 /// Called when the engine service user checks whether the voice is valid or not in TTS engine.
272 /// <param name="language">The language is specified as an ISO 3166 alpha-2 two-letter country code followed by ISO 639-1 for the two-letter language code.
273 /// For example, "ko_KR" for Korean, "en_US" for American English</param>
274 /// <param name="type">The voice type</param>
275 /// <param name="isValid">A variable for checking whether the corresponding voice is valid or not. true to be valid, false to be invalid</param>
277 /// Following Error Codes can be returned
279 /// 2. InvalidParameter
281 public abstract Error IsValidVoice(string language, int type, out bool isValid);
284 /// Called when the engine service user sets the default pitch of TTS engine.
286 /// <param name="pitch">The default pitch</param>
288 /// Following Error Codes can be returned
291 /// 3. OperationFailed
292 /// 4. InvalidParameter
294 public abstract Error SetPitch(int pitch);
297 /// Called when the engine service user requests to load the corresponding voice type for the first time.
299 /// <param name="language">The language is specified as an ISO 3166 alpha-2 two-letter country code followed by ISO 639-1 for the two-letter language code.
300 /// For example, "ko_KR" for Korean, "en_US" for American English</param>
301 /// <param name="type">The voice type</param>
303 /// Following Error Codes can be returned
306 /// 3. OperationFailed
308 /// 5. InvalidParameter
311 public abstract Error LoadVoice(string language, int type);
314 /// Called when the engine service user requests to unload the corresponding voice type or to stop using voice.
316 /// <param name="language">The language is specified as an ISO 3166 alpha-2 two-letter country code followed by ISO 639-1 for the two-letter language code.
317 /// For example, "ko_KR" for Korean, "en_US" for American English</param>
318 /// <param name="type">The voice type</param>
320 /// Following Error Codes can be returned
323 /// 3. OperationFailed
325 /// 5. InvalidParameter
327 public abstract Error UnloadVoice(string language, int type);
330 /// Called when the engine service user requests for TTS engine to check whether the application agreed the usage of TTS engine.
331 /// This callback function is called when the engine service user requests for TTS engine to check the application's agreement about using the engine.
332 /// According to the need, the engine developer can provide some user interfaces to check the agreement.
335 /// If the TTS engine developer wants not to check the agreement, the developer has need to return proper values as isAgreed in accordance with the intention.
336 /// true if the developer regards that every application agreed the usage of the engine, false if the developer regards that every application disagreed.
337 /// NOTE that, however, there may be any legal issue unless the developer checks the agreement.
338 /// Therefore, we suggest that the engine developers should provide a function to check the agreement.
340 /// <param name="appid">The Application ID</param>
341 /// <param name="isAgreed">A variable for checking whether the application agreed to use TTS engine or not. true to agree, false to disagree</param>
343 /// Following Error Codes can be returned
346 /// 3. NotSupportedFeature
347 /// 4. InvalidParameter
349 public abstract Error CheckAppAgreed(string appid, out bool isAgreed);
352 /// Called when the engine service user checks whether TTS engine needs the application's credential.
354 /// <returns> true if TTS engine needs the application's credential, otherwise false </returns>
355 public abstract bool NeedAppCredential();
358 /// Called when the engine service user cancels to synthesize a voice.
361 /// Following Error Codes can be returned
366 /// StartSynthesis should be performed
368 public abstract Error CancelSynthesis();
371 /// Public Constructor
374 /// http://tizen.org/feature/speech.synthesis
382 /// Main function for Text-To-Speech (TTS) engine.
383 /// This function is the main function for operating TTS engine.
386 /// http://tizen.org/feature/speech.synthesis
389 /// ServiceAppMain should be used for working the engine after this function.
391 /// <param name="argc">The argument count(original)</param>
392 /// <param name="argv">The argument(original)</param>
393 /// <exception cref="ArgumentException">Thrown in case of Invalid Parameter</exception>
394 /// <exception cref="NotSupportedException">Thrown in case of Not supported</exception>
395 /// <exception cref="InvalidOperationException">thrown in case of Operation failure</exception>
396 public void EngineMain(int argc, string[] argv)
398 _callbackStructGCHandle.CallbackStruct.version = 1;
399 _callbackStructGCHandle.CallbackStruct.getInfo = _getInfoCb;
400 _callbackStructGCHandle.CallbackStruct.initialize = Initialize;
401 _callbackStructGCHandle.CallbackStruct.deinitialize = _deinitializeCb;
402 _callbackStructGCHandle.CallbackStruct.supportedVoice = ForEachSupportedVoices;
403 _callbackStructGCHandle.CallbackStruct.validVoice = IsValidVoice;
404 _callbackStructGCHandle.CallbackStruct.pitch = SetPitch;
405 _callbackStructGCHandle.CallbackStruct.loadVoice = LoadVoice;
406 _callbackStructGCHandle.CallbackStruct.unloadVoice = UnloadVoice;
407 _callbackStructGCHandle.CallbackStruct.startSynthesis = _startSynthesisCb;
408 _callbackStructGCHandle.CallbackStruct.cancelSynthesis = CancelSynthesis;
409 _callbackStructGCHandle.CallbackStruct.checkAppAgreed = CheckAppAgreed;
410 _callbackStructGCHandle.CallbackStruct.needAppCredential = NeedAppCredential;
411 _structIntPtrHandle = Marshal.AllocHGlobal(Marshal.SizeOf(_callbackStructGCHandle.CallbackStruct));
412 Marshal.StructureToPtr<RequestCallbackStruct>(_callbackStructGCHandle.CallbackStruct, _structIntPtrHandle, false);
413 Error error = TTSEMain(argc, argv, _structIntPtrHandle);
414 if (error != Error.None)
416 Log.Error(LogTag, "TTSEMain Failed with error " + error);
417 throw ExceptionFactory.CreateException((ErrorCode)error);
420 Log.Info(LogTag, "After TTSEMain");
424 /// Gets the speed range from Tizen platform
427 /// http://tizen.org/feature/speech.synthesis
430 /// This API is used when TTS engine wants to get the speed range from Tizen platform
432 /// <param name="min">The minimum speed value</param>
433 /// <param name="normal">The normal speed value</param>
434 /// <param name="max">The maximum speed value</param>
435 /// <exception cref="NotSupportedException">Thrown in case of Not supported</exception>
436 /// <exception cref="InvalidOperationException">thrown in case of Operation failure</exception>
437 public void GetSpeedRange(out int min, out int normal, out int max)
439 Error error = TTSEGetSpeedRange(out min, out normal, out max);
440 if (error != Error.None)
442 Log.Error(LogTag, "TTSEGetSpeedRange Failed with error " + error);
443 throw ExceptionFactory.CreateException((ErrorCode)error);
449 /// Gets the pitch range from Tizen platform.
452 /// http://tizen.org/feature/speech.synthesis
455 /// This API is used when TTS engine wants to get the pitch range from Tizen platform.
457 /// <param name="min">The minimum pitch value</param>
458 /// <param name="normal">The normal pitch value</param>
459 /// <param name="max">The maximum pitch value</param>
460 /// <exception cref="NotSupportedException">Thrown in case of Not supported</exception>
461 /// <exception cref="InvalidOperationException">thrown in case of Operation failure</exception>
462 public void GetPitchRange(out int min, out int normal, out int max)
464 Error error = TTSEGetPitchRange(out min, out normal, out max);
465 if (error != Error.None)
467 Log.Error(LogTag, "TTSEGetPitchRange Failed with error " + error);
468 throw ExceptionFactory.CreateException((ErrorCode)error);
474 /// Sends the synthesized result to the engine service user.
477 /// http://tizen.org/feature/speech.synthesis
480 /// This API is used in StartSynthesis(), when TTS engine sends the synthesized result to the engine service user.
481 /// The synthesized result must be transferred to the engine service user through this function.
483 /// <param name="resultEvent">The result event</param>
484 /// <param name="data">Result data</param>
485 /// <param name="dataSize">Result data size</param>
486 /// <param name="audioType">The audio type</param>
487 /// <param name="rate">The sample rate</param>
488 /// <exception cref="ArgumentException">Thrown in case of Invalid Parameter</exception>
489 /// <exception cref="NotSupportedException">Thrown in case of Not supported</exception>
490 /// <exception cref="InvalidOperationException">thrown in case of Operation failure</exception>
492 /// EngineMain function should be invoked before this function is called. StartSynthesis() will invoke this function.
494 public void SendResult(ResultEvent resultEvent, IntPtr data, int dataSize, AudioType audioType, int rate)
496 Error error = TTSESendResult(resultEvent, data, dataSize, audioType, rate, IntPtr.Zero);
497 if (error != Error.None)
499 Log.Error(LogTag, "TTSESendResult Failed with error " + error);
500 throw ExceptionFactory.CreateException((ErrorCode)error);
505 /// Sends the error to the engine service user.
508 /// http://tizen.org/feature/speech.synthesis
510 /// <param name="error">The error reason</param>
511 /// <param name="msg">The error message</param>
513 /// EngineMain function should be invoked before this function is called.
515 public void SendError(Error error, string msg)
517 Error err = TTSESendError(error, msg);
518 if (err != Error.None)
520 Log.Error(LogTag, "SendError Failed with error " + err);
521 throw ExceptionFactory.CreateException((ErrorCode)error);
527 /// Sets a callback function for setting the private data.
530 /// http://tizen.org/feature/speech.synthesis
532 /// <param name="callback">
533 /// Called when the engine service user gets the private data from Tts engine.
535 /// a = Key -- The key field of private data
536 /// b = data -- The data field of private data
537 /// Following Error Codes can be returned
539 /// 2. InvalidParameter
540 /// 3. OperationFailed
543 /// <exception cref="ArgumentException">Thrown in case of Invalid Parameter</exception>
544 /// <exception cref="UnauthorizedAccessException">Thrown in case of Permission denied</exception>
545 /// <exception cref="NotSupportedException">Thrown in case of Not supported</exception>
546 /// <exception cref="InvalidOperationException">thrown in case of Operation failure</exception>
548 /// Main function should be invoked before this function is called.
550 public void SetPrivateDataSetDelegate(Action<string> callback)
552 _privateDatacallback = callback;
553 _privateDataSetCb = (string key, string data) =>
555 return _privateDatacallback.Invoke(key, data);
557 Error error = TTSESetPrivateDataSetCb(_privateDataSetCb);
558 if (error != Error.None)
560 Log.Error(LogTag, "SetPrivateDataSetDelegate Failed with error " + error);
561 throw ExceptionFactory.CreateException((ErrorCode)error);
567 /// Sets a callback function for setting the private data.
570 /// http://tizen.org/feature/speech.synthesis
572 /// <param name="callback">callback function
573 /// Called when TTS engine receives the private data from the engine service user.
574 /// This callback function is called when the engine service user sends the private data to TTS engine.
576 /// a = Key -- The key field of private data
577 /// b = data -- The data field of private data
578 /// Following Error Codes can be returned
580 /// 2. InvalidParameter
581 /// 3. OperationFailed
584 /// <exception cref="ArgumentException">Thrown in case of Invalid Parameter</exception>
585 /// <exception cref="UnauthorizedAccessException">Thrown in case of Permission denied</exception>
586 /// <exception cref="NotSupportedException">Thrown in case of Not supported</exception>
587 /// <exception cref="InvalidOperationException">thrown in case of Operation failure</exception>
589 /// Main function should be invoked before this function is called.
591 public void SetPrivateDataRequestedDelegate(OutAction<string> callback)
593 _privateDataRequestedCallback = callback;
594 _privateDataRequestedCb = (string key, out string data) =>
596 return _privateDataRequestedCallback.Invoke(key, out data);
598 Error error = TTSESetPrivateDataRequestedCb(_privateDataRequestedCb);
599 if (error != Error.None)
601 Log.Error(LogTag, "SetPrivateDataRequestedDelegate Failed with error " + error);
602 throw ExceptionFactory.CreateException((ErrorCode)error);
606 private StartSynthesisCb _startSynthesisCb = (IntPtr language, int type, IntPtr text, int speed, IntPtr appid, IntPtr credential, IntPtr userData) =>
612 if (language != null)
613 lan = Marshal.PtrToStringAnsi(language);
615 txt = Marshal.PtrToStringAnsi(text);
617 apid = Marshal.PtrToStringAnsi(appid);
618 if (credential != null)
619 cre = Marshal.PtrToStringAnsi(credential);
620 return _engine.StartSynthesis(lan, type, txt, speed, apid, cre, IntPtr.Zero);
623 private GetInfoCb _getInfoCb = (out IntPtr engineUuid, out IntPtr engineName, out IntPtr engineSetting, out int useNetwork) =>
629 Error err = _engine.GetInformation(out uuid, out name, out setting, out network);
638 engineUuid = Marshal.StringToHGlobalAnsi(uuid);
639 engineName = Marshal.StringToHGlobalAnsi(name);
640 engineSetting = Marshal.StringToHGlobalAnsi(setting);
644 private DeinitializeCb _deinitializeCb = () =>
646 Marshal.FreeHGlobal(_engine._structIntPtrHandle);
647 return _engine.Deinitialize();