[VoiceControl/VoiceControlWidget] Fix invalid null checking (#96)
[platform/core/csapi/tizenfx.git] / src / 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     /// Enumeration for the error values that can occur.
27     /// </summary>
28     /// <since_tizen> 3 </since_tizen>
29     public enum Error
30     {
31         /// <summary>
32         /// Successful, no error.
33         /// </summary>
34         None,
35         /// <summary>
36         /// Out of memory.
37         /// </summary>
38         OutOfMemory,
39         /// <summary>
40         /// I/O error.
41         /// </summary>
42         IoError,
43         /// <summary>
44         /// Invalid parameter.
45         /// </summary>
46         InvalidParameter,
47         /// <summary>
48         /// No answer from the STT service.
49         /// </summary>
50         TimedOut,
51         /// <summary>
52         /// Device or resource busy.
53         /// </summary>
54         RecorderBusy,
55         /// <summary>
56         /// Permission denied.
57         /// </summary>
58         PermissionDenied,
59         /// <summary>
60         /// VC NOT supported.
61         /// </summary>
62         NotSupported,
63         /// <summary>
64         /// Invalid state.
65         /// </summary>
66         InvalidState,
67         /// <summary>
68         /// Invalid language.
69         /// </summary>
70         InvalidLanguage,
71         /// <summary>
72         /// No available engine.
73         /// </summary>
74         EngineNotFound,
75         /// <summary>
76         /// Operation failed.
77         /// </summary>
78         OperationFailed,
79         /// <summary>
80         /// Operation rejected.
81         /// </summary>
82         OperationRejected,
83         /// <summary>
84         /// List reached end.
85         /// </summary>
86         IterationEnd,
87         /// <summary>
88         /// List empty.
89         /// </summary>
90         Empty,
91         /// <summary>
92         /// Service reset.
93         /// </summary>
94         ServiceReset,
95         /// <summary>
96         /// Progress to ready is not finished.
97         /// </summary>
98         InProgressToReady,
99         /// <summary>
100         /// Progress to recording is not finished.
101         /// </summary>
102         InProgressToRecording,
103         /// <summary>
104         /// Progress to processing is not finished.
105         /// </summary>
106         InProgressToProcessing
107     };
108
109     /// <summary>
110     /// Enumeration for the client state.
111     /// </summary>
112     /// <since_tizen> 3 </since_tizen>
113     public enum State
114     {
115         /// <summary>
116         /// 'None' state.
117         /// </summary>
118         None = 0,
119         /// <summary>
120         /// 'Initialized' state.
121         /// </summary>
122         Initialized = 1,
123         /// <summary>
124         /// 'Ready' state.
125         /// </summary>
126         Ready = 2,
127         /// <summary>
128         /// The state cannot be determined.
129         /// </summary>
130         Unavailable
131     };
132
133     /// <summary>
134     /// Enumeration for the service state.
135     /// </summary>
136     /// <since_tizen> 3 </since_tizen>
137     public enum ServiceState
138     {
139         /// <summary>
140         /// 'None' state.
141         /// </summary>
142         None = 0,
143         /// <summary>
144         /// 'Ready' state.
145         /// </summary>
146         Ready = 1,
147         /// <summary>
148         /// 'Recording' state.
149         /// </summary>
150         Recording = 2,
151         /// <summary>
152         /// 'Processing' state.
153         /// </summary>
154         Processing = 3,
155         /// <summary>
156         /// The state cannot be determined.
157         /// </summary>
158         Unavailable
159     };
160
161     /// <summary>
162     /// Enumeration for the result event.
163     /// </summary>
164     /// <since_tizen> 3 </since_tizen>
165     public enum ResultEvent
166     {
167         /// <summary>
168         /// Normal result.
169         /// </summary>
170         Success = 0,
171         /// <summary>
172         /// Rejected result.
173         /// </summary>
174         Rejected = 1
175     };
176
177     /// <summary>
178     /// Enumeration for the command type.
179     /// </summary>
180     /// <since_tizen> 3 </since_tizen>
181     public enum CommandType
182     {
183         /// <summary>
184         /// Foreground command by the client.
185         /// </summary>
186         Foreground = 1,
187         /// <summary>
188         /// Background command by the client.
189         /// </summary>
190         Background = 2,
191         /// <summary>
192         /// The undefined command.
193         /// </summary>
194         Undefined = -1
195     };
196
197     /// <summary>
198     /// A main function of the voice control API registers the command and gets a notification for the recognition result.
199     /// Applications can add their own commands and provide results when their command is recognized by the user voice input.
200     /// </summary>
201     /// <since_tizen> 3 </since_tizen>
202     public static class VoiceControlClient
203     {
204         private static event EventHandler<RecognitionResultEventArgs> _recognitionResult;
205         private static event EventHandler<StateChangedEventArgs> _stateChanged;
206         private static event EventHandler<ServiceStateChangedEventArgs> _serviceStateChanged;
207         private static event EventHandler<ErrorOccuredEventArgs> _errorOccured;
208         private static event EventHandler<CurrentLanguageChangedEventArgs> _currentLanguageChanged;
209         private static VcResultCb s_resultDelegate;
210         private static VcStateChangedCb s_stateDelegate;
211         private static VcServiceStateChangedCb s_serviceStateDelegate;
212         private static VcErrorCb s_errorDelegate;
213         private static VcCurrentLanguageChangedCb s_languageDelegate;
214         private static List<string> s_supportedLanguages;
215         private static VcSupportedLanguageCb s_supportedLanguagesCb;
216         private static VcResultCb s_resultCb;
217         private static RecognitionResult s_recognitionResult;
218
219         /// <summary>
220         /// Gets the current language.
221         /// A language is specified as an ISO 3166 alpha-2 two letter country-code
222         /// followed by ISO 639-1 for the two-letter language code.
223         /// For example, "ko_KR" for Korean, "en_US" for American English.
224         /// An empty string is returned in case of some internal error.
225         /// </summary>
226         /// <since_tizen> 3 </since_tizen>
227         /// <value>
228         /// The current language in voice control.
229         /// </value>
230         /// <privilege>
231         /// http://tizen.org/privilege/recorder
232         /// </privilege>
233         /// <pre>
234         /// The state must be initialized or ready.
235         /// </pre>
236         public static string CurrentLanguage
237         {
238             get
239             {
240                 string currentLanguage;
241
242                 ErrorCode error = VcGetCurrentLanguage(out currentLanguage);
243                 if (error != ErrorCode.None)
244                 {
245                     Log.Error(LogTag, "CurrentLanguage Failed with error " + error);
246                     return "";
247                 }
248
249                 return currentLanguage;
250             }
251         }
252
253         /// <summary>
254         /// Gets the current state of the voice control client.
255         /// </summary>
256         /// <since_tizen> 3 </since_tizen>
257         /// <value>
258         /// The current state of the voice control client.
259         /// </value>
260         /// <privilege>
261         /// http://tizen.org/privilege/recorder
262         /// </privilege>
263         /// <pre>
264         /// The state must be initialized or ready.
265         /// </pre>
266         public static State State
267         {
268             get
269             {
270                 State state;
271
272                 ErrorCode error = VcGetState(out state);
273                 if (error != ErrorCode.None)
274                 {
275                     Log.Error(LogTag, "State Failed with error " + error);
276                     return State.Unavailable;
277                 }
278
279                 return state;
280             }
281         }
282
283         /// <summary>
284         /// Gets the current state of the voice control service.
285         /// </summary>
286         /// <since_tizen> 3 </since_tizen>
287         /// <value>
288         /// The current state of the voice control service.
289         /// </value>
290         /// <privilege>
291         /// http://tizen.org/privilege/recorder
292         /// </privilege>
293         /// <pre>
294         /// The state must be ready.
295         /// </pre>
296         public static ServiceState ServiceState
297         {
298             get
299             {
300                 ServiceState state;
301
302                 ErrorCode error = VcGetServiceState(out state);
303                 if (error != ErrorCode.None)
304                 {
305                     Log.Error(LogTag, "ServiceState Failed with error " + error);
306                     return ServiceState.Unavailable;
307                 }
308
309                 return state;
310             }
311         }
312
313         /// <summary>
314         /// Sets the invocation name.
315         /// </summary>
316         /// <since_tizen> 3 </since_tizen>
317         /// <privilege>
318         /// http://tizen.org/privilege/recorder
319         /// </privilege>
320         /// <privlevel>
321         /// public
322         /// </privlevel>
323         /// <feature>
324         /// http://tizen.org/feature/speech.control
325         /// http://tizen.org/feature/microphone
326         /// </feature>
327         /// <remarks>
328         /// The invocation name is used to activate background commands. The invocation name can be same as the application name or any other phrase.
329         /// For example, an application "Tizen Sample" has a background command, "Play music", and the invocation name of the application is set to "Tizen Sample".
330         /// In order to activate the background command, users can say "Tizen Sample, Play music". The invocation name is dependent on the current language.
331         /// For example, if the current language is "en_US"(English), the invocation name is also "en_US".
332         /// If the current language is "ja_JP"(Japanese) and the invocation name is "en_US", the invocation name will not be recognized.
333         /// This function should be called before the SetCommandList().
334         /// </remarks>
335         /// <param name="name">Invocation name to be invoked by an application.</param>
336         /// <exception cref="InvalidOperationException">This exception can be due to an invalid state.</exception>
337         /// <exception cref="ArgumentException">This exception can be due to an invalid parameter.</exception>
338         /// <exception cref="NotSupportedException">This exception can be due to not supported.</exception>
339         /// <exception cref="UnauthorizedAccessException">This exception can be due to permission denied.</exception>
340         /// <pre>
341         /// The state must be ready.
342         /// </pre>
343         public static void SetInvocationName(string name)
344         {
345             ErrorCode error = VcSetInvocationName(name);
346             if (error != ErrorCode.None)
347             {
348                 Log.Error(LogTag, "SetInvocationName Failed with error " + error);
349                 throw ExceptionFactory.CreateException(error);
350             }
351         }
352
353         /// <summary>
354         /// Initializes the voice control.
355         /// </summary>
356         /// <since_tizen> 3 </since_tizen>
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 the voice control.
386         /// </summary>
387         /// <since_tizen> 3 </since_tizen>
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 an 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         /// <since_tizen> 3 </since_tizen>
416         /// <privilege>
417         /// http://tizen.org/privilege/recorder
418         /// </privilege>
419         /// <privlevel>
420         /// public
421         /// </privlevel>
422         /// <feature>
423         /// http://tizen.org/feature/speech.control
424         /// http://tizen.org/feature/microphone
425         /// </feature>
426         /// <exception cref="InvalidOperationException">This exception can be due to an invalid state.</exception>
427         /// <exception cref="InvalidOperationException">This exception can be due to operation failed.</exception>
428         /// <exception cref="NotSupportedException">This exception can be due to not supported.</exception>
429         /// <exception cref="UnauthorizedAccessException">This exception can be due to permission denied.</exception>
430         /// <pre>
431         /// The state must be initialized.
432         /// </pre>
433         /// <post>
434         /// The state must be ready.
435         /// </post>
436         public static void Prepare()
437         {
438             ErrorCode error = VcPrepare();
439             if (error != ErrorCode.None)
440             {
441                 Log.Error(LogTag, "Prepare Failed with error " + error);
442                 throw ExceptionFactory.CreateException(error);
443             }
444         }
445
446         /// <summary>
447         /// Disconnects the voice control service.
448         /// </summary>
449         /// <since_tizen> 3 </since_tizen>
450         /// <privilege>
451         /// http://tizen.org/privilege/recorder
452         /// </privilege>
453         /// <privlevel>
454         /// public
455         /// </privlevel>
456         /// <feature>
457         /// http://tizen.org/feature/speech.control
458         /// http://tizen.org/feature/microphone
459         /// </feature>
460         /// <exception cref="InvalidOperationException">This exception can be due to an invalid state.</exception>
461         /// <exception cref="NotSupportedException">This exception can be due to not supported.</exception>
462         /// <exception cref="UnauthorizedAccessException">This exception can be due to permission denied.</exception>
463         /// <pre>
464         /// The state must be ready.
465         /// </pre>
466         /// <post>
467         /// The state must be initialized.
468         /// </post>
469         public static void Unprepare()
470         {
471             ErrorCode error = VcUnprepare();
472             if (error != ErrorCode.None)
473             {
474                 Log.Error(LogTag, "Unprepare Failed with error " + error);
475                 throw ExceptionFactory.CreateException(error);
476             }
477         }
478
479         /// <summary>
480         /// Retrieves all the supported languages.
481         /// A language is specified as an ISO 3166 alpha-2 two letter country-code
482         /// followed by ISO 639-1 for the two-letter language code.
483         /// For example, "ko_KR" for Korean, "en_US" for American English.
484         /// </summary>
485         /// <since_tizen> 3 </since_tizen>
486         /// <privilege>
487         /// http://tizen.org/privilege/recorder
488         /// </privilege>
489         /// <privlevel>
490         /// public
491         /// </privlevel>
492         /// <feature>
493         /// http://tizen.org/feature/speech.control
494         /// http://tizen.org/feature/microphone
495         /// </feature>
496         /// <exception cref="InvalidOperationException">This exception can be due to an invalid state.</exception>
497         /// <exception cref="InvalidOperationException">This exception can be due to operation failed.</exception>
498         /// <exception cref="NotSupportedException">This exception can be due to not supported.</exception>
499         /// <exception cref="UnauthorizedAccessException">This exception can be due to permission denied.</exception>
500         /// <pre>
501         /// The state must be ready or initialized.
502         /// </pre>
503         public static IEnumerable<string> GetSupportedLanguages()
504         {
505             s_supportedLanguages = new List<string>();
506             s_supportedLanguagesCb = (IntPtr language, IntPtr userData) =>
507             {
508                 string languageStr = Marshal.PtrToStringAnsi(language);
509                 s_supportedLanguages.Add(languageStr);
510                 return true;
511             };
512             ErrorCode error = VcForeachSupportedLanguages(s_supportedLanguagesCb, IntPtr.Zero);
513             if (error != ErrorCode.None)
514             {
515                 Log.Error(LogTag, "GetSupportedLanguages Failed with error " + error);
516                 throw ExceptionFactory.CreateException(error);
517             }
518
519             return s_supportedLanguages;
520         }
521
522         /// <summary>
523         /// Gets the system command list.
524         /// </summary>
525         /// <since_tizen> 3 </since_tizen>
526         /// <returns>
527         /// The command list, else null in case of no system commands.
528         /// </returns>
529         /// <privilege>
530         /// http://tizen.org/privilege/recorder
531         /// </privilege>
532         /// <privlevel>
533         /// public.
534         /// </privlevel>
535         /// <feature>
536         /// http://tizen.org/feature/speech.control
537         /// http://tizen.org/feature/microphone
538         /// </feature>
539         /// <remarks>
540         /// In the system command list, there are system commands predefined by product manufacturers.
541         /// Those commands have the highest priority. Therefore, the user cannot set any commands similar to system commands.
542         /// </remarks>
543         /// <exception cref="InvalidOperationException">This exception can be due to an invalid state.</exception>
544         /// <exception cref="InvalidOperationException">This exception can be due to operation failed.</exception>
545         /// <exception cref="NotSupportedException">This exception can be due to not supported.</exception>
546         /// <exception cref="UnauthorizedAccessException">This exception can be due to permission denied.</exception>
547         /// <pre>
548         /// The state must be ready.
549         /// </pre>
550         public static VoiceCommandList GetSystemCommandList()
551         {
552             IntPtr handle = IntPtr.Zero;
553             ErrorCode error = VcGetSystemCommandList(out handle);
554             if (error != ErrorCode.None)
555             {
556                 Log.Error(LogTag, "GetSystemCommandList Failed with error " + error);
557                 throw ExceptionFactory.CreateException(error);
558             }
559
560             if (handle == IntPtr.Zero)
561             {
562                 Log.Error(LogTag, "GetSystemCommandList handle is null");
563                 return null;
564             }
565
566             SafeCommandListHandle list = new SafeCommandListHandle(handle);
567             return new VoiceCommandList(list);
568         }
569
570         /// <summary>
571         /// Requests to start the dialogue.
572         /// By using this function, the developer can start requesting the dialogue to the framework.
573         /// 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.
574         /// 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.
575         /// Also, the developer can set whether the dialogue starts automatically or not, using autoStart.
576         /// If the developer sets autoStart as True, the framework will start to record the next speech and continue the dialogue.
577         /// </summary>
578         /// <since_tizen> 3 </since_tizen>
579         /// <privilege>
580         /// http://tizen.org/privilege/recorder
581         /// </privilege>
582         /// <privlevel>
583         /// public
584         /// </privlevel>
585         /// <feature>
586         /// http://tizen.org/feature/speech.control
587         /// http://tizen.org/feature/microphone
588         /// </feature>
589         /// <remarks>
590         /// If autoStart is True, the recognition will start again. In this case, it can be restarted up to 4 times.
591         /// </remarks>
592         /// <param name="dispText">Text to be displayed on the screen.</param>
593         /// <param name="uttText">Text to be spoken.</param>
594         /// <param name="autoStart">A variable for setting whether the dialog session will be restarted automatically or not.</param>
595         /// <exception cref="InvalidOperationException">This exception can be due to an invalid state.</exception>
596         /// <exception cref="ArgumentException">This exception can be due to an invalid parameter.</exception>
597         /// <exception cref="NotSupportedException">This exception can be due to not supported.</exception>
598         /// <exception cref="UnauthorizedAccessException">This exception can be due to permission denied.</exception>
599         /// <pre>
600         /// The state must be ready.
601         /// </pre>
602         public static void RequestDialog(string dispText, string uttText, bool autoStart)
603         {
604             ErrorCode error = VcRequestDialog(dispText, uttText, autoStart);
605             if (error != ErrorCode.None)
606             {
607                 Log.Error(LogTag, "RequestDialog Failed with error " + error);
608                 throw ExceptionFactory.CreateException(error);
609             }
610         }
611
612         /// <summary>
613         /// Sets the command list.
614         /// </summary>
615         /// <since_tizen> 3 </since_tizen>
616         /// <privilege>
617         /// http://tizen.org/privilege/recorder
618         /// </privilege>
619         /// <privlevel>
620         /// public
621         /// </privlevel>
622         /// <feature>
623         /// http://tizen.org/feature/speech.control
624         /// http://tizen.org/feature/microphone
625         /// </feature>
626         /// <remarks>
627         /// The command type is valid for CommandType 'Foreground' or 'Background'.
628         /// The matched commands of the command list should be set and they should include type and command text at least.
629         /// </remarks>
630         /// <param name="list">Command list</param>
631         /// <param name="type">Command type</param>
632         /// <exception cref="InvalidOperationException">This exception can be due to an invalid state.</exception>
633         /// <exception cref="ArgumentException">This exception can be due to an invalid parameter.</exception>
634         /// <exception cref="NotSupportedException">This exception can be due to not supported.</exception>
635         /// <exception cref="UnauthorizedAccessException">This exception can be due to permission denied.</exception>
636         /// <pre>
637         /// The state must be ready.
638         /// </pre>
639         public static void SetCommandList(VoiceCommandList list, CommandType type)
640         {
641             if ((type == CommandType.Foreground) || (type == CommandType.Background))
642             {
643                 ErrorCode error = VcSetCommandList(list._handle, (VoiceCommandType)type);
644                 if (error != ErrorCode.None)
645                 {
646                     Log.Error(LogTag, "SetCommandList Failed with error " + error);
647                     throw ExceptionFactory.CreateException(error);
648                 }
649             }
650
651             else
652             {
653                 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
654             }
655         }
656
657         /// <summary>
658         /// Unsets the command list.
659         /// </summary>
660         /// <since_tizen> 3 </since_tizen>
661         /// <privilege>
662         /// http://tizen.org/privilege/recorder
663         /// </privilege>
664         /// <privlevel>
665         /// public
666         /// </privlevel>
667         /// <feature>
668         /// http://tizen.org/feature/speech.control
669         /// http://tizen.org/feature/microphone
670         /// </feature>
671         /// <param name="type">Command type</param>
672         /// <exception cref="InvalidOperationException">This exception can be due to an invalid state.</exception>
673         /// <exception cref="ArgumentException">This exception can be due to an invalid parameter.</exception>
674         /// <exception cref="NotSupportedException">This exception can be due to not supported.</exception>
675         /// <exception cref="UnauthorizedAccessException">This exception can be due to permission denied.</exception>
676         /// <pre>
677         /// The state should be ready.
678         /// </pre>
679         public static void UnsetCommandList(CommandType type)
680         {
681             if ((type == CommandType.Foreground) || (type == CommandType.Background))
682             {
683                 VoiceCommandType commandType = VoiceCommandType.Foreground;
684                 if (type == CommandType.Background)
685                     commandType = VoiceCommandType.BackGround;
686                 ErrorCode error = VcUnsetCommandList(commandType);
687                 if (error != ErrorCode.None)
688                 {
689                     Log.Error(LogTag, "UnsetCommandList Failed with error " + error);
690                     throw ExceptionFactory.CreateException(error);
691                 }
692             }
693
694             else
695             {
696                 throw ExceptionFactory.CreateException(ErrorCode.InvalidParameter);
697             }
698         }
699
700         /// <summary>
701         /// Gets the recognition result.
702         /// </summary>
703         /// <since_tizen> 3 </since_tizen>
704         /// <privilege>
705         /// http://tizen.org/privilege/recorder
706         /// </privilege>
707         /// <privlevel>
708         /// public
709         /// </privlevel>
710         /// <feature>
711         /// http://tizen.org/feature/speech.control
712         /// http://tizen.org/feature/microphone
713         /// </feature>
714         /// <exception cref="InvalidOperationException">This exception can be due to an invalid state.</exception>
715         /// <exception cref="ArgumentException">This exception can be due to an invalid parameter.</exception>
716         /// <exception cref="NotSupportedException">This exception can be due to not supported.</exception>
717         /// <returns>The recognition result if possible, else a null object.</returns>
718         /// <pre>
719         /// The state must be ready.
720         /// </pre>
721         public static RecognitionResult GetResult()
722         {
723             s_recognitionResult = null;
724             s_resultCb = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
725             {
726                 if (IntPtr.Zero != cmdList && IntPtr.Zero != result)
727                 {
728                     s_recognitionResult = new RecognitionResult(evt, cmdList, result);
729                 }
730                 else
731                 {
732                     Log.Info(LogTag, "cmdList or result is null");
733                 }
734             };
735             ErrorCode error = VcGetResult(s_resultCb, IntPtr.Zero);
736             if (error != ErrorCode.None)
737             {
738                 Log.Error(LogTag, "GetResult Failed with error " + error);
739                 throw ExceptionFactory.CreateException(error);
740             }
741
742             return s_recognitionResult;
743         }
744
745         /// <summary>
746         /// Event to be invoked when the recognition is done.
747         /// </summary>
748         /// <since_tizen> 3 </since_tizen>
749         /// <pre>
750         /// The state must be initialized.
751         /// </pre>
752         public static event EventHandler<RecognitionResultEventArgs> RecognitionResult
753         {
754             add
755             {
756                 s_resultDelegate = (ResultEvent evt, IntPtr cmdList, IntPtr result, IntPtr userData) =>
757                 {
758                     Log.Info(LogTag, "Recognition Result Event Triggered");
759                     if (IntPtr.Zero != cmdList && IntPtr.Zero != result)
760                     {
761                         RecognitionResultEventArgs args = new RecognitionResultEventArgs(new RecognitionResult(evt, cmdList, result));
762                         _recognitionResult?.Invoke(null, args);
763                     }
764                     else
765                     {
766                         Log.Info(LogTag, "Recognition Result Event null received");
767                     }
768                 };
769                 ErrorCode error = VcSetResultCb(s_resultDelegate, IntPtr.Zero);
770                 if (error != ErrorCode.None)
771                 {
772                     Log.Error(LogTag, "Add RecognitionResult Failed with error " + error);
773                 }
774                 else
775                 {
776                     _recognitionResult += value;
777                 }
778             }
779
780             remove
781             {
782                 ErrorCode error = VcUnsetResultCb();
783                 if (error != ErrorCode.None)
784                 {
785                     Log.Error(LogTag, "Remove RecognitionResult Failed with error " + error);
786                 }
787
788                 _recognitionResult -= value;
789             }
790         }
791
792         /// <summary>
793         /// Event to be invoked when the VoiceControl service state changes.
794         /// </summary>
795         /// <since_tizen> 3 </since_tizen>
796         /// <pre>
797         /// The state must be initialized.
798         /// </pre>
799         public static event EventHandler<ServiceStateChangedEventArgs> ServiceStateChanged
800         {
801             add
802             {
803                 s_serviceStateDelegate = (ServiceState previous, ServiceState current, IntPtr userData) =>
804                 {
805                     ServiceStateChangedEventArgs args = new ServiceStateChangedEventArgs(previous, current);
806                     _serviceStateChanged?.Invoke(null, args);
807                 };
808                 ErrorCode error = VcSetServiceStateChangedCb(s_serviceStateDelegate, IntPtr.Zero);
809                 if (error != ErrorCode.None)
810                 {
811                     Log.Error(LogTag, "Add ServiceStateChanged Failed with error " + error);
812                 }
813                 else
814                 {
815                     _serviceStateChanged += value;
816                 }
817             }
818
819             remove
820             {
821                 ErrorCode error = VcUnsetServiceStateChangedCb();
822                 if (error != ErrorCode.None)
823                 {
824                     Log.Error(LogTag, "Remove ServiceStateChanged Failed with error " + error);
825                 }
826
827                 _serviceStateChanged -= value;
828             }
829         }
830
831         /// <summary>
832         /// Event to be invoked when the VoiceControl client state changes.
833         /// </summary>
834         /// <since_tizen> 3 </since_tizen>
835         /// <pre>
836         /// The state must be initialized.
837         /// </pre>
838         public static event EventHandler<StateChangedEventArgs> StateChanged
839         {
840             add
841             {
842                 s_stateDelegate = (State previous, State current, IntPtr userData) =>
843                 {
844                     StateChangedEventArgs args = new StateChangedEventArgs(previous, current);
845                     _stateChanged?.Invoke(null, args);
846                 };
847                 ErrorCode error = VcSetStateChangedCb(s_stateDelegate, IntPtr.Zero);
848                 if (error != ErrorCode.None)
849                 {
850                     Log.Error(LogTag, "Add StateChanged Failed with error " + error);
851                 }
852                 else
853                 {
854                     _stateChanged += value;
855                 }
856             }
857
858             remove
859             {
860                 ErrorCode error = VcUnsetStateChangedCb();
861                 if (error != ErrorCode.None)
862                 {
863                     Log.Error(LogTag, "Remove StateChanged Failed with error " + error);
864                 }
865
866                 _stateChanged -= value;
867             }
868         }
869
870         /// <summary>
871         /// Event to be invoked when an error occurs.
872         /// </summary>
873         /// <since_tizen> 3 </since_tizen>
874         /// <pre>
875         /// The state must be initialized.
876         /// </pre>
877         public static event EventHandler<ErrorOccuredEventArgs> ErrorOccured
878         {
879             add
880             {
881                 s_errorDelegate = (ErrorCode reason, IntPtr userData) =>
882             {
883                 ErrorOccuredEventArgs args = new ErrorOccuredEventArgs(reason);
884                 _errorOccured?.Invoke(null, args);
885             };
886                 ErrorCode error = VcSetErrorCb(s_errorDelegate, IntPtr.Zero);
887                 if (error != ErrorCode.None)
888                 {
889                     Log.Error(LogTag, "Add ErrorOccured Failed with error " + error);
890                 }
891
892                 else
893                 {
894                     _errorOccured += value;
895                 }
896             }
897
898
899             remove
900             {
901                 ErrorCode error = VcUnsetErrorCb();
902                 if (error != ErrorCode.None)
903                 {
904                     Log.Error(LogTag, "Remove ErrorOccured Failed with error " + error);
905                 }
906
907                 _errorOccured -= value;
908             }
909         }
910
911         /// <summary>
912         /// Event to be invoked when the default language changes.
913         /// </summary>
914         /// <since_tizen> 3 </since_tizen>
915         /// <pre>
916         /// The state must be initialized.
917         /// </pre>
918         public static event EventHandler<CurrentLanguageChangedEventArgs> CurrentLanguageChanged
919         {
920             add
921             {
922                 s_languageDelegate = (IntPtr previousLanguage, IntPtr currentLanguage, IntPtr userData) =>
923             {
924                 string previousLanguageString = Marshal.PtrToStringAnsi(previousLanguage);
925                 string currentLanguageString = Marshal.PtrToStringAnsi(currentLanguage);
926                 CurrentLanguageChangedEventArgs args = new CurrentLanguageChangedEventArgs(previousLanguageString, currentLanguageString);
927                 _currentLanguageChanged?.Invoke(null, args);
928             };
929                 ErrorCode error = VcSetCurrentLanguageChangedCb(s_languageDelegate, IntPtr.Zero);
930                 if (error != ErrorCode.None)
931                 {
932                     Log.Error(LogTag, "Add CurrentLanguageChanged Failed with error " + error);
933                 }
934
935                 else
936                 {
937                     _currentLanguageChanged += value;
938                 }
939             }
940
941             remove
942             {
943                 ErrorCode error = VcUnsetCurrentLanguageChangedCb();
944                 if (error != ErrorCode.None)
945                 {
946                     Log.Error(LogTag, "Remove CurrentLanguageChanged Failed with error " + error);
947                 }
948
949                 _currentLanguageChanged -= value;
950             }
951         }
952     }
953 }