Modification of GetResult API
[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         public delegate void RecognitionResultDelegate(ResultEvent evt, VoiceCommandList cmdList, string result);
209
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;
224
225         /// <summary>
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
231         /// </summary>
232         /// <value>
233         /// Current language in voice control.
234         /// </value>
235         /// <privilege>
236         /// http://tizen.org/privilege/recorder
237         /// </privilege>
238         /// <precondition>
239         /// The State must be Initialized or Ready.
240         /// </precondition>
241         public static string CurrentLanguage
242         {
243             get
244             {
245                 string currentLanguage;
246
247                 ErrorCode error = VcGetCurrentLanguage(out currentLanguage);
248                 if (error != ErrorCode.None)
249                 {
250                     Log.Error(LogTag, "CurrentLanguage Failed with error " + error);
251                     return "";
252                 }
253
254                 return currentLanguage;
255             }
256         }
257
258         /// <summary>
259         /// Gets current state of voice control client.
260         /// </summary>
261         /// <value>
262         /// Current state of voice control client.
263         /// </value>
264         /// <privilege>
265         /// http://tizen.org/privilege/recorder
266         /// </privilege>
267         /// <precondition>
268         /// The State must be Initialized or Ready.
269         /// </precondition>
270         public static State State
271         {
272             get
273             {
274                 State state;
275
276                 ErrorCode error = VcGetState(out state);
277                 if (error != ErrorCode.None)
278                 {
279                     Log.Error(LogTag, "State Failed with error " + error);
280                     return State.Unavailable;
281                 }
282
283                 return state;
284             }
285         }
286
287         /// <summary>
288         /// Gets current state of voice control service.
289         /// </summary>
290         /// <value>
291         /// Current state of voice control service.
292         /// </value>
293         /// <privilege>
294         /// http://tizen.org/privilege/recorder
295         /// </privilege>
296         /// <precondition>
297         /// The State must be Ready.
298         /// </precondition>
299         public static ServiceState ServiceState
300         {
301             get
302             {
303                 ServiceState state;
304
305                 ErrorCode error = VcGetServiceState(out state);
306                 if (error != ErrorCode.None)
307                 {
308                     Log.Error(LogTag, "ServiceState Failed with error " + error);
309                     return ServiceState.Unavailable;
310                 }
311
312                 return state;
313             }
314         }
315
316         /// <summary>
317         /// Sets the invocation name.
318         /// </summary>
319         /// <privilege>
320         /// http://tizen.org/privilege/recorder
321         /// </privilege>
322         /// <privlevel>
323         /// public
324         /// </privlevel>
325         /// <feature>
326         /// http://tizen.org/feature/speech.control
327         /// http://tizen.org/feature/microphone
328         /// </feature>
329         /// <remarks>
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().
336         /// </remarks>
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>
342         /// <precondition>
343         /// The State must be Ready.
344         /// </precondition>
345         public static void SetInvocationName(string name)
346         {
347             ErrorCode error = VcSetInvocationName(name);
348             if (error != ErrorCode.None)
349             {
350                 Log.Error(LogTag, "SetInvocationName Failed with error " + error);
351                 throw ExceptionFactory.CreateException(error);
352             }
353         }
354
355         /// <summary>
356         /// Initializes voice control.
357         /// </summary>
358         /// <privilege>
359         /// http://tizen.org/privilege/recorder
360         /// </privilege>
361         /// <privlevel>
362         /// public
363         /// </privlevel>
364         /// <feature>
365         /// http://tizen.org/feature/speech.control
366         /// http://tizen.org/feature/microphone
367         /// </feature>
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>
372         /// <postcondition>
373         /// The State will be Initialized.
374         /// </postcondition>
375         public static void Initialize()
376         {
377             ErrorCode error = VcInitialize();
378             if (error != ErrorCode.None)
379             {
380                 Log.Error(LogTag, "Initialize Failed with error " + error);
381                 throw ExceptionFactory.CreateException(error);
382             }
383         }
384
385         /// <summary>
386         /// Deinitializes voice control.
387         /// </summary>
388         /// <privilege>
389         /// http://tizen.org/privilege/recorder
390         /// </privilege>
391         /// <privlevel>
392         /// public
393         /// </privlevel>
394         /// <feature>
395         /// http://tizen.org/feature/speech.control
396         /// http://tizen.org/feature/microphone
397         /// </feature>
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()
403         {
404             ErrorCode error = VcDeinitialize();
405             if (error != ErrorCode.None)
406             {
407                 Log.Error(LogTag, "Deinitialize Failed with error " + error);
408                 throw ExceptionFactory.CreateException(error);
409             }
410         }
411
412         /// <summary>
413         /// Connects the voice control service.
414         /// </summary>
415         /// <privilege>
416         /// http://tizen.org/privilege/recorder
417         /// </privilege>
418         /// <privlevel>
419         /// public
420         /// </privlevel>
421         /// <feature>
422         /// http://tizen.org/feature/speech.control
423         /// http://tizen.org/feature/microphone
424         /// </feature>
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>
429         /// <precondition>
430         /// The State should be Initialized
431         /// </precondition>
432         /// <postcondition>
433         /// The State will be Ready
434         /// </postcondition>
435         public static void Prepare()
436         {
437             ErrorCode error = VcPrepare();
438             if (error != ErrorCode.None)
439             {
440                 Log.Error(LogTag, "Prepare Failed with error " + error);
441                 throw ExceptionFactory.CreateException(error);
442             }
443         }
444
445         /// <summary>
446         /// Disconnects the voice control service.
447         /// </summary>
448         /// <privilege>
449         /// http://tizen.org/privilege/recorder
450         /// </privilege>
451         /// <privlevel>
452         /// public
453         /// </privlevel>
454         /// <feature>
455         /// http://tizen.org/feature/speech.control
456         /// http://tizen.org/feature/microphone
457         /// </feature>
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>
461         /// <precondition>
462         /// The State should be Ready
463         /// </precondition>
464         /// <postcondition>
465         /// The State should be Initialized
466         /// </postcondition>
467         public static void Unprepare()
468         {
469             ErrorCode error = VcUnprepare();
470             if (error != ErrorCode.None)
471             {
472                 Log.Error(LogTag, "Unprepare Failed with error " + error);
473                 throw ExceptionFactory.CreateException(error);
474             }
475         }
476
477         /// <summary>
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.
482         /// </summary>
483         /// <privilege>
484         /// http://tizen.org/privilege/recorder
485         /// </privilege>
486         /// <privlevel>
487         /// public
488         /// </privlevel>
489         /// <feature>
490         /// http://tizen.org/feature/speech.control
491         /// http://tizen.org/feature/microphone
492         /// </feature>
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>
497         /// <precondition>
498         /// The State should be Ready or Initialized
499         /// </precondition>
500         public static IEnumerable<string> GetSupportedLanguages()
501         {
502             s_supportedLanguages = new List<string>();
503             s_supportedLanguagesCb = (IntPtr language, IntPtr userData) =>
504             {
505                 string languageStr = Marshal.PtrToStringAnsi(language);
506                 s_supportedLanguages.Add(languageStr);
507                 return true;
508             };
509             ErrorCode error = VcForeachSupportedLanguages(s_supportedLanguagesCb, IntPtr.Zero);
510             if (error != ErrorCode.None)
511             {
512                 Log.Error(LogTag, "GetSupportedLanguages Failed with error " + error);
513                 throw ExceptionFactory.CreateException(error);
514             }
515
516             return s_supportedLanguages;
517         }
518
519         /// <summary>
520         /// Gets the system command list.
521         /// </summary>
522         /// <returns>
523         /// The Command List else null in case of no System Commands
524         /// </returns>
525         /// <privilege>
526         /// http://tizen.org/privilege/recorder
527         /// </privilege>
528         /// <privlevel>
529         /// public
530         /// </privlevel>
531         /// <feature>
532         /// http://tizen.org/feature/speech.control
533         /// http://tizen.org/feature/microphone
534         /// </feature>
535         /// <remarks>
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.
538         /// </remarks>
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>
543         /// <precondition>
544         /// The State should be Ready
545         /// </precondition>
546         public static VoiceCommandList GetSystemCommandList()
547         {
548             IntPtr handle = IntPtr.Zero;
549             ErrorCode error = VcGetSystemCommandList(out handle);
550             if (error != ErrorCode.None)
551             {
552                 Log.Error(LogTag, "GetSystemCommandList Failed with error " + error);
553                 throw ExceptionFactory.CreateException(error);
554             }
555
556             if (handle == IntPtr.Zero)
557             {
558                 Log.Error(LogTag, "GetSystemCommandList handle is null");
559                 return null;
560             }
561
562             SafeCommandListHandle list = new SafeCommandListHandle(handle);
563             return new VoiceCommandList(list);
564         }
565
566         /// <summary>
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.
573         /// </summary>
574         /// <privilege>
575         /// http://tizen.org/privilege/recorder
576         /// </privilege>
577         /// <privlevel>
578         /// public
579         /// </privlevel>
580         /// <feature>
581         /// http://tizen.org/feature/speech.control
582         /// http://tizen.org/feature/microphone
583         /// </feature>
584         /// <remarks>
585         /// If autoStart is true, the recognition will start again. In this case, it can be restarted up to 4 times.
586         /// </remarks>
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>
594         /// <precondition>
595         /// The State should be Ready
596         /// </precondition>
597         public static void RequestDialog(string dispText, string uttText, bool autoStart)
598         {
599             ErrorCode error = VcRequestDialog(dispText, uttText, autoStart);
600             if (error != ErrorCode.None)
601             {
602                 Log.Error(LogTag, "RequestDialog Failed with error " + error);
603                 throw ExceptionFactory.CreateException(error);
604             }
605         }
606
607         /// <summary>
608         /// Sets command list.
609         /// </summary>
610         /// <privilege>
611         /// http://tizen.org/privilege/recorder
612         /// </privilege>
613         /// <privlevel>
614         /// public
615         /// </privlevel>
616         /// <feature>
617         /// http://tizen.org/feature/speech.control
618         /// http://tizen.org/feature/microphone
619         /// </feature>
620         /// <remarks>
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.
623         /// </remarks>
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>
630         /// <precondition>
631         /// The State should be Ready
632         /// </precondition>
633         public static void SetCommandList(VoiceCommandList list, CommandType type)
634         {
635             if ((type == CommandType.Foreground) || (type == CommandType.Background))
636             {
637                 ErrorCode error = VcSetCommandList(list._handle, (VoiceCommandType)type);
638                 if (error != ErrorCode.None)
639                 {
640                     Log.Error(LogTag, "SetCommandList Failed with error " + error);
641                     throw ExceptionFactory.CreateException(error);
642                 }
643             }
644
645             else
646             {
647                 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
648             }
649         }
650
651         /// <summary>
652         /// Unsets command list.
653         /// </summary>
654         /// <privilege>
655         /// http://tizen.org/privilege/recorder
656         /// </privilege>
657         /// <privlevel>
658         /// public
659         /// </privlevel>
660         /// <feature>
661         /// http://tizen.org/feature/speech.control
662         /// http://tizen.org/feature/microphone
663         /// </feature>
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>
669         /// <precondition>
670         /// The State should be Ready
671         /// </precondition>
672         public static void UnsetCommandList(CommandType type)
673         {
674             if ((type == CommandType.Foreground) || (type == CommandType.Background))
675             {
676                 VoiceCommandType commandType = VoiceCommandType.Foreground;
677                 if (type == CommandType.Background)
678                     commandType = VoiceCommandType.BackGround;
679                 ErrorCode error = VcUnsetCommandList(commandType);
680                 if (error != ErrorCode.None)
681                 {
682                     Log.Error(LogTag, "UnsetCommandList Failed with error " + error);
683                     throw ExceptionFactory.CreateException(error);
684                 }
685             }
686
687             else
688             {
689                 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
690             }
691         }
692
693         /// <summary>
694         /// Gets the recognition result.
695         /// </summary>
696         /// <privilege>
697         /// http://tizen.org/privilege/recorder
698         /// </privilege>
699         /// <privlevel>
700         /// public
701         /// </privlevel>
702         /// <feature>
703         /// http://tizen.org/feature/speech.control
704         /// http://tizen.org/feature/microphone
705         /// </feature>
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>
710         /// <precondition>
711         /// The State should be Ready
712         /// </precondition>
713         public static RecognitionResult GetResult()
714         {
715             s_recognitionResult = null;
716             s_resultCb = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
717             {
718                 s_recognitionResult = new RecognitionResult(evt, cmdList, result);
719             };
720             ErrorCode error = VcGetResult(s_resultCb, IntPtr.Zero);
721             if (error != ErrorCode.None)
722             {
723                 Log.Error(LogTag, "GetResult Failed with error " + error);
724                 throw ExceptionFactory.CreateException(error);
725             }
726
727             return s_recognitionResult;
728         }
729
730         /// <summary>
731         /// Event to be invoked when the recognition is done.
732         /// </summary>
733         /// <precondition>
734         /// The State should be Initialized
735         /// </precondition>
736         public static event EventHandler<RecognitionResultEventArgs> RecognitionResult
737         {
738             add
739             {
740                 s_resultDelegate = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
741                 {
742                     Log.Info(LogTag, "Recognition Result Event Triggered");
743                     if ((cmdList != null) && (result != null))
744                     {
745                         RecognitionResultEventArgs args = new RecognitionResultEventArgs(new RecognitionResult( evt, cmdList, result));
746                         _recognitionResult?.Invoke(null, args);
747                     }
748                     else
749                     {
750                         Log.Info(LogTag, "Recognition Result Event null received");
751                     }
752                 };
753                 ErrorCode error = VcSetResultCb(s_resultDelegate, IntPtr.Zero);
754                 if (error != ErrorCode.None)
755                 {
756                     Log.Error(LogTag, "Add RecognitionResult Failed with error " + error);
757                 }
758                 else
759                 {
760                     _recognitionResult += value;
761                 }
762             }
763
764             remove
765             {
766                 ErrorCode error = VcUnsetResultCb();
767                 if (error != ErrorCode.None)
768                 {
769                     Log.Error(LogTag, "Remove RecognitionResult Failed with error " + error);
770                 }
771
772                 _recognitionResult -= value;
773             }
774         }
775
776         /// <summary>
777         /// Event to be invoked when VoiceControl service state changes.
778         /// </summary>
779         /// <precondition>
780         /// The State should be Initialized
781         /// </precondition>
782         public static event EventHandler<ServiceStateChangedEventArgs> ServiceStateChanged
783         {
784             add
785             {
786                 s_serviceStateDelegate = (ServiceState previous, ServiceState current, IntPtr userData) =>
787                 {
788                     ServiceStateChangedEventArgs args = new ServiceStateChangedEventArgs(previous, current);
789                     _serviceStateChanged?.Invoke(null, args);
790                 };
791                 ErrorCode error = VcSetServiceStateChangedCb(s_serviceStateDelegate, IntPtr.Zero);
792                 if (error != ErrorCode.None)
793                 {
794                     Log.Error(LogTag, "Add ServiceStateChanged Failed with error " + error);
795                 }
796                 else
797                 {
798                     _serviceStateChanged += value;
799                 }
800             }
801
802             remove
803             {
804                 ErrorCode error = VcUnsetServiceStateChangedCb();
805                 if (error != ErrorCode.None)
806                 {
807                     Log.Error(LogTag, "Remove ServiceStateChanged Failed with error " + error);
808                 }
809
810                 _serviceStateChanged -= value;
811             }
812         }
813
814         /// <summary>
815         /// Event to be invoked when VoiceControl client state changes.
816         /// </summary>
817         /// <precondition>
818         /// The State should be Initialized
819         /// </precondition>
820         public static event EventHandler<StateChangedEventArgs> StateChanged
821         {
822             add
823             {
824                 s_stateDelegate = (State previous, State current, IntPtr userData) =>
825                 {
826                     StateChangedEventArgs args = new StateChangedEventArgs(previous, current);
827                     _stateChanged?.Invoke(null, args);
828                 };
829                 ErrorCode error = VcSetStateChangedCb(s_stateDelegate, IntPtr.Zero);
830                 if (error != ErrorCode.None)
831                 {
832                     Log.Error(LogTag, "Add StateChanged Failed with error " + error);
833                 }
834                 else
835                 {
836                     _stateChanged += value;
837                 }
838             }
839
840             remove
841             {
842                 ErrorCode error = VcUnsetStateChangedCb();
843                 if (error != ErrorCode.None)
844                 {
845                     Log.Error(LogTag, "Remove StateChanged Failed with error " + error);
846                 }
847
848                 _stateChanged -= value;
849             }
850         }
851
852         /// <summary>
853         /// Event to be invoked when an error occurs.
854         /// </summary>
855         /// <precondition>
856         /// The State should be Initialized
857         /// </precondition>
858         public static event EventHandler<ErrorOccuredEventArgs> ErrorOccured
859         {
860             add
861             {
862                 s_errorDelegate = (ErrorCode reason, IntPtr userData) =>
863             {
864                 ErrorOccuredEventArgs args = new ErrorOccuredEventArgs(reason);
865                 _errorOccured?.Invoke(null, args);
866             };
867                 ErrorCode error = VcSetErrorCb(s_errorDelegate, IntPtr.Zero);
868                 if (error != ErrorCode.None)
869                 {
870                     Log.Error(LogTag, "Add ErrorOccured Failed with error " + error);
871                 }
872
873                 else
874                 {
875                     _errorOccured += value;
876                 }
877             }
878
879
880             remove
881             {
882                 ErrorCode error = VcUnsetErrorCb();
883                 if (error != ErrorCode.None)
884                 {
885                     Log.Error(LogTag, "Remove ErrorOccured Failed with error " + error);
886                 }
887
888                 _errorOccured -= value;
889             }
890         }
891
892         /// <summary>
893         /// Event to be invoked when default laungage change.
894         /// </summary>
895         /// <precondition>
896         /// The State should be Initialized
897         /// </precondition>
898         public static event EventHandler<CurrentLanguageChangedEventArgs> CurrentLanguageChanged
899         {
900             add
901             {
902                 s_languageDelegate = (IntPtr previousLanguage, IntPtr currentLanguage, IntPtr userData) =>
903             {
904                 string previousLanguageString = Marshal.PtrToStringAnsi(previousLanguage);
905                 string currentLanguageString = Marshal.PtrToStringAnsi(currentLanguage);
906                 CurrentLanguageChangedEventArgs args = new CurrentLanguageChangedEventArgs(previousLanguageString, currentLanguageString);
907                 _currentLanguageChanged?.Invoke(null, args);
908             };
909                 ErrorCode error = VcSetCurrentLanguageChangedCb(s_languageDelegate, IntPtr.Zero);
910                 if (error != ErrorCode.None)
911                 {
912                     Log.Error(LogTag, "Add CurrentLanguageChanged Failed with error " + error);
913                 }
914
915                 else
916                 {
917                     _currentLanguageChanged += value;
918                 }
919             }
920
921             remove
922             {
923                 ErrorCode error = VcUnsetCurrentLanguageChangedCb();
924                 if (error != ErrorCode.None)
925                 {
926                     Log.Error(LogTag, "Remove CurrentLanguageChanged Failed with error " + error);
927                 }
928
929                 _currentLanguageChanged -= value;
930             }
931         }
932     }
933 }