Add descriptions for privilege and features
[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
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         /// <precondition>
238         /// The State must be Initialized or Ready.
239         /// </precondition>
240         public static string GetCurrentLanaguge
241         {
242             get
243             {
244                 string currentLanaguge;
245
246                 ErrorCode error = VcGetCurrentLanguage(out currentLanaguge);
247                 if (error != ErrorCode.None)
248                 {
249                     Log.Error(LogTag, "CurrentLanaguge Failed with error " + error);
250                     return "";
251                 }
252
253                 return currentLanaguge;
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         /// <precondition>
267         /// The State must be Initialized or Ready.
268         /// </precondition>
269         public static State GetState
270         {
271             get
272             {
273                 State state;
274
275                 ErrorCode error = VcGetState(out state);
276                 if (error != ErrorCode.None)
277                 {
278                     Log.Error(LogTag, "GetState 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         /// <precondition>
296         /// The State must be Ready.
297         /// </precondition>
298         public static ServiceState GetServiceState
299         {
300             get
301             {
302                 ServiceState state;
303
304                 ErrorCode error = VcGetServiceState(out state);
305                 if (error != ErrorCode.None)
306                 {
307                     Log.Error(LogTag, "GetServiceState 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">
338         /// This Exception can be due to the following reaons
339         /// 1. Invalid parameter
340         /// 2. Invalid state
341         /// 3. Not Supported
342         /// 4. Permission Denied
343         /// </exception>
344         /// <precondition>
345         /// The State must be Ready.
346         /// </precondition>
347         public static void SetInvocationName(string name)
348         {
349             ErrorCode error = VcSetInvocationName(name);
350             if (error != ErrorCode.None)
351             {
352                 Log.Error(LogTag, "SetInvocationName Failed with error " + error);
353                 throw ExceptionFactory.CreateException(error);
354             }
355         }
356
357         /// <summary>
358         /// Initializes voice control.
359         /// </summary>
360         /// <privilege>
361         /// http://tizen.org/privilege/recorder
362         /// </privilege>
363         /// <privlevel>
364         /// public
365         /// </privlevel>
366         /// <feature>
367         /// http://tizen.org/feature/speech.control
368         /// http://tizen.org/feature/microphone
369         /// </feature>
370         /// <exception cref="InvalidOperationException">
371         /// This Exception can be due to the following reaons
372         /// 1. Out Of Memory
373         /// 2. Operation Failed
374         /// 3. Not Supported
375         /// 4. Permission Denied
376         /// </exception>
377         /// <postcondition>
378         /// The State will be Initialized.
379         /// </postcondition>
380         public static void Initialize()
381         {
382             ErrorCode error = VcInitialize();
383             if (error != ErrorCode.None)
384             {
385                 Log.Error(LogTag, "Initialize Failed with error " + error);
386                 throw ExceptionFactory.CreateException(error);
387             }
388         }
389
390         /// <summary>
391         /// Deinitializes voice control.
392         /// </summary>
393         /// <privilege>
394         /// http://tizen.org/privilege/recorder
395         /// </privilege>
396         /// <privlevel>
397         /// public
398         /// </privlevel>
399         /// <feature>
400         /// http://tizen.org/feature/speech.control
401         /// http://tizen.org/feature/microphone
402         /// </feature>
403         /// <exception cref="InvalidOperationException">
404         /// This Exception can be due to the following reaons
405         /// 1. Operation Failed
406         /// 2. Invalid state
407         /// 3. Not Supported
408         /// 4. Permission Denied
409         /// </exception>
410         public static void Deinitialize()
411         {
412             ErrorCode error = VcDeinitialize();
413             if (error != ErrorCode.None)
414             {
415                 Log.Error(LogTag, "Deinitialize Failed with error " + error);
416                 throw ExceptionFactory.CreateException(error);
417             }
418         }
419
420         /// <summary>
421         /// Connects the voice control service.
422         /// </summary>
423         /// <privilege>
424         /// http://tizen.org/privilege/recorder
425         /// </privilege>
426         /// <privlevel>
427         /// public
428         /// </privlevel>
429         /// <feature>
430         /// http://tizen.org/feature/speech.control
431         /// http://tizen.org/feature/microphone
432         /// </feature>
433         /// <exception cref="InvalidOperationException">
434         /// This Exception can be due to the following reaons
435         /// 1. Operation Failed
436         /// 2. Not Supported
437         /// 3. Permission Denied
438         /// 4. Invalid State
439         /// </exception>
440         /// <precondition>
441         /// The State should be Initialized
442         /// </precondition>
443         /// <postcondition>
444         /// The State will be Ready
445         /// </postcondition>
446         public static void Prepare()
447         {
448             ErrorCode error = VcPrepare();
449             if (error != ErrorCode.None)
450             {
451                 Log.Error(LogTag, "Prepare Failed with error " + error);
452                 throw ExceptionFactory.CreateException(error);
453             }
454         }
455
456         /// <summary>
457         /// Disconnects the voice control service.
458         /// </summary>
459         /// <privilege>
460         /// http://tizen.org/privilege/recorder
461         /// </privilege>
462         /// <privlevel>
463         /// public
464         /// </privlevel>
465         /// <feature>
466         /// http://tizen.org/feature/speech.control
467         /// http://tizen.org/feature/microphone
468         /// </feature>
469         /// <exception cref="InvalidOperationException">
470         /// This Exception can be due to the following reaons
471         /// 1. Not Supported
472         /// 2. Permission Denied
473         /// 3. Invalid State
474         /// </exception>
475         /// <precondition>
476         /// The State should be Ready
477         /// </precondition>
478         /// <postcondition>
479         /// The State should be Initialized
480         /// </postcondition>
481         public static void Unprepare()
482         {
483             ErrorCode error = VcUnprepare();
484             if (error != ErrorCode.None)
485             {
486                 Log.Error(LogTag, "Unprepare Failed with error " + error);
487                 throw ExceptionFactory.CreateException(error);
488             }
489         }
490
491         /// <summary>
492         /// Retrieves all supported languages.
493         /// A language is specified as an ISO 3166 alpha-2 two letter country-code
494         /// followed by ISO 639-1 for the two-letter language code.
495         /// For example, "ko_KR" for Korean, "en_US" for American English.
496         /// </summary>
497         /// <privilege>
498         /// http://tizen.org/privilege/recorder
499         /// </privilege>
500         /// <privlevel>
501         /// public
502         /// </privlevel>
503         /// <feature>
504         /// http://tizen.org/feature/speech.control
505         /// http://tizen.org/feature/microphone
506         /// </feature>
507         /// <exception cref="InvalidOperationException">
508         /// This Exception can be due to the following reaons
509         /// 1. Operation Failed
510         /// 2. Not Supported
511         /// 3. Permission Denied
512         /// 4. Invalid State
513         /// </exception>
514         /// <precondition>
515         /// The State should be Ready or Initialized
516         /// </precondition>
517         public static IEnumerable<string> GetSupportedLangauges()
518         {
519             s_supportedLanguages = new List<string>();
520             s_supportedLanguagesCb = (IntPtr language, IntPtr userData) =>
521             {
522                 string languageStr = Marshal.PtrToStringAnsi(language);
523                 s_supportedLanguages.Add(languageStr);
524                 return true;
525             };
526             ErrorCode error = VcForeachSupportedLanguages(s_supportedLanguagesCb, IntPtr.Zero);
527             if (error != ErrorCode.None)
528             {
529                 Log.Error(LogTag, "GetSupportedLangauges Failed with error " + error);
530                 throw ExceptionFactory.CreateException(error);
531             }
532
533             return s_supportedLanguages;
534         }
535
536         /// <summary>
537         /// Gets the system command list.
538         /// </summary>
539         /// <returns>
540         /// The Command List else null in case of no System Commands
541         /// </returns>
542         /// <privilege>
543         /// http://tizen.org/privilege/recorder
544         /// </privilege>
545         /// <privlevel>
546         /// public
547         /// </privlevel>
548         /// <feature>
549         /// http://tizen.org/feature/speech.control
550         /// http://tizen.org/feature/microphone
551         /// </feature>
552         /// <remarks>
553         /// In the system command list, there are system commands predefined by product manufacturers.
554         /// Those commands have the highest priority. Therefore, the user can not set any commands same with the system commands.
555         /// </remarks>
556         /// <exception cref="InvalidOperationException">
557         /// This Exception can be due to the following reaons
558         /// 1. Not Supported
559         /// 2. Permission Denied
560         /// 3. Invalid State
561         /// </exception>
562         /// <precondition>
563         /// The State should be Ready
564         /// </precondition>
565         public static VoiceCommandList GetSytemCommandList()
566         {
567             IntPtr handle = IntPtr.Zero;
568             ErrorCode error = VcGetSystemCommandList(out handle);
569             if (error != ErrorCode.None)
570             {
571                 Log.Error(LogTag, "GetSystemCommandList Failed with error " + error);
572                 throw ExceptionFactory.CreateException(error);
573             }
574
575             if (handle == IntPtr.Zero)
576             {
577                 Log.Error(LogTag, "GetSystemCommandList handle is null");
578                 return null;
579             }
580
581             SafeCommandListHandle list = new SafeCommandListHandle(handle);
582             return new VoiceCommandList(list);
583         }
584
585         /// <summary>
586         /// Requests to start the dialogue.
587         /// Using this function, the developer can request starting the dialogue to the framework.
588         /// 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.
589         /// 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.
590         /// Also, the developer can set whether the dialogue starts automatically or not, using autoStart.
591         /// If the developer sets autoStart as true, the framework will start to record next speech and continue the dialogue.
592         /// </summary>
593         /// <privilege>
594         /// http://tizen.org/privilege/recorder
595         /// </privilege>
596         /// <privlevel>
597         /// public
598         /// </privlevel>
599         /// <feature>
600         /// http://tizen.org/feature/speech.control
601         /// http://tizen.org/feature/microphone
602         /// </feature>
603         /// <remarks>
604         /// If autoStart is true, the recognition will start again. In this case, it can be restarted up to 4 times.
605         /// </remarks>
606         /// <param name="dispText"> Text to be displayed on the screen/// </param>
607         /// <param name="uttText">Text to be spoken</param>
608         /// <param name="autoStart">A variable for setting whether the dialog session will be restarted automatically or not</param>
609         /// <exception cref="InvalidOperationException">
610         /// This Exception can be due to the following reaons
611         /// 1. Not Supported
612         /// 2. Permission Denied
613         /// 3. Invalid State
614         /// 4. Invalid parameter
615         /// </exception>
616         /// <precondition>
617         /// The State should be Ready
618         /// </precondition>
619         public static void RequestDialog(string dispText, string uttText, bool autoStart)
620         {
621             ErrorCode error = VcRequestDialog(dispText, uttText, autoStart);
622             if (error != ErrorCode.None)
623             {
624                 Log.Error(LogTag, "RequestDialog Failed with error " + error);
625                 throw ExceptionFactory.CreateException(error);
626             }
627         }
628
629         /// <summary>
630         /// Sets command list.
631         /// </summary>
632         /// <privilege>
633         /// http://tizen.org/privilege/recorder
634         /// </privilege>
635         /// <privlevel>
636         /// public
637         /// </privlevel>
638         /// <feature>
639         /// http://tizen.org/feature/speech.control
640         /// http://tizen.org/feature/microphone
641         /// </feature>
642         /// <remarks>
643         /// The command type is valid for CommandType 'Foreground' or 'Background'.
644         /// The matched commands of command list should be set and they should include type and command text at least.
645         /// </remarks>
646         /// <param name="list">Command list</param>
647         /// <param name="type">Command type</param>
648         /// <exception cref="InvalidOperationException">
649         /// This Exception can be due to the following reaons
650         /// 1. Not Supported
651         /// 2. Permission Denied
652         /// 3. Invalid State
653         /// 4. Invalid parameter
654         /// </exception>
655         /// <precondition>
656         /// The State should be Ready
657         /// </precondition>
658         public static void SetCommandList(VoiceCommandList list, CommandType type)
659         {
660             if ((type == CommandType.Foreground) || (type == CommandType.Background))
661             {
662                 ErrorCode error = VcSetCommandList(list._handle, (VoiceCommandType)type);
663                 if (error != ErrorCode.None)
664                 {
665                     Log.Error(LogTag, "SetCommandList Failed with error " + error);
666                     throw ExceptionFactory.CreateException(error);
667                 }
668             }
669
670             else
671             {
672                 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
673             }
674         }
675
676         /// <summary>
677         /// Unsets command list.
678         /// </summary>
679         /// <privilege>
680         /// http://tizen.org/privilege/recorder
681         /// </privilege>
682         /// <privlevel>
683         /// public
684         /// </privlevel>
685         /// <feature>
686         /// http://tizen.org/feature/speech.control
687         /// http://tizen.org/feature/microphone
688         /// </feature>
689         /// <param name="type">Command type</param>
690         /// <exception cref="InvalidOperationException">
691         /// This Exception can be due to the following reaons
692         /// 1. Not Supported
693         /// 2. Permission Denied
694         /// 3. Invalid State
695         /// 4. Invalid parameter
696         /// </exception>
697         /// <precondition>
698         /// The State should be Ready
699         /// </precondition>
700         public static void UnsetCommandList(CommandType type)
701         {
702             if ((type == CommandType.Foreground) || (type == CommandType.Background))
703             {
704                 VoiceCommandType commandType = VoiceCommandType.Foreground;
705                 if (type == CommandType.Background)
706                     commandType = VoiceCommandType.BackGround;
707                 ErrorCode error = VcUnsetCommandList(commandType);
708                 if (error != ErrorCode.None)
709                 {
710                     Log.Error(LogTag, "UnsetCommandList Failed with error " + error);
711                     throw ExceptionFactory.CreateException(error);
712                 }
713             }
714
715             else
716             {
717                 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
718             }
719         }
720
721         /// <summary>
722         /// Gets the recognition result.
723         /// </summary>
724         /// <privilege>
725         /// http://tizen.org/privilege/recorder
726         /// </privilege>
727         /// <privlevel>
728         /// public
729         /// </privlevel>
730         /// <feature>
731         /// http://tizen.org/feature/speech.control
732         /// http://tizen.org/feature/microphone
733         /// </feature>
734         /// <param name="resultDelegate">
735         /// Callback function to get recognition result
736         /// </param>
737         /// <exception cref="InvalidOperationException">
738         /// This Exception can be due to the following reaons
739         /// 1. Not Supported
740         /// 2. Invalid State
741         /// 3. Invalid parameter
742         /// </exception>
743         /// <precondition>
744         /// The State should be Ready
745         /// </precondition>
746         public static void GetResult(RecognitionResultDelegate resultDelegate)
747         {
748             s_resultCb = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
749             {
750                 VoiceCommandList list = new VoiceCommandList(new SafeCommandListHandle(cmdList));
751                 string resultStr = Marshal.PtrToStringAnsi(result);
752                 resultDelegate(evt, list, resultStr);
753             };
754             ErrorCode error = VcGetResult(s_resultCb, IntPtr.Zero);
755             if (error != ErrorCode.None)
756             {
757                 Log.Error(LogTag, "GetResult Failed with error " + error);
758                 throw ExceptionFactory.CreateException(error);
759             }
760         }
761
762         /// <summary>
763         /// Event to be invoked when the recognition is done.
764         /// </summary>
765         /// <precondition>
766         /// The State should be Initialized
767         /// </precondition>
768         public static event EventHandler<RecognitionResultEventArgs> RecognitionResult
769         {
770             add
771             {
772                 s_resultDelegate = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
773                 {
774                     Log.Info(LogTag, "Recognition Result Event Triggered");
775                     if ((cmdList != null) && (result != null))
776                     {
777                         RecognitionResultEventArgs args = new RecognitionResultEventArgs(evt, cmdList, result);
778                         _recognitionResult?.Invoke(null, args);
779                     }
780                     else
781                     {
782                         Log.Info(LogTag, "Recognition Result Event null received");
783                     }
784                 };
785                 ErrorCode error = VcSetResultCb(s_resultDelegate, IntPtr.Zero);
786                 if (error != ErrorCode.None)
787                 {
788                     Log.Error(LogTag, "Add RecognitionResult Failed with error " + error);
789                 }
790                 else
791                 {
792                     _recognitionResult += value;
793                 }
794             }
795
796             remove
797             {
798                 ErrorCode error = VcUnsetResultCb();
799                 if (error != ErrorCode.None)
800                 {
801                     Log.Error(LogTag, "Remove RecognitionResult Failed with error " + error);
802                 }
803
804                 _recognitionResult -= value;
805             }
806         }
807
808         /// <summary>
809         /// Event to be invoked when VoiceControl service state changes.
810         /// </summary>
811         /// <precondition>
812         /// The State should be Initialized
813         /// </precondition>
814         public static event EventHandler<ServiceStateChangedEventArgs> ServiceStateChanged
815         {
816             add
817             {
818                 s_serviceStateDelegate = (ServiceState previous, ServiceState current, IntPtr userData) =>
819                 {
820                     ServiceStateChangedEventArgs args = new ServiceStateChangedEventArgs(previous, current);
821                     _serviceStateChanged?.Invoke(null, args);
822                 };
823                 ErrorCode error = VcSetServiceStateChangedCb(s_serviceStateDelegate, IntPtr.Zero);
824                 if (error != ErrorCode.None)
825                 {
826                     Log.Error(LogTag, "Add ServiceStateChanged Failed with error " + error);
827                 }
828                 else
829                 {
830                     _serviceStateChanged += value;
831                 }
832             }
833
834             remove
835             {
836                 ErrorCode error = VcUnsetServiceStateChangedCb();
837                 if (error != ErrorCode.None)
838                 {
839                     Log.Error(LogTag, "Remove ServiceStateChanged Failed with error " + error);
840                 }
841
842                 _serviceStateChanged -= value;
843             }
844         }
845
846         /// <summary>
847         /// Event to be invoked when VoiceControl client state changes.
848         /// </summary>
849         /// <precondition>
850         /// The State should be Initialized
851         /// </precondition>
852         public static event EventHandler<StateChangedEventArgs> StateChanged
853         {
854             add
855             {
856                 s_stateDelegate = (State previous, State current, IntPtr userData) =>
857                 {
858                     StateChangedEventArgs args = new StateChangedEventArgs(previous, current);
859                     _stateChanged?.Invoke(null, args);
860                 };
861                 ErrorCode error = VcSetStateChangedCb(s_stateDelegate, IntPtr.Zero);
862                 if (error != ErrorCode.None)
863                 {
864                     Log.Error(LogTag, "Add StateChanged Failed with error " + error);
865                 }
866                 else
867                 {
868                     _stateChanged += value;
869                 }
870             }
871
872             remove
873             {
874                 ErrorCode error = VcUnsetStateChangedCb();
875                 if (error != ErrorCode.None)
876                 {
877                     Log.Error(LogTag, "Remove StateChanged Failed with error " + error);
878                 }
879
880                 _stateChanged -= value;
881             }
882         }
883
884         /// <summary>
885         /// Event to be invoked when an error occurs.
886         /// </summary>
887         /// <precondition>
888         /// The State should be Initialized
889         /// </precondition>
890         public static event EventHandler<ErrorOccuredEventArgs> ErrorOccured
891         {
892             add
893             {
894                 s_errorDelegate = (ErrorCode reason, IntPtr userData) =>
895             {
896                 ErrorOccuredEventArgs args = new ErrorOccuredEventArgs(reason);
897                 _errorOccured?.Invoke(null, args);
898             };
899                 ErrorCode error = VcSetErrorCb(s_errorDelegate, IntPtr.Zero);
900                 if (error != ErrorCode.None)
901                 {
902                     Log.Error(LogTag, "Add ErrorOccured Failed with error " + error);
903                 }
904
905                 else
906                 {
907                     _errorOccured += value;
908                 }
909             }
910
911
912             remove
913             {
914                 ErrorCode error = VcUnsetErrorCb();
915                 if (error != ErrorCode.None)
916                 {
917                     Log.Error(LogTag, "Remove ErrorOccured Failed with error " + error);
918                 }
919
920                 _errorOccured -= value;
921             }
922         }
923
924         /// <summary>
925         /// Event to be invoked when default laungage change.
926         /// </summary>
927         /// <precondition>
928         /// The State should be Initialized
929         /// </precondition>
930         public static event EventHandler<CurrentLanguageChangedEventArgs> CurrentLanguageChanged
931         {
932             add
933             {
934                 s_languageDelegate = (IntPtr previousLanguage, IntPtr currentLanguage, IntPtr userData) =>
935             {
936                 string previousLanguageString = Marshal.PtrToStringAnsi(previousLanguage);
937                 string currentLanguageString = Marshal.PtrToStringAnsi(currentLanguage);
938                 CurrentLanguageChangedEventArgs args = new CurrentLanguageChangedEventArgs(previousLanguageString, currentLanguageString);
939                 _currentLanguageChanged?.Invoke(null, args);
940             };
941                 ErrorCode error = VcSetCurrentLanguageChangedCb(s_languageDelegate, IntPtr.Zero);
942                 if (error != ErrorCode.None)
943                 {
944                     Log.Error(LogTag, "Add CurrentLanguageChanged Failed with error " + error);
945                 }
946
947                 else
948                 {
949                     _currentLanguageChanged += value;
950                 }
951             }
952
953             remove
954             {
955                 ErrorCode error = VcUnsetCurrentLanguageChangedCb();
956                 if (error != ErrorCode.None)
957                 {
958                     Log.Error(LogTag, "Remove CurrentLanguageChanged Failed with error " + error);
959                 }
960
961                 _currentLanguageChanged -= value;
962             }
963         }
964     }
965 }