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
379 /// Main function for Text-To-Speech (TTS) engine.
380 /// This function is the main function for operating TTS engine.
383 /// ServiceAppMain should be used for working the engine after this function.
385 /// <param name="argc">The argument count(original)</param>
386 /// <param name="argv">The argument(original)</param>
387 /// <exception cref="ArgumentException">Thrown in case of Invalid Parameter</exception>
388 /// <exception cref="NotSupportedException">Thrown in case of Not supported</exception>
389 /// <exception cref="InvalidOperationException">thrown in case of Operation failure</exception>
390 public void EngineMain(int argc, string[] argv)
392 _callbackStructGCHandle.CallbackStruct.version = 1;
393 _callbackStructGCHandle.CallbackStruct.getInfo = _getInfoCb;
394 _callbackStructGCHandle.CallbackStruct.initialize = Initialize;
395 _callbackStructGCHandle.CallbackStruct.deinitialize = _deinitializeCb;
396 _callbackStructGCHandle.CallbackStruct.supportedVoice = ForEachSupportedVoices;
397 _callbackStructGCHandle.CallbackStruct.validVoice = IsValidVoice;
398 _callbackStructGCHandle.CallbackStruct.pitch = SetPitch;
399 _callbackStructGCHandle.CallbackStruct.loadVoice = LoadVoice;
400 _callbackStructGCHandle.CallbackStruct.unloadVoice = UnloadVoice;
401 _callbackStructGCHandle.CallbackStruct.startSynthesis = _startSynthesisCb;
402 _callbackStructGCHandle.CallbackStruct.cancelSynthesis = CancelSynthesis;
403 _callbackStructGCHandle.CallbackStruct.checkAppAgreed = CheckAppAgreed;
404 _callbackStructGCHandle.CallbackStruct.needAppCredential = NeedAppCredential;
405 _structIntPtrHandle = Marshal.AllocHGlobal(Marshal.SizeOf(_callbackStructGCHandle.CallbackStruct));
406 Marshal.StructureToPtr<RequestCallbackStruct>(_callbackStructGCHandle.CallbackStruct, _structIntPtrHandle, false);
407 Error error = TTSEMain(argc, argv, _structIntPtrHandle);
408 if (error != Error.None)
410 Log.Error(LogTag, "TTSEMain Failed with error " + error);
411 throw ExceptionFactory.CreateException((ErrorCode)error);
414 Log.Info(LogTag, "After TTSEMain");
418 /// Gets the speed range from Tizen platform
421 /// This API is used when TTS engine wants to get the speed range from Tizen platform
423 /// <param name="min">The minimum speed value</param>
424 /// <param name="normal">The normal speed value</param>
425 /// <param name="max">The maximum speed value</param>
426 /// <exception cref="NotSupportedException">Thrown in case of Not supported</exception>
427 /// <exception cref="InvalidOperationException">thrown in case of Operation failure</exception>
428 public void GetSpeedRange(out int min, out int normal, out int max)
430 Error error = TTSEGetSpeedRange(out min, out normal, out max);
431 if (error != Error.None)
433 Log.Error(LogTag, "TTSEGetSpeedRange Failed with error " + error);
434 throw ExceptionFactory.CreateException((ErrorCode)error);
440 /// Gets the pitch range from Tizen platform.
443 /// This API is used when TTS engine wants to get the pitch range from Tizen platform.
445 /// <param name="min">The minimum pitch value</param>
446 /// <param name="normal">The normal pitch value</param>
447 /// <param name="max">The maximum pitch value</param>
448 /// <exception cref="NotSupportedException">Thrown in case of Not supported</exception>
449 /// <exception cref="InvalidOperationException">thrown in case of Operation failure</exception>
450 public void GetPitchRange(out int min, out int normal, out int max)
452 Error error = TTSEGetPitchRange(out min, out normal, out max);
453 if (error != Error.None)
455 Log.Error(LogTag, "TTSEGetPitchRange Failed with error " + error);
456 throw ExceptionFactory.CreateException((ErrorCode)error);
462 /// Sends the synthesized result to the engine service user.
465 /// This API is used in StartSynthesis(), when TTS engine sends the synthesized result to the engine service user.
466 /// The synthesized result must be transferred to the engine service user through this function.
468 /// <param name="resultEvent">The result event</param>
469 /// <param name="data">Result data</param>
470 /// <param name="dataSize">Result data size</param>
471 /// <param name="audioType">The audio type</param>
472 /// <param name="rate">The sample rate</param>
473 /// <exception cref="ArgumentException">Thrown in case of Invalid Parameter</exception>
474 /// <exception cref="NotSupportedException">Thrown in case of Not supported</exception>
475 /// <exception cref="InvalidOperationException">thrown in case of Operation failure</exception>
477 /// EngineMain function should be invoked before this function is called. StartSynthesis() will invoke this function.
479 public void SendResult(ResultEvent resultEvent, IntPtr data, int dataSize, AudioType audioType, int rate)
481 Error error = TTSESendResult(resultEvent, data, dataSize, audioType, rate, IntPtr.Zero);
482 if (error != Error.None)
484 Log.Error(LogTag, "TTSESendResult Failed with error " + error);
485 throw ExceptionFactory.CreateException((ErrorCode)error);
490 /// Sends the error to the engine service user.
492 /// <param name="error">The error reason</param>
493 /// <param name="msg">The error message</param>
495 /// EngineMain function should be invoked before this function is called.
497 public void SendError(Error error, string msg)
499 Error err = TTSESendError(error, msg);
500 if (err != Error.None)
502 Log.Error(LogTag, "SendError Failed with error " + err);
503 throw ExceptionFactory.CreateException((ErrorCode)error);
509 /// Sets a callback function for setting the private data.
511 /// <param name="callback">
512 /// Called when the engine service user gets the private data from Tts engine.
514 /// a = Key -- The key field of private data
515 /// b = data -- The data field of private data
516 /// Following Error Codes can be returned
518 /// 2. InvalidParameter
519 /// 3. OperationFailed
522 /// <exception cref="ArgumentException">Thrown in case of Invalid Parameter</exception>
523 /// <exception cref="UnauthorizedAccessException">Thrown in case of Permission denied</exception>
524 /// <exception cref="NotSupportedException">Thrown in case of Not supported</exception>
525 /// <exception cref="InvalidOperationException">thrown in case of Operation failure</exception>
527 /// Main function should be invoked before this function is called.
529 public void SetPrivateDataSetDelegate(Action<string> callback)
531 _privateDatacallback = callback;
532 _privateDataSetCb = (string key, string data) =>
534 return _privateDatacallback.Invoke(key, data);
536 Error error = TTSESetPrivateDataSetCb(_privateDataSetCb);
537 if (error != Error.None)
539 Log.Error(LogTag, "SetPrivateDataSetDelegate Failed with error " + error);
540 throw ExceptionFactory.CreateException((ErrorCode)error);
546 /// Sets a callback function for setting the private data.
548 /// <param name="callback">callback function
549 /// Called when TTS engine receives the private data from the engine service user.
550 /// This callback function is called when the engine service user sends the private data to TTS engine.
552 /// a = Key -- The key field of private data
553 /// b = data -- The data field of private data
554 /// Following Error Codes can be returned
556 /// 2. InvalidParameter
557 /// 3. OperationFailed
560 /// <exception cref="ArgumentException">Thrown in case of Invalid Parameter</exception>
561 /// <exception cref="UnauthorizedAccessException">Thrown in case of Permission denied</exception>
562 /// <exception cref="NotSupportedException">Thrown in case of Not supported</exception>
563 /// <exception cref="InvalidOperationException">thrown in case of Operation failure</exception>
565 /// Main function should be invoked before this function is called.
567 public void SetPrivateDataRequestedDelegate(OutAction<string> callback)
569 _privateDataRequestedCallback = callback;
570 _privateDataRequestedCb = (string key, out string data) =>
572 return _privateDataRequestedCallback.Invoke(key, out data);
574 Error error = TTSESetPrivateDataRequestedCb(_privateDataRequestedCb);
575 if (error != Error.None)
577 Log.Error(LogTag, "SetPrivateDataRequestedDelegate Failed with error " + error);
578 throw ExceptionFactory.CreateException((ErrorCode)error);
582 private StartSynthesisCb _startSynthesisCb = (IntPtr language, int type, IntPtr text, int speed, IntPtr appid, IntPtr credential, IntPtr userData) =>
588 if (language != null)
589 lan = Marshal.PtrToStringAnsi(language);
591 txt = Marshal.PtrToStringAnsi(text);
593 apid = Marshal.PtrToStringAnsi(appid);
594 if (credential != null)
595 cre = Marshal.PtrToStringAnsi(credential);
596 return _engine.StartSynthesis(lan, type, txt, speed, apid, cre, IntPtr.Zero);
599 private GetInfoCb _getInfoCb = (out IntPtr engineUuid, out IntPtr engineName, out IntPtr engineSetting, out int useNetwork) =>
605 Error err = _engine.GetInformation(out uuid, out name, out setting, out network);
614 engineUuid = Marshal.StringToHGlobalAnsi(uuid);
615 engineName = Marshal.StringToHGlobalAnsi(name);
616 engineSetting = Marshal.StringToHGlobalAnsi(setting);
620 private DeinitializeCb _deinitializeCb = () =>
622 Marshal.FreeHGlobal(_engine._structIntPtrHandle);
623 return _engine.Deinitialize();