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.Collections.Generic;
19 using System.Runtime.InteropServices;
20 using static Interop.VoiceControl;
21 using static Interop.VoiceControlCommand;
23 namespace Tizen.Uix.VoiceControl
26 /// Enum for Error values that can occur
28 /// <since_tizen> 3 </since_tizen>
32 /// Successful, No error
48 /// No answer from the STT service
52 /// Device or resource busy
72 /// No available engine
80 /// Operation Rejected
96 /// Progress to ready is not finished
100 /// Progress to recording is not finished
102 InProgressToRecording,
104 /// Progress to processing is not finished
106 InProgressToProcessing
110 /// Enumeration for the client state.
112 /// <since_tizen> 3 </since_tizen>
120 /// 'Initialized' state
128 /// state cannot be determined
134 /// Enumerations of service state.
136 /// <since_tizen> 3 </since_tizen>
137 public enum ServiceState
148 /// 'Recording' state
152 /// 'Processing' state
156 /// state cannot be determined
162 /// Enumerations of result event.
164 /// <since_tizen> 3 </since_tizen>
165 public enum ResultEvent
178 /// Enumerations of command type.
180 /// <since_tizen> 3 </since_tizen>
181 public enum CommandType
184 /// Foreground command by client
188 /// Background command by client
192 /// Undefined command
198 /// A main function of Voice Control API register command and gets notification for recognition result.
199 /// Applications can add their own commands and be provided result when their command is recognized by user voice input.
201 /// <since_tizen> 3 </since_tizen>
202 public static class VoiceControlClient
205 /// Called when client gets the recognition result.
207 /// <since_tizen> 3 </since_tizen>
209 /// If the duplicated commands are recognized, the event(e.g. Result.Rejected) of command may be rejected
210 /// for selecting command as priority.If you set similar or same commands or the recognized results are multi-results, cmdList has the multi commands.
212 /// <param name="evt">The ResultEvent</param>
213 /// <param name="cmdList">Command List</param>
214 /// <param name="result">Result</param>
216 private static event EventHandler<RecognitionResultEventArgs> _recognitionResult;
217 private static event EventHandler<StateChangedEventArgs> _stateChanged;
218 private static event EventHandler<ServiceStateChangedEventArgs> _serviceStateChanged;
219 private static event EventHandler<ErrorOccuredEventArgs> _errorOccured;
220 private static event EventHandler<CurrentLanguageChangedEventArgs> _currentLanguageChanged;
221 private static VcResultCb s_resultDelegate;
222 private static VcStateChangedCb s_stateDelegate;
223 private static VcServiceStateChangedCb s_serviceStateDelegate;
224 private static VcErrorCb s_errorDelegate;
225 private static VcCurrentLanguageChangedCb s_languageDelegate;
226 private static List<string> s_supportedLanguages;
227 private static VcSupportedLanguageCb s_supportedLanguagesCb;
228 private static VcResultCb s_resultCb;
229 private static RecognitionResult s_recognitionResult;
232 /// Gets current language.
233 /// A language is specified as an ISO 3166 alpha-2 two letter country-code
234 /// followed by ISO 639-1 for the two-letter language code.
235 /// For example, "ko_KR" for Korean, "en_US" for American English.
236 /// Empty string is returned incase of some internal error
238 /// <since_tizen> 3 </since_tizen>
240 /// Current language in voice control.
243 /// http://tizen.org/privilege/recorder
246 /// The State must be Initialized or Ready.
248 public static string CurrentLanguage
252 string currentLanguage;
254 ErrorCode error = VcGetCurrentLanguage(out currentLanguage);
255 if (error != ErrorCode.None)
257 Log.Error(LogTag, "CurrentLanguage Failed with error " + error);
261 return currentLanguage;
266 /// Gets current state of voice control client.
268 /// <since_tizen> 3 </since_tizen>
270 /// Current state of voice control client.
273 /// http://tizen.org/privilege/recorder
276 /// The State must be Initialized or Ready.
278 public static State State
284 ErrorCode error = VcGetState(out state);
285 if (error != ErrorCode.None)
287 Log.Error(LogTag, "State Failed with error " + error);
288 return State.Unavailable;
296 /// Gets current state of voice control service.
298 /// <since_tizen> 3 </since_tizen>
300 /// Current state of voice control service.
303 /// http://tizen.org/privilege/recorder
306 /// The State must be Ready.
308 public static ServiceState ServiceState
314 ErrorCode error = VcGetServiceState(out state);
315 if (error != ErrorCode.None)
317 Log.Error(LogTag, "ServiceState Failed with error " + error);
318 return ServiceState.Unavailable;
326 /// Sets the invocation name.
328 /// <since_tizen> 3 </since_tizen>
330 /// http://tizen.org/privilege/recorder
336 /// http://tizen.org/feature/speech.control
337 /// http://tizen.org/feature/microphone
340 /// Invocation name is used to activate background commands. The invocation name can be the same as the application name or any other phrase.
341 /// For example, an application "Tizen Sample" has a background command, "Play music", and the invocation name of the application is set to "Tizen Sample".
342 /// In order to activate the background command, users can say "Tizen Sample, Play music". The invocation name is dependent on the current language.
343 /// For example, if the current language is "en_US"(English), the invocation name is also "en_US".
344 /// If the current language is "ja_JP"(Japanese) and the invocation name is "en_US", the invocation name will not be recognized.
345 /// This function should be called before SetCommandList().
347 /// <param name="name">Invocation name that an application wants to be invoked by</param>
348 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
349 /// <exception cref="ArgumentException"> This Exception can be due to Invalid Parameter. </exception>
350 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
351 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
353 /// The State must be Ready.
355 public static void SetInvocationName(string name)
357 ErrorCode error = VcSetInvocationName(name);
358 if (error != ErrorCode.None)
360 Log.Error(LogTag, "SetInvocationName Failed with error " + error);
361 throw ExceptionFactory.CreateException(error);
366 /// Initializes voice control.
368 /// <since_tizen> 3 </since_tizen>
370 /// http://tizen.org/privilege/recorder
376 /// http://tizen.org/feature/speech.control
377 /// http://tizen.org/feature/microphone
379 /// <exception cref="InvalidOperationException"> This Exception can be due to Operation Failed. </exception>
380 /// <exception cref="OutOfMemoryException"> This Exception can be due to Out Of Memory. </exception>
381 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
382 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
384 /// The State will be Initialized.
386 public static void Initialize()
388 ErrorCode error = VcInitialize();
389 if (error != ErrorCode.None)
391 Log.Error(LogTag, "Initialize Failed with error " + error);
392 throw ExceptionFactory.CreateException(error);
397 /// Deinitializes voice control.
399 /// <since_tizen> 3 </since_tizen>
401 /// http://tizen.org/privilege/recorder
407 /// http://tizen.org/feature/speech.control
408 /// http://tizen.org/feature/microphone
410 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
411 /// <exception cref="InvalidOperationException"> This Exception can be due to Operation Failed. </exception>
412 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
413 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
414 public static void Deinitialize()
416 ErrorCode error = VcDeinitialize();
417 if (error != ErrorCode.None)
419 Log.Error(LogTag, "Deinitialize Failed with error " + error);
420 throw ExceptionFactory.CreateException(error);
425 /// Connects the voice control service.
427 /// <since_tizen> 3 </since_tizen>
429 /// http://tizen.org/privilege/recorder
435 /// http://tizen.org/feature/speech.control
436 /// http://tizen.org/feature/microphone
438 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
439 /// <exception cref="InvalidOperationException"> This Exception can be due to Operation Failed. </exception>
440 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
441 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
443 /// The State should be Initialized
446 /// The State will be Ready
448 public static void Prepare()
450 ErrorCode error = VcPrepare();
451 if (error != ErrorCode.None)
453 Log.Error(LogTag, "Prepare Failed with error " + error);
454 throw ExceptionFactory.CreateException(error);
459 /// Disconnects the voice control service.
461 /// <since_tizen> 3 </since_tizen>
463 /// http://tizen.org/privilege/recorder
469 /// http://tizen.org/feature/speech.control
470 /// http://tizen.org/feature/microphone
472 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
473 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
474 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
476 /// The State should be Ready
479 /// The State should be Initialized
481 public static void Unprepare()
483 ErrorCode error = VcUnprepare();
484 if (error != ErrorCode.None)
486 Log.Error(LogTag, "Unprepare Failed with error " + error);
487 throw ExceptionFactory.CreateException(error);
492 /// Retrieves all supported languages.
493 /// A language is specified as an ISO 3166 alpha-2 two letter country-code
494 /// followed by ISO 639-1 for the two-letter language code.
495 /// For example, "ko_KR" for Korean, "en_US" for American English.
497 /// <since_tizen> 3 </since_tizen>
499 /// http://tizen.org/privilege/recorder
505 /// http://tizen.org/feature/speech.control
506 /// http://tizen.org/feature/microphone
508 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
509 /// <exception cref="InvalidOperationException"> This Exception can be due to Operation Failed. </exception>
510 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
511 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
513 /// The State should be Ready or Initialized
515 public static IEnumerable<string> GetSupportedLanguages()
517 s_supportedLanguages = new List<string>();
518 s_supportedLanguagesCb = (IntPtr language, IntPtr userData) =>
520 string languageStr = Marshal.PtrToStringAnsi(language);
521 s_supportedLanguages.Add(languageStr);
524 ErrorCode error = VcForeachSupportedLanguages(s_supportedLanguagesCb, IntPtr.Zero);
525 if (error != ErrorCode.None)
527 Log.Error(LogTag, "GetSupportedLanguages Failed with error " + error);
528 throw ExceptionFactory.CreateException(error);
531 return s_supportedLanguages;
535 /// Gets the system command list.
537 /// <since_tizen> 3 </since_tizen>
539 /// The Command List else null in case of no System Commands
542 /// http://tizen.org/privilege/recorder
548 /// http://tizen.org/feature/speech.control
549 /// http://tizen.org/feature/microphone
552 /// In the system command list, there are system commands predefined by product manufacturers.
553 /// Those commands have the highest priority. Therefore, the user can not set any commands same with the system commands.
555 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
556 /// <exception cref="InvalidOperationException"> This Exception can be due to Operation Failed. </exception>
557 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
558 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
560 /// The State should be Ready
562 public static VoiceCommandList GetSystemCommandList()
564 IntPtr handle = IntPtr.Zero;
565 ErrorCode error = VcGetSystemCommandList(out handle);
566 if (error != ErrorCode.None)
568 Log.Error(LogTag, "GetSystemCommandList Failed with error " + error);
569 throw ExceptionFactory.CreateException(error);
572 if (handle == IntPtr.Zero)
574 Log.Error(LogTag, "GetSystemCommandList handle is null");
578 SafeCommandListHandle list = new SafeCommandListHandle(handle);
579 return new VoiceCommandList(list);
583 /// Requests to start the dialogue.
584 /// Using this function, the developer can request starting the dialogue to the framework.
585 /// When the developer requests the dialogue, two types of texts, dispText and uttText, can be sent by this function.dispText is a text for displaying, and uttText is that for uttering.
586 /// For example, if dispText is "October 10th" and uttText is "Today is October 10th.", "October 10th" will be displayed on the screen and "Today is October 10th." will be spoken.
587 /// Also, the developer can set whether the dialogue starts automatically or not, using autoStart.
588 /// If the developer sets autoStart as true, the framework will start to record next speech and continue the dialogue.
590 /// <since_tizen> 3 </since_tizen>
592 /// http://tizen.org/privilege/recorder
598 /// http://tizen.org/feature/speech.control
599 /// http://tizen.org/feature/microphone
602 /// If autoStart is true, the recognition will start again. In this case, it can be restarted up to 4 times.
604 /// <param name="dispText"> Text to be displayed on the screen/// </param>
605 /// <param name="uttText">Text to be spoken</param>
606 /// <param name="autoStart">A variable for setting whether the dialog session will be restarted automatically or not</param>
607 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
608 /// <exception cref="ArgumentException"> This Exception can be due to Invalid Parameter. </exception>
609 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
610 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
612 /// The State should be Ready
614 public static void RequestDialog(string dispText, string uttText, bool autoStart)
616 ErrorCode error = VcRequestDialog(dispText, uttText, autoStart);
617 if (error != ErrorCode.None)
619 Log.Error(LogTag, "RequestDialog Failed with error " + error);
620 throw ExceptionFactory.CreateException(error);
625 /// Sets command list.
627 /// <since_tizen> 3 </since_tizen>
629 /// http://tizen.org/privilege/recorder
635 /// http://tizen.org/feature/speech.control
636 /// http://tizen.org/feature/microphone
639 /// The command type is valid for CommandType 'Foreground' or 'Background'.
640 /// The matched commands of command list should be set and they should include type and command text at least.
642 /// <param name="list">Command list</param>
643 /// <param name="type">Command type</param>
644 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
645 /// <exception cref="ArgumentException"> This Exception can be due to Invalid Parameter. </exception>
646 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
647 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
649 /// The State should be Ready
651 public static void SetCommandList(VoiceCommandList list, CommandType type)
653 if ((type == CommandType.Foreground) || (type == CommandType.Background))
655 ErrorCode error = VcSetCommandList(list._handle, (VoiceCommandType)type);
656 if (error != ErrorCode.None)
658 Log.Error(LogTag, "SetCommandList Failed with error " + error);
659 throw ExceptionFactory.CreateException(error);
665 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
670 /// Unsets command list.
672 /// <since_tizen> 3 </since_tizen>
674 /// http://tizen.org/privilege/recorder
680 /// http://tizen.org/feature/speech.control
681 /// http://tizen.org/feature/microphone
683 /// <param name="type">Command type</param>
684 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
685 /// <exception cref="ArgumentException"> This Exception can be due to Invalid Parameter. </exception>
686 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
687 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
689 /// The State should be Ready
691 public static void UnsetCommandList(CommandType type)
693 if ((type == CommandType.Foreground) || (type == CommandType.Background))
695 VoiceCommandType commandType = VoiceCommandType.Foreground;
696 if (type == CommandType.Background)
697 commandType = VoiceCommandType.BackGround;
698 ErrorCode error = VcUnsetCommandList(commandType);
699 if (error != ErrorCode.None)
701 Log.Error(LogTag, "UnsetCommandList Failed with error " + error);
702 throw ExceptionFactory.CreateException(error);
708 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
713 /// Gets the recognition result.
715 /// <since_tizen> 3 </since_tizen>
717 /// http://tizen.org/privilege/recorder
723 /// http://tizen.org/feature/speech.control
724 /// http://tizen.org/feature/microphone
726 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
727 /// <exception cref="ArgumentException"> This Exception can be due to Invalid Parameter. </exception>
728 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
729 /// <returns>The Recognition Result if possible else a null object</returns>
731 /// The State should be Ready
733 public static RecognitionResult GetResult()
735 s_recognitionResult = null;
736 s_resultCb = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
738 s_recognitionResult = new RecognitionResult(evt, cmdList, result);
740 ErrorCode error = VcGetResult(s_resultCb, IntPtr.Zero);
741 if (error != ErrorCode.None)
743 Log.Error(LogTag, "GetResult Failed with error " + error);
744 throw ExceptionFactory.CreateException(error);
747 return s_recognitionResult;
751 /// Event to be invoked when the recognition is done.
753 /// <since_tizen> 3 </since_tizen>
755 /// The State should be Initialized
757 public static event EventHandler<RecognitionResultEventArgs> RecognitionResult
761 s_resultDelegate = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
763 Log.Info(LogTag, "Recognition Result Event Triggered");
764 if ((cmdList != null) && (result != null))
766 RecognitionResultEventArgs args = new RecognitionResultEventArgs(new RecognitionResult( evt, cmdList, result));
767 _recognitionResult?.Invoke(null, args);
771 Log.Info(LogTag, "Recognition Result Event null received");
774 ErrorCode error = VcSetResultCb(s_resultDelegate, IntPtr.Zero);
775 if (error != ErrorCode.None)
777 Log.Error(LogTag, "Add RecognitionResult Failed with error " + error);
781 _recognitionResult += value;
787 ErrorCode error = VcUnsetResultCb();
788 if (error != ErrorCode.None)
790 Log.Error(LogTag, "Remove RecognitionResult Failed with error " + error);
793 _recognitionResult -= value;
798 /// Event to be invoked when VoiceControl service state changes.
800 /// <since_tizen> 3 </since_tizen>
802 /// The State should be Initialized
804 public static event EventHandler<ServiceStateChangedEventArgs> ServiceStateChanged
808 s_serviceStateDelegate = (ServiceState previous, ServiceState current, IntPtr userData) =>
810 ServiceStateChangedEventArgs args = new ServiceStateChangedEventArgs(previous, current);
811 _serviceStateChanged?.Invoke(null, args);
813 ErrorCode error = VcSetServiceStateChangedCb(s_serviceStateDelegate, IntPtr.Zero);
814 if (error != ErrorCode.None)
816 Log.Error(LogTag, "Add ServiceStateChanged Failed with error " + error);
820 _serviceStateChanged += value;
826 ErrorCode error = VcUnsetServiceStateChangedCb();
827 if (error != ErrorCode.None)
829 Log.Error(LogTag, "Remove ServiceStateChanged Failed with error " + error);
832 _serviceStateChanged -= value;
837 /// Event to be invoked when VoiceControl client state changes.
839 /// <since_tizen> 3 </since_tizen>
841 /// The State should be Initialized
843 public static event EventHandler<StateChangedEventArgs> StateChanged
847 s_stateDelegate = (State previous, State current, IntPtr userData) =>
849 StateChangedEventArgs args = new StateChangedEventArgs(previous, current);
850 _stateChanged?.Invoke(null, args);
852 ErrorCode error = VcSetStateChangedCb(s_stateDelegate, IntPtr.Zero);
853 if (error != ErrorCode.None)
855 Log.Error(LogTag, "Add StateChanged Failed with error " + error);
859 _stateChanged += value;
865 ErrorCode error = VcUnsetStateChangedCb();
866 if (error != ErrorCode.None)
868 Log.Error(LogTag, "Remove StateChanged Failed with error " + error);
871 _stateChanged -= value;
876 /// Event to be invoked when an error occurs.
878 /// <since_tizen> 3 </since_tizen>
880 /// The State should be Initialized
882 public static event EventHandler<ErrorOccuredEventArgs> ErrorOccured
886 s_errorDelegate = (ErrorCode reason, IntPtr userData) =>
888 ErrorOccuredEventArgs args = new ErrorOccuredEventArgs(reason);
889 _errorOccured?.Invoke(null, args);
891 ErrorCode error = VcSetErrorCb(s_errorDelegate, IntPtr.Zero);
892 if (error != ErrorCode.None)
894 Log.Error(LogTag, "Add ErrorOccured Failed with error " + error);
899 _errorOccured += value;
906 ErrorCode error = VcUnsetErrorCb();
907 if (error != ErrorCode.None)
909 Log.Error(LogTag, "Remove ErrorOccured Failed with error " + error);
912 _errorOccured -= value;
917 /// Event to be invoked when default laungage change.
919 /// <since_tizen> 3 </since_tizen>
921 /// The State should be Initialized
923 public static event EventHandler<CurrentLanguageChangedEventArgs> CurrentLanguageChanged
927 s_languageDelegate = (IntPtr previousLanguage, IntPtr currentLanguage, IntPtr userData) =>
929 string previousLanguageString = Marshal.PtrToStringAnsi(previousLanguage);
930 string currentLanguageString = Marshal.PtrToStringAnsi(currentLanguage);
931 CurrentLanguageChangedEventArgs args = new CurrentLanguageChangedEventArgs(previousLanguageString, currentLanguageString);
932 _currentLanguageChanged?.Invoke(null, args);
934 ErrorCode error = VcSetCurrentLanguageChangedCb(s_languageDelegate, IntPtr.Zero);
935 if (error != ErrorCode.None)
937 Log.Error(LogTag, "Add CurrentLanguageChanged Failed with error " + error);
942 _currentLanguageChanged += value;
948 ErrorCode error = VcUnsetCurrentLanguageChangedCb();
949 if (error != ErrorCode.None)
951 Log.Error(LogTag, "Remove CurrentLanguageChanged Failed with error " + error);
954 _currentLanguageChanged -= value;