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;
223 private static RecognitionResult s_recognitionResult;
226 /// Gets current language.
227 /// A language is specified as an ISO 3166 alpha-2 two letter country-code
228 /// followed by ISO 639-1 for the two-letter language code.
229 /// For example, "ko_KR" for Korean, "en_US" for American English.
230 /// Empty string is returned incase of some internal error
233 /// Current language in voice control.
236 /// http://tizen.org/privilege/recorder
239 /// The State must be Initialized or Ready.
241 public static string CurrentLanguage
245 string currentLanguage;
247 ErrorCode error = VcGetCurrentLanguage(out currentLanguage);
248 if (error != ErrorCode.None)
250 Log.Error(LogTag, "CurrentLanguage Failed with error " + error);
254 return currentLanguage;
259 /// Gets current state of voice control client.
262 /// Current state of voice control client.
265 /// http://tizen.org/privilege/recorder
268 /// The State must be Initialized or Ready.
270 public static State State
276 ErrorCode error = VcGetState(out state);
277 if (error != ErrorCode.None)
279 Log.Error(LogTag, "State Failed with error " + error);
280 return State.Unavailable;
288 /// Gets current state of voice control service.
291 /// Current state of voice control service.
294 /// http://tizen.org/privilege/recorder
297 /// The State must be Ready.
299 public static ServiceState ServiceState
305 ErrorCode error = VcGetServiceState(out state);
306 if (error != ErrorCode.None)
308 Log.Error(LogTag, "ServiceState Failed with error " + error);
309 return ServiceState.Unavailable;
317 /// Sets the invocation name.
320 /// http://tizen.org/privilege/recorder
326 /// http://tizen.org/feature/speech.control
327 /// http://tizen.org/feature/microphone
330 /// Invocation name is used to activate background commands. The invocation name can be the same as the application name or any other phrase.
331 /// For example, an application "Tizen Sample" has a background command, "Play music", and the invocation name of the application is set to "Tizen Sample".
332 /// In order to activate the background command, users can say "Tizen Sample, Play music". The invocation name is dependent on the current language.
333 /// For example, if the current language is "en_US"(English), the invocation name is also "en_US".
334 /// If the current language is "ja_JP"(Japanese) and the invocation name is "en_US", the invocation name will not be recognized.
335 /// This function should be called before SetCommandList().
337 /// <param name="name">Invocation name that an application wants to be invoked by</param>
338 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
339 /// <exception cref="ArgumentException"> This Exception can be due to Invalid Parameter. </exception>
340 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
341 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
343 /// The State must be Ready.
345 public static void SetInvocationName(string name)
347 ErrorCode error = VcSetInvocationName(name);
348 if (error != ErrorCode.None)
350 Log.Error(LogTag, "SetInvocationName Failed with error " + error);
351 throw ExceptionFactory.CreateException(error);
356 /// Initializes voice control.
359 /// http://tizen.org/privilege/recorder
365 /// http://tizen.org/feature/speech.control
366 /// http://tizen.org/feature/microphone
368 /// <exception cref="InvalidOperationException"> This Exception can be due to Operation Failed. </exception>
369 /// <exception cref="OutOfMemoryException"> This Exception can be due to Out Of Memory. </exception>
370 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
371 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
373 /// The State will be Initialized.
375 public static void Initialize()
377 ErrorCode error = VcInitialize();
378 if (error != ErrorCode.None)
380 Log.Error(LogTag, "Initialize Failed with error " + error);
381 throw ExceptionFactory.CreateException(error);
386 /// Deinitializes voice control.
389 /// http://tizen.org/privilege/recorder
395 /// http://tizen.org/feature/speech.control
396 /// http://tizen.org/feature/microphone
398 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
399 /// <exception cref="InvalidOperationException"> This Exception can be due to Operation Failed. </exception>
400 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
401 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
402 public static void Deinitialize()
404 ErrorCode error = VcDeinitialize();
405 if (error != ErrorCode.None)
407 Log.Error(LogTag, "Deinitialize Failed with error " + error);
408 throw ExceptionFactory.CreateException(error);
413 /// Connects the voice control service.
416 /// http://tizen.org/privilege/recorder
422 /// http://tizen.org/feature/speech.control
423 /// http://tizen.org/feature/microphone
425 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
426 /// <exception cref="InvalidOperationException"> This Exception can be due to Operation Failed. </exception>
427 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
428 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
430 /// The State should be Initialized
433 /// The State will be Ready
435 public static void Prepare()
437 ErrorCode error = VcPrepare();
438 if (error != ErrorCode.None)
440 Log.Error(LogTag, "Prepare Failed with error " + error);
441 throw ExceptionFactory.CreateException(error);
446 /// Disconnects the voice control service.
449 /// http://tizen.org/privilege/recorder
455 /// http://tizen.org/feature/speech.control
456 /// http://tizen.org/feature/microphone
458 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
459 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
460 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
462 /// The State should be Ready
465 /// The State should be Initialized
467 public static void Unprepare()
469 ErrorCode error = VcUnprepare();
470 if (error != ErrorCode.None)
472 Log.Error(LogTag, "Unprepare Failed with error " + error);
473 throw ExceptionFactory.CreateException(error);
478 /// Retrieves all supported languages.
479 /// A language is specified as an ISO 3166 alpha-2 two letter country-code
480 /// followed by ISO 639-1 for the two-letter language code.
481 /// For example, "ko_KR" for Korean, "en_US" for American English.
484 /// http://tizen.org/privilege/recorder
490 /// http://tizen.org/feature/speech.control
491 /// http://tizen.org/feature/microphone
493 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
494 /// <exception cref="InvalidOperationException"> This Exception can be due to Operation Failed. </exception>
495 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
496 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
498 /// The State should be Ready or Initialized
500 public static IEnumerable<string> GetSupportedLanguages()
502 s_supportedLanguages = new List<string>();
503 s_supportedLanguagesCb = (IntPtr language, IntPtr userData) =>
505 string languageStr = Marshal.PtrToStringAnsi(language);
506 s_supportedLanguages.Add(languageStr);
509 ErrorCode error = VcForeachSupportedLanguages(s_supportedLanguagesCb, IntPtr.Zero);
510 if (error != ErrorCode.None)
512 Log.Error(LogTag, "GetSupportedLanguages Failed with error " + error);
513 throw ExceptionFactory.CreateException(error);
516 return s_supportedLanguages;
520 /// Gets the system command list.
523 /// The Command List else null in case of no System Commands
526 /// http://tizen.org/privilege/recorder
532 /// http://tizen.org/feature/speech.control
533 /// http://tizen.org/feature/microphone
536 /// In the system command list, there are system commands predefined by product manufacturers.
537 /// Those commands have the highest priority. Therefore, the user can not set any commands same with the system commands.
539 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
540 /// <exception cref="InvalidOperationException"> This Exception can be due to Operation Failed. </exception>
541 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
542 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
544 /// The State should be Ready
546 public static VoiceCommandList GetSystemCommandList()
548 IntPtr handle = IntPtr.Zero;
549 ErrorCode error = VcGetSystemCommandList(out handle);
550 if (error != ErrorCode.None)
552 Log.Error(LogTag, "GetSystemCommandList Failed with error " + error);
553 throw ExceptionFactory.CreateException(error);
556 if (handle == IntPtr.Zero)
558 Log.Error(LogTag, "GetSystemCommandList handle is null");
562 SafeCommandListHandle list = new SafeCommandListHandle(handle);
563 return new VoiceCommandList(list);
567 /// Requests to start the dialogue.
568 /// Using this function, the developer can request starting the dialogue to the framework.
569 /// 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.
570 /// 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.
571 /// Also, the developer can set whether the dialogue starts automatically or not, using autoStart.
572 /// If the developer sets autoStart as true, the framework will start to record next speech and continue the dialogue.
575 /// http://tizen.org/privilege/recorder
581 /// http://tizen.org/feature/speech.control
582 /// http://tizen.org/feature/microphone
585 /// If autoStart is true, the recognition will start again. In this case, it can be restarted up to 4 times.
587 /// <param name="dispText"> Text to be displayed on the screen/// </param>
588 /// <param name="uttText">Text to be spoken</param>
589 /// <param name="autoStart">A variable for setting whether the dialog session will be restarted automatically or not</param>
590 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
591 /// <exception cref="ArgumentException"> This Exception can be due to Invalid Parameter. </exception>
592 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
593 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
595 /// The State should be Ready
597 public static void RequestDialog(string dispText, string uttText, bool autoStart)
599 ErrorCode error = VcRequestDialog(dispText, uttText, autoStart);
600 if (error != ErrorCode.None)
602 Log.Error(LogTag, "RequestDialog Failed with error " + error);
603 throw ExceptionFactory.CreateException(error);
608 /// Sets command list.
611 /// http://tizen.org/privilege/recorder
617 /// http://tizen.org/feature/speech.control
618 /// http://tizen.org/feature/microphone
621 /// The command type is valid for CommandType 'Foreground' or 'Background'.
622 /// The matched commands of command list should be set and they should include type and command text at least.
624 /// <param name="list">Command list</param>
625 /// <param name="type">Command type</param>
626 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
627 /// <exception cref="ArgumentException"> This Exception can be due to Invalid Parameter. </exception>
628 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
629 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
631 /// The State should be Ready
633 public static void SetCommandList(VoiceCommandList list, CommandType type)
635 if ((type == CommandType.Foreground) || (type == CommandType.Background))
637 ErrorCode error = VcSetCommandList(list._handle, (VoiceCommandType)type);
638 if (error != ErrorCode.None)
640 Log.Error(LogTag, "SetCommandList Failed with error " + error);
641 throw ExceptionFactory.CreateException(error);
647 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
652 /// Unsets command list.
655 /// http://tizen.org/privilege/recorder
661 /// http://tizen.org/feature/speech.control
662 /// http://tizen.org/feature/microphone
664 /// <param name="type">Command type</param>
665 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
666 /// <exception cref="ArgumentException"> This Exception can be due to Invalid Parameter. </exception>
667 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
668 /// <exception cref="UnauthorizedAccessException"> This Exception can be due to Permission Denied. </exception>
670 /// The State should be Ready
672 public static void UnsetCommandList(CommandType type)
674 if ((type == CommandType.Foreground) || (type == CommandType.Background))
676 VoiceCommandType commandType = VoiceCommandType.Foreground;
677 if (type == CommandType.Background)
678 commandType = VoiceCommandType.BackGround;
679 ErrorCode error = VcUnsetCommandList(commandType);
680 if (error != ErrorCode.None)
682 Log.Error(LogTag, "UnsetCommandList Failed with error " + error);
683 throw ExceptionFactory.CreateException(error);
689 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
694 /// Gets the recognition result.
697 /// http://tizen.org/privilege/recorder
703 /// http://tizen.org/feature/speech.control
704 /// http://tizen.org/feature/microphone
706 /// <exception cref="InvalidOperationException"> This Exception can be due to Invalid State. </exception>
707 /// <exception cref="ArgumentException"> This Exception can be due to Invalid Parameter. </exception>
708 /// <exception cref="NotSupportedException"> This Exception can be due to Not Supported. </exception>
709 /// <returns>The Recognition Result if possible else a null object</returns>
711 /// The State should be Ready
713 public static RecognitionResult GetResult()
715 s_recognitionResult = null;
716 s_resultCb = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
718 s_recognitionResult = new RecognitionResult(evt, cmdList, result);
720 ErrorCode error = VcGetResult(s_resultCb, IntPtr.Zero);
721 if (error != ErrorCode.None)
723 Log.Error(LogTag, "GetResult Failed with error " + error);
724 throw ExceptionFactory.CreateException(error);
727 return s_recognitionResult;
731 /// Event to be invoked when the recognition is done.
734 /// The State should be Initialized
736 public static event EventHandler<RecognitionResultEventArgs> RecognitionResult
740 s_resultDelegate = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
742 Log.Info(LogTag, "Recognition Result Event Triggered");
743 if ((cmdList != null) && (result != null))
745 RecognitionResultEventArgs args = new RecognitionResultEventArgs(new RecognitionResult( evt, cmdList, result));
746 _recognitionResult?.Invoke(null, args);
750 Log.Info(LogTag, "Recognition Result Event null received");
753 ErrorCode error = VcSetResultCb(s_resultDelegate, IntPtr.Zero);
754 if (error != ErrorCode.None)
756 Log.Error(LogTag, "Add RecognitionResult Failed with error " + error);
760 _recognitionResult += value;
766 ErrorCode error = VcUnsetResultCb();
767 if (error != ErrorCode.None)
769 Log.Error(LogTag, "Remove RecognitionResult Failed with error " + error);
772 _recognitionResult -= value;
777 /// Event to be invoked when VoiceControl service state changes.
780 /// The State should be Initialized
782 public static event EventHandler<ServiceStateChangedEventArgs> ServiceStateChanged
786 s_serviceStateDelegate = (ServiceState previous, ServiceState current, IntPtr userData) =>
788 ServiceStateChangedEventArgs args = new ServiceStateChangedEventArgs(previous, current);
789 _serviceStateChanged?.Invoke(null, args);
791 ErrorCode error = VcSetServiceStateChangedCb(s_serviceStateDelegate, IntPtr.Zero);
792 if (error != ErrorCode.None)
794 Log.Error(LogTag, "Add ServiceStateChanged Failed with error " + error);
798 _serviceStateChanged += value;
804 ErrorCode error = VcUnsetServiceStateChangedCb();
805 if (error != ErrorCode.None)
807 Log.Error(LogTag, "Remove ServiceStateChanged Failed with error " + error);
810 _serviceStateChanged -= value;
815 /// Event to be invoked when VoiceControl client state changes.
818 /// The State should be Initialized
820 public static event EventHandler<StateChangedEventArgs> StateChanged
824 s_stateDelegate = (State previous, State current, IntPtr userData) =>
826 StateChangedEventArgs args = new StateChangedEventArgs(previous, current);
827 _stateChanged?.Invoke(null, args);
829 ErrorCode error = VcSetStateChangedCb(s_stateDelegate, IntPtr.Zero);
830 if (error != ErrorCode.None)
832 Log.Error(LogTag, "Add StateChanged Failed with error " + error);
836 _stateChanged += value;
842 ErrorCode error = VcUnsetStateChangedCb();
843 if (error != ErrorCode.None)
845 Log.Error(LogTag, "Remove StateChanged Failed with error " + error);
848 _stateChanged -= value;
853 /// Event to be invoked when an error occurs.
856 /// The State should be Initialized
858 public static event EventHandler<ErrorOccuredEventArgs> ErrorOccured
862 s_errorDelegate = (ErrorCode reason, IntPtr userData) =>
864 ErrorOccuredEventArgs args = new ErrorOccuredEventArgs(reason);
865 _errorOccured?.Invoke(null, args);
867 ErrorCode error = VcSetErrorCb(s_errorDelegate, IntPtr.Zero);
868 if (error != ErrorCode.None)
870 Log.Error(LogTag, "Add ErrorOccured Failed with error " + error);
875 _errorOccured += value;
882 ErrorCode error = VcUnsetErrorCb();
883 if (error != ErrorCode.None)
885 Log.Error(LogTag, "Remove ErrorOccured Failed with error " + error);
888 _errorOccured -= value;
893 /// Event to be invoked when default laungage change.
896 /// The State should be Initialized
898 public static event EventHandler<CurrentLanguageChangedEventArgs> CurrentLanguageChanged
902 s_languageDelegate = (IntPtr previousLanguage, IntPtr currentLanguage, IntPtr userData) =>
904 string previousLanguageString = Marshal.PtrToStringAnsi(previousLanguage);
905 string currentLanguageString = Marshal.PtrToStringAnsi(currentLanguage);
906 CurrentLanguageChangedEventArgs args = new CurrentLanguageChangedEventArgs(previousLanguageString, currentLanguageString);
907 _currentLanguageChanged?.Invoke(null, args);
909 ErrorCode error = VcSetCurrentLanguageChangedCb(s_languageDelegate, IntPtr.Zero);
910 if (error != ErrorCode.None)
912 Log.Error(LogTag, "Add CurrentLanguageChanged Failed with error " + error);
917 _currentLanguageChanged += value;
923 ErrorCode error = VcUnsetCurrentLanguageChangedCb();
924 if (error != ErrorCode.None)
926 Log.Error(LogTag, "Remove CurrentLanguageChanged Failed with error " + error);
929 _currentLanguageChanged -= value;