[Camera/Recorder]
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia / Recorder / Recorder.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 Tizen.Internals.Errors;
21
22 namespace Tizen.Multimedia
23 {
24         static internal class RecorderLog
25         {
26                 internal const string Tag = "Tizen.Multimedia.Recorder";
27         }
28
29     /// <summary>
30     /// The recorder class provides methods to create audio/video recorder,
31         ///  to start, stop and save the recorded content. It also provides methods
32         ///  to get/set various attributes and capabilities of recorder.
33     /// </summary>
34         /// <privilege>
35         /// http://tizen.org/privilege/recorder
36         /// </privilege>
37         public class Recorder : IDisposable
38         {
39         private IntPtr _handle;
40         private bool _disposed = false;
41                 private EventHandler<RecorderStateChangedEventArgs> _recorderStateChanged;
42                 private Interop.Recorder.StatechangedCallback _recorderStateChangedCallback;
43                 private EventHandler<RecordingStatusChangedEventArgs> _recordingStatusChanged;
44                 private Interop.Recorder.RecordingStatusCallback _recordingStatusCallback;
45                 private EventHandler<RecordingLimitReachedEventArgs> _recordingLimitReached;
46                 private Interop.Recorder.RecordingLimitReachedCallback _recordingLimitReachedCallback;
47                 private EventHandler<AudioStreamDeliveredEventArgs> _audioStreamDelivered;
48                 private Interop.Recorder.AudioStreamCallback _audioStreamCallback;
49                 private EventHandler<RecorderInterruptedEventArgs> _recorderInterrupted;
50                 private Interop.Recorder.InterruptedCallback _interruptedCallback;
51                 private EventHandler<RecordingErrorOccurredEventArgs> _recordingErrorOccured;
52                 private Interop.Recorder.RecorderErrorCallback _recorderErrorCallback;
53                 private List<RecorderFileFormat> _formats;
54                 private List<RecorderAudioCodec> _audioCodec;
55                 private List<RecorderVideoCodec> _videoCodec;
56                 private List<RecorderVideoResolution> _resolutions;
57                 RecorderVideoResolution _videoResolution = null;
58
59         /// <summary>
60         /// Audio recorder constructor.
61         /// </summary>
62                 public Recorder()
63                 {
64                         int ret = Interop.Recorder.Create (out _handle);
65                         if (ret != (int)RecorderError.None)
66                         {
67                                 RecorderErrorFactory.ThrowException (ret, "Failed to create Audio recorder");
68                         }
69                         _formats = new List<RecorderFileFormat>();
70                         _audioCodec = new List<RecorderAudioCodec>();
71                         _videoCodec = new List<RecorderVideoCodec> ();
72                         _resolutions = new List<RecorderVideoResolution> ();
73                         _videoResolution = new RecorderVideoResolution (_handle);
74                 }
75
76         /// <summary>
77         /// Video recorder constructor.
78         /// </summary>
79         /// <param name="camera">
80         /// The camera object.
81         /// </param>
82         public Recorder(Camera camera)
83         {
84                         int ret = Interop.Recorder.CreateVideo (camera.GetHandle(), out _handle);
85                         if (ret != (int)RecorderError.None)
86                         {
87                                 RecorderErrorFactory.ThrowException (ret, "Failed to create Video recorder");
88                         }
89                         _formats = new List<RecorderFileFormat>();
90                         _audioCodec = new List<RecorderAudioCodec>();
91                         _videoCodec = new List<RecorderVideoCodec> ();
92                         _resolutions = new List<RecorderVideoResolution> ();
93                         _videoResolution = new RecorderVideoResolution (_handle);
94         }
95
96         /// <summary>
97         /// Recorder destructor.
98         /// </summary>
99         ~Recorder()
100         {
101                         Dispose (false);
102         }
103
104         /// <summary>
105         /// Event that occurs when recorder is interrupted.
106         /// </summary>
107         public event EventHandler<RecorderInterruptedEventArgs> RecorderInterrupted
108                 {
109                         add
110                         {
111                                 if (_recorderInterrupted == null)
112                                 {
113                                         RegisterRecorderInterruptedEvent();
114                                 }
115                                 _recorderInterrupted += value;
116                         }
117                         remove
118                         {
119                                 _recorderInterrupted -= value;
120                                 if (_recorderInterrupted == null)
121                                 {
122                                         UnregisterRecorderInterruptedEvent ();
123                                 }
124                         }
125                 }
126
127                 /// <summary>
128                 /// Event that occurs when audio stream data is being delivered.
129                 /// </summary>
130                 public event EventHandler<AudioStreamDeliveredEventArgs> AudioStreamDelivered
131                 {
132                         add
133                         {
134                                 if (_audioStreamDelivered == null)
135                                 {
136                                         RegisterAudioStreamDeliveredEvent();
137                                 }
138                                 _audioStreamDelivered += value;
139                         }
140                         remove
141                         {
142                                 _audioStreamDelivered -= value;
143                                 if (_audioStreamDelivered == null)
144                                 {
145                                         UnregisterAudioStreamDeliveredEvent ();
146                                 }
147                         }
148                 }
149
150                 /// <summary>
151                 /// This event occurs when recorder state is changed.
152                 /// </summary>
153                 public event EventHandler<RecorderStateChangedEventArgs> RecorderStateChanged
154                 {
155                         add
156                         {
157                                 if (_recorderStateChanged == null)
158                                 {
159                                         RegisterStateChangedEvent();
160                                 }
161                                 _recorderStateChanged += value;
162                         }
163                         remove
164                         {
165                                 _recorderStateChanged -= value;
166                                 if (_recorderStateChanged == null)
167                                 {
168                                         UnregisterStateChangedEvent ();
169                                 }
170                         }
171                 }
172
173                 /// <summary>
174                 /// Event that occurs when recording information changes.
175                 /// </summary>
176                 public event EventHandler<RecordingStatusChangedEventArgs> RecordingStatusChanged
177                 {
178                         add
179                         {
180                                 if (_recordingStatusChanged == null)
181                                 {
182                                         RegisterRecordingStatusChangedEvent();
183                                 }
184                                 _recordingStatusChanged += value;
185                         }
186                         remove
187                         {
188                                 _recordingStatusChanged -= value;
189                                 if (_recordingStatusChanged == null)
190                                 {
191                                         UnregisterRecordingStatusChangedEvent ();
192                                 }
193                         }
194                 }
195
196                 /// <summary>
197                 /// Event that occurs when recording limit is reached.
198                 /// </summary>
199                 public event EventHandler<RecordingLimitReachedEventArgs> RecordingLimitReached
200                 {
201                         add
202                         {
203                                 if (_recordingLimitReached == null)
204                                 {
205                                         RegisterRecordingLimitReachedEvent();
206                                 }
207                                 _recordingLimitReached += value;
208                         }
209                         remove
210                         {
211                                 _recordingLimitReached -= value;
212                                 if (_recordingLimitReached == null)
213                                 {
214                                         UnregisterRecordingLimitReachedEvent ();
215                                 }
216                         }
217                 }
218
219                 /// <summary>
220                 /// Event that occurs when an error occurs during recorder operation.
221                 /// </summary>
222                 public event EventHandler<RecordingErrorOccurredEventArgs> RecordingErrorOccurred
223                 {
224                         add
225                         {
226                                 if (_recordingErrorOccured == null)
227                                 {
228                                         RegisterRecordingErrorOccuredEvent();
229                                 }
230                                 _recordingErrorOccured += value;
231                         }
232                         remove
233                         {
234                                 _recordingErrorOccured -= value;
235                                 if (_recordingErrorOccured == null)
236                                 {
237                                         UnregisterRecordingErrorOccuredEvent ();
238                                 }
239                         }
240                 }
241
242         /// <summary>
243         /// The file path to record.
244         /// </summary>
245         /// <remarks>
246         /// If the same file already exists in the file system, then old file
247         /// will be overwritten.
248         /// </remarks>
249         public string FilePath
250         {
251             get
252             {
253                                 IntPtr val;
254                                 int ret = Interop.Recorder.GetFileName (_handle, out val);
255                                 if ((RecorderError)ret != RecorderError.None)
256                                 {
257                                         Log.Error (RecorderLog.Tag, "Failed to get filepath, " + (RecorderError)ret);
258                                 }
259                                 string result = Marshal.PtrToStringAnsi (val);
260                                 Interop.Libc.Free (val);
261                                 return result;
262             }
263             set
264             {
265                                 int ret = Interop.Recorder.SetFileName (_handle, value);
266                                 if ((RecorderError)ret != RecorderError.None)
267                                 {
268                                         Log.Error (RecorderLog.Tag, "Failed to set filepath, " + (RecorderError)ret);
269                                         RecorderErrorFactory.ThrowException (ret, "Failed to set filepath");
270                                 }
271             }
272         }
273
274         /// <summary>
275         /// Get the peak audio input level in dB
276         /// </summary>
277         /// <remarks>
278         /// 0dB indicates maximum input level, -300dB indicates minimum input level.
279         /// </remarks>
280         public double AudioLevel
281         {
282             get
283             {
284                                 double level = 0;
285
286                                 int ret = Interop.Recorder.GetAudioLevel (_handle, out level);
287                                 if ((RecorderError)ret != RecorderError.None)
288                                 {
289                                         Log.Error (RecorderLog.Tag, "Failed to get Audio level, " + (RecorderError)ret);
290                                 }
291                                 return level;
292             }
293         }
294
295         /// <summary>
296         /// The current state of the recorder.
297         /// </summary>
298         public RecorderState State
299         {
300             get
301             {
302                                 int val = 0;
303
304                                 int ret = Interop.Recorder.GetState (_handle, out val);
305                                 if ((RecorderError)ret != RecorderError.None)
306                                 {
307                                         Log.Error (RecorderLog.Tag, "Failed to get recorder state, " + (RecorderError)ret);
308                                 }
309                                 return (RecorderState)val;
310             }
311         }
312
313         /// <summary>
314         /// The file format for recording media stream.
315         /// </summary>
316         public RecorderFileFormat FileFormat
317         {
318             get
319             {
320                                 int val = 0;
321
322                                 int ret = Interop.Recorder.GetFileFormat (_handle, out val);
323                                 if ((RecorderError)ret != RecorderError.None)
324                                 {
325                                         Log.Error (RecorderLog.Tag, "Failed to get file format, " + (RecorderError)ret);
326                                 }
327                                 return (RecorderFileFormat)val;
328             }
329             set
330             {
331                                 int ret = Interop.Recorder.SetFileFormat (_handle, (int)value);
332                                 if ((RecorderError)ret != RecorderError.None)
333                                 {
334                                         Log.Error (RecorderLog.Tag, "Failed to set file format, " + (RecorderError)ret);
335                                         RecorderErrorFactory.ThrowException (ret);
336                                 }
337             }
338         }
339
340         /// <summary>
341         /// The audio codec for encoding an audio stream.
342         /// </summary>
343         public RecorderAudioCodec AudioCodec
344         {
345             get
346             {
347                                 int val = 0;
348
349                                 int ret = Interop.Recorder.GetAudioEncoder (_handle, out val);
350                                 if ((RecorderError)ret != RecorderError.None)
351                                 {
352                                         Log.Error (RecorderLog.Tag, "Failed to get audio codec, " + (RecorderError)ret);
353                                 }
354                                 return (RecorderAudioCodec)val;
355             }
356             set
357             {
358                                 int ret = Interop.Recorder.SetAudioEncoder (_handle, (int)value);
359                                 if ((RecorderError)ret != RecorderError.None)
360                                 {
361                                         Log.Error (RecorderLog.Tag, "Failed to set audio codec, " + (RecorderError)ret);
362                                         RecorderErrorFactory.ThrowException (ret);
363                                 }
364             }
365         }
366
367         /// <summary>
368         /// The video codec for encoding video stream.
369         /// </summary>
370         public RecorderVideoCodec VideoCodec
371         {
372             get
373             {
374                                 int val = 0;
375
376                                 int ret = Interop.Recorder.GetVideoEncoder (_handle, out val);
377                                 if ((RecorderError)ret != RecorderError.None)
378                                 {
379                                                 Log.Error( RecorderLog.Tag, "Failed to get video codec, " + (RecorderError)ret);
380                                 }
381                                 return (RecorderVideoCodec)val;
382             }
383             set
384             {
385                                 int ret = Interop.Recorder.SetVideoEncoder (_handle, (int)value);
386
387                                 if ((RecorderError)ret != RecorderError.None)
388                                 {
389                                         Log.Error(RecorderLog.Tag, "Failed to set video codec, " + (RecorderError)ret);
390                                         RecorderErrorFactory.ThrowException(ret);
391                                 }
392             }
393         }
394
395                 /// <summary>
396                 /// The maximum size of a recording file in KB(kilobytes). If 0, means
397                 /// unlimited recording size.
398                 /// </summary>
399                 /// <remarks>
400                 /// After reaching the limitation, the data which is being recorded will
401                 /// be discarded and not written to the file.
402                 /// The recorder state must be in 'Ready' or 'Created' state.
403                 /// </remarks>
404                 ///
405                 public int SizeLimit
406                 {
407                         get
408                         {
409                                 int val = 0;
410
411                                 int ret = Interop.RecorderAttribute.GetSizeLimit (_handle, out val);
412                                 if ((RecorderError)ret != RecorderError.None)
413                                 {
414                                         Log.Error (RecorderLog.Tag, "Failed to get sizelimit, " + (RecorderError)ret);
415                                 }
416                                 return val;
417                         }
418                         set
419                         {
420                                 int ret = Interop.RecorderAttribute.SetSizeLimit (_handle, value);
421                                 if ((RecorderError)ret != RecorderError.None)
422                                 {
423                                         Log.Error (RecorderLog.Tag, "Failed to set sizelimit, " + (RecorderError)ret);
424                                         RecorderErrorFactory.ThrowException (ret, "Failed to set sizelimit");
425                                 }
426                         }
427                 }
428
429                 /// <summary>
430                 /// The time limit of a recording file in Seconds. If 0, means unlimited recording
431                 /// time.
432                 /// </summary>
433                 /// <remarks>
434                 /// After reaching the limitation, the data which is being recorded will
435                 /// be discarded and not written to the file.
436                 /// The recorder state must be in 'Ready' or 'Created' state.
437                 /// </remarks>
438                 public int TimeLimit
439                 {
440                         get
441                         {
442                                 int val = 0;
443
444                                 int ret = Interop.RecorderAttribute.GetTimeLimit (_handle, out val);
445                                 if ((RecorderError)ret != RecorderError.None)
446                                 {
447                                         Log.Error (RecorderLog.Tag, "Failed to get timelimit, " + (RecorderError)ret);
448                                 }
449                                 return val;
450                         }
451                         set
452                         {
453                                 int ret = Interop.RecorderAttribute.SetTimeLimit (_handle, value);
454                                 if ((RecorderError)ret != RecorderError.None)
455                                 {
456                                         Log.Error (RecorderLog.Tag, "Failed to set timelimit, " + (RecorderError)ret);
457                                         RecorderErrorFactory.ThrowException (ret, "Failed to set timelimit");
458                                 }
459                         }
460                 }
461
462                 /// <summary>
463                 /// The sampling rate of an audio stream in hertz.
464                 /// </summary>
465                 public int AudioSampleRate
466                 {
467                         get
468                         {
469                                 int val = 0;
470
471                                 int ret = Interop.RecorderAttribute.GetAudioSampleRate (_handle, out val);
472                                 if ((RecorderError)ret != RecorderError.None)
473                                 {
474                                         Log.Error (RecorderLog.Tag, "Failed to get audio samplerate, " + (RecorderError)ret);
475                                 }
476                                 return val;
477                         }
478                         set
479                         {
480                                 int ret = Interop.RecorderAttribute.SetAudioSampleRate (_handle, value);
481                                 if ((RecorderError)ret != RecorderError.None)
482                                 {
483                                         Log.Error (RecorderLog.Tag, "Failed to set audio samplerate, " + (RecorderError)ret);
484                                         RecorderErrorFactory.ThrowException (ret, "Failed to set audio samplerate");
485                                 }
486                         }
487                 }
488
489                 /// <summary>
490                 /// The bitrate of an audio encoder in bits per second.
491                 /// </summary>
492                 public int AudioBitRate
493                 {
494                         get
495                         {
496                                 int val = 0;
497
498                                 int ret = Interop.RecorderAttribute.GetAudioEncoderBitrate (_handle, out val);
499                                 if ((RecorderError)ret != RecorderError.None)
500                                 {
501                                         Log.Error (RecorderLog.Tag, "Failed to get audio bitrate, " + (RecorderError)ret);
502                                 }
503                                 return val;
504                         }
505                         set
506                         {
507                                 int ret = Interop.RecorderAttribute.SetAudioEncoderBitrate (_handle, value);
508                                 if ((RecorderError)ret != RecorderError.None)
509                                 {
510                                         Log.Error (RecorderLog.Tag, "Failed to set audio bitrate, " + (RecorderError)ret);
511                                         RecorderErrorFactory.ThrowException (ret, "Failed to set audio bitrate");
512                                 }
513                         }
514                 }
515
516                 /// <summary>
517                 /// The bitrate of an video encoder in bits per second.
518                 /// </summary>
519                 public int VideoBitRate
520                 {
521                         get
522                         {
523                                 int val = 0;
524
525                                 int ret = Interop.RecorderAttribute.GetVideoEncoderBitrate (_handle, out val);
526                                 if ((RecorderError)ret != RecorderError.None)
527                                 {
528                                         Log.Error (RecorderLog.Tag, "Failed to get video bitrate, " + (RecorderError)ret);
529                                 }
530                                 return val;
531                         }
532                         set
533                         {
534                                 int ret = Interop.RecorderAttribute.SetVideoEncoderBitrate (_handle, value);
535                                 if ((RecorderError)ret != RecorderError.None)
536                                 {
537                                         Log.Error (RecorderLog.Tag, "Failed to set video bitrate, " + (RecorderError)ret);
538                                         RecorderErrorFactory.ThrowException (ret, "Failed to set video bitrate");
539                                 }
540                         }
541                 }
542
543                 /// <summary>
544                 /// The mute state of a recorder.
545                 /// </summary>
546                 public bool Mute
547                 {
548                         get
549                         {
550                                 bool val;
551
552                                 val = Interop.RecorderAttribute.GetMute (_handle);
553                                 int ret = ErrorFacts.GetLastResult ();
554                                 if ((RecorderError)ret != RecorderError.None)
555                                 {
556                                         RecorderError err;
557                                         err = (RecorderError) ret;
558                                         Log.Error (RecorderLog.Tag, "Failed to get the mute state of recorder, return " + err.ToString());
559                                 }
560                                 return val;
561                         }
562                         set
563                         {
564                                 int ret = Interop.RecorderAttribute.SetMute (_handle, value);
565                                 if ((RecorderError)ret != RecorderError.None)
566                                 {
567                                         Log.Error (RecorderLog.Tag, "Failed to set mute, " + (RecorderError)ret);
568                                         RecorderErrorFactory.ThrowException (ret, "Failed to set mute");
569                                 }
570                         }
571                 }
572
573                 /// <summary>
574                 /// The video recording motion rate
575                 /// </summary>
576                 /// <remarks>
577                 /// The attribute is valid only in a video recorder.
578                 /// If the rate is in range of 0-1, video is recorded in a slow motion mode.
579                 /// If the rate is bigger than 1, video is recorded in a fast motion mode.
580                 /// </remarks>
581                 public double MotionRate
582                 {
583                         get
584                         {
585                                 double val = 0.0;
586
587                                 int ret = Interop.RecorderAttribute.GetMotionRate (_handle, out val);
588                                 if ((RecorderError)ret != RecorderError.None)
589                                 {
590                                         Log.Error (RecorderLog.Tag, "Failed to get video motionrate, " + (RecorderError)ret);
591                                 }
592                                 return val;
593                         }
594                         set
595                         {
596                                 int ret = Interop.RecorderAttribute.SetMotionRate (_handle, (double)value);
597                                 if ((RecorderError)ret != RecorderError.None)
598                                 {
599                                         Log.Error (RecorderLog.Tag, "Failed to set video motionrate, " + (RecorderError)ret);
600                                         RecorderErrorFactory.ThrowException (ret, "Failed to set video motionrate");
601                                 }
602                         }
603                 }
604
605                 /// <summary>
606                 /// The number of audio channel.
607                 /// </summary>
608                 /// <remarks>
609                 /// The attribute is applied only in Created state.
610                 /// For mono recording, set channel to 1.
611                 /// For stereo recording, set channel to 2.
612                 /// </remarks>
613                 public int AudioChannel
614                 {
615                         get
616                         {
617                                 int val = 0;
618
619                                 int ret = Interop.RecorderAttribute.GetAudioChannel (_handle, out val);
620                                 if ((RecorderError)ret != RecorderError.None)
621                                 {
622                                         Log.Error (RecorderLog.Tag, "Failed to get audio channel, " + (RecorderError)ret);
623                                 }
624                                 return val;
625                         }
626                         set
627                         {
628                                 int ret = Interop.RecorderAttribute.SetAudioChannel (_handle, value);
629                                 if ((RecorderError)ret != RecorderError.None)
630                                 {
631                                         Log.Error (RecorderLog.Tag, "Failed to set audio channel, " + (RecorderError)ret);
632                                         RecorderErrorFactory.ThrowException (ret, "Failed to set audio channel");
633                                 }
634                         }
635                 }
636
637                 /// <summary>
638                 /// The audio device for recording.
639                 /// </summary>
640                 public RecorderAudioDevice AudioDevice
641                 {
642                         get
643                         {
644                                 int val = 0;
645
646                                 int ret = Interop.RecorderAttribute.GetAudioDevice (_handle, out val);
647                                 if ((RecorderError)ret != RecorderError.None)
648                                 {
649                                         Log.Error (RecorderLog.Tag, "Failed to get audio device, " + (RecorderError)ret);
650                                 }
651                                 return (RecorderAudioDevice)val;
652                         }
653                         set
654                         {
655                                 int ret = Interop.RecorderAttribute.SetAudioDevice (_handle, (int)value);
656                                 if ((RecorderError)ret != RecorderError.None)
657                                 {
658                                         Log.Error (RecorderLog.Tag, "Failed to set audio device, " + (RecorderError)ret);
659                                         RecorderErrorFactory.ThrowException (ret, "Failed to set audio device");
660                                 }
661                         }
662                 }
663
664                 /// <summary>
665                 /// The orientation in a video metadata tag.
666                 /// </summary>
667                 public RecorderOrientation OrientationTag
668                 {
669                         get
670                         {
671                                 int val = 0;
672
673                                 int ret = Interop.RecorderAttribute.GetOrientationTag (_handle, out val);
674                                 if ((RecorderError)ret != RecorderError.None)
675                                 {
676                                         Log.Error (RecorderLog.Tag, "Failed to get recorder orientation, " + (RecorderError)ret);
677                                 }
678                                 return (RecorderOrientation)val;
679                         }
680                         set
681                         {
682                                 int ret = Interop.RecorderAttribute.SetOrientationTag (_handle, (int)value);
683                                 if ((RecorderError)ret != RecorderError.None)
684                                 {
685                                         Log.Error (RecorderLog.Tag, "Failed to set recorder orientation, " + (RecorderError)ret);
686                                         RecorderErrorFactory.ThrowException (ret, "Failed to set audio orientation");
687                                 }
688                         }
689                 }
690
691         /// <summary>
692         /// Video resolution of the video recording.
693         /// </summary>
694         public RecorderVideoResolution Resolution
695         {
696             get
697             {
698                                 return _videoResolution;
699             }
700         }
701
702                 /// <summary>
703                 /// Retrieves all the file formats supported by the recorder.
704                 /// </summary>
705                 /// <returns>
706                 /// It returns a list containing all the supported file
707                 /// formats by recorder.
708                 /// </returns>
709                 public IEnumerable<RecorderFileFormat> SupportedFileFormats
710                 {
711                         get
712                         {
713                                 if (_formats.Count == 0)
714                                 {
715                                         Interop.RecorderCapablity.FileFormatCallback callback = (RecorderFileFormat format, IntPtr userData) =>
716                                         {
717                                                 _formats.Add (format);
718                                                 return true;
719                                         };
720                                         int ret = Interop.RecorderCapablity.FileFormats (_handle, callback, IntPtr.Zero);
721                                         if (ret != (int)RecorderError.None)
722                                         {
723                                                 RecorderErrorFactory.ThrowException (ret, "Failed to get the supported fileformats");
724                                         }
725                                 }
726                                 return _formats;
727                         }
728                 }
729
730                 /// <summary>
731                 /// Retrieves all the audio encoders supported by the recorder.
732                 /// </summary>
733                 /// <returns>
734                 /// It returns a list containing all the supported audio encoders
735                 /// by recorder.
736                 /// </returns>
737                 public IEnumerable<RecorderAudioCodec> SupportedAudioEncodings
738                 {
739                         get
740                         {
741                                 if (_audioCodec.Count == 0)
742                                 {
743                                         Interop.RecorderCapablity.AudioEncoderCallback callback = (RecorderAudioCodec codec, IntPtr userData) =>
744                                         {
745                                                 _audioCodec.Add(codec);
746                                                 return true;
747                                         };
748                                         int ret = Interop.RecorderCapablity.AudioEncoders (_handle, callback, IntPtr.Zero);
749                                         if (ret != (int)RecorderError.None)
750                                         {
751                                                 RecorderErrorFactory.ThrowException (ret, "Failed to get the supported audio encoders");
752                                         }
753                                 }
754                                 return _audioCodec;
755                         }
756                 }
757
758                 /// <summary>
759                 /// Retrieves all the video encoders supported by the recorder.
760                 /// </summary>
761                 /// <returns>
762                 /// It returns a list containing all the supported video encoders
763                 /// by recorder.
764                 /// </returns>
765                 public IEnumerable<RecorderVideoCodec> SupportedVideoEncodings
766                 {
767                         get
768                         {
769                                 if (_videoCodec.Count == 0)
770                                 {
771                                         Interop.RecorderCapablity.VideoEncoderCallback callback = (RecorderVideoCodec codec, IntPtr userData) =>
772                                         {
773                                                 _videoCodec.Add(codec);
774                                                 return true;
775                                         };
776                                         int ret = Interop.RecorderCapablity.VideoEncoders (_handle, callback, IntPtr.Zero);
777                                         if (ret != (int)RecorderError.None)
778                                         {
779                                                 RecorderErrorFactory.ThrowException (ret, "Failed to get the supported video encoders");
780                                         }
781                                 }
782                                 return _videoCodec;
783                         }
784                 }
785
786                 /// <summary>
787                 /// Retrieves all the video resolutions supported by the recorder.
788                 /// </summary>
789                 /// <returns>
790                 /// It returns videoresolution list containing the width and height of
791                 /// different resolutions supported by recorder.
792                 /// </returns>
793                 public IEnumerable<RecorderVideoResolution> SupportedVideoResolutions
794                 {
795                         get
796                         {
797                                 if (_resolutions.Count == 0)
798                                 {
799                                         Interop.RecorderCapablity.VideoResolutionCallback callback = (int width, int height, IntPtr userData) =>
800                                         {
801                                                 RecorderVideoResolution temp = new RecorderVideoResolution(width, height);
802                                                 _resolutions.Add(temp);
803                                                 return true;
804                                         };
805                                         int ret = Interop.RecorderCapablity.VideoResolution (_handle, callback, IntPtr.Zero);
806                                         if (ret != (int)RecorderError.None)
807                                         {
808                                                 RecorderErrorFactory.ThrowException (ret, "Failed to get the supported video resolutions");
809                                         }
810                                 }
811                                 return _resolutions;
812                         }
813                 }
814
815                 /// <summary>
816                 /// Prepare the media recorder for recording.
817                 /// </summary>
818                 /// <remarks>
819                 /// Before calling the function, it is required to set AudioEncoder,
820                 /// videoencoder and fileformat properties of recorder.
821                 /// </remarks>
822                 /// <privilege>
823                 /// http://tizen.org/privilege/recorder
824                 /// </privilege>
825                 public void Prepare()
826                 {
827                         int ret = Interop.Recorder.Prepare (_handle);
828                         if (ret != (int)RecorderError.None)
829                         {
830                                 RecorderErrorFactory.ThrowException (ret, "Failed to prepare media recorder for recording");
831                         }
832                 }
833
834                 /// <summary>
835                 /// Resets the media recorder.
836                 /// </summary>
837                 /// <privilege>
838                 /// http://tizen.org/privilege/recorder
839                 /// </privilege>
840                 public void Unprepare()
841                 {
842                         int ret = Interop.Recorder.Unprepare (_handle);
843                         if (ret != (int)RecorderError.None)
844                         {
845                                 RecorderErrorFactory.ThrowException (ret, "Failed to reset the media recorder");
846                         }
847                 }
848
849                 /// <summary>
850                 /// Starts the recording.
851                 /// </summary>
852                 /// <remarks>
853                 /// If file path has been set to an existing file, this file is removed automatically and updated by new one.
854                 /// In the video recorder, some preview format does not support record mode. It will return InvalidOperation error.
855                 ///     You should use default preview format or CameraPixelFormatNv12 in the record mode.
856                 ///     The filename should be set before this function is invoked.
857                 /// </remarks>
858                 /// <privilege>
859                 /// http://tizen.org/privilege/recorder
860                 /// </privilege>
861                 public void Start()
862                 {
863                         int ret = Interop.Recorder.Start (_handle);
864                         if (ret != (int)RecorderError.None)
865                         {
866                                 RecorderErrorFactory.ThrowException (ret, "Failed to start the media recorder");
867                         }
868                 }
869
870                 /// <summary>
871                 /// Pause the recording.
872                 /// </summary>
873                 /// <remarks>
874                 /// Recording can be resumed with Start().
875                 /// </remarks>
876                 /// <privilege>
877                 /// http://tizen.org/privilege/recorder
878                 /// </privilege>
879                 public void Pause()
880                 {
881                         int ret = Interop.Recorder.Pause (_handle);
882                         if (ret != (int)RecorderError.None)
883                         {
884                                 RecorderErrorFactory.ThrowException (ret, "Failed to pause the media recorder");
885                         }
886                 }
887
888                 /// <summary>
889                 /// Stops recording and saves the result.
890                 /// </summary>
891                 /// <privilege>
892                 /// http://tizen.org/privilege/recorder
893                 /// </privilege>
894                 public void Commit()
895                 {
896                         int ret = Interop.Recorder.Commit (_handle);
897                         if (ret != (int)RecorderError.None)
898                         {
899                                 RecorderErrorFactory.ThrowException (ret, "Failed to save the recorded content");
900                         }
901                 }
902
903                 /// <summary>
904                 /// Cancels the recording.
905                 /// The recording data is discarded and not written in the recording file.
906                 /// </summary>
907                 /// <privilege>
908                 /// http://tizen.org/privilege/recorder
909                 /// </privilege>
910                 public void Cancel()
911                 {
912                         int ret = Interop.Recorder.Cancel (_handle);
913                         if (ret != (int)RecorderError.None)
914                         {
915                                 RecorderErrorFactory.ThrowException (ret, "Failed to cancel the recording");
916                         }
917                 }
918
919                 /// <summary>
920                 /// Sets the audio stream policy.
921                 /// </summary>
922                 /// <param name="policy">Policy.</param>
923                 public void SetAudioStreamPolicy(AudioStreamPolicy policy)
924                 {
925                         int ret = Interop.Recorder.SetAudioStreamPolicy (_handle, policy.Handle);
926
927                         if (ret != (int)RecorderError.None)
928                         {
929                                 RecorderErrorFactory.ThrowException (ret, "Failed to set audio stream policy");
930                         }
931                 }
932
933                 /// <summary>
934                 /// Release any unmanaged resources used by this object.
935                 /// </summary>
936                 public void Dispose()
937                 {
938                         Dispose(true);
939                         GC.SuppressFinalize(this);
940                 }
941
942                 protected virtual void Dispose(bool disposing)
943                 {
944                         if (!_disposed)
945                         {
946                                 if (disposing)
947                                 {
948                     // to be used if there are any other disposable objects
949                                 }
950                                 if (_handle != IntPtr.Zero)
951                                 {
952                                         Interop.Recorder.Destroy (_handle);
953                                         _handle = IntPtr.Zero;
954                                 }
955                                 _disposed = true;
956                         }
957                 }
958
959                 private void RegisterRecorderInterruptedEvent()
960                 {
961                         _interruptedCallback = (RecorderPolicy policy, RecorderState previous, RecorderState current, IntPtr userData) =>
962                         {
963                                 RecorderInterruptedEventArgs eventArgs = new RecorderInterruptedEventArgs(policy, previous, current);
964                                 _recorderInterrupted?.Invoke(this, eventArgs);
965                         };
966                         int ret = Interop.Recorder.SetInterruptedCallback (_handle, _interruptedCallback, IntPtr.Zero);
967                         if (ret != (int)RecorderError.None)
968                         {
969                                 RecorderErrorFactory.ThrowException (ret, "Setting Interrupted callback failed");
970                         }
971                 }
972
973                 private void UnregisterRecorderInterruptedEvent()
974                 {
975                         int ret = Interop.Recorder.UnsetInterruptedCallback (_handle);
976                         if (ret != (int)RecorderError.None)
977                         {
978                                 RecorderErrorFactory.ThrowException (ret, "Unsetting Interrupted callback failed");
979                         }
980                 }
981
982                 private void RegisterAudioStreamDeliveredEvent()
983                 {
984                         _audioStreamCallback = (IntPtr stream, int size, AudioSampleType type, int channel, uint recordingTime, IntPtr userData) =>
985                         {
986                                 byte[] streamArray = new byte[size];
987                                 Marshal.Copy(stream, streamArray, 0, size);
988                                 AudioStreamDeliveredEventArgs eventArgs = new AudioStreamDeliveredEventArgs(streamArray, type, channel, recordingTime);
989                                 _audioStreamDelivered?.Invoke(this, eventArgs);
990                         };
991                         int ret = Interop.Recorder.SetAudioStreamCallback (_handle, _audioStreamCallback, IntPtr.Zero);
992                         if (ret != (int)RecorderError.None)
993                         {
994                                 RecorderErrorFactory.ThrowException (ret, "Setting audiostream callback failed");
995                         }
996                 }
997
998                 private void UnregisterAudioStreamDeliveredEvent()
999                 {
1000                         int ret = Interop.Recorder.UnsetAudioStreamCallback (_handle);
1001                         if (ret != (int)RecorderError.None)
1002                         {
1003                                 RecorderErrorFactory.ThrowException (ret, "Unsetting audiostream callback failed");
1004                         }
1005                 }
1006
1007                 private void RegisterStateChangedEvent()
1008                 {
1009                         _recorderStateChangedCallback = (RecorderState previous, RecorderState current, bool byPolicy, IntPtr userData) =>
1010                         {
1011                                 RecorderStateChangedEventArgs eventArgs = new RecorderStateChangedEventArgs(previous, current, byPolicy);
1012                                 _recorderStateChanged?.Invoke(this, eventArgs);
1013                         };
1014                         int ret = Interop.Recorder.SetStateChangedCallback (_handle, _recorderStateChangedCallback , IntPtr.Zero);
1015                         if (ret != (int)RecorderError.None)
1016                         {
1017                                 RecorderErrorFactory.ThrowException (ret, "Setting state changed callback failed");
1018                         }
1019                 }
1020
1021                 private void UnregisterStateChangedEvent()
1022                 {
1023                         int ret = Interop.Recorder.UnsetStateChangedCallback (_handle);
1024                         if (ret != (int)RecorderError.None)
1025                         {
1026                                 RecorderErrorFactory.ThrowException (ret, "Unsetting state changed callback failed");
1027                         }
1028                 }
1029
1030                 private void RegisterRecordingStatusChangedEvent()
1031                 {
1032                         _recordingStatusCallback = (ulong elapsedTime, ulong fileSize, IntPtr userData) =>
1033                         {
1034                                 RecordingStatusChangedEventArgs eventArgs = new RecordingStatusChangedEventArgs(elapsedTime, fileSize);
1035                                 _recordingStatusChanged?.Invoke(this, eventArgs);
1036                         };
1037                         int ret = Interop.Recorder.SetStatusChangedCallback (_handle, _recordingStatusCallback, IntPtr.Zero);
1038                         if (ret != (int)RecorderError.None)
1039                         {
1040                                 RecorderErrorFactory.ThrowException (ret, "Setting status changed callback failed");
1041                         }
1042                 }
1043
1044                 private void UnregisterRecordingStatusChangedEvent()
1045                 {
1046                         int ret = Interop.Recorder.UnsetStatusChangedCallback (_handle);
1047                         if (ret != (int)RecorderError.None)
1048                         {
1049                                 RecorderErrorFactory.ThrowException (ret, "Unsetting status changed callback failed");
1050                         }
1051                 }
1052
1053                 private void RegisterRecordingLimitReachedEvent()
1054                 {
1055                         _recordingLimitReachedCallback = (RecordingLimitType type, IntPtr userData) =>
1056                         {
1057                                 RecordingLimitReachedEventArgs eventArgs = new RecordingLimitReachedEventArgs(type);
1058                                 _recordingLimitReached?.Invoke(this, eventArgs);
1059                         };
1060                         int ret = Interop.Recorder.SetLimitReachedCallback (_handle, _recordingLimitReachedCallback, IntPtr.Zero);
1061                         if (ret != (int)RecorderError.None)
1062                         {
1063                                 RecorderErrorFactory.ThrowException (ret, "Setting limit reached callback failed");
1064                         }
1065                 }
1066
1067                 private void UnregisterRecordingLimitReachedEvent()
1068                 {
1069                         int ret = Interop.Recorder.UnsetLimitReachedCallback (_handle);
1070                         if (ret != (int)RecorderError.None)
1071                         {
1072                                 RecorderErrorFactory.ThrowException(ret, "Unsetting limit reached callback failed");
1073                         }
1074                 }
1075
1076                 private void RegisterRecordingErrorOccuredEvent()
1077                 {
1078                         _recorderErrorCallback = (RecorderErrorCode error, RecorderState current, IntPtr userData) =>
1079                         {
1080                                 RecordingErrorOccurredEventArgs eventArgs = new RecordingErrorOccurredEventArgs(error, current);
1081                                 _recordingErrorOccured?.Invoke(this, eventArgs);
1082                         };
1083                         int ret = Interop.Recorder.SetErrorCallback (_handle, _recorderErrorCallback, IntPtr.Zero);
1084                         if (ret != (int)RecorderError.None)
1085                         {
1086                                 RecorderErrorFactory.ThrowException (ret, "Setting Error callback failed");
1087                         }
1088                 }
1089
1090                 private void UnregisterRecordingErrorOccuredEvent()
1091                 {
1092                         int ret = Interop.Recorder.UnsetErrorCallback (_handle);
1093                         if (ret != (int)RecorderError.None)
1094                         {
1095                                 RecorderErrorFactory.ThrowException (ret, "Unsetting Error callback failed");
1096                         }
1097                 }
1098         }
1099 }
1100