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
31 /// Successful, No error
47 /// No answer from the STT service
51 /// Device or resource busy
71 /// No available engine
79 /// Operation Rejected
95 /// Progress to ready is not finished
99 /// Progress to recording is not finished
101 InProgressToRecording,
103 /// Progress to processing is not finished
105 InProgressToProcessing
109 /// Enumeration for the client state.
118 /// 'Initialized' state
126 /// state cannot be determined
132 /// Enumerations of service state.
134 public enum ServiceState
145 /// 'Recording' state
149 /// 'Processing' state
153 /// state cannot be determined
159 /// Enumerations of result event.
161 public enum ResultEvent
174 /// Enumerations of command type.
176 public enum CommandType
179 /// Foreground command by client
183 /// Background command by client
187 /// Undefined command
193 /// A main function of Voice Control API register command and gets notification for recognition result.
194 /// Applications can add their own commands and be provided result when their command is recognized by user voice input.
196 public static class VoiceControlClient
199 /// Called when client gets the recognition result.
202 /// If the duplicated commands are recognized, the event(e.g. Result.Rejected) of command may be rejected
203 /// for selecting command as priority.If you set similar or same commands or the recognized results are multi-results, cmdList has the multi commands.
205 /// <param name="evt">The ResultEvent</param>
206 /// <param name="cmdList">Command List</param>
207 /// <param name="result">Result</param>
208 public delegate void RecognitionResultDelegate(ResultEvent evt, VoiceCommandList cmdList, string result);
210 private static event EventHandler<RecognitionResultEventArgs> _recognitionResult;
211 private static event EventHandler<StateChangedEventArgs> _stateChanged;
212 private static event EventHandler<ServiceStateChangedEventArgs> _serviceStateChanged;
213 private static event EventHandler<ErrorOccuredEventArgs> _errorOccured;
214 private static event EventHandler<CurrentLanguageChangedEventArgs> _currentLanguageChanged;
215 private static VcResultCb s_resultDelegate;
216 private static VcStateChangedCb s_stateDelegate;
217 private static VcServiceStateChangedCb s_serviceStateDelegate;
218 private static VcErrorCb s_errorDelegate;
219 private static VcCurrentLanguageChangedCb s_languageDelegate;
220 private static List<string> s_supportedLanguages;
221 private static VcSupportedLanguageCb s_supportedLanguagesCb;
222 private static VcResultCb s_resultCb;
225 /// Gets current language.
226 /// A language is specified as an ISO 3166 alpha-2 two letter country-code
227 /// followed by ISO 639-1 for the two-letter language code.
228 /// For example, "ko_KR" for Korean, "en_US" for American English.
229 /// Empty string is returned incase of some internal error
232 /// Current language in voice control.
235 /// http://tizen.org/privilege/recorder
238 /// The State must be Initialized or Ready.
240 public static string GetCurrentLanaguge
244 string currentLanaguge;
246 ErrorCode error = VcGetCurrentLanguage(out currentLanaguge);
247 if (error != ErrorCode.None)
249 Log.Error(LogTag, "CurrentLanaguge Failed with error " + error);
253 return currentLanaguge;
258 /// Gets current state of voice control client.
261 /// Current state of voice control client.
264 /// http://tizen.org/privilege/recorder
267 /// The State must be Initialized or Ready.
269 public static State GetState
275 ErrorCode error = VcGetState(out state);
276 if (error != ErrorCode.None)
278 Log.Error(LogTag, "GetState Failed with error " + error);
279 return State.Unavailable;
287 /// Gets current state of voice control service.
290 /// Current state of voice control service.
293 /// http://tizen.org/privilege/recorder
296 /// The State must be Ready.
298 public static ServiceState GetServiceState
304 ErrorCode error = VcGetServiceState(out state);
305 if (error != ErrorCode.None)
307 Log.Error(LogTag, "GetServiceState Failed with error " + error);
308 return ServiceState.Unavailable;
316 /// Sets the invocation name.
319 /// http://tizen.org/privilege/recorder
325 /// http://tizen.org/feature/speech.control
326 /// http://tizen.org/feature/microphone
329 /// Invocation name is used to activate background commands. The invocation name can be the same as the application name or any other phrase.
330 /// For example, an application "Tizen Sample" has a background command, "Play music", and the invocation name of the application is set to "Tizen Sample".
331 /// In order to activate the background command, users can say "Tizen Sample, Play music". The invocation name is dependent on the current language.
332 /// For example, if the current language is "en_US"(English), the invocation name is also "en_US".
333 /// If the current language is "ja_JP"(Japanese) and the invocation name is "en_US", the invocation name will not be recognized.
334 /// This function should be called before SetCommandList().
336 /// <param name="name">Invocation name that an application wants to be invoked by</param>
337 /// <exception cref="InvalidOperationException">
338 /// This Exception can be due to the following reaons
339 /// 1. Invalid parameter
342 /// 4. Permission Denied
345 /// The State must be Ready.
347 public static void SetInvocationName(string name)
349 ErrorCode error = VcSetInvocationName(name);
350 if (error != ErrorCode.None)
352 Log.Error(LogTag, "SetInvocationName Failed with error " + error);
353 throw ExceptionFactory.CreateException(error);
358 /// Initializes voice control.
361 /// http://tizen.org/privilege/recorder
367 /// http://tizen.org/feature/speech.control
368 /// http://tizen.org/feature/microphone
370 /// <exception cref="InvalidOperationException">
371 /// This Exception can be due to the following reaons
373 /// 2. Operation Failed
375 /// 4. Permission Denied
378 /// The State will be Initialized.
380 public static void Initialize()
382 ErrorCode error = VcInitialize();
383 if (error != ErrorCode.None)
385 Log.Error(LogTag, "Initialize Failed with error " + error);
386 throw ExceptionFactory.CreateException(error);
391 /// Deinitializes voice control.
394 /// http://tizen.org/privilege/recorder
400 /// http://tizen.org/feature/speech.control
401 /// http://tizen.org/feature/microphone
403 /// <exception cref="InvalidOperationException">
404 /// This Exception can be due to the following reaons
405 /// 1. Operation Failed
408 /// 4. Permission Denied
410 public static void Deinitialize()
412 ErrorCode error = VcDeinitialize();
413 if (error != ErrorCode.None)
415 Log.Error(LogTag, "Deinitialize Failed with error " + error);
416 throw ExceptionFactory.CreateException(error);
421 /// Connects the voice control service.
424 /// http://tizen.org/privilege/recorder
430 /// http://tizen.org/feature/speech.control
431 /// http://tizen.org/feature/microphone
433 /// <exception cref="InvalidOperationException">
434 /// This Exception can be due to the following reaons
435 /// 1. Operation Failed
437 /// 3. Permission Denied
441 /// The State should be Initialized
444 /// The State will be Ready
446 public static void Prepare()
448 ErrorCode error = VcPrepare();
449 if (error != ErrorCode.None)
451 Log.Error(LogTag, "Prepare Failed with error " + error);
452 throw ExceptionFactory.CreateException(error);
457 /// Disconnects the voice control service.
460 /// http://tizen.org/privilege/recorder
466 /// http://tizen.org/feature/speech.control
467 /// http://tizen.org/feature/microphone
469 /// <exception cref="InvalidOperationException">
470 /// This Exception can be due to the following reaons
472 /// 2. Permission Denied
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.
498 /// http://tizen.org/privilege/recorder
504 /// http://tizen.org/feature/speech.control
505 /// http://tizen.org/feature/microphone
507 /// <exception cref="InvalidOperationException">
508 /// This Exception can be due to the following reaons
509 /// 1. Operation Failed
511 /// 3. Permission Denied
515 /// The State should be Ready or Initialized
517 public static IEnumerable<string> GetSupportedLangauges()
519 s_supportedLanguages = new List<string>();
520 s_supportedLanguagesCb = (IntPtr language, IntPtr userData) =>
522 string languageStr = Marshal.PtrToStringAnsi(language);
523 s_supportedLanguages.Add(languageStr);
526 ErrorCode error = VcForeachSupportedLanguages(s_supportedLanguagesCb, IntPtr.Zero);
527 if (error != ErrorCode.None)
529 Log.Error(LogTag, "GetSupportedLangauges Failed with error " + error);
530 throw ExceptionFactory.CreateException(error);
533 return s_supportedLanguages;
537 /// Gets the system command list.
540 /// The Command List else null in case of no System Commands
543 /// http://tizen.org/privilege/recorder
549 /// http://tizen.org/feature/speech.control
550 /// http://tizen.org/feature/microphone
553 /// In the system command list, there are system commands predefined by product manufacturers.
554 /// Those commands have the highest priority. Therefore, the user can not set any commands same with the system commands.
556 /// <exception cref="InvalidOperationException">
557 /// This Exception can be due to the following reaons
559 /// 2. Permission Denied
563 /// The State should be Ready
565 public static VoiceCommandList GetSytemCommandList()
567 IntPtr handle = IntPtr.Zero;
568 ErrorCode error = VcGetSystemCommandList(out handle);
569 if (error != ErrorCode.None)
571 Log.Error(LogTag, "GetSystemCommandList Failed with error " + error);
572 throw ExceptionFactory.CreateException(error);
575 if (handle == IntPtr.Zero)
577 Log.Error(LogTag, "GetSystemCommandList handle is null");
581 SafeCommandListHandle list = new SafeCommandListHandle(handle);
582 return new VoiceCommandList(list);
586 /// Requests to start the dialogue.
587 /// Using this function, the developer can request starting the dialogue to the framework.
588 /// 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.
589 /// 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.
590 /// Also, the developer can set whether the dialogue starts automatically or not, using autoStart.
591 /// If the developer sets autoStart as true, the framework will start to record next speech and continue the dialogue.
594 /// http://tizen.org/privilege/recorder
600 /// http://tizen.org/feature/speech.control
601 /// http://tizen.org/feature/microphone
604 /// If autoStart is true, the recognition will start again. In this case, it can be restarted up to 4 times.
606 /// <param name="dispText"> Text to be displayed on the screen/// </param>
607 /// <param name="uttText">Text to be spoken</param>
608 /// <param name="autoStart">A variable for setting whether the dialog session will be restarted automatically or not</param>
609 /// <exception cref="InvalidOperationException">
610 /// This Exception can be due to the following reaons
612 /// 2. Permission Denied
614 /// 4. Invalid parameter
617 /// The State should be Ready
619 public static void RequestDialog(string dispText, string uttText, bool autoStart)
621 ErrorCode error = VcRequestDialog(dispText, uttText, autoStart);
622 if (error != ErrorCode.None)
624 Log.Error(LogTag, "RequestDialog Failed with error " + error);
625 throw ExceptionFactory.CreateException(error);
630 /// Sets command list.
633 /// http://tizen.org/privilege/recorder
639 /// http://tizen.org/feature/speech.control
640 /// http://tizen.org/feature/microphone
643 /// The command type is valid for CommandType 'Foreground' or 'Background'.
644 /// The matched commands of command list should be set and they should include type and command text at least.
646 /// <param name="list">Command list</param>
647 /// <param name="type">Command type</param>
648 /// <exception cref="InvalidOperationException">
649 /// This Exception can be due to the following reaons
651 /// 2. Permission Denied
653 /// 4. Invalid parameter
656 /// The State should be Ready
658 public static void SetCommandList(VoiceCommandList list, CommandType type)
660 if ((type == CommandType.Foreground) || (type == CommandType.Background))
662 ErrorCode error = VcSetCommandList(list._handle, (VoiceCommandType)type);
663 if (error != ErrorCode.None)
665 Log.Error(LogTag, "SetCommandList Failed with error " + error);
666 throw ExceptionFactory.CreateException(error);
672 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
677 /// Unsets command list.
680 /// http://tizen.org/privilege/recorder
686 /// http://tizen.org/feature/speech.control
687 /// http://tizen.org/feature/microphone
689 /// <param name="type">Command type</param>
690 /// <exception cref="InvalidOperationException">
691 /// This Exception can be due to the following reaons
693 /// 2. Permission Denied
695 /// 4. Invalid parameter
698 /// The State should be Ready
700 public static void UnsetCommandList(CommandType type)
702 if ((type == CommandType.Foreground) || (type == CommandType.Background))
704 VoiceCommandType commandType = VoiceCommandType.Foreground;
705 if (type == CommandType.Background)
706 commandType = VoiceCommandType.BackGround;
707 ErrorCode error = VcUnsetCommandList(commandType);
708 if (error != ErrorCode.None)
710 Log.Error(LogTag, "UnsetCommandList Failed with error " + error);
711 throw ExceptionFactory.CreateException(error);
717 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
722 /// Gets the recognition result.
725 /// http://tizen.org/privilege/recorder
731 /// http://tizen.org/feature/speech.control
732 /// http://tizen.org/feature/microphone
734 /// <param name="resultDelegate">
735 /// Callback function to get recognition result
737 /// <exception cref="InvalidOperationException">
738 /// This Exception can be due to the following reaons
741 /// 3. Invalid parameter
744 /// The State should be Ready
746 public static void GetResult(RecognitionResultDelegate resultDelegate)
748 s_resultCb = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
750 VoiceCommandList list = new VoiceCommandList(new SafeCommandListHandle(cmdList));
751 string resultStr = Marshal.PtrToStringAnsi(result);
752 resultDelegate(evt, list, resultStr);
754 ErrorCode error = VcGetResult(s_resultCb, IntPtr.Zero);
755 if (error != ErrorCode.None)
757 Log.Error(LogTag, "GetResult Failed with error " + error);
758 throw ExceptionFactory.CreateException(error);
763 /// Event to be invoked when the recognition is done.
766 /// The State should be Initialized
768 public static event EventHandler<RecognitionResultEventArgs> RecognitionResult
772 s_resultDelegate = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
774 Log.Info(LogTag, "Recognition Result Event Triggered");
775 if ((cmdList != null) && (result != null))
777 RecognitionResultEventArgs args = new RecognitionResultEventArgs(evt, cmdList, result);
778 _recognitionResult?.Invoke(null, args);
782 Log.Info(LogTag, "Recognition Result Event null received");
785 ErrorCode error = VcSetResultCb(s_resultDelegate, IntPtr.Zero);
786 if (error != ErrorCode.None)
788 Log.Error(LogTag, "Add RecognitionResult Failed with error " + error);
792 _recognitionResult += value;
798 ErrorCode error = VcUnsetResultCb();
799 if (error != ErrorCode.None)
801 Log.Error(LogTag, "Remove RecognitionResult Failed with error " + error);
804 _recognitionResult -= value;
809 /// Event to be invoked when VoiceControl service state changes.
812 /// The State should be Initialized
814 public static event EventHandler<ServiceStateChangedEventArgs> ServiceStateChanged
818 s_serviceStateDelegate = (ServiceState previous, ServiceState current, IntPtr userData) =>
820 ServiceStateChangedEventArgs args = new ServiceStateChangedEventArgs(previous, current);
821 _serviceStateChanged?.Invoke(null, args);
823 ErrorCode error = VcSetServiceStateChangedCb(s_serviceStateDelegate, IntPtr.Zero);
824 if (error != ErrorCode.None)
826 Log.Error(LogTag, "Add ServiceStateChanged Failed with error " + error);
830 _serviceStateChanged += value;
836 ErrorCode error = VcUnsetServiceStateChangedCb();
837 if (error != ErrorCode.None)
839 Log.Error(LogTag, "Remove ServiceStateChanged Failed with error " + error);
842 _serviceStateChanged -= value;
847 /// Event to be invoked when VoiceControl client state changes.
850 /// The State should be Initialized
852 public static event EventHandler<StateChangedEventArgs> StateChanged
856 s_stateDelegate = (State previous, State current, IntPtr userData) =>
858 StateChangedEventArgs args = new StateChangedEventArgs(previous, current);
859 _stateChanged?.Invoke(null, args);
861 ErrorCode error = VcSetStateChangedCb(s_stateDelegate, IntPtr.Zero);
862 if (error != ErrorCode.None)
864 Log.Error(LogTag, "Add StateChanged Failed with error " + error);
868 _stateChanged += value;
874 ErrorCode error = VcUnsetStateChangedCb();
875 if (error != ErrorCode.None)
877 Log.Error(LogTag, "Remove StateChanged Failed with error " + error);
880 _stateChanged -= value;
885 /// Event to be invoked when an error occurs.
888 /// The State should be Initialized
890 public static event EventHandler<ErrorOccuredEventArgs> ErrorOccured
894 s_errorDelegate = (ErrorCode reason, IntPtr userData) =>
896 ErrorOccuredEventArgs args = new ErrorOccuredEventArgs(reason);
897 _errorOccured?.Invoke(null, args);
899 ErrorCode error = VcSetErrorCb(s_errorDelegate, IntPtr.Zero);
900 if (error != ErrorCode.None)
902 Log.Error(LogTag, "Add ErrorOccured Failed with error " + error);
907 _errorOccured += value;
914 ErrorCode error = VcUnsetErrorCb();
915 if (error != ErrorCode.None)
917 Log.Error(LogTag, "Remove ErrorOccured Failed with error " + error);
920 _errorOccured -= value;
925 /// Event to be invoked when default laungage change.
928 /// The State should be Initialized
930 public static event EventHandler<CurrentLanguageChangedEventArgs> CurrentLanguageChanged
934 s_languageDelegate = (IntPtr previousLanguage, IntPtr currentLanguage, IntPtr userData) =>
936 string previousLanguageString = Marshal.PtrToStringAnsi(previousLanguage);
937 string currentLanguageString = Marshal.PtrToStringAnsi(currentLanguage);
938 CurrentLanguageChangedEventArgs args = new CurrentLanguageChangedEventArgs(previousLanguageString, currentLanguageString);
939 _currentLanguageChanged?.Invoke(null, args);
941 ErrorCode error = VcSetCurrentLanguageChangedCb(s_languageDelegate, IntPtr.Zero);
942 if (error != ErrorCode.None)
944 Log.Error(LogTag, "Add CurrentLanguageChanged Failed with error " + error);
949 _currentLanguageChanged += value;
955 ErrorCode error = VcUnsetCurrentLanguageChangedCb();
956 if (error != ErrorCode.None)
958 Log.Error(LogTag, "Remove CurrentLanguageChanged Failed with error " + error);
961 _currentLanguageChanged -= value;