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 the audio types.
26 /// <since_tizen> 4 </since_tizen>
30 /// Signed 16-bit audio type.
34 /// Unsigned 8-bit audio type.
44 /// Enumeration for the results.
46 /// <since_tizen> 4 </since_tizen>
47 public enum ResultEvent
50 /// Event when the voice synthesis fails.
54 /// Event when the sound data is the first data by the callback function.
58 /// Event when the next sound data exists, not the first and the last.
62 /// Event when the sound data is the last data or the sound data is the only result.
68 /// Enumeration for the voice types.
70 /// <since_tizen> 4 </since_tizen>
78 /// Female voice type.
82 /// Child's voice type.
88 /// Enumeration for the error values that can occur.
90 /// <since_tizen> 4 </since_tizen>
94 /// Successful, no error.
96 None = ErrorCode.None,
100 OutOfMemory = ErrorCode.OutOfMemory,
104 IoError = ErrorCode.IoError,
106 /// Invalid parameter.
108 InvalidParameter = ErrorCode.InvalidParameter,
110 /// Network down (Out of network).
112 NetworkDown = ErrorCode.NetworkDown,
116 InvalidState = ErrorCode.InvalidState,
120 InvalidVoice = ErrorCode.InvalidVoice,
122 /// Operation failed.
124 OperationFailed = ErrorCode.OperationFailed,
126 /// Not supported feature of the current engine.
128 NotSupportedFeature = ErrorCode.NotSupportedFeature,
132 NotSupported = ErrorCode.NotSupported,
134 /// Permission denied.
136 PermissionDenied = ErrorCode.PermissionDenied
140 /// This class represents the TTS engine, which has to be inherited to make the engine.
142 /// <since_tizen> 4 </since_tizen>
143 public abstract class Engine
145 private CallbackStructGCHandle _callbackStructGCHandle = new CallbackStructGCHandle();
146 private PrivateDataSetCb _privateDataSetCb;
147 private Action<string> _privateDatacallback;
148 private PrivateDataRequestedCb _privateDataRequestedCb;
149 private OutAction<string> _privateDataRequestedCallback;
150 private static Engine _engine;
151 private IntPtr _structIntPtrHandle;
154 /// An action with 2 input parameters returning an error.
156 /// <typeparam name="T">Generic type for parameter 1.</typeparam>
157 /// <param name="a">The input parameter 1.</param>
158 /// <param name="b">The input parameter 2.</param>
159 /// <returns>Error value.</returns>
160 /// <since_tizen> 4 </since_tizen>
161 public delegate Error Action<T>(T a, T b);
164 /// An action with 2 out parameters returning an error.
166 /// <typeparam name="T">Generic type for parameter 1.</typeparam>
167 /// <param name="a">The input parameter 1.</param>
168 /// <param name="b">The input parameter 2.</param>
169 /// <returns>Error value.</returns>
170 /// <since_tizen> 4 </since_tizen>
171 public delegate Error OutAction<T>(T a, out T b);
174 /// Called when the TTS engine informs the engine service user about whole supported language and voice type list.
175 /// This callback function is implemented by the engine service user, therefore, the engine developer does NOT have to implement this callback function.
178 /// This callback function is called by ForEachSupportedVoices() to inform the whole supported voice list. userData must be transferred from ForEachSupportedVoices().
180 /// <param name="language">The language is specified as an ISO 3166 alpha-2 two-letter country code followed by an ISO 639-1 for the two-letter language code.
181 /// For example, "ko_KR" for Korean, "en_US" for American English.</param>
182 /// <param name="type">The voice type.</param>
183 /// <param name="userData">The user data passed from ForEachSupportedVoices().</param>
184 /// <returns>true to continue with the next iteration of the loop, false to break out of the loop.</returns>
185 /// <precondition>ForEachSupportedVoices() will invoke this callback function.</precondition>
186 /// <since_tizen> 4 </since_tizen>
187 public delegate bool SupportedVoice(string language, VoiceType type, IntPtr userData);
190 /// Called when the engine service user starts to synthesize a voice, asynchronously.
193 /// In this callback function, the TTS engine must transfer the synthesized result to the engine service user using SendResult().
194 /// Also, if the TTS engine needs the application's credential, it can set the credential granted to the application.
196 /// <param name="language">The language is specified as an ISO 3166 alpha-2 two-letter country code followed by an ISO 639-1 for the two-letter language code.
197 /// For example, "ko_KR" for Korean, "en_US" for American English.</param>
198 /// <param name="type">The voice type.</param>
199 /// <param name="text">Texts.</param>
200 /// <param name="speed">The speed of speaking.</param>
201 /// <param name="appid">The application ID.</param>
202 /// <param name="credential">The credential granted to the application.</param>
203 /// <param name="userData">The user data which must be passed to the SendResult() function.</param>
205 /// The following error codes can be returned:
208 /// 3. InvalidParameter
210 /// 5. OperationFailed
212 /// 7. PermissionDenied
214 /// <postcondition>This function invokes SendResult().</postcondition>
215 /// <since_tizen> 4 </since_tizen>
216 public abstract Error StartSynthesis(string language, int type, string text, int speed, string appid, string credential, IntPtr userData);
219 /// Called when the engine service user requests the basic information of the TTS engine.
222 /// The allocated engineUuid, engineName, and engineSetting will be released internally.
223 /// In order to upload the engine at Tizen Appstore, both a service application and a UI application are necessary.
224 /// Therefore, engineSetting must be transferred to the engine service user.
226 /// <param name="engineUuid">UUID of the engine.</param>
227 /// <param name="engineName">Name of the engine.</param>
228 /// <param name="engineSetting">The engine setting application (UI application)'s ID.</param>
229 /// <param name="useNetwork">The status for using the network.</param>
231 /// The following error codes can be returned:
235 /// <since_tizen> 4 </since_tizen>
236 public abstract Error GetInformation(out string engineUuid, out string engineName, out string engineSetting, out bool useNetwork);
239 /// Called when the engine service user initializes the TTS engine.
242 /// The following error codes can be returned:
245 /// 3. NotSupportedFeature
246 /// 4. PermissionDenied
248 /// <since_tizen> 4 </since_tizen>
249 public abstract Error Initialize();
252 /// Called when the engine service user deinitializes the TTS engine.
255 /// NOTE that the engine may be terminated automatically. When this callback function is invoked, the release of the resources is necessary.
258 /// The following error codes can be returned:
262 /// <since_tizen> 4 </since_tizen>
263 public abstract Error Deinitialize();
266 /// Called when the engine service user gets the whole supported voice list.
269 /// In this function, the engine service user's callback function 'SupportedVoice()' is invoked repeatedly for getting all the supported voices,
270 /// and userData must be transferred to 'SupportedVoice()'. If 'SupportedVoice()' returns false, it should be stopped to call 'SupportedVoice()'.</remarks>
271 /// <param name="callback">The callback function.</param>
272 /// <param name="userData">The user data which must be passed to SupportedVoice().</param>
274 /// The following error codes can be returned:
276 /// 2. OperationFailed
278 /// <postcondition>This callback function invokes SupportedVoice() repeatedly for getting all the supported voices.</postcondition>
279 /// <since_tizen> 4 </since_tizen>
280 public abstract Error ForEachSupportedVoices(SupportedVoice callback, IntPtr userData);
283 /// Called when the engine service user checks whether the voice is valid or not in the TTS engine.
285 /// <param name="language">The language is specified as an ISO 3166 alpha-2 two-letter country code followed by an ISO 639-1 for the two-letter language code.
286 /// For example, "ko_KR" for Korean, "en_US" for American English.</param>
287 /// <param name="type">The voice type.</param>
288 /// <param name="isValid">A variable for checking whether the corresponding voice is valid or not. true to be valid, false to be invalid.</param>
290 /// The following error codes can be returned:
292 /// 2. InvalidParameter
294 /// <since_tizen> 4 </since_tizen>
295 public abstract Error IsValidVoice(string language, int type, out bool isValid);
298 /// Called when the engine service user sets the default pitch of the TTS engine.
300 /// <param name="pitch">The default pitch.</param>
302 /// The following error codes can be returned:
305 /// 3. OperationFailed
306 /// 4. InvalidParameter
308 /// <since_tizen> 4 </since_tizen>
309 public abstract Error SetPitch(int pitch);
312 /// Called when the engine service user requests to load the corresponding voice type for the first time.
314 /// <param name="language">The language is specified as an ISO 3166 alpha-2 two-letter country code followed by an ISO 639-1 for the two-letter language code.
315 /// For example, "ko_KR" for Korean, "en_US" for American English.</param>
316 /// <param name="type">The voice type.</param>
318 /// The following error codes can be returned:
321 /// 3. OperationFailed
323 /// 5. InvalidParameter
326 /// <since_tizen> 4 </since_tizen>
327 public abstract Error LoadVoice(string language, int type);
330 /// Called when the engine service user requests to unload the corresponding voice type or to stop using voice.
332 /// <param name="language">The language is specified as an ISO 3166 alpha-2 two-letter country code followed by an ISO 639-1 for the two-letter language code.
333 /// For example, "ko_KR" for Korean, "en_US" for American English.</param>
334 /// <param name="type">The voice type.</param>
336 /// The following error codes can be returned:
339 /// 3. OperationFailed
341 /// 5. InvalidParameter
343 /// <since_tizen> 4 </since_tizen>
344 public abstract Error UnloadVoice(string language, int type);
347 /// Called when the engine service user requests for the TTS engine to check whether the application agreed the usage of the TTS engine.
348 /// This callback function is called when the engine service user requests for the TTS engine to check the application's agreement about using the the engine.
349 /// According to the need, the engine developer can provide some user interfaces to check the agreement.
352 /// If the TTS engine developer does not want to check the agreement, the developer needs to return proper values as isAgreed in accordance with the intention.
353 /// true if the developer regards that every application agreed the usage of the engine, false if the developer regards that every application disagreed.
354 /// NOTE that, however, there may be any legal issue unless the developer checks the agreement.
355 /// Therefore, we suggest that the engine developers should provide a function to check the agreement.
357 /// <param name="appid">The application ID.</param>
358 /// <param name="isAgreed">A variable for checking whether the application agreed to use the TTS engine or not. true to agree, false to disagree.</param>
360 /// The following error codes can be returned:
363 /// 3. NotSupportedFeature
364 /// 4. InvalidParameter
366 /// <since_tizen> 4 </since_tizen>
367 public abstract Error CheckAppAgreed(string appid, out bool isAgreed);
370 /// Called when the engine service user checks whether the TTS engine needs the application's credentials.
372 /// <returns>true if TTS engine needs the application's credentials, otherwise false. </returns>
373 /// <since_tizen> 4 </since_tizen>
374 public abstract bool NeedAppCredential();
377 /// Called when the engine service user cancels to synthesize a voice.
380 /// The following error codes can be returned:
385 /// StartSynthesis should be performed.
387 /// <since_tizen> 4 </since_tizen>
388 public abstract Error CancelSynthesis();
391 /// Public constructor.
394 /// http://tizen.org/feature/speech.synthesis
396 /// <since_tizen> 4 </since_tizen>
403 /// Main function for the Text-To-Speech (TTS) engine.
404 /// This function is the main function for operating the TTS engine.
407 /// http://tizen.org/feature/speech.synthesis
410 /// ServiceAppMain should be used for working the engine after this function.
412 /// <param name="argc">The argument count (original).</param>
413 /// <param name="argv">The argument (original).</param>
414 /// <exception cref="NotSupportedException">Thrown in case of not supported.</exception>
415 /// <exception cref="InvalidOperationException">Thrown in case of operation failure.</exception>
416 /// <since_tizen> 4 </since_tizen>
417 public void EngineMain(int argc, string[] argv)
419 _callbackStructGCHandle.CallbackStruct.version = 1;
420 _callbackStructGCHandle.CallbackStruct.getInfo = _getInfoCb;
421 _callbackStructGCHandle.CallbackStruct.initialize = Initialize;
422 _callbackStructGCHandle.CallbackStruct.deinitialize = _deinitializeCb;
423 _callbackStructGCHandle.CallbackStruct.supportedVoice = ForEachSupportedVoices;
424 _callbackStructGCHandle.CallbackStruct.validVoice = IsValidVoice;
425 _callbackStructGCHandle.CallbackStruct.pitch = SetPitch;
426 _callbackStructGCHandle.CallbackStruct.loadVoice = LoadVoice;
427 _callbackStructGCHandle.CallbackStruct.unloadVoice = UnloadVoice;
428 _callbackStructGCHandle.CallbackStruct.startSynthesis = _startSynthesisCb;
429 _callbackStructGCHandle.CallbackStruct.cancelSynthesis = CancelSynthesis;
430 _callbackStructGCHandle.CallbackStruct.checkAppAgreed = CheckAppAgreed;
431 _callbackStructGCHandle.CallbackStruct.needAppCredential = NeedAppCredential;
432 _structIntPtrHandle = Marshal.AllocHGlobal(Marshal.SizeOf(_callbackStructGCHandle.CallbackStruct));
433 Marshal.StructureToPtr<RequestCallbackStruct>(_callbackStructGCHandle.CallbackStruct, _structIntPtrHandle, false);
434 Error error = TTSEMain(argc, argv, _structIntPtrHandle);
435 if (error != Error.None)
437 Log.Error(LogTag, "TTSEMain Failed with error " + error);
438 throw ExceptionFactory.CreateException((ErrorCode)error);
441 Log.Info(LogTag, "After TTSEMain");
445 /// Gets the speed range from the Tizen platform.
448 /// http://tizen.org/feature/speech.synthesis
451 /// This API is used when the TTS engine wants to get the speed range from the Tizen platform.
453 /// <param name="min">The minimum speed value.</param>
454 /// <param name="normal">The normal speed value.</param>
455 /// <param name="max">The maximum speed value.</param>
456 /// <exception cref="NotSupportedException">Thrown in case of not supported.</exception>
457 /// <exception cref="InvalidOperationException">Thrown in case of operation failure.</exception>
458 /// <since_tizen> 4 </since_tizen>
459 public void GetSpeedRange(out int min, out int normal, out int max)
461 Error error = TTSEGetSpeedRange(out min, out normal, out max);
462 if (error != Error.None)
464 Log.Error(LogTag, "TTSEGetSpeedRange Failed with error " + error);
465 throw ExceptionFactory.CreateException((ErrorCode)error);
471 /// Gets the pitch range from the Tizen platform.
474 /// http://tizen.org/feature/speech.synthesis
477 /// This API is used when the TTS engine wants to get the pitch range from the Tizen platform.
479 /// <param name="min">The minimum pitch value.</param>
480 /// <param name="normal">The normal pitch value.</param>
481 /// <param name="max">The maximum pitch value.</param>
482 /// <exception cref="NotSupportedException">Thrown in case of not supported.</exception>
483 /// <exception cref="InvalidOperationException">Thrown in case of operation failure.</exception>
484 /// <since_tizen> 4 </since_tizen>
485 public void GetPitchRange(out int min, out int normal, out int max)
487 Error error = TTSEGetPitchRange(out min, out normal, out max);
488 if (error != Error.None)
490 Log.Error(LogTag, "TTSEGetPitchRange Failed with error " + error);
491 throw ExceptionFactory.CreateException((ErrorCode)error);
497 /// Sends the synthesized result to the engine service user.
500 /// http://tizen.org/feature/speech.synthesis
503 /// This API is used in StartSynthesis(), when the TTS engine sends the synthesized result to the engine service user.
504 /// The synthesized result must be transferred to the engine service user through this function.
506 /// <param name="resultEvent">The result event.</param>
507 /// <param name="data">The result data.</param>
508 /// <param name="dataSize">The result data size.</param>
509 /// <param name="audioType">The audio type.</param>
510 /// <param name="rate">The sample rate.</param>
511 /// <exception cref="ArgumentException">Thrown in case of an invalid parameter.</exception>
512 /// <exception cref="NotSupportedException">Thrown in case of not supported.</exception>
513 /// <exception cref="InvalidOperationException">Thrown in case of operation failure.</exception>
515 /// EngineMain function should be invoked before this function is called. StartSynthesis() will invoke this function.
517 /// <since_tizen> 4 </since_tizen>
518 public void SendResult(ResultEvent resultEvent, IntPtr data, int dataSize, AudioType audioType, int rate)
520 Error error = TTSESendResult(resultEvent, data, dataSize, audioType, rate, IntPtr.Zero);
521 if (error != Error.None)
523 Log.Error(LogTag, "TTSESendResult Failed with error " + error);
524 throw ExceptionFactory.CreateException((ErrorCode)error);
529 /// Sends the error to the engine service user.
532 /// http://tizen.org/feature/speech.synthesis
534 /// <param name="error">The error reason.</param>
535 /// <param name="msg">The error message.</param>
536 /// <exception cref="NotSupportedException">Thrown in case of not supported.</exception>
537 /// <exception cref="InvalidOperationException">Thrown in case of operation failure.</exception>
539 /// EngineMain function should be invoked before this function is called.
541 /// <since_tizen> 4 </since_tizen>
542 public void SendError(Error error, string msg)
544 Error err = TTSESendError(error, msg);
545 if (err != Error.None)
547 Log.Error(LogTag, "SendError Failed with error " + err);
548 throw ExceptionFactory.CreateException((ErrorCode)error);
554 /// Sets a callback function for setting the private data.
557 /// http://tizen.org/feature/speech.synthesis
559 /// <param name="callback">
560 /// Called when the engine service user gets the private data from the TTS engine.
562 /// a = Key -- The key field of private data.
563 /// b = data -- The data field of private data.
564 /// The following error codes can be returned:
566 /// 2. InvalidParameter
567 /// 3. OperationFailed
570 /// <exception cref="ArgumentException">Thrown in case of an invalid parameter.</exception>
571 /// <exception cref="NotSupportedException">Thrown in case of not supported.</exception>
572 /// <exception cref="InvalidOperationException">thrown in case of operation failure.</exception>
574 /// Main function should be invoked before this function is called.
576 /// <since_tizen> 4 </since_tizen>
577 public void SetPrivateDataSetDelegate(Action<string> callback)
579 if (null == callback)
581 Log.Error(LogTag, "callback is null");
582 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
585 _privateDatacallback = callback;
586 _privateDataSetCb = (string key, string data) =>
588 return _privateDatacallback.Invoke(key, data);
590 Error error = TTSESetPrivateDataSetCb(_privateDataSetCb);
591 if (error != Error.None)
593 Log.Error(LogTag, "SetPrivateDataSetDelegate Failed with error " + error);
594 throw ExceptionFactory.CreateException((ErrorCode)error);
600 /// Sets a callback function for setting the private data.
603 /// http://tizen.org/feature/speech.synthesis
605 /// <param name="callback">The callback function.
606 /// Called when the TTS engine receives the private data from the engine service user.
607 /// This callback function is called when the engine service user sends the private data to the TTS engine.
609 /// a = Key -- The key field of private data.
610 /// b = data -- The data field of private data.
611 /// The following error codes can be returned:
613 /// 2. InvalidParameter
614 /// 3. OperationFailed
617 /// <exception cref="ArgumentException">Thrown in case of an invalid parameter.</exception>
618 /// <exception cref="NotSupportedException">Thrown in case of not supported.</exception>
619 /// <exception cref="InvalidOperationException">thrown in case of operation failure.</exception>
621 /// Main function should be invoked before this function is called.
623 /// <since_tizen> 4 </since_tizen>
624 public void SetPrivateDataRequestedDelegate(OutAction<string> callback)
626 if (null == callback)
628 Log.Error(LogTag, "callback is null");
629 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
632 _privateDataRequestedCallback = callback;
633 _privateDataRequestedCb = (string key, out string data) =>
635 return _privateDataRequestedCallback.Invoke(key, out data);
637 Error error = TTSESetPrivateDataRequestedCb(_privateDataRequestedCb);
638 if (error != Error.None)
640 Log.Error(LogTag, "SetPrivateDataRequestedDelegate Failed with error " + error);
641 throw ExceptionFactory.CreateException((ErrorCode)error);
645 private StartSynthesisCb _startSynthesisCb = (IntPtr language, int type, IntPtr text, int speed, IntPtr appid, IntPtr credential, IntPtr userData) =>
651 if (language != null)
652 lan = Marshal.PtrToStringAnsi(language);
654 txt = Marshal.PtrToStringAnsi(text);
656 apid = Marshal.PtrToStringAnsi(appid);
657 if (credential != null)
658 cre = Marshal.PtrToStringAnsi(credential);
659 return _engine.StartSynthesis(lan, type, txt, speed, apid, cre, IntPtr.Zero);
662 private GetInfoCb _getInfoCb = (out IntPtr engineUuid, out IntPtr engineName, out IntPtr engineSetting, out int useNetwork) =>
668 Error err = _engine.GetInformation(out uuid, out name, out setting, out network);
677 engineUuid = Marshal.StringToHGlobalAnsi(uuid);
678 engineName = Marshal.StringToHGlobalAnsi(name);
679 engineSetting = Marshal.StringToHGlobalAnsi(setting);
683 private DeinitializeCb _deinitializeCb = () =>
685 Marshal.FreeHGlobal(_engine._structIntPtrHandle);
686 return _engine.Deinitialize();