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));
}
}
--- /dev/null
+/*
+ * 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
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);
}
}
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
--- /dev/null
+/*
+ * 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
+++ /dev/null
-/*
- * 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; }
- }
-}
--- /dev/null
+/*
+ * 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; }
+ }
+}
*/
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; }
}
}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
+ }
+}
--- /dev/null
+/*
+ * 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
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;
}
#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
}
}
--- /dev/null
+/*
+ * 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
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; }
}
}
* 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>
}
/// <summary>
- /// Enumeration for Audio capture devices.
+ /// Specifies audio capture devices for <see cref="Recorder"/>.
/// </summary>
- /// <since_tizen> 3 </since_tizen>
public enum RecorderAudioDevice
{
/// <summary>
}
/// <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>
}
/// <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>
}
/// <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.
}
/// <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>
}
/// <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
--- /dev/null
+/*
+ * 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()}.");
+ }
+ }
+ }
+}
+++ /dev/null
-/*
- * 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());
- }
- }
- }
-}
--- /dev/null
+/*
+ * 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
+++ /dev/null
-/*
- * 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
*/
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; }
}
}
--- /dev/null
+/*
+ * 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; }
+ }
+}
+++ /dev/null
-/*
- * 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
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; }
}
}
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; }
}
}
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; }
}
}
--- /dev/null
+/*
+ * 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; }
+ }
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
/// <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.
/// <summary>
/// Event that occurs when recording status changed.
/// </summary>
- public event EventHandler<RecordingProgressEventArgs> RecordingStatusChanged
+ public event EventHandler<RecordingStatusChangedEventArgs> RecordingStatusChanged
{
add
{
{
_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);
--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
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)
{
--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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
+ }
+}
*/
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.
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.
/// <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>
/// <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; }
- }
}