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>
209 private static event EventHandler<RecognitionResultEventArgs> _recognitionResult;
210 private static event EventHandler<StateChangedEventArgs> _stateChanged;
211 private static event EventHandler<ServiceStateChangedEventArgs> _serviceStateChanged;
212 private static event EventHandler<ErrorOccuredEventArgs> _errorOccured;
213 private static event EventHandler<CurrentLanguageChangedEventArgs> _currentLanguageChanged;
214 private static VcResultCb s_resultDelegate;
215 private static VcStateChangedCb s_stateDelegate;
216 private static VcServiceStateChangedCb s_serviceStateDelegate;
217 private static VcErrorCb s_errorDelegate;
218 private static VcCurrentLanguageChangedCb s_languageDelegate;
219 private static List<string> s_supportedLanguages;
220 private static VcSupportedLanguageCb s_supportedLanguagesCb;
221 private static VcResultCb s_resultCb;
222 private static RecognitionResult s_recognitionResult;
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 CurrentLanguage
244 string currentLanguage;
246 ErrorCode error = VcGetCurrentLanguage(out currentLanguage);
247 if (error != ErrorCode.None)
249 Log.Error(LogTag, "CurrentLanguage Failed with error " + error);
253 return currentLanguage;
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 State
275 ErrorCode error = VcGetState(out state);
276 if (error != ErrorCode.None)
278 Log.Error(LogTag, "State 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 ServiceState
304 ErrorCode error = VcGetServiceState(out state);
305 if (error != ErrorCode.None)
307 Log.Error(LogTag, "ServiceState 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"> This Exception can be due to Invalid State. </exception>
338 /// <exception cref="ArgumentException"> This Exception can be due to Invalid Parameter. </exception>
339 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
340 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
342 /// The State must be Ready.
344 public static void SetInvocationName(string name)
346 ErrorCode error = VcSetInvocationName(name);
347 if (error != ErrorCode.None)
349 Log.Error(LogTag, "SetInvocationName Failed with error " + error);
350 throw ExceptionFactory.CreateException(error);
355 /// Initializes voice control.
358 /// http://tizen.org/privilege/recorder
364 /// http://tizen.org/feature/speech.control
365 /// http://tizen.org/feature/microphone
367 /// <exception cref="InvalidOperationException"> This Exception can be due to Operation Failed. </exception>
368 /// <exception cref="OutOfMemoryException"> This Exception can be due to Out Of Memory. </exception>
369 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
370 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
372 /// The State will be Initialized.
374 public static void Initialize()
376 ErrorCode error = VcInitialize();
377 if (error != ErrorCode.None)
379 Log.Error(LogTag, "Initialize Failed with error " + error);
380 throw ExceptionFactory.CreateException(error);
385 /// Deinitializes voice control.
388 /// http://tizen.org/privilege/recorder
394 /// http://tizen.org/feature/speech.control
395 /// http://tizen.org/feature/microphone
397 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
398 /// <exception cref="InvalidOperationException"> This Exception can be due to Operation Failed. </exception>
399 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
400 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
401 public static void Deinitialize()
403 ErrorCode error = VcDeinitialize();
404 if (error != ErrorCode.None)
406 Log.Error(LogTag, "Deinitialize Failed with error " + error);
407 throw ExceptionFactory.CreateException(error);
412 /// Connects the voice control service.
415 /// http://tizen.org/privilege/recorder
421 /// http://tizen.org/feature/speech.control
422 /// http://tizen.org/feature/microphone
424 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
425 /// <exception cref="InvalidOperationException"> This Exception can be due to Operation Failed. </exception>
426 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
427 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
429 /// The State should be Initialized
432 /// The State will be Ready
434 public static void Prepare()
436 ErrorCode error = VcPrepare();
437 if (error != ErrorCode.None)
439 Log.Error(LogTag, "Prepare Failed with error " + error);
440 throw ExceptionFactory.CreateException(error);
445 /// Disconnects the voice control service.
448 /// http://tizen.org/privilege/recorder
454 /// http://tizen.org/feature/speech.control
455 /// http://tizen.org/feature/microphone
457 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
458 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
459 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
461 /// The State should be Ready
464 /// The State should be Initialized
466 public static void Unprepare()
468 ErrorCode error = VcUnprepare();
469 if (error != ErrorCode.None)
471 Log.Error(LogTag, "Unprepare Failed with error " + error);
472 throw ExceptionFactory.CreateException(error);
477 /// Retrieves all supported languages.
478 /// A language is specified as an ISO 3166 alpha-2 two letter country-code
479 /// followed by ISO 639-1 for the two-letter language code.
480 /// For example, "ko_KR" for Korean, "en_US" for American English.
483 /// http://tizen.org/privilege/recorder
489 /// http://tizen.org/feature/speech.control
490 /// http://tizen.org/feature/microphone
492 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
493 /// <exception cref="InvalidOperationException"> This Exception can be due to Operation Failed. </exception>
494 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
495 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
497 /// The State should be Ready or Initialized
499 public static IEnumerable<string> GetSupportedLanguages()
501 s_supportedLanguages = new List<string>();
502 s_supportedLanguagesCb = (IntPtr language, IntPtr userData) =>
504 string languageStr = Marshal.PtrToStringAnsi(language);
505 s_supportedLanguages.Add(languageStr);
508 ErrorCode error = VcForeachSupportedLanguages(s_supportedLanguagesCb, IntPtr.Zero);
509 if (error != ErrorCode.None)
511 Log.Error(LogTag, "GetSupportedLanguages Failed with error " + error);
512 throw ExceptionFactory.CreateException(error);
515 return s_supportedLanguages;
519 /// Gets the system command list.
522 /// The Command List else null in case of no System Commands
525 /// http://tizen.org/privilege/recorder
531 /// http://tizen.org/feature/speech.control
532 /// http://tizen.org/feature/microphone
535 /// In the system command list, there are system commands predefined by product manufacturers.
536 /// Those commands have the highest priority. Therefore, the user can not set any commands same with the system commands.
538 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
539 /// <exception cref="InvalidOperationException"> This Exception can be due to Operation Failed. </exception>
540 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
541 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
543 /// The State should be Ready
545 public static VoiceCommandList GetSystemCommandList()
547 IntPtr handle = IntPtr.Zero;
548 ErrorCode error = VcGetSystemCommandList(out handle);
549 if (error != ErrorCode.None)
551 Log.Error(LogTag, "GetSystemCommandList Failed with error " + error);
552 throw ExceptionFactory.CreateException(error);
555 if (handle == IntPtr.Zero)
557 Log.Error(LogTag, "GetSystemCommandList handle is null");
561 SafeCommandListHandle list = new SafeCommandListHandle(handle);
562 return new VoiceCommandList(list);
566 /// Requests to start the dialogue.
567 /// Using this function, the developer can request starting the dialogue to the framework.
568 /// 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.
569 /// 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.
570 /// Also, the developer can set whether the dialogue starts automatically or not, using autoStart.
571 /// If the developer sets autoStart as true, the framework will start to record next speech and continue the dialogue.
574 /// http://tizen.org/privilege/recorder
580 /// http://tizen.org/feature/speech.control
581 /// http://tizen.org/feature/microphone
584 /// If autoStart is true, the recognition will start again. In this case, it can be restarted up to 4 times.
586 /// <param name="dispText"> Text to be displayed on the screen/// </param>
587 /// <param name="uttText">Text to be spoken</param>
588 /// <param name="autoStart">A variable for setting whether the dialog session will be restarted automatically or not</param>
589 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
590 /// <exception cref="ArgumentException"> This Exception can be due to Invalid Parameter. </exception>
591 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
592 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
594 /// The State should be Ready
596 public static void RequestDialog(string dispText, string uttText, bool autoStart)
598 ErrorCode error = VcRequestDialog(dispText, uttText, autoStart);
599 if (error != ErrorCode.None)
601 Log.Error(LogTag, "RequestDialog Failed with error " + error);
602 throw ExceptionFactory.CreateException(error);
607 /// Sets command list.
610 /// http://tizen.org/privilege/recorder
616 /// http://tizen.org/feature/speech.control
617 /// http://tizen.org/feature/microphone
620 /// The command type is valid for CommandType 'Foreground' or 'Background'.
621 /// The matched commands of command list should be set and they should include type and command text at least.
623 /// <param name="list">Command list</param>
624 /// <param name="type">Command type</param>
625 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
626 /// <exception cref="ArgumentException"> This Exception can be due to Invalid Parameter. </exception>
627 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
628 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
630 /// The State should be Ready
632 public static void SetCommandList(VoiceCommandList list, CommandType type)
634 if ((type == CommandType.Foreground) || (type == CommandType.Background))
636 ErrorCode error = VcSetCommandList(list._handle, (VoiceCommandType)type);
637 if (error != ErrorCode.None)
639 Log.Error(LogTag, "SetCommandList Failed with error " + error);
640 throw ExceptionFactory.CreateException(error);
646 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
651 /// Unsets command list.
654 /// http://tizen.org/privilege/recorder
660 /// http://tizen.org/feature/speech.control
661 /// http://tizen.org/feature/microphone
663 /// <param name="type">Command type</param>
664 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
665 /// <exception cref="ArgumentException"> This Exception can be due to Invalid Parameter. </exception>
666 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
667 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
669 /// The State should be Ready
671 public static void UnsetCommandList(CommandType type)
673 if ((type == CommandType.Foreground) || (type == CommandType.Background))
675 VoiceCommandType commandType = VoiceCommandType.Foreground;
676 if (type == CommandType.Background)
677 commandType = VoiceCommandType.BackGround;
678 ErrorCode error = VcUnsetCommandList(commandType);
679 if (error != ErrorCode.None)
681 Log.Error(LogTag, "UnsetCommandList Failed with error " + error);
682 throw ExceptionFactory.CreateException(error);
688 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
693 /// Gets the recognition result.
696 /// http://tizen.org/privilege/recorder
702 /// http://tizen.org/feature/speech.control
703 /// http://tizen.org/feature/microphone
705 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
706 /// <exception cref="ArgumentException"> This Exception can be due to Invalid Parameter. </exception>
707 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
708 /// <returns>The Recognition Result if possible else a null object</returns>
710 /// The State should be Ready
712 public static RecognitionResult GetResult()
714 s_recognitionResult = null;
715 s_resultCb = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
717 s_recognitionResult = new RecognitionResult(evt, cmdList, result);
719 ErrorCode error = VcGetResult(s_resultCb, IntPtr.Zero);
720 if (error != ErrorCode.None)
722 Log.Error(LogTag, "GetResult Failed with error " + error);
723 throw ExceptionFactory.CreateException(error);
726 return s_recognitionResult;
730 /// Event to be invoked when the recognition is done.
733 /// The State should be Initialized
735 public static event EventHandler<RecognitionResultEventArgs> RecognitionResult
739 s_resultDelegate = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
741 Log.Info(LogTag, "Recognition Result Event Triggered");
742 if ((cmdList != null) && (result != null))
744 RecognitionResultEventArgs args = new RecognitionResultEventArgs(new RecognitionResult( evt, cmdList, result));
745 _recognitionResult?.Invoke(null, args);
749 Log.Info(LogTag, "Recognition Result Event null received");
752 ErrorCode error = VcSetResultCb(s_resultDelegate, IntPtr.Zero);
753 if (error != ErrorCode.None)
755 Log.Error(LogTag, "Add RecognitionResult Failed with error " + error);
759 _recognitionResult += value;
765 ErrorCode error = VcUnsetResultCb();
766 if (error != ErrorCode.None)
768 Log.Error(LogTag, "Remove RecognitionResult Failed with error " + error);
771 _recognitionResult -= value;
776 /// Event to be invoked when VoiceControl service state changes.
779 /// The State should be Initialized
781 public static event EventHandler<ServiceStateChangedEventArgs> ServiceStateChanged
785 s_serviceStateDelegate = (ServiceState previous, ServiceState current, IntPtr userData) =>
787 ServiceStateChangedEventArgs args = new ServiceStateChangedEventArgs(previous, current);
788 _serviceStateChanged?.Invoke(null, args);
790 ErrorCode error = VcSetServiceStateChangedCb(s_serviceStateDelegate, IntPtr.Zero);
791 if (error != ErrorCode.None)
793 Log.Error(LogTag, "Add ServiceStateChanged Failed with error " + error);
797 _serviceStateChanged += value;
803 ErrorCode error = VcUnsetServiceStateChangedCb();
804 if (error != ErrorCode.None)
806 Log.Error(LogTag, "Remove ServiceStateChanged Failed with error " + error);
809 _serviceStateChanged -= value;
814 /// Event to be invoked when VoiceControl client state changes.
817 /// The State should be Initialized
819 public static event EventHandler<StateChangedEventArgs> StateChanged
823 s_stateDelegate = (State previous, State current, IntPtr userData) =>
825 StateChangedEventArgs args = new StateChangedEventArgs(previous, current);
826 _stateChanged?.Invoke(null, args);
828 ErrorCode error = VcSetStateChangedCb(s_stateDelegate, IntPtr.Zero);
829 if (error != ErrorCode.None)
831 Log.Error(LogTag, "Add StateChanged Failed with error " + error);
835 _stateChanged += value;
841 ErrorCode error = VcUnsetStateChangedCb();
842 if (error != ErrorCode.None)
844 Log.Error(LogTag, "Remove StateChanged Failed with error " + error);
847 _stateChanged -= value;
852 /// Event to be invoked when an error occurs.
855 /// The State should be Initialized
857 public static event EventHandler<ErrorOccuredEventArgs> ErrorOccured
861 s_errorDelegate = (ErrorCode reason, IntPtr userData) =>
863 ErrorOccuredEventArgs args = new ErrorOccuredEventArgs(reason);
864 _errorOccured?.Invoke(null, args);
866 ErrorCode error = VcSetErrorCb(s_errorDelegate, IntPtr.Zero);
867 if (error != ErrorCode.None)
869 Log.Error(LogTag, "Add ErrorOccured Failed with error " + error);
874 _errorOccured += value;
881 ErrorCode error = VcUnsetErrorCb();
882 if (error != ErrorCode.None)
884 Log.Error(LogTag, "Remove ErrorOccured Failed with error " + error);
887 _errorOccured -= value;
892 /// Event to be invoked when default laungage change.
895 /// The State should be Initialized
897 public static event EventHandler<CurrentLanguageChangedEventArgs> CurrentLanguageChanged
901 s_languageDelegate = (IntPtr previousLanguage, IntPtr currentLanguage, IntPtr userData) =>
903 string previousLanguageString = Marshal.PtrToStringAnsi(previousLanguage);
904 string currentLanguageString = Marshal.PtrToStringAnsi(currentLanguage);
905 CurrentLanguageChangedEventArgs args = new CurrentLanguageChangedEventArgs(previousLanguageString, currentLanguageString);
906 _currentLanguageChanged?.Invoke(null, args);
908 ErrorCode error = VcSetCurrentLanguageChangedCb(s_languageDelegate, IntPtr.Zero);
909 if (error != ErrorCode.None)
911 Log.Error(LogTag, "Add CurrentLanguageChanged Failed with error " + error);
916 _currentLanguageChanged += value;
922 ErrorCode error = VcUnsetCurrentLanguageChangedCb();
923 if (error != ErrorCode.None)
925 Log.Error(LogTag, "Remove CurrentLanguageChanged Failed with error " + error);
928 _currentLanguageChanged -= value;