[Multimedia] Redesigned Recorder API 70/144970/9
authorcoderhyme <jhyo.kim@samsung.com>
Sat, 19 Aug 2017 03:24:00 +0000 (12:24 +0900)
committercoderhyme <jhyo.kim@samsung.com>
Tue, 5 Sep 2017 05:58:20 +0000 (14:58 +0900)
- Splited the recorder into video/audio recorder.
- Removed Options and Settings classes.
- Added apis added in native 4.0

Change-Id: Id81331241aeca7d8fec6033fbfee20b0e2257e87
Signed-off-by: coderhyme <jhyo.kim@samsung.com>
34 files changed:
src/Tizen.Multimedia.Recorder/Interop/Interop.Recorder.Capabilities.cs [moved from src/Tizen.Multimedia.Recorder/Interop/Interop.RecorderFeatures.cs with 67% similarity]
src/Tizen.Multimedia.Recorder/Interop/Interop.Recorder.Events.cs [new file with mode: 0644]
src/Tizen.Multimedia.Recorder/Interop/Interop.Recorder.Settings.cs [moved from src/Tizen.Multimedia.Recorder/Interop/Interop.RecorderSettings.cs with 50% similarity]
src/Tizen.Multimedia.Recorder/Interop/Interop.Recorder.cs
src/Tizen.Multimedia.Recorder/Recorder/AudioRecorder.cs [new file with mode: 0644]
src/Tizen.Multimedia.Recorder/Recorder/AudioStreamDeliveredEventArgs.cs [deleted file]
src/Tizen.Multimedia.Recorder/Recorder/AudioStreamStoringEventArgs.cs [new file with mode: 0644]
src/Tizen.Multimedia.Recorder/Recorder/MuxedStreamDeliveredEventArgs.cs [moved from src/Tizen.Multimedia.Recorder/Recorder/MuxedStreamEventArgs.cs with 52% similarity, mode: 0644]
src/Tizen.Multimedia.Recorder/Recorder/Recorder.Capabilities.cs [new file with mode: 0644]
src/Tizen.Multimedia.Recorder/Recorder/Recorder.Events.cs [new file with mode: 0644]
src/Tizen.Multimedia.Recorder/Recorder/Recorder.Settings.cs [new file with mode: 0644]
src/Tizen.Multimedia.Recorder/Recorder/Recorder.cs
src/Tizen.Multimedia.Recorder/Recorder/RecorderDeviceException.cs [new file with mode: 0644]
src/Tizen.Multimedia.Recorder/Recorder/RecorderDeviceStateChangedEventArgs.cs [moved from src/Tizen.Multimedia.Recorder/Recorder/RecordingProgressEventArgs.cs with 59% similarity, mode: 0644]
src/Tizen.Multimedia.Recorder/Recorder/RecorderEnums.cs
src/Tizen.Multimedia.Recorder/Recorder/RecorderError.cs [new file with mode: 0644]
src/Tizen.Multimedia.Recorder/Recorder/RecorderErrorFactory.cs [deleted file]
src/Tizen.Multimedia.Recorder/Recorder/RecorderExtensions.cs [new file with mode: 0644]
src/Tizen.Multimedia.Recorder/Recorder/RecorderFeatures.cs [deleted file]
src/Tizen.Multimedia.Recorder/Recorder/RecorderInterruptedEventArgs.cs
src/Tizen.Multimedia.Recorder/Recorder/RecorderInterruptingEventArgs.cs [new file with mode: 0644]
src/Tizen.Multimedia.Recorder/Recorder/RecorderSettings.cs [deleted file]
src/Tizen.Multimedia.Recorder/Recorder/RecorderStateChangedEventArgs.cs
src/Tizen.Multimedia.Recorder/Recorder/RecordingErrorOccurredEventArgs.cs
src/Tizen.Multimedia.Recorder/Recorder/RecordingLimitReachedEventArgs.cs
src/Tizen.Multimedia.Recorder/Recorder/RecordingStatusChangedEventArgs.cs [new file with mode: 0644]
src/Tizen.Multimedia.Recorder/Recorder/VideoRecorder.Capabilities.cs [new file with mode: 0644]
src/Tizen.Multimedia.Recorder/Recorder/VideoRecorder.cs [new file with mode: 0644]
src/Tizen.Multimedia.StreamRecorder/StreamRecorder/StreamRecorder.cs
src/Tizen.Multimedia/Common.Internal/DependentMediaBuffer.cs [new file with mode: 0644]
src/Tizen.Multimedia/Common.Internal/IBufferOwner.cs
src/Tizen.Multimedia/Common.Internal/MediaBufferBase.cs [new file with mode: 0644]
src/Tizen.Multimedia/Common.Internal/ScopedMediaBuffer.cs [new file with mode: 0644]
src/Tizen.Multimedia/Common/IMediaBuffer.cs

@@ -20,30 +20,34 @@ using Tizen.Multimedia;
 
 internal static partial class Interop
 {
-    internal static partial class RecorderFeatures
+    internal static partial class Recorder
     {
         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
         internal delegate bool VideoResolutionCallback(int width, int height, IntPtr userData);
 
         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-        internal delegate bool FileFormatCallback(RecorderFileFormat format, IntPtr userData);
+        internal delegate bool VideoEncoderCallback(RecorderVideoCodec value, IntPtr userData);
 
         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-        internal delegate bool AudioEncoderCallback(RecorderAudioCodec codec, IntPtr userData);
+        internal delegate bool AudioEncoderCallback(RecorderAudioCodec value, IntPtr userData);
 
         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-        internal delegate bool VideoEncoderCallback(RecorderVideoCodec codec, IntPtr userData);
+        internal delegate bool FileFormatCallback(RecorderFileFormat value, IntPtr userData);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_foreach_supported_file_format")]
-        internal static extern RecorderError FileFormats(IntPtr handle, FileFormatCallback callback, IntPtr userData);
+        internal static extern RecorderErrorCode GetFileFormats(RecorderHandle handle,
+            FileFormatCallback callback, IntPtr userData = default(IntPtr));
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_foreach_supported_audio_encoder")]
-        internal static extern RecorderError AudioEncoders(IntPtr handle, AudioEncoderCallback callback, IntPtr userData);
+        internal static extern RecorderErrorCode GetAudioEncoders(RecorderHandle handle,
+            AudioEncoderCallback callback, IntPtr userData = default(IntPtr));
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_foreach_supported_video_encoder")]
-        internal static extern RecorderError VideoEncoders(IntPtr handle, VideoEncoderCallback callback, IntPtr userData);
+        internal static extern RecorderErrorCode GetVideoEncoders(RecorderHandle handle,
+            VideoEncoderCallback callback, IntPtr userData = default(IntPtr));
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_foreach_supported_video_resolution")]
-        internal static extern RecorderError VideoResolution(IntPtr handle, VideoResolutionCallback callback, IntPtr userData);
+        public static extern RecorderErrorCode GetVideoResolutions(RecorderHandle handle,
+            VideoResolutionCallback callback, IntPtr userData = default(IntPtr));
     }
 }
diff --git a/src/Tizen.Multimedia.Recorder/Interop/Interop.Recorder.Events.cs b/src/Tizen.Multimedia.Recorder/Interop/Interop.Recorder.Events.cs
new file mode 100644 (file)
index 0000000..c525aa3
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Runtime.InteropServices;
+using Tizen.Multimedia;
+
+internal static partial class Interop
+{
+
+    internal static partial class Recorder
+    {
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        internal delegate void RecorderErrorCallback(RecorderError error, RecorderState current, IntPtr userData);
+
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        internal delegate void RecordingLimitReachedCallback(RecordingLimitType type, IntPtr userData);
+
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        internal delegate void RecordingProgressCallback(ulong elapsedTime, ulong fileSize, IntPtr userData);
+
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        internal delegate void AudioStreamCallback(IntPtr stream, int size, AudioSampleType type, int channel,
+            uint timeStamp, IntPtr userData);
+
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        internal delegate void StatechangedCallback(RecorderState previous, RecorderState current, bool byPolicy, IntPtr userData);
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_error_cb")]
+        internal static extern RecorderErrorCode SetErrorCallback(RecorderHandle handle, RecorderErrorCallback callback,
+            IntPtr userData);
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_unset_error_cb")]
+        internal static extern RecorderErrorCode UnsetErrorCallback(RecorderHandle handle);
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_state_changed_cb")]
+        internal static extern RecorderErrorCode SetStateChangedCallback(RecorderHandle handle,
+            StatechangedCallback callback, IntPtr userData);
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_unset_state_changed_cb")]
+        internal static extern RecorderErrorCode UnsetStateChangedCallback(RecorderHandle handle);
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_recording_status_cb")]
+        internal static extern RecorderErrorCode SetRecordingProgressCallback(RecorderHandle handle,
+            RecordingProgressCallback callback, IntPtr userData);
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_unset_recording_status_cb")]
+        internal static extern RecorderErrorCode UnsetRecordingProgressCallback(RecorderHandle handle);
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_audio_stream_cb")]
+        internal static extern RecorderErrorCode SetAudioStreamCallback(RecorderHandle handle,
+            AudioStreamCallback callback, IntPtr userData);
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_unset_audio_stream_cb")]
+        internal static extern RecorderErrorCode UnsetAudioStreamCallback(RecorderHandle handle);
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_recording_limit_reached_cb")]
+        internal static extern RecorderErrorCode SetLimitReachedCallback(RecorderHandle handle,
+            RecordingLimitReachedCallback callback, IntPtr userData);
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_unset_recording_limit_reached_cb")]
+        internal static extern RecorderErrorCode UnsetLimitReachedCallback(RecorderHandle handle);
+
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        internal delegate void MuxedStreamCallback(IntPtr stream, int size, ulong offset, IntPtr userData);
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_muxed_stream_cb")]
+        internal static extern RecorderErrorCode SetMuxedStreamCallback(RecorderHandle handle,
+            MuxedStreamCallback callback, IntPtr userData);
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_unset_muxed_stream_cb")]
+        internal static extern RecorderErrorCode UnsetMuxedStreamCallback(RecorderHandle handle);
+
+
+        #region InterruptCallback
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        internal delegate void InterruptedCallback(RecorderPolicy policy, RecorderState previous,
+                RecorderState current, IntPtr userData);
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_interrupted_cb")]
+        internal static extern RecorderErrorCode SetInterruptedCallback(RecorderHandle handle,
+            InterruptedCallback callback, IntPtr userData);
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_unset_interrupted_cb")]
+        internal static extern RecorderErrorCode UnsetInterruptedCallback(RecorderHandle handle);
+
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        internal delegate void InterruptStartedCallback(RecorderPolicy policy, RecorderState state,
+                IntPtr userData);
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_interrupt_started_cb")]
+        internal static extern RecorderErrorCode SetInterruptStartedCallback(RecorderHandle handle,
+            InterruptStartedCallback callback, IntPtr userData = default(IntPtr));
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_unset_interrupt_started_cb")]
+        internal static extern RecorderErrorCode UnsetInterruptStartedCallback(RecorderHandle handle);
+
+        #endregion
+
+
+        #region DeviceStateChangedCallback
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        internal delegate void DeviceStateChangedCallback(RecorderType type, RecorderDeviceState state, IntPtr userData);
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_add_device_state_changed_cb")]
+        internal static extern RecorderErrorCode AddDeviceStateChangedCallback(DeviceStateChangedCallback callback,
+            IntPtr userData, out int id);
+
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_remove_device_state_changed_cb")]
+        internal static extern RecorderErrorCode RemoveDeviceStateChangedCallback(int id);
+        #endregion
+    }
+}
\ No newline at end of file
@@ -20,100 +20,100 @@ using Tizen.Multimedia;
 
 internal static partial class Interop
 {
-    internal static partial class RecorderSettings
+    internal static partial class Recorder
     {
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_get_audio_channel")]
-        internal static extern RecorderError GetAudioChannel(IntPtr handle, out int channelCount);
+        internal static extern RecorderErrorCode GetAudioChannel(RecorderHandle handle, out int channelCount);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_set_audio_channel")]
-        internal static extern RecorderError SetAudioChannel(IntPtr handle, int channelCount);
+        internal static extern RecorderErrorCode SetAudioChannel(RecorderHandle handle, int channelCount);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_get_audio_device")]
-        internal static extern RecorderError GetAudioDevice(IntPtr handle, out RecorderAudioDevice device);
+        internal static extern RecorderErrorCode GetAudioDevice(RecorderHandle handle, out RecorderAudioDevice device);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_set_audio_device")]
-        internal static extern RecorderError SetAudioDevice(IntPtr handle, RecorderAudioDevice device);
+        internal static extern RecorderErrorCode SetAudioDevice(RecorderHandle handle, RecorderAudioDevice device);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_get_audio_level")]
-        internal static extern RecorderError GetAudioLevel(IntPtr handle, out double dB);
+        internal static extern RecorderErrorCode GetAudioLevel(RecorderHandle handle, out double dB);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_get_audio_samplerate")]
-        internal static extern RecorderError GetAudioSampleRate(IntPtr handle, out int sampleRate);
+        internal static extern RecorderErrorCode GetAudioSampleRate(RecorderHandle handle, out int sampleRate);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_set_audio_samplerate")]
-        internal static extern RecorderError SetAudioSampleRate(IntPtr handle, int sampleRate);
+        internal static extern RecorderErrorCode SetAudioSampleRate(RecorderHandle handle, int sampleRate);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_get_audio_encoder_bitrate")]
-        internal static extern RecorderError GetAudioEncoderBitrate(IntPtr handle, out int bitRate);
+        internal static extern RecorderErrorCode GetAudioEncoderBitrate(RecorderHandle handle, out int bitRate);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_set_audio_encoder_bitrate")]
-        internal static extern RecorderError SetAudioEncoderBitrate(IntPtr handle, int bitRate);
+        internal static extern RecorderErrorCode SetAudioEncoderBitrate(RecorderHandle handle, int bitRate);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_get_video_encoder_bitrate")]
-        internal static extern RecorderError GetVideoEncoderBitrate(IntPtr handle, out int bitRate);
+        internal static extern RecorderErrorCode GetVideoEncoderBitrate(RecorderHandle handle, out int bitRate);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_set_video_encoder_bitrate")]
-        internal static extern RecorderError SetVideoEncoderBitrate(IntPtr handle, int bitRate);
+        internal static extern RecorderErrorCode SetVideoEncoderBitrate(RecorderHandle handle, int bitRate);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_get_audio_encoder")]
-        internal static extern RecorderError GetAudioEncoder(IntPtr handle, out RecorderAudioCodec codec);
+        internal static extern RecorderErrorCode GetAudioEncoder(RecorderHandle handle, out RecorderAudioCodec codec);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_audio_encoder")]
-        internal static extern RecorderError SetAudioEncoder(IntPtr handle, RecorderAudioCodec codec);
+        internal static extern RecorderErrorCode SetAudioEncoder(RecorderHandle handle, RecorderAudioCodec codec);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_get_video_encoder")]
-        internal static extern RecorderError GetVideoEncoder(IntPtr handle, out RecorderVideoCodec codec);
+        internal static extern RecorderErrorCode GetVideoEncoder(RecorderHandle handle, out RecorderVideoCodec codec);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_video_encoder")]
-        internal static extern RecorderError SetVideoEncoder(IntPtr handle, RecorderVideoCodec codec);
+        internal static extern RecorderErrorCode SetVideoEncoder(RecorderHandle handle, RecorderVideoCodec codec);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_get_file_format")]
-        internal static extern RecorderError GetFileFormat(IntPtr handle, out RecorderFileFormat format);
+        internal static extern RecorderErrorCode GetFileFormat(RecorderHandle handle, out RecorderFileFormat format);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_file_format")]
-        internal static extern RecorderError SetFileFormat(IntPtr handle, RecorderFileFormat format);
+        internal static extern RecorderErrorCode SetFileFormat(RecorderHandle handle, RecorderFileFormat format);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_get_filename")]
-        internal static extern RecorderError GetFileName(IntPtr handle, out IntPtr path);
+        internal static extern RecorderErrorCode GetFileName(RecorderHandle handle, out IntPtr path);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_filename")]
-        internal static extern RecorderError SetFileName(IntPtr handle, string path);
+        internal static extern RecorderErrorCode SetFileName(RecorderHandle handle, string path);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_get_size_limit")]
-        internal static extern RecorderError GetSizeLimit(IntPtr handle, out int kbyte);
+        internal static extern RecorderErrorCode GetSizeLimit(RecorderHandle handle, out int kbyte);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_set_size_limit")]
-        internal static extern RecorderError SetSizeLimit(IntPtr handle, int kbyte);
+        internal static extern RecorderErrorCode SetSizeLimit(RecorderHandle handle, int kbyte);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_get_time_limit")]
-        internal static extern RecorderError GetTimeLimit(IntPtr handle, out int second);
+        internal static extern RecorderErrorCode GetTimeLimit(RecorderHandle handle, out int second);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_set_time_limit")]
-        internal static extern RecorderError SetTimeLimit(IntPtr handle, int second);
+        internal static extern RecorderErrorCode SetTimeLimit(RecorderHandle handle, int second);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_is_muted")]
         [return: MarshalAs(UnmanagedType.I1)]
-        internal static extern bool GetMute(IntPtr handle);
+        internal static extern bool GetMute(RecorderHandle handle);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_set_mute")]
-        internal static extern RecorderError SetMute(IntPtr handle, bool enable);
+        internal static extern RecorderErrorCode SetMute(RecorderHandle handle, bool enable);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_get_recording_motion_rate")]
-        internal static extern RecorderError GetMotionRate(IntPtr handle, out double motionRate);
+        internal static extern RecorderErrorCode GetMotionRate(RecorderHandle handle, out double motionRate);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_set_recording_motion_rate")]
-        internal static extern RecorderError SetMotionRate(IntPtr handle, double motionRate);
+        internal static extern RecorderErrorCode SetMotionRate(RecorderHandle handle, double motionRate);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_get_orientation_tag")]
-        internal static extern RecorderError GetOrientationTag(IntPtr handle, out Rotation orientation);
+        internal static extern RecorderErrorCode GetOrientationTag(RecorderHandle handle, out Rotation orientation);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_attr_set_orientation_tag")]
-        internal static extern RecorderError SetOrientationTag(IntPtr handle, Rotation orientation);
+        internal static extern RecorderErrorCode SetOrientationTag(RecorderHandle handle, Rotation orientation);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_get_video_resolution")]
-        internal static extern RecorderError GetVideoResolution(IntPtr handle, out int width, out int height);
+        internal static extern RecorderErrorCode GetVideoResolution(RecorderHandle handle, out int width, out int height);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_video_resolution")]
-        internal static extern RecorderError SetVideoResolution(IntPtr handle, int width, int height);
+        internal static extern RecorderErrorCode SetVideoResolution(RecorderHandle handle, int width, int height);
     }
 }
