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 /// http://tizen.org/privilege/recorder
235 /// The State must be Initialized or Ready.
237 public static string GetCurrentLanaguge
241 string currentLanaguge;
243 ErrorCode error = VcGetCurrentLanguage(out currentLanaguge);
244 if (error != ErrorCode.None)
246 Log.Error(LogTag, "CurrentLanaguge Failed with error " + error);
250 return currentLanaguge;
255 /// Gets current state of voice control client.
258 /// http://tizen.org/privilege/recorder
261 /// The State must be Initialized or Ready.
263 public static State GetState
269 ErrorCode error = VcGetState(out state);
270 if (error != ErrorCode.None)
272 Log.Error(LogTag, "GetState Failed with error " + error);
273 return State.Unavailable;
281 /// Gets current state of voice control service.
284 /// http://tizen.org/privilege/recorder
287 /// The State must be Ready.
289 public static ServiceState GetServiceState
295 ErrorCode error = VcGetServiceState(out state);
296 if (error != ErrorCode.None)
298 Log.Error(LogTag, "GetServiceState Failed with error " + error);
299 return ServiceState.Unavailable;
307 /// Sets the invocation name.
310 /// http://tizen.org/privilege/recorder
313 /// Invocation name is used to activate background commands. The invocation name can be the same as the application name or any other phrase.
314 /// For example, an application "Tizen Sample" has a background command, "Play music", and the invocation name of the application is set to "Tizen Sample".
315 /// In order to activate the background command, users can say "Tizen Sample, Play music". The invocation name is dependent on the current language.
316 /// For example, if the current language is "en_US"(English), the invocation name is also "en_US".
317 /// If the current language is "ja_JP"(Japanese) and the invocation name is "en_US", the invocation name will not be recognized.
318 /// This function should be called before SetCommandList().
320 /// <param name="name">Invocation name that an application wants to be invoked by</param>
321 /// <exception cref="InvalidOperationException">
322 /// This Exception can be due to the following reaons
323 /// 1. Invalid parameter
326 /// 4. Permission Denied
329 /// The State must be Ready.
331 public static void SetInvocationName(string name)
333 ErrorCode error = VcSetInvocationName(name);
334 if (error != ErrorCode.None)
336 Log.Error(LogTag, "SetInvocationName Failed with error " + error);
337 throw ExceptionFactory.CreateException(error);
342 /// Initializes voice control.
345 /// http://tizen.org/privilege/recorder
347 /// <exception cref="InvalidOperationException">
348 /// This Exception can be due to the following reaons
350 /// 2. Operation Failed
352 /// 4. Permission Denied
355 /// The State will be Initialized.
357 public static void Initialize()
359 ErrorCode error = VcInitialize();
360 if (error != ErrorCode.None)
362 Log.Error(LogTag, "Initialize Failed with error " + error);
363 throw ExceptionFactory.CreateException(error);
368 /// Deinitializes voice control.
371 /// http://tizen.org/privilege/recorder
373 /// <exception cref="InvalidOperationException">
374 /// This Exception can be due to the following reaons
375 /// 1. Operation Failed
378 /// 4. Permission Denied
380 public static void Deinitialize()
382 ErrorCode error = VcDeinitialize();
383 if (error != ErrorCode.None)
385 Log.Error(LogTag, "Deinitialize Failed with error " + error);
386 throw ExceptionFactory.CreateException(error);
391 /// Connects the voice control service.
394 /// http://tizen.org/privilege/recorder
396 /// <exception cref="InvalidOperationException">
397 /// This Exception can be due to the following reaons
398 /// 1. Operation Failed
400 /// 3. Permission Denied
404 /// The State should be Initialized
407 /// The State will be Ready
409 public static void Prepare()
411 ErrorCode error = VcPrepare();
412 if (error != ErrorCode.None)
414 Log.Error(LogTag, "Prepare Failed with error " + error);
415 throw ExceptionFactory.CreateException(error);
420 /// Disconnects the voice control service.
423 /// http://tizen.org/privilege/recorder
425 /// <exception cref="InvalidOperationException">
426 /// This Exception can be due to the following reaons
428 /// 2. Permission Denied
432 /// The State should be Ready
435 /// The State should be Initialized
437 public static void Unprepare()
439 ErrorCode error = VcUnprepare();
440 if (error != ErrorCode.None)
442 Log.Error(LogTag, "Unprepare Failed with error " + error);
443 throw ExceptionFactory.CreateException(error);
448 /// Retrieves all supported languages.
449 /// A language is specified as an ISO 3166 alpha-2 two letter country-code
450 /// followed by ISO 639-1 for the two-letter language code.
451 /// For example, "ko_KR" for Korean, "en_US" for American English.
454 /// http://tizen.org/privilege/recorder
456 /// <exception cref="InvalidOperationException">
457 /// This Exception can be due to the following reaons
458 /// 1. Operation Failed
460 /// 3. Permission Denied
464 /// The State should be Ready or Initialized
466 public static IEnumerable<string> GetSupportedLangauges()
468 s_supportedLanguages = new List<string>();
469 s_supportedLanguagesCb = (IntPtr language, IntPtr userData) =>
471 string languageStr = Marshal.PtrToStringAnsi(language);
472 s_supportedLanguages.Add(languageStr);
475 ErrorCode error = VcForeachSupportedLanguages(s_supportedLanguagesCb, IntPtr.Zero);
476 if (error != ErrorCode.None)
478 Log.Error(LogTag, "GetSupportedLangauges Failed with error " + error);
479 throw ExceptionFactory.CreateException(error);
482 return s_supportedLanguages;
486 /// Gets the system command list.
489 /// The Command List else null in case of no System Commands
492 /// http://tizen.org/privilege/recorder
495 /// In the system command list, there are system commands predefined by product manufacturers.
496 /// Those commands have the highest priority. Therefore, the user can not set any commands same with the system commands.
498 /// <exception cref="InvalidOperationException">
499 /// This Exception can be due to the following reaons
501 /// 2. Permission Denied
505 /// The State should be Ready
507 public static VoiceCommandList GetSytemCommandList()
509 IntPtr handle = IntPtr.Zero;
510 ErrorCode error = VcGetSystemCommandList(out handle);
511 if (error != ErrorCode.None)
513 Log.Error(LogTag, "GetSystemCommandList Failed with error " + error);
514 throw ExceptionFactory.CreateException(error);
517 if (handle == IntPtr.Zero)
519 Log.Error(LogTag, "GetSystemCommandList handle is null");
523 SafeCommandListHandle list = new SafeCommandListHandle(handle);
524 return new VoiceCommandList(list);
528 /// Requests to start the dialogue.
529 /// Using this function, the developer can request starting the dialogue to the framework.
530 /// 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.
531 /// 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.
532 /// Also, the developer can set whether the dialogue starts automatically or not, using autoStart.
533 /// If the developer sets autoStart as true, the framework will start to record next speech and continue the dialogue.
536 /// http://tizen.org/privilege/recorder
539 /// If autoStart is true, the recognition will start again. In this case, it can be restarted up to 4 times.
541 /// <param name="dispText"> Text to be displayed on the screen/// </param>
542 /// <param name="uttText">Text to be spoken</param>
543 /// <param name="autoStart">A variable for setting whether the dialog session will be restarted automatically or not</param>
544 /// <exception cref="InvalidOperationException">
545 /// This Exception can be due to the following reaons
547 /// 2. Permission Denied
549 /// 4. Invalid parameter
552 /// The State should be Ready
554 public static void RequestDialog(string dispText, string uttText, bool autoStart)
556 ErrorCode error = VcRequestDialog(dispText, uttText, autoStart);
557 if (error != ErrorCode.None)
559 Log.Error(LogTag, "RequestDialog Failed with error " + error);
560 throw ExceptionFactory.CreateException(error);
565 /// Sets command list.
568 /// http://tizen.org/privilege/recorder
571 /// The command type is valid for CommandType 'Foreground' or 'Background'.
572 /// The matched commands of command list should be set and they should include type and command text at least.
574 /// <param name="list">Command list</param>
575 /// <param name="type">Command type</param>
576 /// <exception cref="InvalidOperationException">
577 /// This Exception can be due to the following reaons
579 /// 2. Permission Denied
581 /// 4. Invalid parameter
584 /// The State should be Ready
586 public static void SetCommandList(VoiceCommandList list, CommandType type)
588 if ((type == CommandType.Foreground) || (type == CommandType.Background))
590 ErrorCode error = VcSetCommandList(list._handle, (VoiceCommandType)type);
591 if (error != ErrorCode.None)
593 Log.Error(LogTag, "SetCommandList Failed with error " + error);
594 throw ExceptionFactory.CreateException(error);
600 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
605 /// Unsets command list.
608 /// http://tizen.org/privilege/recorder
610 /// <param name="type">Command type</param>
611 /// <exception cref="InvalidOperationException">
612 /// This Exception can be due to the following reaons
614 /// 2. Permission Denied
616 /// 4. Invalid parameter
619 /// The State should be Ready
621 public static void UnsetCommandList(CommandType type)
623 if ((type == CommandType.Foreground) || (type == CommandType.Background))
625 VoiceCommandType commandType = VoiceCommandType.Foreground;
626 if (type == CommandType.Background)
627 commandType = VoiceCommandType.BackGround;
628 ErrorCode error = VcUnsetCommandList(commandType);
629 if (error != ErrorCode.None)
631 Log.Error(LogTag, "UnsetCommandList Failed with error " + error);
632 throw ExceptionFactory.CreateException(error);
638 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
643 /// Gets the recognition result.
646 /// http://tizen.org/privilege/recorder
648 /// <param name="resultDelegate">
649 /// Callback function to get recognition result
651 /// <exception cref="InvalidOperationException">
652 /// This Exception can be due to the following reaons
655 /// 3. Invalid parameter
658 /// The State should be Ready
660 public static void GetResult(RecognitionResultDelegate resultDelegate)
662 s_resultCb = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
664 VoiceCommandList list = new VoiceCommandList(new SafeCommandListHandle(cmdList));
665 string resultStr = Marshal.PtrToStringAnsi(result);
666 resultDelegate(evt, list, resultStr);
668 ErrorCode error = VcGetResult(s_resultCb, IntPtr.Zero);
669 if (error != ErrorCode.None)
671 Log.Error(LogTag, "GetResult Failed with error " + error);
672 throw ExceptionFactory.CreateException(error);
677 /// Event to be invoked when the recognition is done.
680 /// The State should be Initialized
682 public static event EventHandler<RecognitionResultEventArgs> RecognitionResult
686 s_resultDelegate = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
688 Log.Info(LogTag, "Recognition Result Event Triggered");
689 if ((cmdList != null) && (result != null))
691 RecognitionResultEventArgs args = new RecognitionResultEventArgs(evt, cmdList, result);
692 _recognitionResult?.Invoke(null, args);
696 Log.Info(LogTag, "Recognition Result Event null received");
699 ErrorCode error = VcSetResultCb(s_resultDelegate, IntPtr.Zero);
700 if (error != ErrorCode.None)
702 Log.Error(LogTag, "Add RecognitionResult Failed with error " + error);
706 _recognitionResult += value;
712 ErrorCode error = VcUnsetResultCb();
713 if (error != ErrorCode.None)
715 Log.Error(LogTag, "Remove RecognitionResult Failed with error " + error);
718 _recognitionResult -= value;
723 /// Event to be invoked when VoiceControl service state changes.
726 /// The State should be Initialized
728 public static event EventHandler<ServiceStateChangedEventArgs> ServiceStateChanged
732 s_serviceStateDelegate = (ServiceState previous, ServiceState current, IntPtr userData) =>
734 ServiceStateChangedEventArgs args = new ServiceStateChangedEventArgs(previous, current);
735 _serviceStateChanged?.Invoke(null, args);
737 ErrorCode error = VcSetServiceStateChangedCb(s_serviceStateDelegate, IntPtr.Zero);
738 if (error != ErrorCode.None)
740 Log.Error(LogTag, "Add ServiceStateChanged Failed with error " + error);
744 _serviceStateChanged += value;
750 ErrorCode error = VcUnsetServiceStateChangedCb();
751 if (error != ErrorCode.None)
753 Log.Error(LogTag, "Remove ServiceStateChanged Failed with error " + error);
756 _serviceStateChanged -= value;
761 /// Event to be invoked when VoiceControl client state changes.
764 /// The State should be Initialized
766 public static event EventHandler<StateChangedEventArgs> StateChanged
770 s_stateDelegate = (State previous, State current, IntPtr userData) =>
772 StateChangedEventArgs args = new StateChangedEventArgs(previous, current);
773 _stateChanged?.Invoke(null, args);
775 ErrorCode error = VcSetStateChangedCb(s_stateDelegate, IntPtr.Zero);
776 if (error != ErrorCode.None)
778 Log.Error(LogTag, "Add StateChanged Failed with error " + error);
782 _stateChanged += value;
788 ErrorCode error = VcUnsetStateChangedCb();
789 if (error != ErrorCode.None)
791 Log.Error(LogTag, "Remove StateChanged Failed with error " + error);
794 _stateChanged -= value;
799 /// Event to be invoked when an error occurs.
802 /// The State should be Initialized
804 public static event EventHandler<ErrorOccuredEventArgs> ErrorOccured
808 s_errorDelegate = (ErrorCode reason, IntPtr userData) =>
810 ErrorOccuredEventArgs args = new ErrorOccuredEventArgs(reason);
811 _errorOccured?.Invoke(null, args);
813 ErrorCode error = VcSetErrorCb(s_errorDelegate, IntPtr.Zero);
814 if (error != ErrorCode.None)
816 Log.Error(LogTag, "Add ErrorOccured Failed with error " + error);
821 _errorOccured += value;
828 ErrorCode error = VcUnsetErrorCb();
829 if (error != ErrorCode.None)
831 Log.Error(LogTag, "Remove ErrorOccured Failed with error " + error);
834 _errorOccured -= value;
839 /// Event to be invoked when default laungage change.
842 /// The State should be Initialized
844 public static event EventHandler<CurrentLanguageChangedEventArgs> CurrentLanguageChanged
848 s_languageDelegate = (IntPtr previousLanguage, IntPtr currentLanguage, IntPtr userData) =>
850 string previousLanguageString = Marshal.PtrToStringAnsi(previousLanguage);
851 string currentLanguageString = Marshal.PtrToStringAnsi(currentLanguage);
852 CurrentLanguageChangedEventArgs args = new CurrentLanguageChangedEventArgs(previousLanguageString, currentLanguageString);
853 _currentLanguageChanged?.Invoke(null, args);
855 ErrorCode error = VcSetCurrentLanguageChangedCb(s_languageDelegate, IntPtr.Zero);
856 if (error != ErrorCode.None)
858 Log.Error(LogTag, "Add CurrentLanguageChanged Failed with error " + error);
863 _currentLanguageChanged += value;
869 ErrorCode error = VcUnsetCurrentLanguageChangedCb();
870 if (error != ErrorCode.None)
872 Log.Error(LogTag, "Remove CurrentLanguageChanged Failed with error " + error);
875 _currentLanguageChanged -= value;