e7ea9f5313c1650471543aced95b4b72368be29d
[platform/core/csapi/uix-voice-control.git] / Tizen.Uix.VoiceControl / Tizen.Uix.VoiceControl / VoiceControlClient.cs
1 /*
2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17 using System;
18 using System.Collections.Generic;
19 using System.Runtime.InteropServices;
20 using static Interop.VoiceControl;
21 using static Interop.VoiceControlCommand;
22
23 namespace Tizen.Uix.VoiceControl
24 {
25     /// <summary>
26     /// Enum for Error values that can occur
27     /// </summary>
28     public enum Error
29     {
30         /// <summary>
31         /// Successful, No error
32         /// </summary>
33         None,
34         /// <summary>
35         /// Out of Memory
36         /// </summary>
37         OutOfMemory,
38         /// <summary>
39         /// I/O error
40         /// </summary>
41         IoError,
42         /// <summary>
43         /// Invalid parameter
44         /// </summary>
45         InvalidParameter,
46         /// <summary>
47         /// No answer from the STT service
48         /// </summary>
49         TimedOut,
50         /// <summary>
51         /// Device or resource busy
52         /// </summary>
53         RecorderBusy,
54         /// <summary>
55         /// Permission denied
56         /// </summary>
57         PermissionDenied,
58         /// <summary>
59         /// VC NOT supported
60         /// </summary>
61         NotSupported,
62         /// <summary>
63         /// Invalid state
64         /// </summary>
65         InvalidState,
66         /// <summary>
67         /// Invalid language
68         /// </summary>
69         InvalidLanguage,
70         /// <summary>
71         /// No available engine
72         /// </summary>
73         EngineNotFound,
74         /// <summary>
75         /// Operation failed
76         /// </summary>
77         OperationFailed,
78         /// <summary>
79         /// Operation Rejected
80         /// </summary>
81         OperationRejected,
82         /// <summary>
83         /// List reached end
84         /// </summary>
85         IterationEnd,
86         /// <summary>
87         /// List Empty
88         /// </summary>
89         Empty,
90         /// <summary>
91         /// Service reset
92         /// </summary>
93         ServiceReset,
94         /// <summary>
95         /// Progress to ready is not finished
96         /// </summary>
97         InProgressToReady,
98         /// <summary>
99         /// Progress to recording is not finished
100         /// </summary>
101         InProgressToRecording,
102         /// <summary>
103         /// Progress to processing is not finished
104         /// </summary>
105         InProgressToProcessing
106     };
107
108     /// <summary>
109     /// Enumeration for the client state.
110     /// </summary>
111     public enum State
112     {
113         /// <summary>
114         /// 'None' state
115         /// </summary>
116         None = 0,
117         /// <summary>
118         /// 'Initialized' state
119         /// </summary>
120         Initialized = 1,
121         /// <summary>
122         /// 'Ready' state
123         /// </summary>
124         Ready = 2,
125         /// <summary>
126         /// state cannot be determined
127         /// </summary>
128         Unavailable
129     };
130
131     /// <summary>
132     /// Enumerations of service state.
133     /// </summary>
134     public enum ServiceState
135     {
136         /// <summary>
137         /// 'None' state
138         /// </summary>
139         None = 0,
140         /// <summary>
141         /// 'Ready' state
142         /// </summary>
143         Ready = 1,
144         /// <summary>
145         /// 'Recording' state
146         /// </summary>
147         Recording = 2,
148         /// <summary>
149         /// 'Processing' state
150         /// </summary>
151         Processing = 3,
152         /// <summary>
153         /// state cannot be determined
154         /// </summary>
155         Unavailable
156     };
157
158     /// <summary>
159     /// Enumerations of result event.
160     /// </summary>
161     public enum ResultEvent
162     {
163         /// <summary>
164         /// Normal result
165         /// </summary>
166         Success = 0,
167         /// <summary>
168         /// Rejected result
169         /// </summary>
170         Rejected = 1
171     };
172
173     /// <summary>
174     /// Enumerations of command type.
175     /// </summary>
176     public enum CommandType
177     {
178         /// <summary>
179         /// Foreground command by client
180         /// </summary>
181         Foreground = 1,
182         /// <summary>
183         /// Background command by client
184         /// </summary>
185         Background = 2,
186         /// <summary>
187         /// Undefined command
188         /// </summary>
189         Undefined = -1
190     };
191
192     /// <summary>
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.
195     /// </summary>
196     public static class VoiceControlClient
197     {
198         /// <summary>
199         /// Called when client gets the recognition result.
200         /// </summary>
201         /// <remarks>
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.
204         /// </remarks>
205         /// <param name="evt">The ResultEvent</param>
206         /// <param name="cmdList">Command List</param>
207         /// <param name="result">Result</param>
208
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;
223
224         /// <summary>
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
230         /// </summary>
231         /// <value>
232         /// Current language in voice control.
233         /// </value>
234         /// <privilege>
235         /// http://tizen.org/privilege/recorder
236         /// </privilege>
237         /// <pre>
238         /// The State must be Initialized or Ready.
239         /// </pre>
240         public static string CurrentLanguage
241         {
242             get
243             {
244                 string currentLanguage;
245
246                 ErrorCode error = VcGetCurrentLanguage(out currentLanguage);
247                 if (error != ErrorCode.None)
248                 {
249                     Log.Error(LogTag, "CurrentLanguage Failed with error " + error);
250                     return "";
251                 }
252
253                 return currentLanguage;
254             }
255         }
256
257         /// <summary>
258         /// Gets current state of voice control client.
259         /// </summary>
260         /// <value>
261         /// Current state of voice control client.
262         /// </value>
263         /// <privilege>
264         /// http://tizen.org/privilege/recorder
265         /// </privilege>
266         /// <pre>
267         /// The State must be Initialized or Ready.
268         /// </pre>
269         public static State State
270         {
271             get
272             {
273                 State state;
274
275                 ErrorCode error = VcGetState(out state);
276                 if (error != ErrorCode.None)
277                 {
278                     Log.Error(LogTag, "State Failed with error " + error);
279                     return State.Unavailable;
280                 }
281
282                 return state;
283             }
284         }
285
286         /// <summary>
287         /// Gets current state of voice control service.
288         /// </summary>
289         /// <value>
290         /// Current state of voice control service.
291         /// </value>
292         /// <privilege>
293         /// http://tizen.org/privilege/recorder
294         /// </privilege>
295         /// <pre>
296         /// The State must be Ready.
297         /// </pre>
298         public static ServiceState ServiceState
299         {
300             get
301             {
302                 ServiceState state;
303
304                 ErrorCode error = VcGetServiceState(out state);
305                 if (error != ErrorCode.None)
306                 {
307                     Log.Error(LogTag, "ServiceState Failed with error " + error);
308                     return ServiceState.Unavailable;
309                 }
310
311                 return state;
312             }
313         }
314
315         /// <summary>
316         /// Sets the invocation name.
317         /// </summary>
318         /// <privilege>
319         /// http://tizen.org/privilege/recorder
320         /// </privilege>
321         /// <privlevel>
322         /// public
323         /// </privlevel>
324         /// <feature>
325         /// http://tizen.org/feature/speech.control
326         /// http://tizen.org/feature/microphone
327         /// </feature>
328         /// <remarks>
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().
335         /// </remarks>
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>
341         /// <pre>
342         /// The State must be Ready.
343         /// </pre>
344         public static void SetInvocationName(string name)
345         {
346             ErrorCode error = VcSetInvocationName(name);
347             if (error != ErrorCode.None)
348             {
349                 Log.Error(LogTag, "SetInvocationName Failed with error " + error);
350                 throw ExceptionFactory.CreateException(error);
351             }
352         }
353
354         /// <summary>
355         /// Initializes voice control.
356         /// </summary>
357         /// <privilege>
358         /// http://tizen.org/privilege/recorder
359         /// </privilege>
360         /// <privlevel>
361         /// public
362         /// </privlevel>
363         /// <feature>
364         /// http://tizen.org/feature/speech.control
365         /// http://tizen.org/feature/microphone
366         /// </feature>
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>
371         /// <post>
372         /// The State will be Initialized.
373         /// </post>
374         public static void Initialize()
375         {
376             ErrorCode error = VcInitialize();
377             if (error != ErrorCode.None)
378             {
379                 Log.Error(LogTag, "Initialize Failed with error " + error);
380                 throw ExceptionFactory.CreateException(error);
381             }
382         }
383
384         /// <summary>
385         /// Deinitializes voice control.
386         /// </summary>
387         /// <privilege>
388         /// http://tizen.org/privilege/recorder
389         /// </privilege>
390         /// <privlevel>
391         /// public
392         /// </privlevel>
393         /// <feature>
394         /// http://tizen.org/feature/speech.control
395         /// http://tizen.org/feature/microphone
396         /// </feature>
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()
402         {
403             ErrorCode error = VcDeinitialize();
404             if (error != ErrorCode.None)
405             {
406                 Log.Error(LogTag, "Deinitialize Failed with error " + error);
407                 throw ExceptionFactory.CreateException(error);
408             }
409         }
410
411         /// <summary>
412         /// Connects the voice control service.
413         /// </summary>
414         /// <privilege>
415         /// http://tizen.org/privilege/recorder
416         /// </privilege>
417         /// <privlevel>
418         /// public
419         /// </privlevel>
420         /// <feature>
421         /// http://tizen.org/feature/speech.control
422         /// http://tizen.org/feature/microphone
423         /// </feature>
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>
428         /// <pre>
429         /// The State should be Initialized
430         /// </pre>
431         /// <post>
432         /// The State will be Ready
433         /// </post>
434         public static void Prepare()
435         {
436             ErrorCode error = VcPrepare();
437             if (error != ErrorCode.None)
438             {
439                 Log.Error(LogTag, "Prepare Failed with error " + error);
440                 throw ExceptionFactory.CreateException(error);
441             }
442         }
443
444         /// <summary>
445         /// Disconnects the voice control service.
446         /// </summary>
447         /// <privilege>
448         /// http://tizen.org/privilege/recorder
449         /// </privilege>
450         /// <privlevel>
451         /// public
452         /// </privlevel>
453         /// <feature>
454         /// http://tizen.org/feature/speech.control
455         /// http://tizen.org/feature/microphone
456         /// </feature>
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>
460         /// <pre>
461         /// The State should be Ready
462         /// </pre>
463         /// <post>
464         /// The State should be Initialized
465         /// </post>
466         public static void Unprepare()
467         {
468             ErrorCode error = VcUnprepare();
469             if (error != ErrorCode.None)
470             {
471                 Log.Error(LogTag, "Unprepare Failed with error " + error);
472                 throw ExceptionFactory.CreateException(error);
473             }
474         }
475
476         /// <summary>
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.
481         /// </summary>
482         /// <privilege>
483         /// http://tizen.org/privilege/recorder
484         /// </privilege>
485         /// <privlevel>
486         /// public
487         /// </privlevel>
488         /// <feature>
489         /// http://tizen.org/feature/speech.control
490         /// http://tizen.org/feature/microphone
491         /// </feature>
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>
496         /// <pre>
497         /// The State should be Ready or Initialized
498         /// </pre>
499         public static IEnumerable<string> GetSupportedLanguages()
500         {
501             s_supportedLanguages = new List<string>();
502             s_supportedLanguagesCb = (IntPtr language, IntPtr userData) =>
503             {
504                 string languageStr = Marshal.PtrToStringAnsi(language);
505                 s_supportedLanguages.Add(languageStr);
506                 return true;
507             };
508             ErrorCode error = VcForeachSupportedLanguages(s_supportedLanguagesCb, IntPtr.Zero);
509             if (error != ErrorCode.None)
510             {
511                 Log.Error(LogTag, "GetSupportedLanguages Failed with error " + error);
512                 throw ExceptionFactory.CreateException(error);
513             }
514
515             return s_supportedLanguages;
516         }
517
518         /// <summary>
519         /// Gets the system command list.
520         /// </summary>
521         /// <returns>
522         /// The Command List else null in case of no System Commands
523         /// </returns>
524         /// <privilege>
525         /// http://tizen.org/privilege/recorder
526         /// </privilege>
527         /// <privlevel>
528         /// public
529         /// </privlevel>
530         /// <feature>
531         /// http://tizen.org/feature/speech.control
532         /// http://tizen.org/feature/microphone
533         /// </feature>
534         /// <remarks>
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.
537         /// </remarks>
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>
542         /// <pre>
543         /// The State should be Ready
544         /// </pre>
545         public static VoiceCommandList GetSystemCommandList()
546         {
547             IntPtr handle = IntPtr.Zero;
548             ErrorCode error = VcGetSystemCommandList(out handle);
549             if (error != ErrorCode.None)
550             {
551                 Log.Error(LogTag, "GetSystemCommandList Failed with error " + error);
552                 throw ExceptionFactory.CreateException(error);
553             }
554
555             if (handle == IntPtr.Zero)
556             {
557                 Log.Error(LogTag, "GetSystemCommandList handle is null");
558                 return null;
559             }
560
561             SafeCommandListHandle list = new SafeCommandListHandle(handle);
562             return new VoiceCommandList(list);
563         }
564
565         /// <summary>
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.
572         /// </summary>
573         /// <privilege>
574         /// http://tizen.org/privilege/recorder
575         /// </privilege>
576         /// <privlevel>
577         /// public
578         /// </privlevel>
579         /// <feature>
580         /// http://tizen.org/feature/speech.control
581         /// http://tizen.org/feature/microphone
582         /// </feature>
583         /// <remarks>
584         /// If autoStart is true, the recognition will start again. In this case, it can be restarted up to 4 times.
585         /// </remarks>
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>
593         /// <pre>
594         /// The State should be Ready
595         /// </pre>
596         public static void RequestDialog(string dispText, string uttText, bool autoStart)
597         {
598             ErrorCode error = VcRequestDialog(dispText, uttText, autoStart);
599             if (error != ErrorCode.None)
600             {
601                 Log.Error(LogTag, "RequestDialog Failed with error " + error);
602                 throw ExceptionFactory.CreateException(error);
603             }
604         }
605
606         /// <summary>
607         /// Sets command list.
608         /// </summary>
609         /// <privilege>
610         /// http://tizen.org/privilege/recorder
611         /// </privilege>
612         /// <privlevel>
613         /// public
614         /// </privlevel>
615         /// <feature>
616         /// http://tizen.org/feature/speech.control
617         /// http://tizen.org/feature/microphone
618         /// </feature>
619         /// <remarks>
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.
622         /// </remarks>
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>
629         /// <pre>
630         /// The State should be Ready
631         /// </pre>
632         public static void SetCommandList(VoiceCommandList list, CommandType type)
633         {
634             if ((type == CommandType.Foreground) || (type == CommandType.Background))
635             {
636                 ErrorCode error = VcSetCommandList(list._handle, (VoiceCommandType)type);
637                 if (error != ErrorCode.None)
638                 {
639                     Log.Error(LogTag, "SetCommandList Failed with error " + error);
640                     throw ExceptionFactory.CreateException(error);
641                 }
642             }
643
644             else
645             {
646                 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
647             }
648         }
649
650         /// <summary>
651         /// Unsets command list.
652         /// </summary>
653         /// <privilege>
654         /// http://tizen.org/privilege/recorder
655         /// </privilege>
656         /// <privlevel>
657         /// public
658         /// </privlevel>
659         /// <feature>
660         /// http://tizen.org/feature/speech.control
661         /// http://tizen.org/feature/microphone
662         /// </feature>
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>
668         /// <pre>
669         /// The State should be Ready
670         /// </pre>
671         public static void UnsetCommandList(CommandType type)
672         {
673             if ((type == CommandType.Foreground) || (type == CommandType.Background))
674             {
675                 VoiceCommandType commandType = VoiceCommandType.Foreground;
676                 if (type == CommandType.Background)
677                     commandType = VoiceCommandType.BackGround;
678                 ErrorCode error = VcUnsetCommandList(commandType);
679                 if (error != ErrorCode.None)
680                 {
681                     Log.Error(LogTag, "UnsetCommandList Failed with error " + error);
682                     throw ExceptionFactory.CreateException(error);
683                 }
684             }
685
686             else
687             {
688                 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
689             }
690         }
691
692         /// <summary>
693         /// Gets the recognition result.
694         /// </summary>
695         /// <privilege>
696         /// http://tizen.org/privilege/recorder
697         /// </privilege>
698         /// <privlevel>
699         /// public
700         /// </privlevel>
701         /// <feature>
702         /// http://tizen.org/feature/speech.control
703         /// http://tizen.org/feature/microphone
704         /// </feature>
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>
709         /// <pre>
710         /// The State should be Ready
711         /// </pre>
712         public static RecognitionResult GetResult()
713         {
714             s_recognitionResult = null;
715             s_resultCb = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
716             {
717                 s_recognitionResult = new RecognitionResult(evt, cmdList, result);
718             };
719             ErrorCode error = VcGetResult(s_resultCb, IntPtr.Zero);
720             if (error != ErrorCode.None)
721             {
722                 Log.Error(LogTag, "GetResult Failed with error " + error);
723                 throw ExceptionFactory.CreateException(error);
724             }
725
726             return s_recognitionResult;
727         }
728
729         /// <summary>
730         /// Event to be invoked when the recognition is done.
731         /// </summary>
732         /// <pre>
733         /// The State should be Initialized
734         /// </pre>
735         public static event EventHandler<RecognitionResultEventArgs> RecognitionResult
736         {
737             add
738             {
739                 s_resultDelegate = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
740                 {
741                     Log.Info(LogTag, "Recognition Result Event Triggered");
742                     if ((cmdList != null) && (result != null))
743                     {
744                         RecognitionResultEventArgs args = new RecognitionResultEventArgs(new RecognitionResult( evt, cmdList, result));
745                         _recognitionResult?.Invoke(null, args);
746                     }
747                     else
748                     {
749                         Log.Info(LogTag, "Recognition Result Event null received");
750                     }
751                 };
752                 ErrorCode error = VcSetResultCb(s_resultDelegate, IntPtr.Zero);
753                 if (error != ErrorCode.None)
754                 {
755                     Log.Error(LogTag, "Add RecognitionResult Failed with error " + error);
756                 }
757                 else
758                 {
759                     _recognitionResult += value;
760                 }
761             }
762
763             remove
764             {
765                 ErrorCode error = VcUnsetResultCb();
766                 if (error != ErrorCode.None)
767                 {
768                     Log.Error(LogTag, "Remove RecognitionResult Failed with error " + error);
769                 }
770
771                 _recognitionResult -= value;
772             }
773         }
774
775         /// <summary>
776         /// Event to be invoked when VoiceControl service state changes.
777         /// </summary>
778         /// <pre>
779         /// The State should be Initialized
780         /// </pre>
781         public static event EventHandler<ServiceStateChangedEventArgs> ServiceStateChanged
782         {
783             add
784             {
785                 s_serviceStateDelegate = (ServiceState previous, ServiceState current, IntPtr userData) =>
786                 {
787                     ServiceStateChangedEventArgs args = new ServiceStateChangedEventArgs(previous, current);
788                     _serviceStateChanged?.Invoke(null, args);
789                 };
790                 ErrorCode error = VcSetServiceStateChangedCb(s_serviceStateDelegate, IntPtr.Zero);
791                 if (error != ErrorCode.None)
792                 {
793                     Log.Error(LogTag, "Add ServiceStateChanged Failed with error " + error);
794                 }
795                 else
796                 {
797                     _serviceStateChanged += value;
798                 }
799             }
800
801             remove
802             {
803                 ErrorCode error = VcUnsetServiceStateChangedCb();
804                 if (error != ErrorCode.None)
805                 {
806                     Log.Error(LogTag, "Remove ServiceStateChanged Failed with error " + error);
807                 }
808
809                 _serviceStateChanged -= value;
810             }
811         }
812
813         /// <summary>
814         /// Event to be invoked when VoiceControl client state changes.
815         /// </summary>
816         /// <pre>
817         /// The State should be Initialized
818         /// </pre>
819         public static event EventHandler<StateChangedEventArgs> StateChanged
820         {
821             add
822             {
823                 s_stateDelegate = (State previous, State current, IntPtr userData) =>
824                 {
825                     StateChangedEventArgs args = new StateChangedEventArgs(previous, current);
826                     _stateChanged?.Invoke(null, args);
827                 };
828                 ErrorCode error = VcSetStateChangedCb(s_stateDelegate, IntPtr.Zero);
829                 if (error != ErrorCode.None)
830                 {
831                     Log.Error(LogTag, "Add StateChanged Failed with error " + error);
832                 }
833                 else
834                 {
835                     _stateChanged += value;
836                 }
837             }
838
839             remove
840             {
841                 ErrorCode error = VcUnsetStateChangedCb();
842                 if (error != ErrorCode.None)
843                 {
844                     Log.Error(LogTag, "Remove StateChanged Failed with error " + error);
845                 }
846
847                 _stateChanged -= value;
848             }
849         }
850
851         /// <summary>
852         /// Event to be invoked when an error occurs.
853         /// </summary>
854         /// <pre>
855         /// The State should be Initialized
856         /// </pre>
857         public static event EventHandler<ErrorOccuredEventArgs> ErrorOccured
858         {
859             add
860             {
861                 s_errorDelegate = (ErrorCode reason, IntPtr userData) =>
862             {
863                 ErrorOccuredEventArgs args = new ErrorOccuredEventArgs(reason);
864                 _errorOccured?.Invoke(null, args);
865             };
866                 ErrorCode error = VcSetErrorCb(s_errorDelegate, IntPtr.Zero);
867                 if (error != ErrorCode.None)
868                 {
869                     Log.Error(LogTag, "Add ErrorOccured Failed with error " + error);
870                 }
871
872                 else
873                 {
874                     _errorOccured += value;
875                 }
876             }
877
878
879             remove
880             {
881                 ErrorCode error = VcUnsetErrorCb();
882                 if (error != ErrorCode.None)
883                 {
884                     Log.Error(LogTag, "Remove ErrorOccured Failed with error " + error);
885                 }
886
887                 _errorOccured -= value;
888             }
889         }
890
891         /// <summary>
892         /// Event to be invoked when default laungage change.
893         /// </summary>
894         /// <pre>
895         /// The State should be Initialized
896         /// </pre>
897         public static event EventHandler<CurrentLanguageChangedEventArgs> CurrentLanguageChanged
898         {
899             add
900             {
901                 s_languageDelegate = (IntPtr previousLanguage, IntPtr currentLanguage, IntPtr userData) =>
902             {
903                 string previousLanguageString = Marshal.PtrToStringAnsi(previousLanguage);
904                 string currentLanguageString = Marshal.PtrToStringAnsi(currentLanguage);
905                 CurrentLanguageChangedEventArgs args = new CurrentLanguageChangedEventArgs(previousLanguageString, currentLanguageString);
906                 _currentLanguageChanged?.Invoke(null, args);
907             };
908                 ErrorCode error = VcSetCurrentLanguageChangedCb(s_languageDelegate, IntPtr.Zero);
909                 if (error != ErrorCode.None)
910                 {
911                     Log.Error(LogTag, "Add CurrentLanguageChanged Failed with error " + error);
912                 }
913
914                 else
915                 {
916                     _currentLanguageChanged += value;
917                 }
918             }
919
920             remove
921             {
922                 ErrorCode error = VcUnsetCurrentLanguageChangedCb();
923                 if (error != ErrorCode.None)
924                 {
925                     Log.Error(LogTag, "Remove CurrentLanguageChanged Failed with error " + error);
926                 }
927
928                 _currentLanguageChanged -= value;
929             }
930         }
931     }
932 }