index 514b9ad..5fa70fb 100644 (file)
@@ -20,102 +20,73 @@ using Tizen.Multimedia;
 
 internal static partial class Interop
 {
+
     internal static partial class Recorder
     {
-        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-        internal delegate void RecorderErrorCallback(RecorderErrorCode error, RecorderState current, IntPtr userData);
-
-        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-        internal delegate void InterruptedCallback(RecorderPolicy policy, RecorderState previous, RecorderState current, IntPtr userData);
-
-        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-        internal delegate void RecordingLimitReachedCallback(RecordingLimitType type, IntPtr userData);
-
-        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-        internal delegate void RecordingProgressCallback(ulong elapsedTime, ulong fileSize, IntPtr userData);
-
-        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-        internal delegate void AudioStreamCallback(IntPtr stream, int size, AudioSampleType type, int channel, uint timeStamp, IntPtr userData);
-
-        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-        internal delegate void StatechangedCallback(RecorderState previous, RecorderState current, bool byPolicy, IntPtr userData);
-
-        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-        internal delegate void MuxedStreamCallback(IntPtr stream, int size, ulong offset, IntPtr userData);
-
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_create_audiorecorder")]
-        internal static extern RecorderError Create(out IntPtr handle);
+        internal static extern RecorderErrorCode Create(out RecorderHandle handle);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_create_videorecorder")]
-        internal static extern RecorderError CreateVideo(IntPtr cameraHandle, out IntPtr handle);
-
-        [DllImport(Libraries.Recorder, EntryPoint = "recorder_destroy")]
-        internal static extern RecorderError Destroy(IntPtr handle);
+        internal static extern RecorderErrorCode CreateVideo(IntPtr cameraHandle, out RecorderHandle handle);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_prepare")]
-        internal static extern RecorderError Prepare(IntPtr handle);
+        internal static extern RecorderErrorCode Prepare(RecorderHandle handle);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_unprepare")]
-        internal static extern RecorderError Unprepare(IntPtr handle);
+        internal static extern RecorderErrorCode Unprepare(RecorderHandle handle);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_start")]
-        internal static extern RecorderError Start(IntPtr handle);
+        internal static extern RecorderErrorCode Start(RecorderHandle handle);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_pause")]
-        internal static extern RecorderError Pause(IntPtr handle);
+        internal static extern RecorderErrorCode Pause(RecorderHandle handle);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_commit")]
-        internal static extern RecorderError Commit(IntPtr handle);
+        internal static extern RecorderErrorCode Commit(RecorderHandle handle);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_cancel")]
-        internal static extern RecorderError Cancel(IntPtr handle);
+        internal static extern RecorderErrorCode Cancel(RecorderHandle handle);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_get_state")]
-        internal static extern RecorderError GetState(IntPtr handle, out RecorderState state);
+        internal static extern RecorderErrorCode GetState(RecorderHandle handle, out RecorderState state);
 
         [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_sound_stream_info")]
-        internal static extern RecorderError SetAudioStreamPolicy(IntPtr handle, AudioStreamPolicyHandle streamInfoHandle);
+        internal static extern RecorderErrorCode SetAudioStreamPolicy(RecorderHandle handle, AudioStreamPolicyHandle streamInfoHandle);
 
-        [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_error_cb")]
-        internal static extern RecorderError SetErrorCallback(IntPtr handle, RecorderErrorCallback callback, IntPtr userData);
-
-        [DllImport(Libraries.Recorder, EntryPoint = "recorder_unset_error_cb")]
-        internal static extern RecorderError UnsetErrorCallback(IntPtr handle);
-
-        [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_interrupted_cb")]
-        internal static extern RecorderError SetInterruptedCallback(IntPtr handle, InterruptedCallback callback, IntPtr userData);
-
-        [DllImport(Libraries.Recorder, EntryPoint = "recorder_unset_interrupted_cb")]
-        internal static extern RecorderError UnsetInterruptedCallback(IntPtr handle);
-
-        [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_state_changed_cb")]
-        internal static extern RecorderError SetStateChangedCallback(IntPtr handle, StatechangedCallback callback, IntPtr userData);
-
-        [DllImport(Libraries.Recorder, EntryPoint = "recorder_unset_state_changed_cb")]
-        internal static extern RecorderError UnsetStateChangedCallback(IntPtr handle);
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_get_device_state")]
+        internal static extern RecorderErrorCode GetDeviceState(RecorderType type, out RecorderDeviceState state);
+    }
 
-        [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_recording_status_cb")]
-        internal static extern RecorderError SetRecordingProgressCallback(IntPtr handle, RecordingProgressCallback callback, IntPtr userData);
+    internal class RecorderHandle : SafeHandle
+    {
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_destroy")]
+        private static extern RecorderErrorCode Destroy(IntPtr handle);
 
-        [DllImport(Libraries.Recorder, EntryPoint = "recorder_unset_recording_status_cb")]
-        internal static extern RecorderError UnsetRecordingProgressCallback(IntPtr handle);
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_cancel")]
+        private static extern RecorderErrorCode Cancel(IntPtr handle);
 
-        [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_audio_stream_cb")]
-        internal static extern RecorderError SetAudioStreamCallback(IntPtr handle, AudioStreamCallback callback, IntPtr userData);
+        [DllImport(Libraries.Recorder, EntryPoint = "recorder_unprepare")]
+        private static extern RecorderErrorCode Unprepare(IntPtr handle);
 
-        [DllImport(Libraries.Recorder, EntryPoint = "recorder_unset_audio_stream_cb")]
-        internal static extern RecorderError UnsetAudioStreamCallback(IntPtr handle);
+        protected RecorderHandle() : base(IntPtr.Zero, true)
+        {
+        }
 
-        [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_recording_limit_reached_cb")]
-        internal static extern RecorderError SetLimitReachedCallback(IntPtr handle, RecordingLimitReachedCallback callback, IntPtr userData);
+        public override bool IsInvalid => handle == IntPtr.Zero;
 
-        [DllImport(Libraries.Recorder, EntryPoint = "recorder_unset_recording_limit_reached_cb")]
-        internal static extern RecorderError UnsetLimitReachedCallback(IntPtr handle);
+        protected override bool ReleaseHandle()
+        {
+            Cancel(handle).Ignore(RecorderErrorCode.InvalidState).ThrowIfError("Failed to cancel");
+            Unprepare(handle).Ignore(RecorderErrorCode.InvalidState).ThrowIfError("Failed to unprepare");
 
-        [DllImport(Libraries.Recorder, EntryPoint = "recorder_set_muxed_stream_cb")]
-        internal static extern RecorderError SetMuxedStreamCallback(IntPtr handle, MuxedStreamCallback callback, IntPtr userData);
+            var ret = Destroy(handle);
+            if (ret != RecorderErrorCode.None)
+            {
+                Tizen.Log.Debug(GetType().FullName, $"Failed to release native RecorderHandle.");
 
-        [DllImport(Libraries.Recorder, EntryPoint = "recorder_unset_muxed_stream_cb")]
-        internal static extern RecorderError UnsetMuxedStreamCallback(IntPtr handle);
+                return false;
+            }
+            return true;
+        }
     }
 }
\ No newline at end of file
diff --git a/src/Tizen.Multimedia.Recorder/Recorder/AudioRecorder.cs b/src/Tizen.Multimedia.Recorder/Recorder/AudioRecorder.cs
new file mode 100644 (file)
index 0000000..42b415d
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using Native = Interop.Recorder;
+using NativeHandle = Interop.RecorderHandle;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Provides the ability to control audio recording.
+    /// </summary>
+    public class AudioRecorder : Recorder
+    {
+        private static NativeHandle CreateHandle()
+        {
+            Native.Create(out var handle).ThrowIfError("Failed to create Audio recorder");
+
+            return handle;
+        }
+
+        private static void ThrowIfCodecAndFormatNotValid(RecorderAudioCodec audioCodec, RecorderFileFormat fileFormat)
+        {
+            if (audioCodec == RecorderAudioCodec.None)
+            {
+                throw new ArgumentOutOfRangeException(nameof(audioCodec),
+                    "RecorderAudioCodec.None is only available with VideoRecorder.");
+            }
+
+            audioCodec.ThrowIfFormatNotSupported(fileFormat);
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AudioRecorder"/> class with the specified audio codec and file format.
+        /// </summary>
+        /// <param name="audioCodec">The codec for audio encoding.</param>
+        /// <param name="fileFormat">The format of result file.</param>
+        /// <feature>http://tizen.org/feature/microphone</feature>
+        /// <exception cref="InvalidOperationException">An internal error occurred.</exception>
+        /// <exception cref="NotSupportedException">
+        ///     A required feature is not supported.\n
+        ///     -or-\n
+        ///     <paramref name="audioCodec"/> is not supported.\n
+        ///     -or-\n
+        ///     <paramref name="fileFormat"/> is not supported with the specified audio codec.
+        /// </exception>
+        /// <exception cref="ArgumentException">
+        ///     <paramref name="audioCodec"/> is not valid.\n
+        ///     -or-\n
+        ///     <paramref name="fileFormat"/> is not valid.
+        /// </exception>
+        /// <exception cref="ArgumentOutOfRangeException">
+        ///     <paramref name="audioCodec"/> is <see cref="RecorderAudioCodec.None"/>
+        /// </exception>
+        /// <seealso cref="Recorder.GetSupportedAudioCodecs"/>
+        /// <seealso cref="Recorder.GetSupportedFileFormats"/>
+        /// <seealso cref="RecorderExtensions.GetSupportedFileFormats(RecorderAudioCodec)"/>
+        /// <seealso cref="SetFormatAndCodec(RecorderAudioCodec, RecorderFileFormat)"/>
+        public AudioRecorder(RecorderAudioCodec audioCodec, RecorderFileFormat fileFormat) : base(CreateHandle())
+        {
+            SetFormatAndCodec(audioCodec, fileFormat);
+        }
+
+        /// <summary>
+        /// Sets the audio codec and the file format for recording.
+        /// </summary>
+        /// <param name="audioCodec">The codec for audio encoding.</param>
+        /// <param name="fileFormat">The format of result file.</param>
+        /// <exception cref="NotSupportedException">
+        ///     <paramref name="audioCodec"/> is not supported.\n
+        ///     -or-\n
+        ///     <paramref name="fileFormat"/> is not supported with the specified audio codec.
+        /// </exception>
+        /// <exception cref="ArgumentException">
+        ///     <paramref name="audioCodec"/> is not valid.\n
+        ///     -or-\n
+        ///     <paramref name="fileFormat"/> is not valid.
+        /// </exception>
+        /// <exception cref="ArgumentOutOfRangeException">
+        ///     <paramref name="audioCodec"/> is <see cref="RecorderAudioCodec.None"/>
+        /// </exception>
+        /// <seealso cref="Recorder.GetSupportedAudioCodecs"/>
+        /// <seealso cref="Recorder.GetSupportedFileFormats"/>
+        /// <seealso cref="RecorderExtensions.GetSupportedFileFormats(RecorderAudioCodec)"/>
+        /// <seealso cref="Recorder.Start(string)"/>
+        public void SetFormatAndCodec(RecorderAudioCodec audioCodec, RecorderFileFormat fileFormat)
+        {
+            ThrowIfCodecAndFormatNotValid(audioCodec, fileFormat);
+
+            AudioCodec = audioCodec;
+            FileFormat = fileFormat;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Tizen.Multimedia.Recorder/Recorder/AudioStreamDeliveredEventArgs.cs b/src/Tizen.Multimedia.Recorder/Recorder/AudioStreamDeliveredEventArgs.cs
deleted file mode 100755 (executable)
index f774918..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace Tizen.Multimedia
-{
-    /// <summary>
-    /// An extended EventArgs class containing details of audio stream.
-    /// </summary>
-    public class AudioStreamDeliveredEventArgs : EventArgs
-    {
-        internal AudioStreamDeliveredEventArgs(IntPtr stream, int streamSize, AudioSampleType type, int channel, uint recordingTime)
-        {
-            Stream = new byte[streamSize];
-            Marshal.Copy(stream, Stream, 0, streamSize);
-            StreamLength = streamSize;
-            Type = type;
-            Channel = channel;
-            RecordingTime = recordingTime;
-        }
-
-        /// <summary>
-        /// The audio stream data.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public byte[] Stream { get; }
-
-        /// <summary>
-        /// The length of audio stream data.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public int StreamLength { get; }
-
-        /// <summary>
-        /// The audio format type.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public AudioSampleType Type { get; }
-
-        /// <summary>
-        /// The number of channels.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public int Channel { get; }
-
-        /// <summary>
-        /// The recording time of the stream buffer in milliseconds.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public uint RecordingTime { get; }
-    }
-}
diff --git a/src/Tizen.Multimedia.Recorder/Recorder/AudioStreamStoringEventArgs.cs b/src/Tizen.Multimedia.Recorder/Recorder/AudioStreamStoringEventArgs.cs
new file mode 100644 (file)
index 0000000..f06d80a
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Provides data for the <see cref="Recorder.AudioStreamStoring"/> event.
+    /// </summary>
+    public class AudioStreamStoringEventArgs : EventArgs
+    {
+        internal AudioStreamStoringEventArgs(IMediaBuffer stream, AudioSampleType type, int channel,
+            uint recordingTime)
+        {
+            Stream = stream;
+            Type = type;
+            Channels = channel;
+            Timestamp = recordingTime;
+        }
+
+        /// <summary>
+        /// Gets the audio stream buffer.
+        /// </summary>
+        /// <remarks>
+        /// If the stream is modified in the event handler, the modified data will be stored.
+        /// \n
+        /// The buffer is only valid in the event.\n
+        /// Any attempt to access to this buffer after the event ends will throw an exception.
+        /// </remarks>
+        public IMediaBuffer Stream { get; }
+
+        /// <summary>
+        /// Gets the audio format type.
+        /// </summary>
+        public AudioSampleType Type { get; }
+
+        /// <summary>
+        /// Gets the number of channels.
+        /// </summary>
+        public int Channels { get; }
+
+        /// <summary>
+        /// Gets the timestamp(PTS) of stream buffer in milliseconds.
+        /// </summary>
+        public long Timestamp { get; }
+    }
+}
old mode 100755 (executable)
new mode 100644 (file)
similarity index 52%
rename from src/Tizen.Multimedia.Recorder/Recorder/MuxedStreamEventArgs.cs
rename to src/Tizen.Multimedia.Recorder/Recorder/MuxedStreamDeliveredEventArgs.cs
index 7c6ea85..b038bd6
  */
 
 using System;
-using System.Runtime.InteropServices;
 
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// An extended EventArgs class containing details of muxed stream(Audio + Video).
+    /// Provides data for the <see cref="Recorder.MuxedStreamDelivered"/> event.
     /// </summary>
     public class MuxedStreamDeliveredEventArgs : EventArgs
     {
-        internal MuxedStreamDeliveredEventArgs(IntPtr stream, int streamLength, ulong offset)
+        internal MuxedStreamDeliveredEventArgs(IMediaBuffer stream, ulong offset)
         {
-            Stream = new byte[streamLength];
-            Marshal.Copy(stream, Stream, 0, streamLength);
-            StreamLength = streamLength;
-            Offset = offset;
+            Stream = stream;
+            Offset = (long)offset;
         }
 
         /// <summary>
-        /// The muexed stream data.
+        /// Gets the stream buffer that will be recordered.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public byte[] Stream { get; }
+        /// <remarks>
+        /// This buffer is read-only and only valid in the event.\n
+        /// Any attempt to access to this buffer after the event ends will throw an exception.
+        /// </remarks>
+        public IMediaBuffer Stream { get; }
 
         /// <summary>
-        /// The length of muxed stream data.
+        /// The file offset where the buffer will be written.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public int StreamLength { get; }
-
-        /// <summary>
-        /// The offset of the stream data.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public ulong Offset { get; }
+        public long Offset { get; }
     }
 }
diff --git a/src/Tizen.Multimedia.Recorder/Recorder/Recorder.Capabilities.cs b/src/Tizen.Multimedia.Recorder/Recorder/Recorder.Capabilities.cs
new file mode 100644 (file)
index 0000000..7bb79f7
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Native = Interop.Recorder;
+using NativeHandle = Interop.RecorderHandle;
+
+namespace Tizen.Multimedia
+{
+    internal class Capabilities
+    {
+        public IEnumerable<RecorderFileFormat> SupportedFileFormats { get; }
+        public IEnumerable<RecorderAudioCodec> SupportedAudioCodecs { get; }
+        public IEnumerable<RecorderVideoCodec> SupportedVideoCodecs { get; }
+
+        private RecorderErrorCode GetAudioEncoders(NativeHandle handle, List<RecorderAudioCodec> result) =>
+            Native.GetAudioEncoders(handle, (codec, _) => { result.Add(codec); return true; });
+
+        private RecorderErrorCode GetFileFormats(NativeHandle handle, List<RecorderFileFormat> result) =>
+            Native.GetFileFormats(handle, (format, _) => { result.Add(format); return true; });
+
+        private RecorderErrorCode GetVideoEncoders(NativeHandle handle, List<RecorderVideoCodec> result) =>
+            Native.GetVideoEncoders(handle, (codec, _) => { result.Add(codec); return true; });
+
+        private static IEnumerable<T> Load<T>(NativeHandle handle, Func<NativeHandle, List<T>, RecorderErrorCode> loadFunc)
+        {
+            var result = new List<T>();
+
+            var ret = loadFunc(handle, result);
+
+            if (ret == RecorderErrorCode.NotSupported)
+            {
+                return null;
+            }
+
+            ret.ThrowIfError("Failed to load the capabilities");
+
+            return result.AsReadOnly();
+        }
+
+        internal Capabilities(NativeHandle handle)
+        {
+            SupportedVideoCodecs = Load<RecorderVideoCodec>(handle, GetVideoEncoders);
+
+            SupportedAudioCodecs = Load<RecorderAudioCodec>(handle, GetAudioEncoders);
+            SupportedFileFormats = Load<RecorderFileFormat>(handle, GetFileFormats);
+        }
+    }
+
+    public partial class Recorder
+    {
+        internal static Lazy<Capabilities> Capabilities { get; } = new Lazy<Capabilities>(LoadCapabilities);
+
+        private static Capabilities LoadCapabilities()
+        {
+            Native.Create(out var handle).ThrowIfError("Failed to load the capabilities"); ;
+            using (handle)
+            {
+                return new Capabilities(handle);
+            }
+        }
+
+        /// <summary>
+        /// Gets the file formats that the current device supports.
+        /// </summary>
+        public static IEnumerable<RecorderFileFormat> GetSupportedFileFormats() => Capabilities.Value.SupportedFileFormats;
+
+        /// <summary>
+        /// Gets the audio encoders that the current device supports.
+        /// </summary>
+        public static IEnumerable<RecorderAudioCodec> GetSupportedAudioCodecs() => Capabilities.Value.SupportedAudioCodecs;
+
+        internal static void ValidateFileFormat(RecorderFileFormat format)
+        {
+            if (GetSupportedFileFormats().Contains(format) == false)
+            {
+                throw new NotSupportedException($"{format.ToString()} is not supported.");
+            }
+        }
+
+        internal static void ValidateAudioCodec(RecorderAudioCodec codec)
+        {
+            if (GetSupportedAudioCodecs().Contains(codec) == false)
+            {
+                throw new NotSupportedException($"{codec.ToString()} is not supported.");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Tizen.Multimedia.Recorder/Recorder/Recorder.Events.cs b/src/Tizen.Multimedia.Recorder/Recorder/Recorder.Events.cs
new file mode 100644 (file)
index 0000000..e28f85f
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Linq;
+using Native = Interop.Recorder;
+
+namespace Tizen.Multimedia
+{
+    public partial class Recorder
+    {
+        /// <summary>
+        /// Occurs when an error occurs during recorder operation.
+        /// </summary>
+        public event EventHandler<RecordingErrorOccurredEventArgs> ErrorOccurred;
+        private Native.RecorderErrorCallback _errorOccurredCallback;
+
+        /// <summary>
+        /// Occurs after interrupt handling is completed.
+        /// </summary>
+        public event EventHandler<RecorderInterruptedEventArgs> Interrupted;
+        private Native.InterruptedCallback _interruptedCallback;
+
+        /// <summary>
+        /// This event occurs when recorder state is changed.
+        /// </summary>
+        public event EventHandler<RecorderStateChangedEventArgs> StateChanged;
+        private Native.StatechangedCallback _stateChangedCallback;
+
+        /// <summary>
+        /// Occurs when recording information changes.
+        /// </summary>
+        public event EventHandler<RecordingStatusChangedEventArgs> RecordingStatusChanged;
+        private Native.RecordingProgressCallback _recordingProgressCallback;
+
+        //TODO need to test dispose while event handler is running.
+        /// <summary>
+        /// Occurs when audio stream data is being delivered.
+        /// </summary>
+        /// <remarks>
+        /// Do not call <see cref="Commit"/> and <see cref="Cancel"/> in this event.
+        /// </remarks>
+        public event EventHandler<AudioStreamStoringEventArgs> AudioStreamStoring;
+        private Native.AudioStreamCallback _audioStreamCallback;
+
+        /// <summary>
+        /// Occurs when recording limit is reached.
+        /// </summary>
+        /// <remarks>
+        /// After this event is raised, recording data is discarded and not written in the recording file.
+        /// </remarks>
+        public event EventHandler<RecordingLimitReachedEventArgs> RecordingLimitReached;
+        private Native.RecordingLimitReachedCallback _recordingLimitReachedCallback;
+
+        /// <summary>
+        /// Occurs when muxed stream data is being delivered.
+        /// </summary>
+        public event EventHandler<MuxedStreamDeliveredEventArgs> MuxedStreamDelivered;
+        private Native.MuxedStreamCallback _muxedStreamCallback;
+
+        private void RegisterEvents()
+        {
+            RegisterErrorCallback();
+            RegisterInterruptedEvent();
+            RegisterStateChangedEvent();
+            RegisterRecordingProgressEvent();
+            RegisterAudioStreamDeliveredEvent();
+            RegisterRecordingLimitReachedEvent();
+            RegisterMuxedStreamEvent();
+            RegisterInterruptingEvent();
+        }
+
+        private void RegisterErrorCallback()
+        {
+            _errorOccurredCallback = (error, state, _) =>
+            {
+                ErrorOccurred?.Invoke(this, new RecordingErrorOccurredEventArgs(error, state));
+            };
+
+            Native.SetErrorCallback(_handle, _errorOccurredCallback, IntPtr.Zero).
+                ThrowIfError("Failed to initialize ErrorOccurred event");
+        }
+
+        private void RegisterInterruptedEvent()
+        {
+            _interruptedCallback = (policy, previousState, currentState, _) =>
+            {
+                Interrupted?.Invoke(this, new RecorderInterruptedEventArgs(policy, previousState, currentState));
+            };
+            Native.SetInterruptedCallback(_handle, _interruptedCallback, IntPtr.Zero).
+                ThrowIfError("Failed to initialize Interrupted event");
+        }
+
+        private void RegisterStateChangedEvent()
+        {
+            _stateChangedCallback = (RecorderState previous, RecorderState current, bool byPolicy, IntPtr userData) =>
+            {
+                SetState(current);
+                StateChanged?.Invoke(this, new RecorderStateChangedEventArgs(previous, current, byPolicy));
+            };
+
+            Native.SetStateChangedCallback(_handle, _stateChangedCallback, IntPtr.Zero).
+                ThrowIfError("Failed to initialize StateChanged event");
+        }
+
+        private void RegisterRecordingProgressEvent()
+        {
+            _recordingProgressCallback = (ulong elapsedTime, ulong fileSize, IntPtr userData) =>
+            {
+                RecordingStatusChanged?.Invoke(this, new RecordingStatusChangedEventArgs((long)elapsedTime, (long)fileSize));
+            };
+
+            Native.SetRecordingProgressCallback(_handle, _recordingProgressCallback, IntPtr.Zero).
+                ThrowIfError("Failed to initialize RecordingStatusChanged event");
+        }
+
+        private void RegisterAudioStreamDeliveredEvent()
+        {
+            _audioStreamCallback = (stream, streamSize, type, channel, recordingTime, _) =>
+            {
+                var handler = AudioStreamStoring;
+                if (handler != null)
+                {
+                    _isInAudioStreamStoring.Value = true;
+
+                    using (var buffer = new ScopedMediaBuffer(stream, streamSize))
+                    {
+                        handler.Invoke(this,
+                            new AudioStreamStoringEventArgs(buffer, type, channel, recordingTime));
+                    }
+                }
+            };
+
+            Native.SetAudioStreamCallback(_handle, _audioStreamCallback, IntPtr.Zero).
+                ThrowIfError("Failed to initialize AudioStreamStoring event");
+        }
+
+        private void RegisterRecordingLimitReachedEvent()
+        {
+            _recordingLimitReachedCallback = (RecordingLimitType type, IntPtr userData) =>
+            {
+                RecordingLimitReached?.Invoke(this, new RecordingLimitReachedEventArgs(type));
+            };
+
+            Native.SetLimitReachedCallback(_handle, _recordingLimitReachedCallback, IntPtr.Zero).
+                ThrowIfError("Failed to initialize RecordingLimitReached event");
+        }
+
+        private void RegisterMuxedStreamEvent()
+        {
+            _muxedStreamCallback = (IntPtr stream, int streamSize, ulong offset, IntPtr userData) =>
+            {
+                using (var buffer = new ScopedMediaBuffer(stream, streamSize, true))
+                {
+                    MuxedStreamDelivered?.Invoke(this, new MuxedStreamDeliveredEventArgs(buffer, offset));
+                }
+            };
+
+            Native.SetMuxedStreamCallback(_handle, _muxedStreamCallback, IntPtr.Zero).
+                ThrowIfError("Failed to initialize MuxedStreamDelivered event");
+        }
+
+        /// <summary>
+        /// Occurs before interrupt handling is started.
+        /// </summary>
+        public event EventHandler<RecorderInterruptingEventArgs> Interrupting;
+        private Native.InterruptStartedCallback _interruptingCallback;
+
+        private void RegisterInterruptingEvent()
+        {
+            _interruptingCallback = (policy, state, _) =>
+            {
+                Interrupting?.Invoke(this, new RecorderInterruptingEventArgs(policy, state));
+            };
+
+            Native.SetInterruptStartedCallback(_handle, _interruptingCallback).
+                ThrowIfError("Failed to initialize Interrupting event");
+        }
+
+        #region DeviceStateChanged
+
+        private static object _deviceStateChangedLock = new object();
+        private static EventHandler<RecorderDeviceStateChangedEventArgs> _deviceStateChanged;
+        private static Native.DeviceStateChangedCallback _deviceStateChangedCallback;
+        private static int _deviceStateChangedId;
+
+        /// <summary>
+        /// Occurs when a recorder device state changes.
+        /// </summary>
+        public static event EventHandler<RecorderDeviceStateChangedEventArgs> DeviceStateChanged
+        {
+            add
+            {
+                if (value == null)
+                {
+                    return;
+                }
+
+                lock (_deviceStateChangedLock)
+                {
+                    if (_deviceStateChanged == null)
+                    {
+                        RegisterDeviceStateChangedEvent();
+                    }
+
+                    _deviceStateChanged += value;
+                }
+            }
+            remove
+            {
+                if (value == null)
+                {
+                    return;
+                }
+
+                lock (_deviceStateChangedLock)
+                {
+                    if (_deviceStateChanged == value)
+                    {
+                        UnregisterDeviceStateChangedEvent();
+                    }
+
+                    _deviceStateChanged -= value;
+                }
+            }
+        }
+
+        private static void RegisterDeviceStateChangedEvent()
+        {
+            _deviceStateChangedCallback = (type, state, _) =>
+            {
+                _deviceStateChanged?.Invoke(null, new RecorderDeviceStateChangedEventArgs(type, state));
+            };
+
+            Native.AddDeviceStateChangedCallback(_deviceStateChangedCallback, IntPtr.Zero, out _deviceStateChangedId).
+                ThrowIfError("Failed to add the event handler.");
+        }
+
+        private static void UnregisterDeviceStateChangedEvent()
+        {
+            Native.RemoveDeviceStateChangedCallback(_deviceStateChangedId).
+                ThrowIfError("Failed to remove the event handler.");
+
+            _deviceStateChangedCallback = null;
+        }
+        #endregion
+    }
+}
diff --git a/src/Tizen.Multimedia.Recorder/Recorder/Recorder.Settings.cs b/src/Tizen.Multimedia.Recorder/Recorder/Recorder.Settings.cs
new file mode 100644 (file)
index 0000000..f2d28a9
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Diagnostics;
+using Native = Interop.Recorder;
+
+namespace Tizen.Multimedia
+{
+    public partial class Recorder
+    {
+        private RecorderAudioCodec _audioCodec;
+
+        /// <summary>
+        /// Gets the audio codec for encoding an audio stream.
+        /// </summary>
+        /// <seealso cref="GetSupportedAudioCodecs"/>
+        public RecorderAudioCodec AudioCodec
+        {
+            get => _audioCodec;
+            internal set
+            {
+                Debug.Assert(Enum.IsDefined(typeof(RecorderAudioCodec), value));
+
+                if (this is AudioRecorder || value != RecorderAudioCodec.None)
+                {
+                    ValidateAudioCodec(value);
+                }
+
+                Native.SetAudioEncoder(Handle, value).ThrowIfError("Failed to set audio encoder.");
+
+                _audioCodec = value;
+            }
+        }
+
+        private RecorderFileFormat _fileFormat;
+
+        /// <summary>
+        /// Gets the file format of the recording result.
+        /// </summary>
+        /// <seealso cref="GetSupportedFileFormats"/>
+        public RecorderFileFormat FileFormat
+        {
+            get => _fileFormat;
+            internal set
+            {
+                Debug.Assert(Enum.IsDefined(typeof(RecorderFileFormat), value));
+
+                ValidateFileFormat(value);
+
+                Native.SetFileFormat(Handle, value).ThrowIfError("Failed to set file format.");
+
+                _fileFormat = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the number of audio channel.
+        /// </summary>
+        /// <remarks>
+        /// To set, the recorder must be in the <see cref="RecorderState.Idle"/> or <see cref="RecorderState.Ready"/> state.
+        /// </remarks>
+        /// <value>
+        /// For mono recording, set channel to 1.
+        /// For stereo recording, set channel to 2.
+        /// </value>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than or equal to zero.</exception>
+        /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
+        public int AudioChannels
+        {
+            get
+            {
+                Native.GetAudioChannel(Handle, out var val).ThrowIfError("Failed to get audio channel.");
+
+                return val;
+            }
+
+            set
+            {
+                ValidateState(RecorderState.Idle, RecorderState.Ready);
+
+                if (value <= 0)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(value), value,
+                        "Audio channels can't be less than or equal to zero.");
+                }
+
+                Native.SetAudioChannel(Handle, value).ThrowIfError("Failed to set audio channel");
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the audio device for recording.
+        /// </summary>
+        /// <remarks>
+        /// To set, the recorder must be in the <see cref="RecorderState.Idle"/> or <see cref="RecorderState.Ready"/> state.
+        /// </remarks>
+        /// <value>A <see cref="RecorderAudioDevice"/> that specifies the type of audio device.</value>
+        /// <exception cref="ArgumentException"><paramref name="value"/> is not valid.</exception>
+        /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
+        public RecorderAudioDevice AudioDevice
+        {
+            get
+            {
+                Native.GetAudioDevice(Handle, out var val).ThrowIfError("Failed to get the audio device.");
+
+                return val;
+            }
+
+            set
+            {
+                ValidateState(RecorderState.Idle, RecorderState.Ready);
+
+                ValidationUtil.ValidateEnum(typeof(RecorderAudioDevice), value, nameof(value));
+
+                Native.SetAudioDevice(Handle, value).ThrowIfError("Failed to set the audio device.");
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the sampling rate of an audio stream in hertz.
+        /// </summary>
+        /// <remarks>
+        /// To set, the recorder must be in the <see cref="RecorderState.Idle"/> or <see cref="RecorderState.Ready"/> state.
+        /// </remarks>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than or equal to zero.</exception>
+        /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
+        public int AudioSampleRate
+        {
+            get
+            {
+                Native.GetAudioSampleRate(Handle, out var val).
+                    ThrowIfError("Failed to get audio sample rate.");
+
+                return val;
+            }
+
+            set
+            {
+                ValidateState(RecorderState.Idle, RecorderState.Ready);
+
+                if (value <= 0)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(value), value,
+                        "Sample rate can't be less than or equal to zero.");
+                }
+
+                Native.SetAudioSampleRate(Handle, value).
+                    ThrowIfError("Failed to set audio sample rate.");
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the bitrate of an audio encoder in bits per second.
+        /// </summary>
+        /// <remarks>
+        /// To set, the recorder must be in the <see cref="RecorderState.Idle"/> or <see cref="RecorderState.Ready"/> state.
+        /// </remarks>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than or equal to zero.</exception>
+        /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
+        public int AudioBitRate
+        {
+            get
+            {
+                Native.GetAudioEncoderBitrate(Handle, out var val).ThrowIfError("Failed to get audio bitrate.");
+
+                return val;
+            }
+
+            set
+            {
+                ValidateState(RecorderState.Idle, RecorderState.Ready);
+
+                if (value <= 0)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(value), value,
+                        "Bit rate can't be less than or equal to zero.");
+                }
+
+                Native.SetAudioEncoderBitrate(Handle, value).
+                    ThrowIfError("Failed to set audio bitrate");
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the maximum size of a recording file.
+        /// </summary>
+        /// <value>
+        /// The maximum size of a recording file in kilobytes, or 0 for unlimited size.
+        /// </value>
+        /// <remarks>
+        /// After reaching the limitation, the data which is being recorded will
+        /// be discarded and not written to the file.\n
+        /// \n
+        /// To set, the recorder must be in the<see cref="RecorderState.Idle"/> or <see cref= "RecorderState.Ready" /> state.
+        /// </remarks>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception>
+        /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
+        public int SizeLimit
+        {
+            get
+            {
+                int val = 0;
+
+                Native.GetSizeLimit(Handle, out val).
+                    ThrowIfError("Failed to get size limit.");
+
+                return val;
+            }
+
+            set
+            {
+                ValidateState(RecorderState.Idle, RecorderState.Ready);
+
+                if (value < 0)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(value), value,
+                        "Size limit can't be less than zero.");
+                }
+
+                Native.SetSizeLimit(Handle, value).ThrowIfError("Failed to set size limit");
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the time limit of recording.
+        /// </summary>
+        /// <value>
+        /// The time of recording in seconds, or 0 for unlimited time.
+        /// </value>
+        /// <remarks>
+        /// After reaching the limitation, the data which is being recorded will
+        /// be discarded and not written to the file.\n
+        /// \n
+        /// To set, the recorder must be in the<see cref="RecorderState.Idle"/> or <see cref= "RecorderState.Ready" /> state.
+        /// </remarks>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception>
+        /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
+        public int TimeLimit
+        {
+            get
+            {
+                Native.GetTimeLimit(Handle, out var val).
+                    ThrowIfError("Failed to get time limit.");
+
+                return val;
+            }
+
+            set
+            {
+                ValidateState(RecorderState.Idle, RecorderState.Ready);
+
+                if (value < 0)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(value), value,
+                        "Time limit can't be less than zero.");
+                }
+
+                Native.SetTimeLimit(Handle, value).ThrowIfError("Failed to set time limit.");
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the mute state of a recorder.
+        /// </summary>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
+        public bool Muted
+        {
+            get => Native.GetMute(Handle);
+
+            set => Native.SetMute(Handle, value).ThrowIfError("Failed to set mute");
+        }
+    }
+}
\ No newline at end of file
index 701981c..6f5303b 100755 (executable)
 using System;
 using System.Diagnostics;
 using System.Linq;
+using System.Threading;
 using Native = Interop.Recorder;
+using NativeHandle = Interop.RecorderHandle;
 
 namespace Tizen.Multimedia
 {
-    static internal class RecorderLog
-    {
-        internal const string Tag = "Tizen.Multimedia.Recorder";
-    }
-
     /// <summary>
-    /// The recorder class provides methods to create audio/video recorder,
-    ///  to start, stop and save the recorded content. It also provides methods
-    ///  to get/set various attributes and capabilities of recorder.
+    /// Recorder is a base class for audio and video recorders that
+    /// provides the ability to control the recording of a multimedia content.\n
+    /// \n
+    /// Simple audio and audio/video are supported.
     /// </summary>
-    public class Recorder : IDisposable
+    public abstract partial class Recorder : IDisposable
     {
-        private IntPtr _handle = IntPtr.Zero;
-        private bool _disposed = false;
-        private RecorderState _state = RecorderState.None;
+        private readonly NativeHandle _handle;
+        private RecorderState _state;
+        private ThreadLocal<bool> _isInAudioStreamStoring = new ThreadLocal<bool>();
 
-        /// <summary>
-        /// Audio recorder constructor.
-        /// </summary>
-        public Recorder()
+        internal Recorder(NativeHandle handle)
         {
-            RecorderErrorFactory.ThrowIfError(Native.Create(out _handle),
-                "Failed to create Audio recorder");
+            _handle = handle;
 
-            Feature = new RecorderFeatures(this);
-            Setting = new RecorderSettings(this);
-
-            RegisterCallbacks();
+            try
+            {
+                RegisterEvents();
 
-            SetState(RecorderState.Created);
+                SetState(State);
+            }
+            catch (Exception)
+            {
+                _handle.Dispose();
+                throw;
+            }
         }
 
-        /// <summary>
-        /// Video recorder constructor.
-        /// </summary>
-        /// <param name="camera">
-        /// The camera object.
-        /// </param>
-        public Recorder(Camera camera)
+        internal NativeHandle Handle
         {
-            RecorderErrorFactory.ThrowIfError(Native.CreateVideo(camera.Handle, out _handle),
-                "Failed to create Video recorder.");
-
-            Feature = new RecorderFeatures(this);
-            Setting = new RecorderSettings(this);
-
-            RegisterCallbacks();
+            get
+            {
+                if (_disposed)
+                {
+                    throw new ObjectDisposedException(nameof(Recorder));
+                }
 
-            SetState(RecorderState.Created);
+                return _handle;
+            }
         }
 
+        #region Dispose support
+        private bool _disposed;
+
         /// <summary>
-        /// Recorder destructor.
+        /// Releases the unmanaged resources used by the Recorder.
         /// </summary>
-        ~Recorder()
-        {
-            Dispose (false);
-        }
-
-        internal IntPtr GetHandle()
+        public void Dispose()
         {
-            ValidateNotDisposed();
-            return _handle;
+            Dispose(true);
         }
 
-        #region Dispose support
         /// <summary>
-        /// Releases the unmanaged resources used by the Recorder.
+        /// Releases the resources used by the Recorder.
         /// </summary>
-        /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
+        /// <param name="disposing">
+        /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
+        /// </param>
         protected virtual void Dispose(bool disposing)
         {
             if (!_disposed)
             {
-                if (disposing)
-                {
-                    // to be used if there are any other disposable objects
-                }
-                if (_handle != IntPtr.Zero)
+                if (_handle != null)
                 {
-                    Native.Destroy(_handle);
-                    _handle = IntPtr.Zero;
+                    _handle.Dispose();
                 }
-                _disposed = true;
-            }
-        }
-
-        /// <summary>
-        /// Releases all resources used by the Recorder.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
 
-        internal void ValidateNotDisposed()
-        {
-            if (_disposed)
-            {
-                throw new ObjectDisposedException(nameof(Recorder));
+                _disposed = true;
             }
         }
         #endregion Dispose support
 
-        #region Check recorder state
+        #region State validation
         internal void ValidateState(params RecorderState[] required)
         {
-            ValidateNotDisposed();
-
             Debug.Assert(required.Length > 0);
 
             var curState = _state;
             if (!required.Contains(curState))
             {
-                throw new InvalidOperationException($"The recorder is not in a valid state. " +
+                throw new InvalidOperationException("The recorder is not in a valid state. " +
                     $"Current State : { curState }, Valid State : { string.Join(", ", required) }.");
             }
         }
 
-        internal void SetState(RecorderState state)
+        private void SetState(RecorderState state)
         {
             _state = state;
         }
-        #endregion Check recorder state
-
-        #region EventHandlers
-        /// <summary>
-        /// Event that occurs when an error occurs during recorder operation.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public event EventHandler<RecordingErrorOccurredEventArgs> ErrorOccurred;
-        private Native.RecorderErrorCallback _errorOccuredCallback;
-
-        /// <summary>
-        /// Event that occurs when recorder is interrupted.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public event EventHandler<RecorderInterruptedEventArgs> Interrupted;
-        private Native.InterruptedCallback _interruptedCallback;
-
-        /// <summary>
-        /// This event occurs when recorder state is changed.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public event EventHandler<RecorderStateChangedEventArgs> StateChanged;
-        private Native.StatechangedCallback _stateChangedCallback;
-
-        /// <summary>
-        /// Event that occurs when recording information changes.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public event EventHandler<RecordingProgressEventArgs> RecordingProgress;
-        private Native.RecordingProgressCallback _recordingProgressCallback;
-
-        /// <summary>
-        /// Event that occurs when audio stream data is being delivered.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public event EventHandler<AudioStreamDeliveredEventArgs> AudioStreamDelivered;
-        private Native.AudioStreamCallback _audioStreamCallback;
-
-        /// <summary>
-        /// Event that occurs when recording limit is reached.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public event EventHandler<RecordingLimitReachedEventArgs> RecordingLimitReached;
-        private Native.RecordingLimitReachedCallback _recordingLimitReachedCallback;
-
-        /// <summary>
-        /// Event that occurs when muxed stream data is being delivered.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public event EventHandler<MuxedStreamDeliveredEventArgs> MuxedStreamDelivered;
-        private Native.MuxedStreamCallback _muxedStreamCallback;
-        #endregion EventHandlers
+        #endregion
 
         #region Properties
-        /// <summary>
-        /// Gets the various recorder features.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public RecorderFeatures Feature { get; }
 
         /// <summary>
-        /// Get/Set the various recorder settings.
+        /// Gets the current state of the recorder.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public RecorderSettings Setting { get; }
-
-        /// <summary>
-        /// The current state of the recorder.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
         /// <value>A <see cref="RecorderState"/> that specifies the state of recorder.</value>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
         public RecorderState State
         {
             get
             {
-                ValidateNotDisposed();
-
-                RecorderState val = 0;
-
-                RecorderErrorFactory.ThrowIfError(Native.GetState(_handle, out val),
-                    "Failed to get recorder state.");
+                Native.GetState(Handle, out var val).ThrowIfError("Failed to get recorder state.");
 
                 return val;
             }
@@ -237,246 +136,291 @@ namespace Tizen.Multimedia
         #region Methods
         /// <summary>
         /// Prepare the media recorder for recording.
-        /// The recorder must be in the <see cref="RecorderState.Created"/> state.
-        /// After this method is finished without any exception,
-        /// The state of recorder will be changed to <see cref="RecorderState.Ready"/> state.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
         /// <remarks>
-        /// Before calling the function, it is required to set AudioEncoder,
-        /// videoencoder and fileformat properties of recorder.
+        /// The recorder should be in the <see cref="RecorderState.Idle"/> state.\n
+        /// The state of the recorder will be the <see cref="RecorderState.Ready"/> after this.\n
+        /// It has no effect if the current state is the <see cref="RecorderState.Ready"/>.
         /// </remarks>
-        /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
+        /// <exception cref="InvalidOperationException">
+        ///     The recorder is not in the valid state.\n
+        ///     -or-\n
+        ///     An internal error occurred.
+        /// </exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
         public void Prepare()
         {
-            ValidateState(RecorderState.Created);
+            if (_state == RecorderState.Ready)
+            {
+                return;
+            }
+
+            ValidateState(RecorderState.Idle);
 
-            RecorderErrorFactory.ThrowIfError(Native.Prepare(_handle),
-                "Failed to prepare media recorder for recording");
+            Native.Prepare(Handle).ThrowIfError("Failed to prepare media recorder");
 
             SetState(RecorderState.Ready);
         }
 
+        private void ThrowIfAccessedInAudioStreamStoring()
+        {
+            if (_isInAudioStreamStoring.Value)
+            {
+                throw new InvalidOperationException("The method can't be called in the AudioStreamStoring event");
+            }
+        }
+
         /// <summary>
         /// Resets the media recorder.
-        /// The recorder must be in the <see cref="RecorderState.Ready"/> state.
-        /// After this method is finished without any exception,
-        /// The state of recorder will be changed to <see cref="RecorderState.Created"/> state.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
+        /// <remarks>
+        /// The recorder should be in the <see cref="RecorderState.Ready"/> state.
+        /// The state of recorder will be <see cref="RecorderState.Idle"/> after this.
+        /// It has no effect if the current state is the <see cref="RecorderState.Idle"/>.
+        /// </remarks>
+        /// <exception cref="InvalidOperationException">
+        ///     The recorder is not in the valid state.\n
+        ///     -or-\n
+        ///     An internal error occurred.
+        /// </exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
         public void Unprepare()
         {
+            ThrowIfAccessedInAudioStreamStoring();
+
+            if (_state == RecorderState.Idle)
+            {
+                return;
+            }
+
             ValidateState(RecorderState.Ready);
 
-            RecorderErrorFactory.ThrowIfError(Native.Unprepare(_handle),
-                "Failed to reset the media recorder");
+            Native.Unprepare(Handle).ThrowIfError("Failed to reset the media recorder");
 
-            SetState(RecorderState.Created);
+            SetState(RecorderState.Idle);
         }
 
         /// <summary>
         /// Starts the recording.
+        /// </summary>
+        /// <remarks>
         /// The recorder must be in the <see cref="RecorderState.Ready"/> state.
-        /// After this method is finished without any exception,
-        /// The state of recorder will be changed to <see cref="RecorderState.Recording"/> state.
+        /// The state of recorder will be <see cref="RecorderState.Recording"/> after this. \n
+        /// \n
+        /// If the specified path exists, the file is removed automatically and updated by new one.\n
+        /// The mediastorage privilege(http://tizen.org/privilege/mediastorage) is required if the path is relevant to media storage.\n
+        /// The externalstorage privilege(http://tizen.org/privilege/externalstorage) is required if the path is relevant to external storage.\n
+        /// \n
+        /// In the video recorder, some preview format does not support record mode.
+        ///    You should use default preview format or <see cref="CameraPixelFormat.Nv12"/> in the record mode.
+        /// </remarks>
+        /// <param name="savePath">The file path for recording result.</param>
+        /// <privilege>http://tizen.org/privilege/recorder</privilege>
+        /// <exception cref="InvalidOperationException">
+        ///     The recorder is not in the valid state.\n
+        ///     -or-\n
+        ///     The preview format of the camera is not supported.
+        ///     -or-\n
+        ///     An internal error occurred.
+        /// </exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="savePath"/> is null.</exception>
+        /// <exception cref="ArgumentException"><paramref name="savePath"/> is a zero-length string, contains only white space.</exception>
+        /// <exception cref="UnauthorizedAccessException">Caller does not have required privilege.</exception>
+        /// <seealso cref="Commit"/>
+        /// <seealso cref="Cancel"/>
+        public void Start(string savePath)
+        {
+            ValidateState(RecorderState.Ready);
+
+            if (savePath == null)
+            {
+                throw new ArgumentNullException(nameof(savePath));
+            }
+
+            if (string.IsNullOrWhiteSpace(savePath))
+            {
+                throw new ArgumentException($"{nameof(savePath)} is an empty string.", nameof(savePath));
+            }
+
+            Native.SetFileName(Handle, savePath).ThrowIfError("Failed to set save path.");
+
+            Native.Start(Handle).ThrowIfError("Failed to start the media recorder");
+
+            SetState(RecorderState.Recording);
+        }
+
+        /// <summary>
+        /// Resumes the recording.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
         /// <remarks>
-        /// If file path has been set to an existing file, this file is removed automatically and updated by new one.
-        /// In the video recorder, some preview format does not support record mode. It will return InvalidOperation error.
-        ///    You should use default preview format or CameraPixelFormatNv12 in the record mode.
-        ///    The filename should be set before this function is invoked.
+        /// The recorder should be in the <see cref="RecorderState.Paused"/> state.
+        /// The state of recorder will be <see cref="RecorderState.Recording"/> after this.
+        /// It has no effect if the current state is the <see cref="RecorderState.Recording"/>.
         /// </remarks>
-        /// <privilege>
-        /// http://tizen.org/privilege/recorder
-        /// </privilege>
-        /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
-        public void Start()
+        /// <exception cref="InvalidOperationException">
+        ///     The recorder is not in the valid state.\n
+        ///     -or-\n
+        ///     An internal error occurred.
+        /// </exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
+        public void Resume()
         {
-            ValidateState(RecorderState.Ready, RecorderState.Paused);
+            if (_state == RecorderState.Recording)
+            {
+                return;
+            }
+
+            ValidateState(RecorderState.Paused);
 
-            RecorderErrorFactory.ThrowIfError(Native.Start(_handle),
-                "Failed to start the media recorder");
+            Native.Start(Handle).ThrowIfError("Failed to resume the media recorder");
 
             SetState(RecorderState.Recording);
         }
 
         /// <summary>
         /// Pause the recording.
-        /// The recorder must be in the <see cref="RecorderState.Recording"/> state.
-        /// After this method is finished without any exception,
-        /// The state of recorder will be changed to <see cref="RecorderState.Paused"/> state.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
         /// <remarks>
-        /// Recording can be resumed with Start().
+        /// The recorder should be in the <see cref="RecorderState.Recording"/> state.
+        /// The state of recorder will be <see cref="RecorderState.Paused"/> after this.
+        /// It has no effect if the current state is the <see cref="RecorderState.Paused"/>.
         /// </remarks>
-        /// <privilege>
-        /// http://tizen.org/privilege/recorder
-        /// </privilege>
-        /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
+        /// <exception cref="InvalidOperationException">
+        ///     The recorder is not in the valid state.\n
+        ///     -or-\n
+        ///     An internal error occurred.
+        /// </exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
         public void Pause()
         {
+            if (_state == RecorderState.Paused)
+            {
+                return;
+            }
+
             ValidateState(RecorderState.Recording);
 
-            RecorderErrorFactory.ThrowIfError(Native.Pause(_handle),
-                "Failed to pause the media recorder");
+            Native.Pause(Handle).ThrowIfError("Failed to pause the media recorder");
 
             SetState(RecorderState.Paused);
         }
 
         /// <summary>
         /// Stops recording and saves the result.
-        /// The recorder must be in the <see cref="RecorderState.Recording"/> or <see cref="RecorderState.Paused"/> state.
-        /// After this method is finished without any exception,
-        /// The state of recorder will be changed to <see cref="RecorderState.Ready"/> state.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <privilege>
-        /// http://tizen.org/privilege/recorder
-        /// </privilege>
-        /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
+        /// <remarks>
+        /// The recorder must be in the <see cref="RecorderState.Recording"/> or <see cref="RecorderState.Paused"/> state.
+        /// The state of recorder will be <see cref="RecorderState.Ready"/> after the operation.
+        /// </remarks>
+        /// <exception cref="InvalidOperationException">
+        ///     The recorder is not in the valid state.\n
+        ///     -or-\n
+        ///     The method is called in <see cref="AudioStreamStoring"/> event.
+        ///     -or-\n
+        ///     An internal error occurred.
+        /// </exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
         public void Commit()
         {
+            ThrowIfAccessedInAudioStreamStoring();
+
             ValidateState(RecorderState.Recording, RecorderState.Paused);
 
-            RecorderErrorFactory.ThrowIfError(Native.Commit(_handle),
-                "Failed to save the recorded content");
+            Native.Commit(Handle).ThrowIfError("Failed to save the recorded content");
 
             SetState(RecorderState.Ready);
         }
 
         /// <summary>
-        /// Cancels the recording.
+        /// Cancels the recording.\n
         /// The recording data is discarded and not written in the recording file.
-        /// The recorder must be in the <see cref="RecorderState.Recording"/> or <see cref="RecorderState.Paused"/> state.
-        /// After this method is finished without any exception,
-        /// The state of recorder will be changed to <see cref="RecorderState.Ready"/> state.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <privilege>
-        /// http://tizen.org/privilege/recorder
-        /// </privilege>
-        /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
+        /// <remarks>
+        /// The recorder must be in the <see cref="RecorderState.Recording"/> or <see cref="RecorderState.Paused"/> state.
+        /// The state of recorder will be <see cref="RecorderState.Ready"/> after the operation.
+        /// </remarks>
+        /// <exception cref="InvalidOperationException">
+        ///     The recorder is not in the valid state.\n
+        ///     -or-\n
+        ///     The method is called in <see cref="AudioStreamStoring"/> event.
+        ///     -or-\n
+        ///     An internal error occurred.
+        /// </exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
         public void Cancel()
         {
+            ThrowIfAccessedInAudioStreamStoring();
+
             ValidateState(RecorderState.Recording, RecorderState.Paused);
 
-            RecorderErrorFactory.ThrowIfError(Native.Cancel(_handle),
-                "Failed to cancel the recording");
+            Native.Cancel(Handle).ThrowIfError("Failed to cancel the recording");
 
             SetState(RecorderState.Ready);
         }
 
         /// <summary>
-        /// Sets the audio stream policy.
+        /// Apply the audio stream policy.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <param name="policy">Policy.</param>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public void SetAudioStreamPolicy(AudioStreamPolicy policy)
+        /// <remarks>
+        /// The recorder must be in the <see cref="RecorderState.Idle"/> or <see cref="RecorderState.Ready"/> state.
+        /// </remarks>
+        /// <param name="policy">The policy to apply.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="policy"/> is null.</exception>
+        /// <exception cref="InvalidOperationException">
+        ///     The recorder is not in the valid state.\n
+        ///     -or-\n
+        ///     <paramref name="policy"/> is not supported for the recorder.
+        ///     -or-\n
+        ///     An internal error occurred.
+        /// </exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     The recorder already has been disposed of.\n
+        ///     -or-\n
+        ///     <paramref name="policy"/> already has been disposed of.
+        /// </exception>
+        public void ApplyAudioStreamPolicy(AudioStreamPolicy policy)
         {
-            ValidateNotDisposed();
-
-            RecorderErrorFactory.ThrowIfError(Native.SetAudioStreamPolicy(_handle, policy.Handle),
-                "Failed to set audio stream policy");
-        }
-        #endregion Methods
+            if (policy == null)
+            {
+                throw new ArgumentNullException(nameof(policy));
+            }
 
-        #region Callback registrations
-        private void RegisterCallbacks()
-        {
-            RegisterErrorCallback();
-            RegisterInterruptedCallback();
-            RegisterStateChangedCallback();
-            RegisterRecordingProgressCallback();
-            RegisterAudioStreamDeliveredCallback();
-            RegisterRecordingLimitReachedEvent();
-            RegisterMuxedStreamEvent();
-        }
+            ValidateState(RecorderState.Idle, RecorderState.Ready);
 
-        private void RegisterErrorCallback()
-        {
-            _errorOccuredCallback = (RecorderErrorCode error, RecorderState current, IntPtr userData) =>
-            {
-                ErrorOccurred?.Invoke(this, new RecordingErrorOccurredEventArgs(error, current));
-            };
-            RecorderErrorFactory.ThrowIfError(Native.SetErrorCallback(_handle, _errorOccuredCallback, IntPtr.Zero),
-                "Setting Error callback failed");
+            Native.SetAudioStreamPolicy(Handle, policy.Handle).ThrowIfError("Failed to apply the audio stream policy.");
         }
 
-        private void RegisterInterruptedCallback()
+        /// <summary>
+        /// Returns the peak audio input level in dB since the last call to this method.
+        /// </summary>
+        /// <remarks>
+        /// 0dB indicates maximum input level, -300dB indicates minimum input level.\n
+        /// \n
+        /// The recorder must be in the <see cref="RecorderState.Recording"/> or <see cref="RecorderState.Paused"/> state.
+        /// </remarks>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
+        public double GetPeakAudioLevel()
         {
-            _interruptedCallback = (RecorderPolicy policy, RecorderState previous, RecorderState current, IntPtr userData) =>
-            {
-                Interrupted?.Invoke(this, new RecorderInterruptedEventArgs(policy, previous, current));
-            };
-            RecorderErrorFactory.ThrowIfError(Native.SetInterruptedCallback(_handle, _interruptedCallback, IntPtr.Zero),
-                "Setting Interrupted callback failed");
-        }
+            ValidateState(RecorderState.Recording, RecorderState.Paused);
 
-        private void RegisterStateChangedCallback()
-        {
-            _stateChangedCallback = (RecorderState previous, RecorderState current, bool byPolicy, IntPtr userData) =>
-            {
-                SetState(current);
-                Log.Info(RecorderLog.Tag, "Recorder state changed " + previous.ToString() + " -> " + current.ToString());
-                StateChanged?.Invoke(this, new RecorderStateChangedEventArgs(previous, current, byPolicy));
-            };
-            RecorderErrorFactory.ThrowIfError(Native.SetStateChangedCallback(_handle, _stateChangedCallback, IntPtr.Zero),
-                "Setting state changed callback failed");
-        }
+            Native.GetAudioLevel(Handle, out var level).ThrowIfError("Failed to get audio level.");
 
-        private void RegisterRecordingProgressCallback()
-        {
-            _recordingProgressCallback = (ulong elapsedTime, ulong fileSize, IntPtr userData) =>
-            {
-                RecordingProgress?.Invoke(this, new RecordingProgressEventArgs(elapsedTime, fileSize));
-            };
-            RecorderErrorFactory.ThrowIfError(Native.SetRecordingProgressCallback(_handle, _recordingProgressCallback, IntPtr.Zero),
-                "Setting status changed callback failed");
+            return level;
         }
 
-        private void RegisterAudioStreamDeliveredCallback()
+        /// <summary>
+        /// Returns the state of recorder device.
+        /// </summary>
+        /// <exception cref="ArgumentException"><paramref name="type"/> is invalid.</exception>
+        public static RecorderDeviceState GetDeviceState(RecorderType type)
         {
-            _audioStreamCallback = (IntPtr stream, int streamSize, AudioSampleType type, int channel, uint recordingTime, IntPtr userData) =>
-            {
-                AudioStreamDelivered?.Invoke(this, new AudioStreamDeliveredEventArgs(stream, streamSize, type, channel, recordingTime));
-            };
-            RecorderErrorFactory.ThrowIfError(Native.SetAudioStreamCallback(_handle, _audioStreamCallback, IntPtr.Zero),
-                "Setting audiostream callback failed");
-        }
+            ValidationUtil.ValidateEnum(typeof(RecorderType), type, nameof(type));
 
-        private void RegisterRecordingLimitReachedEvent()
-        {
-            _recordingLimitReachedCallback = (RecordingLimitType type, IntPtr userData) =>
-            {
-                RecordingLimitReached?.Invoke(this, new RecordingLimitReachedEventArgs(type));
-            };
-            RecorderErrorFactory.ThrowIfError(Native.SetLimitReachedCallback(_handle, _recordingLimitReachedCallback, IntPtr.Zero),
-                "Setting limit reached callback failed");
-        }
+            Native.GetDeviceState(type, out var state).ThrowIfError("Failed to get device state");
 
-        private void RegisterMuxedStreamEvent()
-        {
-            _muxedStreamCallback = (IntPtr stream, int streamSize, ulong offset, IntPtr userData) =>
-            {
-                MuxedStreamDelivered?.Invoke(this, new MuxedStreamDeliveredEventArgs(stream, streamSize, offset));
-            };
-            RecorderErrorFactory.ThrowIfError(Native.SetMuxedStreamCallback(_handle, _muxedStreamCallback, IntPtr.Zero),
-                "Setting muxed stream callback failed");
+            return state;
         }
-        #endregion Callback registrations
+        #endregion
     }
 }
diff --git a/src/Tizen.Multimedia.Recorder/Recorder/RecorderDeviceException.cs b/src/Tizen.Multimedia.Recorder/Recorder/RecorderDeviceException.cs
new file mode 100644 (file)
index 0000000..1267870
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// The exception that is thrown when a recorder device-related error occurs.
+    /// </summary>
+    public class RecorderDeviceException : Exception
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RecorderDeviceException"/> class.
+        /// </summary>
+        public RecorderDeviceException() : base()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RecorderDeviceException"/> class with a specified error message.
+        /// </summary>
+        public RecorderDeviceException(string message) : base(message)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RecorderDeviceException"/> class with
+        /// a specified error message and inner exception.
+        /// </summary>
+        public RecorderDeviceException(string message, Exception innerException) : base(message, innerException)
+        {
+        }
+    }
+}
\ No newline at end of file
old mode 100755 (executable)
new mode 100644 (file)
similarity index 59%
rename from src/Tizen.Multimedia.Recorder/Recorder/RecordingProgressEventArgs.cs
rename to src/Tizen.Multimedia.Recorder/Recorder/RecorderDeviceStateChangedEventArgs.cs
index f059fc7..1b52f51
@@ -19,26 +19,24 @@ using System;
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// An extened EventArgs class which contain the details of current recording status.
+    /// Provides data for the <see cref="Recorder.DeviceStateChanged"/> event.
     /// </summary>
-    public class RecordingProgressEventArgs : EventArgs
+    public class RecorderDeviceStateChangedEventArgs : EventArgs
     {
-        public RecordingProgressEventArgs(ulong elapsedTime, ulong fileSize)
+        internal RecorderDeviceStateChangedEventArgs(RecorderType type, RecorderDeviceState state)
         {
-            ElapsedTime = elapsedTime;
-            FileSize = fileSize;
+            Type = type;
+            DeviceState = state;
         }
 
         /// <summary>
-        /// The time of recording in milliseconds.
+        /// Gets the recorder type.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public ulong ElapsedTime { get; }
+        public RecorderType Type { get; }
 
         /// <summary>
-        /// The size of the recording file in Kilobyte.
+        /// Gets the device state.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public ulong FileSize { get; }
+        public RecorderDeviceState DeviceState { get; }
     }
 }
index fa7e84c..3639d20 100755 (executable)
  * limitations under the License.
  */
 
-using System;
-
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// Enumeration for Audio Codec.
+    /// Specifies audio codecs for <see cref="Recorder"/>.
     /// </summary>
-    /// <since_tizen> 3 </since_tizen>
+    /// <seealso cref="Recorder.GetSupportedAudioCodecs"/>
     public enum RecorderAudioCodec
     {
         /// <summary>
-        /// Disable Audio track.
+        /// Disabled.
         /// </summary>
-        Disable = -1,
+        None = -1,
         /// <summary>
         /// AMR codec.
         /// </summary>
-        Amr = 0,
+        Amr,
         /// <summary>
         /// AAC codec.
         /// </summary>
@@ -51,9 +49,8 @@ namespace Tizen.Multimedia
     }
 
     /// <summary>
-    /// Enumeration for Audio capture devices.
+    /// Specifies audio capture devices for <see cref="Recorder"/>.
     /// </summary>
-    /// <since_tizen> 3 </since_tizen>
     public enum RecorderAudioDevice
     {
         /// <summary>
@@ -67,9 +64,9 @@ namespace Tizen.Multimedia
     }
 
     /// <summary>
-    /// Enumeration for the file container format.
+    /// Specifies container formats for <see cref="Recorder"/>.
     /// </summary>
-    /// <since_tizen> 3 </since_tizen>
+    /// <seealso cref="Recorder.GetSupportedFileFormats"/>
     public enum RecorderFileFormat
     {
         /// <summary>
@@ -103,29 +100,29 @@ namespace Tizen.Multimedia
     }
 
     /// <summary>
-    /// Enumeration for the recorder policy.
+    /// Specifies recorder policies.
     /// </summary>
-    /// <since_tizen> 3 </since_tizen>
+    /// <seealso cref="Recorder.StateChanged"/>
+    /// <seealso cref="Recorder.Interrupting"/>
+    /// <seealso cref="Recorder.Interrupted"/>
     public enum RecorderPolicy
     {
         /// <summary>
-        /// None.
-        /// </summary>
-        None = 0,
-        /// <summary>
         /// Security policy.
         /// </summary>
         Security = 4,
         /// <summary>
         /// Resource conflict policy.
         /// </summary>
-        ResourceConflict = 5
+        ResourceConflict
     }
 
     /// <summary>
-    /// Enumeration for the recording limit.
+    /// Specifies types of the recording limit for <see cref="Recorder"/>.
     /// </summary>
-    /// <since_tizen> 3 </since_tizen>
+    /// <seealso cref="Recorder.SizeLimit"/>
+    /// <seealso cref="Recorder.TimeLimit"/>
+    /// <seealso cref="Recorder.RecordingLimitReached"/>
     public enum RecordingLimitType
     {
         /// <summary>
@@ -143,19 +140,14 @@ namespace Tizen.Multimedia
     }
 
     /// <summary>
-    /// Enumeration for recorder states.
+    /// Specifies states for <see cref="Recorder"/>.
     /// </summary>
-    /// <since_tizen> 3 </since_tizen>
     public enum RecorderState
     {
         /// <summary>
-        /// Recorder is not created.
-        /// </summary>
-        None,
-        /// <summary>
         /// Recorder is created, but not prepared.
         /// </summary>
-        Created,
+        Idle = 1,
         /// <summary>
         /// Recorder is ready to record. In case of video recorder,
         /// preview display will be shown.
@@ -172,9 +164,9 @@ namespace Tizen.Multimedia
     }
 
     /// <summary>
-    /// Enumeration for video codec.
+    /// Specifies video codecs for <see cref="VideoRecorder"/>.
     /// </summary>
-    /// <since_tizen> 3 </since_tizen>
+    /// <seealso cref="VideoRecorder.GetSupportedVideoCodecs"/>
     public enum RecorderVideoCodec
     {
         /// <summary>
@@ -196,22 +188,71 @@ namespace Tizen.Multimedia
     }
 
     /// <summary>
-    /// Enumeration for recorder failure error.
+    /// Specifies errors for <see cref="Recorder"/>.
     /// </summary>
-    /// <since_tizen> 3 </since_tizen>
-    public enum RecorderErrorCode
+    /// <seealso cref="Recorder.ErrorOccurred"/>
+    public enum RecorderError
     {
         /// <summary>
+        /// ESD situation.
+        /// </summary>
+        Esd = RecorderErrorCode.Esd,
+
+        /// <summary>
         /// Device Error.
         /// </summary>
-        DeviceError = RecorderError.DeviceError,
+        DeviceError = RecorderErrorCode.DeviceError,
+
         /// <summary>
         /// Internal error.
         /// </summary>
-        InvalidOperation = RecorderError.InvalidOperation,
+        InternalError = RecorderErrorCode.InvalidOperation,
+
         /// <summary>
         /// Out of memory.
         /// </summary>
-        OutOfMemory = RecorderError.OutOfMemory
+        OutOfMemory = RecorderErrorCode.OutOfMemory,
+
+        /// <summary>
+        /// Out of storage or the storage has been removed while recording.
+        /// </summary>
+        OutOfStorage = RecorderErrorCode.OutOfStorage
+    }
+
+    /// <summary>
+    /// Specifies recorder types for <see cref="Recorder.DeviceStateChanged"/>.
+    /// </summary>
+    public enum RecorderType
+    {
+        /// <summary>
+        /// Audio recorder.
+        /// </summary>
+        Audio,
+
+        /// <summary>
+        /// Video recorder.
+        /// </summary>
+        Video
+    }
+
+    /// <summary>
+    /// Specifies recorder device states for <see cref="Recorder.DeviceStateChanged"/>.
+    /// </summary>
+    public enum RecorderDeviceState
+    {
+        /// <summary>
+        /// No recording in progress.
+        /// </summary>
+        Idle,
+
+        /// <summary>
+        /// Recording in progress.
+        /// </summary>
+        Recording,
+
+        /// <summary>
+        /// All recordings are paused.
+        /// </summary>
+        Paused
     }
 }
\ No newline at end of file
diff --git a/src/Tizen.Multimedia.Recorder/Recorder/RecorderError.cs b/src/Tizen.Multimedia.Recorder/Recorder/RecorderError.cs
new file mode 100644 (file)
index 0000000..f189686
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.IO;
+using Tizen.Internals.Errors;
+
+namespace Tizen.Multimedia
+{
+    internal enum RecorderErrorCode
+    {
+        TizenErrorRecorder = -0x01950000,
+        RecorderErrorClass = TizenErrorRecorder | 0x10,
+        None = ErrorCode.None,
+        InvalidParameter = ErrorCode.InvalidParameter,
+        InvalidState = RecorderErrorClass | 0x02,
+        OutOfMemory = ErrorCode.OutOfMemory,
+        DeviceError = RecorderErrorClass | 0x04,
+        InvalidOperation = ErrorCode.InvalidOperation,
+        SecurityRestricted = RecorderErrorClass | 0x07,
+        Esd = RecorderErrorClass | 0x0a,
+        OutOfStorage = RecorderErrorClass | 0x0b,
+        PermissionDenied = ErrorCode.PermissionDenied,
+        NotSupported = ErrorCode.NotSupported,
+        ResourceConflict = RecorderErrorClass | 0x0c,
+        ServiceDisconnected = RecorderErrorClass | 0x0d
+    }
+
+    internal static class RecorderErrorCodeExtensions
+    {
+        internal static RecorderErrorCode Ignore(this RecorderErrorCode errorCode, RecorderErrorCode ignore)
+        {
+            return (ignore == errorCode) ? RecorderErrorCode.None : errorCode;
+        }
+
+        internal static void ThrowIfError(this RecorderErrorCode errorCode, string errorMessage)
+        {
+            if (errorCode == RecorderErrorCode.None)
+            {
+                return;
+            }
+
+            switch (errorCode)
+            {
+                case RecorderErrorCode.InvalidParameter:
+                    throw new ArgumentException(errorMessage);
+
+                case RecorderErrorCode.OutOfMemory:
+                    throw new OutOfMemoryException($"{errorMessage}.");
+
+                case RecorderErrorCode.DeviceError:
+                case RecorderErrorCode.Esd:
+                    throw new RecorderDeviceException($"{errorMessage}; {errorCode.ToString()}.");
+
+                case RecorderErrorCode.SecurityRestricted:
+                    throw new UnauthorizedAccessException($"The feature is currently disabled by the device policy; {errorCode.ToString()}.");
+
+                case RecorderErrorCode.PermissionDenied:
+                    throw new UnauthorizedAccessException($"{errorMessage}; {errorCode.ToString()}.");
+
+                case RecorderErrorCode.NotSupported:
+                    throw new NotSupportedException($"{errorMessage}.");
+
+                case RecorderErrorCode.InvalidState:
+                case RecorderErrorCode.InvalidOperation:
+                case RecorderErrorCode.ResourceConflict:
+                case RecorderErrorCode.ServiceDisconnected:
+                    throw new InvalidOperationException($"{errorMessage}; {errorCode.ToString()}.");
+
+                case RecorderErrorCode.OutOfStorage:
+                    throw new IOException($"{errorMessage}; Not enough disk space or specified path is not available to .");
+
+                default:
+                    throw new Exception($"Unknown error : {errorCode.ToString()}.");
+            }
+        }
+    }
+}
diff --git a/src/Tizen.Multimedia.Recorder/Recorder/RecorderErrorFactory.cs b/src/Tizen.Multimedia.Recorder/Recorder/RecorderErrorFactory.cs
deleted file mode 100644 (file)
index 74a8b46..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using System;
-using System.Runtime.CompilerServices;
-using Tizen.Internals.Errors;
-
-namespace Tizen.Multimedia
-{
-    internal enum RecorderError
-    {
-        TizenErrorRecorder = -0x01950000,
-        RecorderErrorClass = TizenErrorRecorder | 0x10,
-        None = ErrorCode.None,
-        InvalidParameter = ErrorCode.InvalidParameter,
-        InvalidState = RecorderErrorClass | 0x02,
-        OutOfMemory = ErrorCode.OutOfMemory,
-        DeviceError = RecorderErrorClass | 0x04,
-        InvalidOperation = ErrorCode.InvalidOperation,
-        SecurityRestricted = RecorderErrorClass | 0x07,
-        Esd = RecorderErrorClass | 0x0a,
-        OutOfStorage = RecorderErrorClass | 0x0b,
-        PermissionDenied = ErrorCode.PermissionDenied,
-        NotSupported = ErrorCode.NotSupported,
-        ResourceConflict = RecorderErrorClass | 0x0c,
-        ServiceDisconnected = RecorderErrorClass | 0x0d
-    }
-
-    internal static class RecorderErrorFactory
-    {
-        internal static void ThrowIfError(RecorderError errorCode, string errorMessage = null,
-            [CallerMemberName] string caller = null, [CallerLineNumber] int line = 0)
-        {
-            if (errorCode == RecorderError.None)
-            {
-                return;
-            }
-
-            Log.Info(RecorderLog.Tag, "errorCode : " + errorCode.ToString() + ", Caller : " + caller + ", line " + line.ToString());
-
-            switch (errorCode)
-            {
-                case RecorderError.InvalidParameter:
-                    throw new ArgumentException(errorMessage);
-
-                case RecorderError.OutOfMemory:
-                    throw new OutOfMemoryException(errorMessage);
-
-                case RecorderError.DeviceError:
-                case RecorderError.Esd:
-                case RecorderError.SecurityRestricted:
-                case RecorderError.PermissionDenied:
-                    throw new UnauthorizedAccessException(errorMessage);
-
-                case RecorderError.NotSupported:
-                    throw new NotSupportedException(errorMessage);
-
-                case RecorderError.InvalidState:
-                case RecorderError.InvalidOperation:
-                case RecorderError.ResourceConflict:
-                case RecorderError.ServiceDisconnected:
-                case RecorderError.OutOfStorage: //TODO need to alloc new proper exception class
-                    throw new InvalidOperationException(errorMessage);
-
-                default:
-                    throw new Exception("Unknown error : " + errorCode.ToString());
-            }
-        }
-    }
-}
diff --git a/src/Tizen.Multimedia.Recorder/Recorder/RecorderExtensions.cs b/src/Tizen.Multimedia.Recorder/Recorder/RecorderExtensions.cs
new file mode 100644 (file)
index 0000000..9182089
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Provides extension methods for <see cref="Recorder"/>.
+    /// </summary>
+    public static class RecorderExtensions
+    {
+        /// <summary>
+        /// Returns supported file formats for a <see cref="RecorderVideoCodec"/>.
+        /// </summary>
+        /// <returns>An IEnumerable of <see cref="RecorderFileFormat"/> representing the supported file formats.</returns>
+        /// <param name="videoCodec">The <see cref="RecorderVideoCodec"/>.</param>
+        /// <exception cref="ArgumentException"><paramref name="videoCodec"/> is invalid.</exception>
+        public static IEnumerable<RecorderFileFormat> GetSupportedFileFormats(this RecorderVideoCodec videoCodec)
+        {
+            ValidationUtil.ValidateEnum(typeof(RecorderVideoCodec), videoCodec, nameof(videoCodec));
+
+            switch (videoCodec)
+            {
+                case RecorderVideoCodec.H263:
+                    yield return RecorderFileFormat.ThreeGp;
+                    break;
+
+                case RecorderVideoCodec.H264:
+                case RecorderVideoCodec.Mpeg4:
+                    yield return RecorderFileFormat.ThreeGp;
+                    yield return RecorderFileFormat.Mp4;
+                    yield return RecorderFileFormat.M2ts;
+                    break;
+
+                case RecorderVideoCodec.Theora:
+                    yield return RecorderFileFormat.Ogg;
+                    break;
+            }
+        }
+
+        /// <summary>
+        /// Returns supported file formats for a <see cref="RecorderAudioCodec"/>.
+        /// </summary>
+        /// <returns>An IEnumerable of <see cref="RecorderFileFormat"/> representing the supported file formats.</returns>
+        /// <param name="audioCodec">The <see cref="RecorderAudioCodec"/>.</param>
+        /// <exception cref="ArgumentException"><paramref name="audioCodec"/> is invalid.</exception>
+        public static IEnumerable<RecorderFileFormat> GetSupportedFileFormats(this RecorderAudioCodec audioCodec)
+        {
+            ValidationUtil.ValidateEnum(typeof(RecorderAudioCodec), audioCodec, nameof(audioCodec));
+
+            switch (audioCodec)
+            {
+                case RecorderAudioCodec.Amr:
+                    yield return RecorderFileFormat.ThreeGp;
+                    yield return RecorderFileFormat.Amr;
+                    break;
+
+                case RecorderAudioCodec.Mp3:
+                    yield return RecorderFileFormat.Mp4;
+                    yield return RecorderFileFormat.M2ts;
+                    break;
+
+                case RecorderAudioCodec.Aac:
+                    yield return RecorderFileFormat.ThreeGp;
+                    yield return RecorderFileFormat.Mp4;
+                    yield return RecorderFileFormat.M2ts;
+                    yield return RecorderFileFormat.Adts;
+                    break;
+
+                case RecorderAudioCodec.Vorbis:
+                    yield return RecorderFileFormat.Ogg;
+                    break;
+
+                case RecorderAudioCodec.Pcm:
+                    yield return RecorderFileFormat.Wav;
+                    break;
+            }
+        }
+
+        internal static void ThrowIfFormatNotSupported(this RecorderAudioCodec audioCodec, RecorderFileFormat fileFormat)
+        {
+            ValidationUtil.ValidateEnum(typeof(RecorderFileFormat), fileFormat, nameof(fileFormat));
+
+            if (audioCodec.GetSupportedFileFormats().Contains(fileFormat) == false)
+            {
+                throw new NotSupportedException($"{audioCodec} does not support {fileFormat}.");
+            }
+        }
+
+        internal static void ThrowIfFormatNotSupported(this RecorderVideoCodec videoCodec, RecorderFileFormat fileFormat)
+        {
+            ValidationUtil.ValidateEnum(typeof(RecorderFileFormat), fileFormat, nameof(fileFormat));
+
+            if (videoCodec.GetSupportedFileFormats().Contains(fileFormat) == false)
+            {
+                throw new NotSupportedException($"{videoCodec} does not support {fileFormat}.");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Tizen.Multimedia.Recorder/Recorder/RecorderFeatures.cs b/src/Tizen.Multimedia.Recorder/Recorder/RecorderFeatures.cs
deleted file mode 100755 (executable)
index f1efa79..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Native = Interop.RecorderFeatures;
-
-namespace Tizen.Multimedia
-{
-    /// <summary>
-    /// The camera setting class provides methods/properties to get and
-    /// set basic camera attributes.
-    /// </summary>
-    public class RecorderFeatures
-    {
-        internal readonly Recorder _recorder = null;
-
-        private List<RecorderFileFormat> _fileFormats;
-        private List<RecorderAudioCodec> _audioCodec;
-        private List<RecorderVideoCodec> _videoCodec;
-        private List<Size> _videoResolution;
-
-        internal RecorderFeatures(Recorder recorder)
-        {
-            _recorder = recorder;
-        }
-
-        /// <summary>
-        /// Retrieves all the file formats supported by the recorder.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <returns>
-        /// It returns a list containing all the supported <see cref="RecorderFileFormat"/>.
-        /// </returns>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public IEnumerable<RecorderFileFormat> SupportedFileFormats
-        {
-            get
-            {
-                if (_fileFormats == null)
-                {
-                    try
-                    {
-                        _fileFormats = new List<RecorderFileFormat>();
-
-                        Native.FileFormatCallback callback = (RecorderFileFormat format, IntPtr userData) =>
-                        {
-                            _fileFormats.Add(format);
-                            return true;
-                        };
-                        RecorderErrorFactory.ThrowIfError(Native.FileFormats(_recorder.GetHandle(), callback, IntPtr.Zero),
-                        "Failed to get the supported fileformats");
-                    }
-                    catch
-                    {
-                        _fileFormats = null;
-                        throw;
-                    }
-                }
-
-                return _fileFormats;
-            }
-        }
-
-        /// <summary>
-        /// Retrieves all the audio encoders supported by the recorder.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <returns>
-        /// It returns a list containing all the supported <see cref="RecorderAudioCodec"/>.
-        /// </returns>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public IEnumerable<RecorderAudioCodec> SupportedAudioEncodings
-        {
-            get
-            {
-                if (_audioCodec == null)
-                {
-                    try
-                    {
-                        _audioCodec = new List<RecorderAudioCodec>();
-
-                        Native.AudioEncoderCallback callback = (RecorderAudioCodec codec, IntPtr userData) =>
-                        {
-                            _audioCodec.Add(codec);
-                            return true;
-                        };
-                        RecorderErrorFactory.ThrowIfError(Native.AudioEncoders(_recorder.GetHandle(), callback, IntPtr.Zero),
-                            "Failed to get the supported audio encoders");
-                    }
-                    catch
-                    {
-                        _audioCodec = null;
-                        throw;
-                    }
-                }
-
-                return _audioCodec;
-            }
-        }
-
-        /// <summary>
-        /// Retrieves all the video encoders supported by the recorder.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <returns>
-        /// It returns a list containing all the supported <see cref="RecorderVideoCodec"/>.
-        /// by recorder.
-        /// </returns>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public IEnumerable<RecorderVideoCodec> SupportedVideoEncodings
-        {
-            get
-            {
-                if (_videoCodec == null)
-                {
-                    try
-                    {
-                        _videoCodec = new List<RecorderVideoCodec>();
-
-                        Native.VideoEncoderCallback callback = (RecorderVideoCodec codec, IntPtr userData) =>
-                        {
-                            _videoCodec.Add(codec);
-                            return true;
-                        };
-                        RecorderErrorFactory.ThrowIfError(Native.VideoEncoders(_recorder.GetHandle(), callback, IntPtr.Zero),
-                            "Failed to get the supported video encoders");
-                    }
-                    catch
-                    {
-                        _videoCodec = null;
-                        throw;
-                    }
-                }
-
-                return _videoCodec;
-            }
-        }
-
-        /// <summary>
-        /// Retrieves all the video resolutions supported by the recorder.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <returns>
-        /// It returns videoresolution list containing the width and height of
-        /// different resolutions supported by recorder.
-        /// </returns>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public IEnumerable<Size> SupportedVideoResolutions
-        {
-            get
-            {
-                if (_videoResolution == null)
-                {
-                    try
-                    {
-                        _videoResolution = new List<Size>();
-
-                        Native.VideoResolutionCallback callback = (int width, int height, IntPtr userData) =>
-                        {
-                            _videoResolution.Add(new Size(width, height));
-                            return true;
-                        };
-                        RecorderErrorFactory.ThrowIfError(Native.VideoResolution(_recorder.GetHandle(), callback, IntPtr.Zero),
-                            "Failed to get the supported video resolutions.");
-                    }
-                    catch
-                    {
-                        _videoResolution = null;
-                        throw;
-                    }
-                }
-
-                return _videoResolution;
-            }
-        }
-    }
-}
\ No newline at end of file
index 71392fc..86be713 100755 (executable)
  */
 
 using System;
-using System.Collections.Generic;
 
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// An extended Eventargs class which contains interrupted policy details, previous and current
-    /// state of the recorder.
+    /// Provides data for the <see cref="Recorder.Interrupted"/> event.
     /// </summary>
     public class RecorderInterruptedEventArgs : EventArgs
     {
         internal RecorderInterruptedEventArgs(RecorderPolicy policy, RecorderState previous, RecorderState current)
         {
-            Policy = policy;
+            Reason = policy;
             Previous = previous;
             Current = current;
         }
 
         /// <summary>
-        /// The policy that interrupted the recorder.
+        /// Gets the policy that interrupted the recorder.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public RecorderPolicy Policy { get; }
+        public RecorderPolicy Reason { get; }
 
         /// <summary>
-        /// The previous state of the recorder.
+        /// Gets the previous state of the recorder.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
         public RecorderState Previous { get; }
 
         /// <summary>
-        /// The current state of the recorder.
+        /// Gets the current state of the recorder.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
         public RecorderState Current { get; }
     }
 }
diff --git a/src/Tizen.Multimedia.Recorder/Recorder/RecorderInterruptingEventArgs.cs b/src/Tizen.Multimedia.Recorder/Recorder/RecorderInterruptingEventArgs.cs
new file mode 100644 (file)
index 0000000..4e90317
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Provides data for the <see cref="Recorder.Interrupting"/> event.
+    /// </summary>
+    public class RecorderInterruptingEventArgs : EventArgs
+    {
+        internal RecorderInterruptingEventArgs(RecorderPolicy policy, RecorderState state)
+        {
+            Reason = policy;
+            State = state;
+        }
+
+        /// <summary>
+        /// Gets the reason of the interrupt.
+        /// </summary>
+        public RecorderPolicy Reason { get; }
+
+        /// <summary>
+        /// Gets the previous state of the recorder.
+        /// </summary>
+        public RecorderState State { get; }
+    }
+}
diff --git a/src/Tizen.Multimedia.Recorder/Recorder/RecorderSettings.cs b/src/Tizen.Multimedia.Recorder/Recorder/RecorderSettings.cs
deleted file mode 100755 (executable)
index 9c92ad7..0000000
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using System;
-using System.Linq;
-using System.Runtime.InteropServices;
-using Tizen.Internals.Errors;
-using Native = Interop.RecorderSettings;
-
-namespace Tizen.Multimedia
-{
-    /// <summary>
-    /// The camera setting class provides methods/properties to get and
-    /// set basic camera attributes.
-    /// </summary>
-    public class RecorderSettings
-    {
-        internal readonly Recorder _recorder = null;
-
-        internal RecorderSettings(Recorder recorder)
-        {
-            _recorder = recorder;
-        }
-
-        /// <summary>
-        /// The number of audio channel.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <value>
-        /// For mono recording, set channel to 1.
-        /// For stereo recording, set channel to 2.
-        /// </value>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public int AudioChannel
-        {
-            get
-            {
-                int val = 0;
-
-                RecorderErrorFactory.ThrowIfError(Native.GetAudioChannel(_recorder.GetHandle(), out val),
-                    "Failed to get audio channel.");
-
-                return val;
-            }
-
-            set
-            {
-                RecorderErrorFactory.ThrowIfError(Native.SetAudioChannel(_recorder.GetHandle(), value),
-                    "Failed to set audio channel");
-            }
-        }
-
-        /// <summary>
-        /// The audio device for recording.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <value>A <see cref="RecorderAudioDevice"/> that specifies the type of audio device.</value>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public RecorderAudioDevice AudioDevice
-        {
-            get
-            {
-                RecorderAudioDevice val = 0;
-
-                RecorderErrorFactory.ThrowIfError(Native.GetAudioDevice(_recorder.GetHandle(), out val),
-                    "Failed to get audio device.");
-
-                return val;
-            }
-
-            set
-            {
-                RecorderErrorFactory.ThrowIfError(Native.SetAudioDevice(_recorder.GetHandle(), value),
-                    "Failed to set audio device.");
-            }
-        }
-
-        /// <summary>
-        /// Get the peak audio input level in dB
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <remarks>
-        /// 0dB indicates maximum input level, -300dB indicates minimum input level.
-        /// </remarks>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public double AudioLevel
-        {
-            get
-            {
-                double level = 0;
-
-                RecorderErrorFactory.ThrowIfError(Native.GetAudioLevel(_recorder.GetHandle(), out level),
-                    "Failed to get Audio level.");
-
-                return level;
-            }
-        }
-
-        /// <summary>
-        /// The sampling rate of an audio stream in hertz.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public int AudioSampleRate
-        {
-            get
-            {
-                int val = 0;
-
-                RecorderErrorFactory.ThrowIfError(Native.GetAudioSampleRate(_recorder.GetHandle(), out val),
-                    "Failed to get audio sample rate.");
-
-                return val;
-            }
-
-            set
-            {
-                RecorderErrorFactory.ThrowIfError(Native.SetAudioSampleRate(_recorder.GetHandle(), value),
-                    "Failed to set audio sample rate.");
-            }
-        }
-
-        /// <summary>
-        /// The bitrate of an audio encoder in bits per second.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public int AudioBitRate
-        {
-            get
-            {
-                int val = 0;
-
-                RecorderErrorFactory.ThrowIfError(Native.GetAudioEncoderBitrate(_recorder.GetHandle(), out val),
-                    "Failed to get audio bitrate.");
-
-                return val;
-            }
-
-            set
-            {
-                RecorderErrorFactory.ThrowIfError(Native.SetAudioEncoderBitrate(_recorder.GetHandle(), value),
-                    "Failed to set audio bitrate");
-            }
-        }
-
-        /// <summary>
-        /// The bitrate of an video encoder in bits per second.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public int VideoBitRate
-        {
-            get
-            {
-                int val = 0;
-
-                RecorderErrorFactory.ThrowIfError(Native.GetVideoEncoderBitrate(_recorder.GetHandle(), out val),
-                    "Failed to get video bitrate.");
-
-                return val;
-            }
-
-            set
-            {
-                RecorderErrorFactory.ThrowIfError(Native.SetVideoEncoderBitrate(_recorder.GetHandle(), value),
-                    "Failed to set video bitrate");
-            }
-        }
-
-        /// <summary>
-        /// The audio codec for encoding an audio stream.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <value>A <see cref="RecorderAudioCodec"/> that specifies the type of audio codec.</value>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public RecorderAudioCodec AudioCodec
-        {
-            get
-            {
-                RecorderAudioCodec val = 0;
-
-                RecorderErrorFactory.ThrowIfError(Native.GetAudioEncoder(_recorder.GetHandle(), out val),
-                    "Failed to get audio codec");
-
-                return val;
-            }
-
-            set
-            {
-                RecorderErrorFactory.ThrowIfError(Native.SetAudioEncoder(_recorder.GetHandle(), value),
-                    "Failed to set audio codec");
-            }
-        }
-
-        /// <summary>
-        /// The video codec for encoding video stream.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <value>A <see cref="RecorderVideoCodec"/> that specifies the type of video codec.</value>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public RecorderVideoCodec VideoCodec
-        {
-            get
-            {
-                RecorderVideoCodec val = 0;
-
-                RecorderErrorFactory.ThrowIfError(Native.GetVideoEncoder(_recorder.GetHandle(), out val),
-                    "Failed to get video codec");
-
-                return val;
-            }
-
-            set
-            {
-                RecorderErrorFactory.ThrowIfError(Native.SetVideoEncoder(_recorder.GetHandle(), value),
-                    "Failed to set video codec");
-            }
-        }
-
-        /// <summary>
-        /// The file format for recording media stream.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <value>A <see cref="RecorderFileFormat"/> that specifies the file format.</value>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public RecorderFileFormat FileFormat
-        {
-            get
-            {
-                RecorderFileFormat val = 0;
-
-                RecorderErrorFactory.ThrowIfError(Native.GetFileFormat(_recorder.GetHandle(), out val),
-                    "Failed to get file format.");
-
-                return val;
-            }
-
-            set
-            {
-                RecorderErrorFactory.ThrowIfError(Native.SetFileFormat(_recorder.GetHandle(), value),
-                    "Failed to set file format");
-            }
-        }
-
-        /// <summary>
-        /// The file path to record.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <remarks>
-        /// If the same file already exists in the file system, then old file
-        /// will be overwritten.
-        /// </remarks>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public string FilePath
-        {
-            get
-            {
-                IntPtr val;
-                RecorderError ret = Native.GetFileName(_recorder.GetHandle(), out val);
-                if (ret != RecorderError.None)
-                {
-                    Log.Error(RecorderLog.Tag, "Failed to get filepath, " + (RecorderError)ret);
-                }
-                string result = Marshal.PtrToStringAnsi(val);
-                LibcSupport.Free(val);
-                return result;
-            }
-
-            set
-            {
-                RecorderErrorFactory.ThrowIfError(Native.SetFileName(_recorder.GetHandle(), value),
-                    "Failed to set filepath");
-            }
-        }
-
-        /// <summary>
-        /// The maximum size of a recording file in KB(kilobytes). If 0, means
-        /// unlimited recording size.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <remarks>
-        /// After reaching the limitation, the data which is being recorded will
-        /// be discarded and not written to the file.
-        /// The recorder state must be in 'Ready' or 'Created' state.
-        /// </remarks>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public int SizeLimit
-        {
-            get
-            {
-                int val = 0;
-
-                RecorderErrorFactory.ThrowIfError(Native.GetSizeLimit(_recorder.GetHandle(), out val),
-                    "Failed to get size limit.");
-
-                return val;
-            }
-
-            set
-            {
-                RecorderErrorFactory.ThrowIfError(Native.SetSizeLimit(_recorder.GetHandle(), value),
-                    "Failed to set size limit");
-            }
-        }
-
-        /// <summary>
-        /// The time limit of a recording file in Seconds. If 0, means unlimited recording
-        /// time.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <remarks>
-        /// After reaching the limitation, the data which is being recorded will
-        /// be discarded and not written to the file.
-        /// The recorder state must be in 'Ready' or 'Created' state.
-        /// </remarks>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public int TimeLimit
-        {
-            get
-            {
-                int val = 0;
-
-                RecorderErrorFactory.ThrowIfError(Native.GetTimeLimit(_recorder.GetHandle(), out val),
-                    "Failed to get time limit.");
-
-                return val;
-            }
-
-            set
-            {
-                RecorderErrorFactory.ThrowIfError(Native.SetTimeLimit(_recorder.GetHandle(), value),
-                    "Failed to set time limit.");
-            }
-        }
-
-        /// <summary>
-        /// The mute state of a recorder.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public bool Mute
-        {
-            get
-            {
-                return Native.GetMute(_recorder.GetHandle());
-            }
-
-            set
-            {
-                RecorderErrorFactory.ThrowIfError(Native.SetMute(_recorder.GetHandle(), value),
-                    "Failed to set mute");
-            }
-        }
-
-        /// <summary>
-        /// The video recording motion rate
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <remarks>
-        /// The attribute is valid only in a video recorder.
-        /// If the rate is in range of 0-1, video is recorded in a slow motion mode.
-        /// If the rate is bigger than 1, video is recorded in a fast motion mode.
-        /// </remarks>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public double MotionRate
-        {
-            get
-            {
-                double val = 0.0;
-
-                RecorderErrorFactory.ThrowIfError(Native.GetMotionRate(_recorder.GetHandle(), out val),
-                    "Failed to get video motion rate.");
-
-                return val;
-            }
-
-            set
-            {
-                RecorderErrorFactory.ThrowIfError(Native.SetMotionRate(_recorder.GetHandle(), value),
-                    "Failed to set video motion rate");
-            }
-        }
-
-        /// <summary>
-        /// The orientation in a video metadata tag.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <value>A <see cref="Rotation"/> that specifies the type of orientation.</value>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public Rotation OrientationTag
-        {
-            get
-            {
-                RecorderErrorFactory.ThrowIfError(Native.GetOrientationTag(_recorder.GetHandle(), out var val),
-                    "Failed to get recorder orientation.");
-
-                return val;
-            }
-
-            set
-            {
-                RecorderErrorFactory.ThrowIfError(Native.SetOrientationTag(_recorder.GetHandle(), value),
-                    "Failed to set recorder orientation");
-            }
-        }
-
-        /// <summary>
-        /// Resolution of the video.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        /// <exception cref="ArgumentException">In case of invalid parameters</exception>
-        /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
-        public Size VideoResolution
-        {
-            get
-            {
-                int width = 0;
-                int height = 0;
-
-                RecorderErrorFactory.ThrowIfError(Native.GetVideoResolution(_recorder.GetHandle(), out width, out height),
-                    "Failed to get camera video resolution");
-
-                return new Size(width, height);
-            }
-
-            set
-            {
-                Size res = value;
-
-                RecorderErrorFactory.ThrowIfError(Native.SetVideoResolution(_recorder.GetHandle(), res.Width, res.Height),
-                    "Failed to set video resolution.");
-            }
-        }
-    }
-}
\ No newline at end of file
index 42e3af0..34b8522 100755 (executable)
@@ -19,35 +19,31 @@ using System;
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// An extended EventArgs class which contains details about previous and current state
-    /// of the recorder when its state is changed.
+    /// Provides data for the <see cref="Recorder.StateChanged"/> event.
     /// </summary>
     public class RecorderStateChangedEventArgs : EventArgs
     {
         internal RecorderStateChangedEventArgs(RecorderState previous, RecorderState current, bool byPolicy)
         {
-            Previous = previous;
-            Current = current;
+            PreviousState = previous;
+            CurrentState = current;
             IsStateChangedByPolicy = byPolicy;
         }
 
         /// <summary>
-        /// Previous state of the recorder.
+        /// Gets the previous state of the recorder.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public RecorderState Previous { get; }
+        public RecorderState PreviousState { get; }
 
         /// <summary>
-        /// Current state of the recorder.
+        /// Gets the current state of the recorder.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public RecorderState Current { get; }
+        public RecorderState CurrentState { get; }
 
         /// <summary>
-        /// true if the state changed by policy such as Resource Conflict or Security, otherwise false
-        /// in normal state change.
+        /// Gets the value indicating whether the state is changed by policy.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
+        /// <value>true if the state changed by policy such as resource conflict or security, otherwise false.</value>
         public bool IsStateChangedByPolicy { get; }
     }
 }
index 80b6070..059ae9f 100755 (executable)
@@ -19,28 +19,18 @@ using System;
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// An extended EventArgs class which contains details about error status and
-    /// state of the recorder when it failed.
+    /// Provides data for the <see cref="Recorder.ErrorOccurred"/> event.
     /// </summary>
     public class RecordingErrorOccurredEventArgs : EventArgs
     {
-        internal RecordingErrorOccurredEventArgs(RecorderErrorCode error, RecorderState state)
+        internal RecordingErrorOccurredEventArgs(RecorderError error, RecorderState state)
         {
             Error = error;
-            State = state;
         }
 
         /// <summary>
-        /// The error code.
+        /// Gets the error.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public RecorderErrorCode Error { get; }
-
-        /// <summary>
-        /// The state of the recorder.
-        /// </summary>
-        /// <since_tizen> 3 </since_tizen>
-        public RecorderState State { get; }
-
+        public RecorderError Error { get; }
     }
 }
index 8606748..7fbcd4e 100755 (executable)
@@ -19,19 +19,23 @@ using System;
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// An extended EventArgs class containing details about the recording limit.
+    /// Provides data for the <see cref="Recorder.RecordingLimitReached"/> event.
     /// </summary>
     public class RecordingLimitReachedEventArgs : EventArgs
     {
-        internal RecordingLimitReachedEventArgs(RecordingLimitType type)
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RecordingLimitReachedEventArgs"/> class
+        /// with the specified type.
+        /// </summary>
+        /// <param name="type">The type of the limit.</param>
+        public RecordingLimitReachedEventArgs(RecordingLimitType type)
         {
             Type = type;
         }
 
         /// <summary>
-        /// The limitation type.
+        /// Gets the type of the limit.
         /// </summary>
-        /// <since_tizen> 3 </since_tizen>
         public RecordingLimitType Type { get; }
     }
 }
diff --git a/src/Tizen.Multimedia.Recorder/Recorder/RecordingStatusChangedEventArgs.cs b/src/Tizen.Multimedia.Recorder/Recorder/RecordingStatusChangedEventArgs.cs
new file mode 100644 (file)
index 0000000..5c5726b
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Provides data for the <see cref="Recorder.RecordingStatusChanged"/> event.
+    /// </summary>
+    public class RecordingStatusChangedEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RecordingStatusChangedEventArgs"/> class
+        /// with the specified elapsed time and file size.
+        /// </summary>
+        /// <param name="elapsedTime">The time of the recording in milliseconds.</param>
+        /// <param name="fileSize">The size of the recording in kilobytes.</param>
+        public RecordingStatusChangedEventArgs(long elapsedTime, long fileSize)
+        {
+            ElapsedTime = elapsedTime;
+            FileSize = fileSize;
+        }
+
+        /// <summary>
+        /// Gets the time of the recording in milliseconds.
+        /// </summary>
+        public long ElapsedTime { get; }
+
+        /// <summary>
+        /// Gets the size of the recording file in kilobytes.
+        /// </summary>
+        public long FileSize { get; }
+    }
+}
diff --git a/src/Tizen.Multimedia.Recorder/Recorder/VideoRecorder.Capabilities.cs b/src/Tizen.Multimedia.Recorder/Recorder/VideoRecorder.Capabilities.cs
new file mode 100644 (file)
index 0000000..7e50b68
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using Native = Interop.Recorder;
+using NativeHandle = Interop.RecorderHandle;
+
+namespace Tizen.Multimedia
+{
+    public partial class VideoRecorder
+    {
+        private static IEnumerable<Size> _frontResolutions;
+        private static IEnumerable<Size> _rearResolutions;
+
+        private static IEnumerable<Size> GetVideoResolutions(NativeHandle handle)
+        {
+            var result = new List<Size>();
+
+            var ret = Native.GetVideoResolutions(handle, (w, h, _) => { result.Add(new Size(w, h)); return true; });
+
+            if (ret == RecorderErrorCode.NotSupported)
+            {
+                throw new NotSupportedException("Video recording is not supported.");
+            }
+
+            ret.ThrowIfError("Failed to load the resolutions");
+
+            return result.AsReadOnly();
+        }
+
+        private static IEnumerable<Size> LoadVideoResolutions(CameraDevice device)
+        {
+            using (var camera = new Camera(device))
+            {
+                Native.CreateVideo(camera.Handle, out var handle).ThrowIfError("Failed to get the resolutions");
+
+                using (handle)
+                {
+                    return GetVideoResolutions(handle);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the video resolutions that the current device supports.
+        /// </summary>
+        /// <feature>http://tizen.org/feature/camera</feature>
+        /// <param name="device">The camera device to retrieve the supported resolutions</param>
+        /// <exception cref="NotSupportedException">A required feature is not supported.</exception>
+        /// <exception cref="ArgumentException"><paramref name="device"/> is invalid.</exception>
+        public static IEnumerable<Size> GetSupportedVideoResolutions(CameraDevice device)
+        {
+            ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
+
+            if (device == CameraDevice.Front)
+            {
+                return _frontResolutions ?? (_frontResolutions = LoadVideoResolutions(CameraDevice.Front));
+            }
+
+            if (device == CameraDevice.Front)
+            {
+                return _rearResolutions ?? (_rearResolutions = LoadVideoResolutions(CameraDevice.Rear));
+            }
+
+            Debug.Fail($"No cache for {device}.");
+
+            return LoadVideoResolutions(device);
+        }
+
+        /// <summary>
+        /// Gets the video encoders that the current device supports.
+        /// </summary>
+        /// <feature>http://tizen.org/feature/camera</feature>
+        /// <exception cref="NotSupportedException">A required feature is not supported.</exception>
+        public static IEnumerable<RecorderVideoCodec> GetSupportedVideoCodecs()
+            => Capabilities.Value.SupportedVideoCodecs ?? throw new NotSupportedException("Video recording is not supported.");
+
+        internal static void ValidateVideoCodec(RecorderVideoCodec codec)
+        {
+            if (GetSupportedVideoCodecs().Contains(codec) == false)
+            {
+                throw new NotSupportedException($"{codec.ToString()} is not supported.");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Tizen.Multimedia.Recorder/Recorder/VideoRecorder.cs b/src/Tizen.Multimedia.Recorder/Recorder/VideoRecorder.cs
new file mode 100644 (file)
index 0000000..78bec71
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Diagnostics;
+using Native = Interop.Recorder;
+using NativeHandle = Interop.RecorderHandle;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Provides the ability to control video recording.
+    /// </summary>
+    public partial class VideoRecorder : Recorder
+    {
+        private static NativeHandle CreateHandle(Camera camera)
+        {
+            if (camera == null)
+            {
+                throw new ArgumentNullException(nameof(camera));
+            }
+
+            Native.CreateVideo(camera.Handle, out var handle).
+                ThrowIfError("Failed to create video recorder.");
+
+            return handle;
+        }
+
+        private static void ThrowIfCodecAndFormatNotValid(RecorderVideoCodec videoCodec,
+            RecorderAudioCodec audioCodec, RecorderFileFormat fileFormat)
+        {
+            videoCodec.ThrowIfFormatNotSupported(fileFormat);
+
+            if (audioCodec != RecorderAudioCodec.None)
+            {
+                audioCodec.ThrowIfFormatNotSupported(fileFormat);
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="VideoRecorder"/> class with the specified camera, video codec and file format.
+        /// </summary>
+        /// <remarks>
+        /// If the state of <see cref="Camera"/> is <see cref="CameraState.Created"/>,
+        /// the <see cref="CameraSettings.PreviewPixelFormat"/> will be changed to the recommended format for recording.\n
+        /// \n
+        /// The initial state of the Recorder will be <see cref="RecorderState.Ready"/>
+        /// if the state of <see cref="Camera"/> is <see cref="CameraState.Preview"/> or <see cref="CameraState.Captured"/>.
+        /// </remarks>
+        /// <param name="camera">The camera object.</param>
+        /// <param name="videoCodec">The codec for video encoding.</param>
+        /// <param name="fileFormat">The format of result file.</param>
+        /// <feature>http://tizen.org/feature/camera</feature>
+        /// <exception cref="InvalidOperationException">An internal error occurred.</exception>
+        /// <exception cref="NotSupportedException">
+        ///     A required feature is not supported.\n
+        ///     -or-\n
+        ///     <paramref name="videoCodec"/> is not supported.\n
+        ///     -or-\n
+        ///     <paramref name="fileFormat"/> is not supported with the specified video codec.
+        /// </exception>
+        /// <exception cref="ArgumentException">
+        ///     <paramref name="videoCodec"/> is not valid.\n
+        ///     -or-\n
+        ///     <paramref name="fileFormat"/> is not valid.
+        /// </exception>
+        /// <exception cref="ObjectDisposedException"><paramref name="camera"/> has been disposed of.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="camera"/> is null.</exception>
+        /// <seealso cref="GetSupportedVideoCodecs"/>
+        /// <seealso cref="Recorder.GetSupportedFileFormats"/>
+        /// <seealso cref="RecorderExtensions.GetSupportedFileFormats(RecorderVideoCodec)"/>
+        /// <seealso cref="SetFormatAndCodec(RecorderVideoCodec, RecorderFileFormat)"/>
+        /// <seealso cref="SetFormatAndCodec(RecorderVideoCodec, RecorderAudioCodec, RecorderFileFormat)"/>
+        public VideoRecorder(Camera camera, RecorderVideoCodec videoCodec, RecorderFileFormat fileFormat) :
+            this(camera, videoCodec, RecorderAudioCodec.None, fileFormat)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="VideoRecorder"/> class with the specified camera, video codec,
+        /// audio codec and file format.
+        /// </summary>
+        /// <remarks>
+        /// If the state of <see cref="Camera"/> is <see cref="CameraState.Created"/>,
+        /// the <see cref="CameraSettings.PreviewPixelFormat"/> will be changed to the recommended format for recording.\n
+        /// \n
+        /// The initial state of the Recorder will be <see cref="RecorderState.Ready"/>
+        /// if the state of <see cref="Camera"/> is <see cref="CameraState.Preview"/> or <see cref="CameraState.Captured"/>.
+        /// </remarks>
+        /// <param name="camera">The camera object.</param>
+        /// <param name="videoCodec">The codec for video encoding.</param>
+        /// <param name="audioCodec">The codec for audio encoding.</param>
+        /// <param name="fileFormat">The format of result file.</param>
+        /// <feature>http://tizen.org/feature/camera</feature>
+        /// <exception cref="InvalidOperationException">An internal error occurred.</exception>
+        /// <exception cref="NotSupportedException">
+        ///     A required feature is not supported.\n
+        ///     -or-\n
+        ///     <paramref name="videoCodec"/> is not supported.\n
+        ///     -or-\n
+        ///     <paramref name="audioCodec"/> is not supported.\n
+        ///     -or-\n
+        ///     <paramref name="fileFormat"/> is not supported with the specified video codec.
+        ///     -or-\n
+        ///     <paramref name="fileFormat"/> is not supported with the specified audio codec.
+        /// </exception>
+        /// <exception cref="ArgumentException">
+        ///     <paramref name="videoCodec"/> is not valid.\n
+        ///     -or-\n
+        ///     <paramref name="audioCodec"/> is not valid.\n
+        ///     -or-\n
+        ///     <paramref name="fileFormat"/> is not valid.
+        /// </exception>
+        /// <exception cref="ObjectDisposedException"><paramref name="camera"/> has been disposed of.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="camera"/> is null.</exception>
+        /// <seealso cref="Recorder.GetSupportedAudioCodecs"/>
+        /// <seealso cref="GetSupportedVideoCodecs"/>
+        /// <seealso cref="Recorder.GetSupportedFileFormats"/>
+        /// <seealso cref="RecorderExtensions.GetSupportedFileFormats(RecorderAudioCodec)"/>
+        /// <seealso cref="RecorderExtensions.GetSupportedFileFormats(RecorderVideoCodec)"/>
+        /// <seealso cref="SetFormatAndCodec(RecorderVideoCodec, RecorderFileFormat)"/>
+        /// <seealso cref="SetFormatAndCodec(RecorderVideoCodec, RecorderAudioCodec, RecorderFileFormat)"/>
+        public VideoRecorder(Camera camera, RecorderVideoCodec videoCodec,
+            RecorderAudioCodec audioCodec, RecorderFileFormat fileFormat) : base(CreateHandle(camera))
+        {
+            SetFormatAndCodec(videoCodec, RecorderAudioCodec.None, fileFormat);
+        }
+
+        /// <summary>
+        /// Sets the video codec and the file format for recording. Audio will not recorded.
+        /// </summary>
+        /// <param name="videoCodec">The codec for video encoding.</param>
+        /// <param name="fileFormat">The format of result file.</param>
+        /// <exception cref="NotSupportedException">
+        ///     <paramref name="videoCodec"/> is not supported.\n
+        ///     -or-\n
+        ///     <paramref name="fileFormat"/> is not supported with the specified video codec.
+        /// </exception>
+        /// <exception cref="ArgumentException">
+        ///     <paramref name="videoCodec"/> is not valid.\n
+        ///     -or-\n
+        ///     <paramref name="fileFormat"/> is not valid.
+        /// </exception>
+        /// <seealso cref="GetSupportedVideoCodecs"/>
+        /// <seealso cref="Recorder.GetSupportedFileFormats"/>
+        /// <seealso cref="RecorderExtensions.GetSupportedFileFormats(RecorderVideoCodec)"/>
+        /// <seealso cref="SetFormatAndCodec(RecorderVideoCodec, RecorderAudioCodec, RecorderFileFormat)"/>
+        /// <seealso cref="Recorder.Start(string)"/>
+        public void SetFormatAndCodec(RecorderVideoCodec videoCodec, RecorderFileFormat fileFormat)
+        {
+            SetFormatAndCodec(videoCodec, RecorderAudioCodec.None, fileFormat);
+        }
+
+        /// <summary>
+        /// Sets the video codec, audio codec and the file format for recording.
+        /// </summary>
+        /// <param name="videoCodec">The codec for video encoding.</param>
+        /// <param name="audioCodec">The codec for audio encoding.</param>
+        /// <param name="fileFormat">The format of result file.</param>
+        /// <exception cref="NotSupportedException">
+        ///     <paramref name="videoCodec"/> is not supported.\n
+        ///     -or-\n
+        ///     <paramref name="audioCodec"/> is not supported.\n
+        ///     -or-\n
+        ///     <paramref name="fileFormat"/> is not supported with the specified video codec.
+        ///     -or-\n
+        ///     <paramref name="fileFormat"/> is not supported with the specified audio codec.
+        /// </exception>
+        /// <exception cref="ArgumentException">
+        ///     <paramref name="videoCodec"/> is not valid.\n
+        ///     -or-\n
+        ///     <paramref name="audioCodec"/> is not valid.\n
+        ///     -or-\n
+        ///     <paramref name="fileFormat"/> is not valid.
+        /// </exception>
+        /// <seealso cref="Recorder.GetSupportedAudioCodecs"/>
+        /// <seealso cref="VideoRecorder.GetSupportedVideoCodecs"/>
+        /// <seealso cref="Recorder.GetSupportedFileFormats"/>
+        /// <seealso cref="RecorderExtensions.GetSupportedFileFormats(RecorderAudioCodec)"/>
+        /// <seealso cref="RecorderExtensions.GetSupportedFileFormats(RecorderVideoCodec)"/>
+        /// <seealso cref="SetFormatAndCodec(RecorderVideoCodec, RecorderFileFormat)"/>
+        /// <seealso cref="Recorder.Start(string)"/>
+        public void SetFormatAndCodec(RecorderVideoCodec videoCodec, RecorderAudioCodec audioCodec, RecorderFileFormat fileFormat)
+        {
+            ThrowIfCodecAndFormatNotValid(videoCodec, audioCodec, fileFormat);
+
+            VideoCodec = videoCodec;
+            AudioCodec = audioCodec;
+            FileFormat = fileFormat;
+        }
+
+        #region Properties
+
+        private RecorderVideoCodec _videoCodec;
+
+        /// <summary>
+        /// Gets the audio codec for encoding an audio stream.
+        /// </summary>
+        public RecorderVideoCodec VideoCodec
+        {
+            get => _videoCodec;
+            internal set
+            {
+                Debug.Assert(Enum.IsDefined(typeof(RecorderVideoCodec), value));
+
+                ValidateVideoCodec(value);
+
+                Native.SetVideoEncoder(Handle, value).ThrowIfError("Failed to set video codec.");
+
+                _videoCodec = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the video recording motion rate.
+        /// </summary>
+        /// <remarks>
+        /// The attribute is valid only in a video recorder.\n
+        /// If the rate is in range of 0-1, video is recorded in a slow motion mode.\n
+        /// If the rate is bigger than 1, video is recorded in a fast motion mode.\n
+        /// \n
+        /// To set, the recorder must be in the <see cref="RecorderState.Idle"/> or <see cref="RecorderState.Ready"/> state.
+        /// </remarks>
+        /// <exception cref="ArgumentOutOfRangeException">The <paramref name="value"/> is less than or equal to 0.</exception>
+        /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
+        public double VideoMotionRate
+        {
+            get
+            {
+                Native.GetMotionRate(Handle, out var val).ThrowIfError("Failed to get video motion rate.");
+
+                return val;
+            }
+
+            set
+            {
+                ValidateState(RecorderState.Idle, RecorderState.Ready);
+
+                if (value <= 0)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(value), value,
+                        "Video Motion rate can't be less than zero.");
+                }
+
+                Native.SetMotionRate(Handle, value).
+                    ThrowIfError("Failed to set video motion rate");
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the orientation in a video metadata tag.
+        /// </summary>
+        /// <value>A <see cref="Rotation"/> that specifies the type of orientation.</value>
+        /// <exception cref="ArgumentException"><paramref name="value"/> is not valid.</exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
+        public Rotation VideoOrientationTag
+        {
+            get
+            {
+                Native.GetOrientationTag(Handle, out var val).ThrowIfError("Failed to get recorder orientation.");
+
+                return val;
+            }
+
+            set
+            {
+                ValidationUtil.ValidateEnum(typeof(Rotation), value, nameof(value));
+
+                Native.SetOrientationTag(Handle, value).
+                    ThrowIfError("Failed to set recorder orientation");
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the resolution of the video recording.
+        /// </summary>
+        /// <remarks>
+        /// To set, the recorder must be in the <see cref="RecorderState.Idle"/> or <see cref="RecorderState.Ready"/> state.
+        /// </remarks>
+        /// <exception cref="ArgumentOutOfRangeException">
+        ///    Width or height of <paramref name="value"/> is less than or equal to zero.
+        /// </exception>
+        /// <exception cref="NotSupportedException"><paramref name="value"> is not supported.</exception>
+        /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
+        /// <seealso cref="Recorder.GetSupportedVideoResolutions(CameraDevice)"/>
+        public Size VideoResolution
+        {
+            get
+            {
+                Native.GetVideoResolution(Handle, out var width, out var height).
+                    ThrowIfError("Failed to get camera video resolution");
+
+                return new Size(width, height);
+            }
+
+            set
+            {
+                ValidateState(RecorderState.Idle, RecorderState.Ready);
+
+                if (value.Width <= 0 || value.Height <= 0)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(value), value,
+                        "Resolution can't be less than or equal to zero.");
+                }
+
+                var ret = Native.SetVideoResolution(Handle, value.Width, value.Height);
+
+                if (ret == RecorderErrorCode.InvalidParameter)
+                {
+                    throw new NotSupportedException($"Resolution({value.ToString()}) is not supported.");
+                }
+
+                ret.ThrowIfError("Failed to set video resolution.");
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the bitrate of an video encoder in bits per second.
+        /// </summary>
+        /// <remarks>
+        /// To set, the recorder must be in the <see cref="RecorderState.Idle"/> or <see cref="RecorderState.Ready"/> state.
+        /// </remarks>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than or equal to zero.</exception>
+        /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
+        /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
+        public int VideoBitRate
+        {
+            get
+            {
+                Native.GetVideoEncoderBitrate(Handle, out var val).ThrowIfError("Failed to get video bitrate.");
+
+                return val;
+            }
+
+            set
+            {
+                ValidateState(RecorderState.Idle, RecorderState.Ready);
+
+                if (value <= 0)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(value), value,
+                        "Bit rate can't be less than or equal to zero.");
+                }
+
+                Native.SetVideoEncoderBitrate(Handle, value).
+                    ThrowIfError("Failed to set video bitrate");
+            }
+        }
+
+        #endregion
+    }
+}
\ No newline at end of file
index c534d6c..91cf1ee 100644 (file)
@@ -41,7 +41,7 @@ namespace Tizen.Multimedia
         /// <summary>
         /// Occurred when recording is progressing for recording status.
         /// </summary>
-        private EventHandler<RecordingProgressEventArgs> _recordingStatusChanged;
+        private EventHandler<RecordingStatusChangedEventArgs> _recordingStatusChanged;
         private Native.RecordingStatusCallback _recordingStatusCallback;
         /// <summary>
         /// Occurred when recording time or size reach limit.
@@ -144,7 +144,7 @@ namespace Tizen.Multimedia
         /// <summary>
         /// Event that occurs when recording status changed.
         /// </summary>
-        public event EventHandler<RecordingProgressEventArgs> RecordingStatusChanged
+        public event EventHandler<RecordingStatusChangedEventArgs> RecordingStatusChanged
         {
             add
             {
@@ -986,7 +986,7 @@ namespace Tizen.Multimedia
         {
             _recordingStatusCallback = (ulong elapsedTime, ulong fileSize, IntPtr userData) =>
             {
-                RecordingProgressEventArgs eventArgs = new RecordingProgressEventArgs(elapsedTime, fileSize);
+                RecordingStatusChangedEventArgs eventArgs = new RecordingStatusChangedEventArgs((long)elapsedTime, (long)fileSize);
                 _recordingStatusChanged?.Invoke(this, eventArgs);
             };
             int ret = Native.SetStatusChangedCallback(_handle, _recordingStatusCallback, IntPtr.Zero);
diff --git a/src/Tizen.Multimedia/Common.Internal/DependentMediaBuffer.cs b/src/Tizen.Multimedia/Common.Internal/DependentMediaBuffer.cs
new file mode 100644 (file)
index 0000000..855c83d
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Diagnostics;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Represents a buffer that is dependent on the owner object.
+    /// </summary>
+    internal class DependentMediaBuffer : MediaBufferBase
+    {
+        private readonly IBufferOwner _owner;
+
+        internal DependentMediaBuffer(IBufferOwner owner, IntPtr dataHandle, int size)
+            : base(dataHandle, size)
+        {
+            Debug.Assert(owner != null, "Owner is null!");
+            Debug.Assert(!owner.IsDisposed, "Owner has been already disposed!");
+
+            _owner = owner;
+        }
+
+
+        internal override void ValidateBufferReadable()
+        {
+            _owner.ValidateBufferReadable(this);
+        }
+
+        internal override void ValidateBufferWritable()
+        {
+            _owner.ValidateBufferWritable(this);
+        }
+    }
+}
index f779510..6553b3a 100644 (file)
@@ -34,7 +34,7 @@ namespace Tizen.Multimedia
 
     internal static class BufferOwnerExtensions
     {
-        internal static void ValidateBufferReadable(this IBufferOwner bufferOwner, IReadOnlyBuffer buffer)
+        internal static void ValidateBufferReadable(this IBufferOwner bufferOwner, IMediaBuffer buffer)
         {
             if (bufferOwner.IsDisposed)
             {
diff --git a/src/Tizen.Multimedia/Common.Internal/MediaBufferBase.cs b/src/Tizen.Multimedia/Common.Internal/MediaBufferBase.cs
new file mode 100644 (file)
index 0000000..90a8226
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace Tizen.Multimedia
+{
+    internal abstract class MediaBufferBase : IMediaBuffer
+    {
+        private readonly IntPtr _dataHandle;
+
+        public int Length { get; }
+
+        internal MediaBufferBase(IntPtr dataHandle, int size, bool isReadOnly)
+        {
+            Debug.Assert(dataHandle != IntPtr.Zero, "dataHandle is null!");
+            Debug.Assert(size >= 0, "size must not be negative!");
+
+            _dataHandle = dataHandle;
+            Length = size;
+            IsReadOnly = false;
+        }
+
+        internal MediaBufferBase(IntPtr dataHandle, int size) :
+            this(dataHandle, size, false)
+        {
+        }
+
+        internal IntPtr DataHandle => _dataHandle;
+
+        public bool IsReadOnly { get; }
+
+        /// <summary>
+        /// Validates the range
+        /// </summary>
+        /// <param name="offset"></param>
+        /// <param name="length"></param>
+        /// <exception cref="ArgumentOutOfRangeException">
+        ///     offset + length is greater than <see cref="Length"/>.
+        ///     <para>-or-</para>
+        ///     offset or length is less than zero.
+        /// </exception>
+        private void ValidateRange(int offset, int length)
+        {
+            if (offset + length > Length)
+            {
+                throw new ArgumentOutOfRangeException($"{nameof(offset)}, {nameof(length)}",
+                    "offset + length can't be greater than length of the buffer.");
+            }
+            if (length < 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(length), length,
+                    $"Length can't be less than zero.");
+            }
+            if (offset < 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(offset), offset,
+                    $"Offset can't be less than zero.");
+            }
+        }
+
+        public byte this[int index]
+        {
+            get
+            {
+                ThrowIfBufferIsNotReadable();
+
+                if (index < 0 || index >= Length)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(index), index,
+                        $"Valid index range is [0, { nameof(Length) }).");
+                }
+
+                return Marshal.ReadByte(DataHandle, index);
+            }
+            set
+            {
+                ThrowIfBufferIsNotWritable();
+
+                Marshal.WriteByte(DataHandle, index, value);
+            }
+        }
+
+        private void ThrowIfBufferIsNotReadable()
+        {
+            ValidateBufferReadable();
+        }
+
+        private void ThrowIfBufferIsNotWritable()
+        {
+            if (IsReadOnly)
+            {
+                throw new NotSupportedException("The buffer is read-only.");
+            }
+
+            ValidateBufferWritable();
+        }
+
+        internal abstract void ValidateBufferReadable();
+
+        internal abstract void ValidateBufferWritable();
+
+        public void CopyFrom(byte[] source, int startIndex, int length, int offset)
+        {
+            ThrowIfBufferIsNotReadable();
+
+            if (startIndex < 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(startIndex), startIndex,
+                    "startIndex can't be less than zero.");
+            }
+            if (startIndex + length > source.Length)
+            {
+                throw new ArgumentOutOfRangeException($"{nameof(startIndex)}, {nameof(length)}",
+                    "startIndex + length can't be greater than source.Length.");
+            }
+
+            ValidateRange(offset, length);
+
+            Marshal.Copy(source, startIndex, IntPtr.Add(_dataHandle, offset), length);
+        }
+
+        public void CopyFrom(byte[] source, int startIndex, int length)
+        {
+            CopyFrom(source, startIndex, length, 0);
+        }
+
+        public void CopyTo(byte[] dest, int startIndex, int length, int offset)
+        {
+            ThrowIfBufferIsNotWritable();
+
+            if (startIndex < 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(startIndex), startIndex,
+                    "startIndex can't be less than zero.");
+            }
+            if (startIndex + length > dest.Length)
+            {
+                throw new ArgumentOutOfRangeException($"{nameof(startIndex)}, {nameof(length)}",
+                    "startIndex + length can't be greater than source.Length.");
+            }
+
+            ValidateRange(offset, length);
+
+            Marshal.Copy(IntPtr.Add(_dataHandle, offset), dest, startIndex, length);
+        }
+
+        public void CopyTo(byte[] dest, int startIndex, int length)
+        {
+            CopyTo(dest, startIndex, length, 0);
+        }
+    }
+}
diff --git a/src/Tizen.Multimedia/Common.Internal/ScopedMediaBuffer.cs b/src/Tizen.Multimedia/Common.Internal/ScopedMediaBuffer.cs
new file mode 100644 (file)
index 0000000..88d9dde
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Represents a scoped buffer which lives shortly such as a callback.
+    /// </summary>
+    internal class ScopedMediaBuffer : MediaBufferBase, IDisposable
+    {
+        internal ScopedMediaBuffer(IntPtr dataHandle, int size, bool isReadOnly)
+            : base(dataHandle, size, isReadOnly)
+        {
+        }
+
+        internal ScopedMediaBuffer(IntPtr dataHandle, int size)
+            : this(dataHandle, size, false)
+        {
+        }
+
+        internal override void ValidateBufferReadable()
+        {
+            if (_disposed)
+            {
+                throw new InvalidOperationException("The buffer has already been invalidated.");
+            }
+        }
+
+        internal override void ValidateBufferWritable() => ValidateBufferReadable();
+
+        #region IDisposable Support
+        private bool _disposed = false;
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (_disposed == false)
+            {
+                _disposed = true;
+            }
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+        }
+        #endregion
+    }
+}
index f1f3f72..0d34db6 100644 (file)
  */
 
 using System;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
 
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// Provides functionality to read a media buffer.
+    /// Provides functionality to read and write a media buffer.
     /// </summary>
-    public interface IReadOnlyBuffer
+    public interface IMediaBuffer
     {
         /// <summary>
         /// Gets or sets a value at the specified index.
@@ -41,13 +39,17 @@ namespace Tizen.Multimedia
             get;
             set;
         }
+
         /// <summary>
         /// Gets the size of the buffer, in bytes.
         /// </summary>
-        int Length
-        {
-            get;
-        }
+        int Length { get; }
+
+        /// <summary>
+        /// Gets the value indicating whether the <see cref="IMediaBuffer"/> is read-only.
+        /// </summary>
+        /// <value> true if the <see cref="IMediaBuffer"/> is read-only; otherwise, false.
+        bool IsReadOnly { get; }
 
         /// <summary>
         /// Copies data from a byte array to the buffer.
@@ -69,13 +71,7 @@ namespace Tizen.Multimedia
         /// <exception cref="ArgumentOutOfRangeException">startIndex, offset or length is not valid.</exception>
         /// <exception cref="ObjectDisposedException">The object that owns the current buffer already has been disposed of.</exception>
         void CopyTo(byte[] dest, int startIndex, int length, int offset);
-    }
 
-    /// <summary>
-    /// Provides functionality to read and write a media buffer.
-    /// </summary>
-    public interface IMediaBuffer : IReadOnlyBuffer
-    {
         /// <summary>
         /// Copies data from the buffer to a byte array.
         /// </summary>
@@ -100,120 +96,4 @@ namespace Tizen.Multimedia
         /// <exception cref="InvalidOperationException">The buffer is not available. i.e. not writable state.</exception>
         void CopyFrom(byte[] source, int startIndex, int length, int offset);
     }
-
-    /// <summary>
-    /// Represents a buffer for a <see cref="MediaPacket"/>.
-    /// </summary>
-    internal class DependentMediaBuffer : IMediaBuffer
-    {
-        private readonly IBufferOwner _owner;
-        private readonly IntPtr _dataHandle;
-
-        internal DependentMediaBuffer(IBufferOwner owner, IntPtr dataHandle, int size)
-        {
-            Debug.Assert(owner != null, "Owner is null!");
-            Debug.Assert(!owner.IsDisposed, "Owner has been already disposed!");
-            Debug.Assert(dataHandle != IntPtr.Zero, "dataHandle is null!");
-            Debug.Assert(size >= 0, "size must not be negative!");
-
-            _owner = owner;
-            _dataHandle = dataHandle;
-            Length = size;
-        }
-
-        public byte this[int index]
-        {
-            get
-            {
-                _owner.ValidateBufferReadable(this);
-
-                if (index < 0 || index >= Length)
-                {
-                    throw new ArgumentOutOfRangeException($"Valid index range is [0, { nameof(Length) }).");
-                }
-
-                return Marshal.ReadByte(_dataHandle, index);
-            }
-            set
-            {
-                _owner.ValidateBufferWritable(this);
-
-                Marshal.WriteByte(_dataHandle, index, value);
-            }
-        }
-
-        /// <summary>
-        /// Validates the range
-        /// </summary>
-        /// <param name="offset"></param>
-        /// <param name="length"></param>
-        /// <exception cref="ArgumentOutOfRangeException">
-        ///     offset + length is greater than <see cref="Length"/>.\n
-        ///     -or-\n
-        ///     offset or length is less than zero.
-        /// </exception>
-        private void ValidateRange(int offset, int length)
-        {
-            if (offset + length > Length)
-            {
-                throw new ArgumentOutOfRangeException("offset + length can't be greater than length of the buffer.");
-            }
-            if (length < 0)
-            {
-                throw new ArgumentOutOfRangeException($"Length can't be less than zero : { length }.");
-            }
-            if (offset < 0)
-            {
-                throw new ArgumentOutOfRangeException($"Offset can't be less than zero : { offset }.");
-            }
-        }
-
-        public void CopyFrom(byte[] source, int startIndex, int length, int offset)
-        {
-            _owner.ValidateBufferReadable(this);
-
-            if (startIndex < 0)
-            {
-                throw new ArgumentOutOfRangeException("startIndex can't be less than zero.");
-            }
-            if (startIndex + length > source.Length)
-            {
-                throw new ArgumentOutOfRangeException("startIndex + length can't be greater than source.Length.");
-            }
-
-            ValidateRange(offset, length);
-
-            Marshal.Copy(source, startIndex, IntPtr.Add(_dataHandle, offset), length);
-        }
-
-        public void CopyFrom(byte[] source, int startIndex, int length)
-        {
-            CopyFrom(source, startIndex, length, 0);
-        }
-
-        public void CopyTo(byte[] dest, int startIndex, int length, int offset)
-        {
-            _owner.ValidateBufferWritable(this);
-
-            if (startIndex < 0)
-            {
-                throw new ArgumentOutOfRangeException("Start index can't be less than zero.");
-            }
-            if (startIndex + length > dest.Length)
-            {
-                throw new ArgumentOutOfRangeException("startIndex + length can't be greater than dest.Length.");
-            }
-
-            ValidateRange(offset, length);
-
-            Marshal.Copy(IntPtr.Add(_dataHandle, offset), dest, startIndex, length);
-        }
-
-        public void CopyTo(byte[] dest, int startIndex, int length)
-        {
-            CopyTo(dest, startIndex, length, 0);
-        }
-
-        public int Length { get; }
-    }
 }