From 8d39fc14c128834634d021cb6b37c0b1ed65da1f Mon Sep 17 00:00:00 2001 From: coderhyme Date: Fri, 14 Apr 2017 15:15:10 +0900 Subject: [PATCH] [Radio] Rename apis and update docs. Change-Id: I9c35abd031fc039bf68505e3e675007914f07576 Signed-off-by: coderhyme --- packaging/csapi-multimedia.spec | 4 +- .../Interop/Interop.ErrorCode.cs | 109 -------- .../Interop/Interop.Radio.cs | 263 +++++------------- .../Interop/Interop.SafeMultimediaHandle.cs | 82 ------ src/Tizen.Multimedia.Radio/Radio/Radio.cs | 303 ++++++++++++--------- src/Tizen.Multimedia.Radio/Radio/RadioError.cs | 69 +++++ .../Radio/RadioInterruptedEventArgs.cs | 13 +- .../Radio/RadioInterruptedReason.cs | 9 +- src/Tizen.Multimedia.Radio/Radio/RadioState.cs | 16 +- .../Radio/ScanUpdatedEventArgs.cs | 12 +- .../Tizen.Multimedia.Radio.csproj | 4 + .../Tizen.Multimedia.Radio.nuspec | 1 + src/Tizen.Multimedia/Tizen.Multimedia.csproj | 2 +- 13 files changed, 353 insertions(+), 534 deletions(-) delete mode 100644 src/Tizen.Multimedia.Radio/Interop/Interop.ErrorCode.cs delete mode 100644 src/Tizen.Multimedia.Radio/Interop/Interop.SafeMultimediaHandle.cs create mode 100644 src/Tizen.Multimedia.Radio/Radio/RadioError.cs diff --git a/packaging/csapi-multimedia.spec b/packaging/csapi-multimedia.spec index 5d51eda..3f02b33 100755 --- a/packaging/csapi-multimedia.spec +++ b/packaging/csapi-multimedia.spec @@ -1,6 +1,6 @@ Name: csapi-multimedia Summary: Tizen Multimedia API for C# -Version: 1.1.1 +Version: 1.1.2 Release: 0 Group: Development/Libraries License: Apache-2.0 @@ -26,7 +26,7 @@ BuildRequires: csapi-information-nuget Tizen.Multimedia.MediaCodec 1.0.0 \ Tizen.Multimedia.MediaPlayer 1.0.0 \ Tizen.Multimedia.Metadata 1.0.0 \ - Tizen.Multimedia.Radio 1.0.0 \ + Tizen.Multimedia.Radio 1.0.1 \ Tizen.Multimedia.Recorder 1.0.0 \ Tizen.Multimedia.StreamRecorder 1.0.0 \ Tizen.Multimedia.Remoting 1.0.0 \ diff --git a/src/Tizen.Multimedia.Radio/Interop/Interop.ErrorCode.cs b/src/Tizen.Multimedia.Radio/Interop/Interop.ErrorCode.cs deleted file mode 100644 index f3d3235..0000000 --- a/src/Tizen.Multimedia.Radio/Interop/Interop.ErrorCode.cs +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.IO; -using System.Runtime.CompilerServices; -using Tizen; - -namespace Tizen.Multimedia -{ - internal static partial class Interop - { - internal enum ErrorCode - { - None = Tizen.Internals.Errors.ErrorCode.None, - OutOfMemory = Tizen.Internals.Errors.ErrorCode.OutOfMemory, - InvalidParameter = Tizen.Internals.Errors.ErrorCode.InvalidParameter, - InvalidOperation = Tizen.Internals.Errors.ErrorCode.InvalidOperation, - PermissionDenied = Tizen.Internals.Errors.ErrorCode.PermissionDenied, - NotSupported = Tizen.Internals.Errors.ErrorCode.NotSupported, - ResourceBusy = Tizen.Internals.Errors.ErrorCode.ResourceBusy, - NoSuchFile = Tizen.Internals.Errors.ErrorCode.NoSuchFile, - - // Radio - InvalidState = -0x019A0000 | 0x01, // RADIO_ERROR_INVALID_STATE - SoundPolicy = -0x019A0000 | 0x02, // RADIO_ERROR_SOUND_POLICY - NoAntenna = -0x019A0000 | 0x03, // RADIO_ERROR_NO_ANTENNA - - // Image/ Video Utility - NotSupportedFormat = -0x01980000 | 0x01, // VIDEO_UTIL_ERROR_NOT_SUPPORTED_FORMAT - } - } - - internal static class ErrorCodeExtensions - { - private const string LogTag = "Tizen.Multimedia"; - - internal static bool IsSuccess(this Interop.ErrorCode err) - { - return err == Interop.ErrorCode.None; - } - - internal static bool IsFailed(this Interop.ErrorCode err) - { - return !err.IsSuccess(); - } - - /// - /// Utility method to check for error, returns false if failed and print warning messages - /// - /// true in case of no error, false otherwise - internal static bool WarnIfFailed(this Interop.ErrorCode err, string msg, [CallerFilePath] string file = "", [CallerMemberName] string func = "", [CallerLineNumber] int line = 0) - { - if (err.IsFailed()) - { - Log.Debug(LogTag, $"{msg}, err: {err.ToString()}", file, func, line); - return false; - } - return true; - } - - /// - /// Utility method to check for error, returns false if failed and throw exception - /// - /// true in case of no error - internal static bool ThrowIfFailed(this Interop.ErrorCode err, string msg, [CallerFilePath] string file = "", [CallerMemberName] string func = "", [CallerLineNumber] int line = 0) - { - if (err.IsFailed()) - { - Log.Error(LogTag, $"{msg}, err: {err.ToString()}", file, func, line); - throw err.GetException(msg); - } - return true; - } - - internal static Exception GetException(this Interop.ErrorCode err, string message) - { - string errMessage = $"{message}, err: {err.ToString()}"; - switch (err) - { - //case ErrorCode.None: - case Interop.ErrorCode.PermissionDenied: return new UnauthorizedAccessException(errMessage); - case Interop.ErrorCode.InvalidParameter: return new ArgumentException(errMessage); - case Interop.ErrorCode.NoSuchFile: return new FileNotFoundException(errMessage); - case Interop.ErrorCode.OutOfMemory: return new OutOfMemoryException(errMessage); - case Interop.ErrorCode.NoAntenna: - case Interop.ErrorCode.NotSupported: return new NotSupportedException(errMessage); - case Interop.ErrorCode.InvalidOperation: - case Interop.ErrorCode.InvalidState: - case Interop.ErrorCode.SoundPolicy: - case Interop.ErrorCode.ResourceBusy: - default: return new InvalidOperationException(errMessage); - } - } - } -} \ No newline at end of file diff --git a/src/Tizen.Multimedia.Radio/Interop/Interop.Radio.cs b/src/Tizen.Multimedia.Radio/Interop/Interop.Radio.cs index d8242ef..929324b 100644 --- a/src/Tizen.Multimedia.Radio/Interop/Interop.Radio.cs +++ b/src/Tizen.Multimedia.Radio/Interop/Interop.Radio.cs @@ -21,234 +21,115 @@ namespace Tizen.Multimedia { internal static partial class Interop { - internal enum RadioState - { - Ready, // RADIO_STATE_READY - Playing, // RADIO_STATE_PLAYING - Scanning, // RADIO_STATE_SCANNING - } - - internal enum RadioInterruptedReason - { - Completed, // RADIO_INTERRUPTED_COMPLETED - Media, // RADIO_INTERRUPTED_BY_MEDIA - Call, // RADIO_INTERRUPTED_BY_CALL - EarjackUnplug, // RADIO_INTERRUPTED_BY_EARJACK_UNPLUG - ResourceConflict, // RADIO_INTERRUPTED_BY_RESOURCE_CONFLICT - Alarm, // RADIO_INTERRUPTED_BY_ALARM - Emergency, // RADIO_INTERRUPTED_BY_EMERGENCY - ResumableMedia, // RADIO_INTERRUPTED_BY_RESUMABLE_MEDIA - Notification, // RADIO_INTERRUPTED_BY_NOTIFICATION - } - - [DllImport(Libraries.Radio, EntryPoint = "radio_get_state")] - internal static extern ErrorCode GetState(this RadioHandle /* radio_h */ radio, out RadioState /* radio_state_e */ state); - - [DllImport(Libraries.Radio, EntryPoint = "radio_start")] - internal static extern ErrorCode Start(this RadioHandle /* radio_h */ radio); - - [DllImport(Libraries.Radio, EntryPoint = "radio_stop")] - internal static extern ErrorCode Stop(this RadioHandle /* radio_h */ radio); - - [DllImport(Libraries.Radio, EntryPoint = "radio_seek_up")] - internal static extern ErrorCode SeekUp(this RadioHandle /* radio_h */ radio, RadioHandle.SeekCompletedCallback callback, IntPtr /* void */ userData); - - [DllImport(Libraries.Radio, EntryPoint = "radio_seek_down")] - internal static extern ErrorCode SeekDown(this RadioHandle /* radio_h */ radio, RadioHandle.SeekCompletedCallback callback, IntPtr /* void */ userData); - - [DllImport(Libraries.Radio, EntryPoint = "radio_set_frequency")] - internal static extern ErrorCode SetFrequency(this RadioHandle /* radio_h */ radio, int frequency); - - [DllImport(Libraries.Radio, EntryPoint = "radio_get_frequency")] - internal static extern ErrorCode GetFrequency(this RadioHandle /* radio_h */ radio, out int frequency); - - [DllImport(Libraries.Radio, EntryPoint = "radio_get_signal_strength")] - internal static extern ErrorCode GetSignalStrength(this RadioHandle /* radio_h */ radio, out int strength); - - [DllImport(Libraries.Radio, EntryPoint = "radio_scan_start")] - internal static extern ErrorCode ScanStart(this RadioHandle /* radio_h */ radio, RadioHandle.ScanUpdatedCallback callback, IntPtr /* void */ userData); - - [DllImport(Libraries.Radio, EntryPoint = "radio_scan_stop")] - internal static extern ErrorCode ScanStop(this RadioHandle /* radio_h */ radio, RadioHandle.ScanStoppedCallback callback, IntPtr /* void */ userData); - - [DllImport(Libraries.Radio, EntryPoint = "radio_set_mute")] - internal static extern ErrorCode SetMute(this RadioHandle /* radio_h */ radio, bool muted); - - [DllImport(Libraries.Radio, EntryPoint = "radio_is_muted")] - internal static extern ErrorCode GetMuted(this RadioHandle /* radio_h */ radio, out bool muted); - - [DllImport(Libraries.Radio, EntryPoint = "radio_set_scan_completed_cb")] - internal static extern ErrorCode SetScanCompletedCb(this RadioHandle /* radio_h */ radio, RadioHandle.ScanCompletedCallback callback, IntPtr /* void */ userData); - - [DllImport(Libraries.Radio, EntryPoint = "radio_unset_scan_completed_cb")] - internal static extern ErrorCode UnsetScanCompletedCb(this RadioHandle /* radio_h */ radio); - - [DllImport(Libraries.Radio, EntryPoint = "radio_set_interrupted_cb")] - internal static extern ErrorCode SetInterruptedCb(this RadioHandle /* radio_h */ radio, RadioHandle.InterruptedCallback callback, IntPtr /* void */ userData); - - [DllImport(Libraries.Radio, EntryPoint = "radio_unset_interrupted_cb")] - internal static extern ErrorCode UnsetInterruptedCb(this RadioHandle /* radio_h */ radio); - - [DllImport(Libraries.Radio, EntryPoint = "radio_get_frequency_range")] - internal static extern ErrorCode GetFrequencyRange(this RadioHandle /* radio_h */ radio, out int minFreq, out int maxFreq); - - [DllImport(Libraries.Radio, EntryPoint = "radio_get_channel_spacing")] - internal static extern ErrorCode GetChannelSpacing(this RadioHandle /* radio_h */ radio, out int channelSpacing); - - [DllImport(Libraries.Radio, EntryPoint = "radio_set_volume")] - internal static extern ErrorCode SetVolume(this RadioHandle /* radio_h */ radio, float volume); - - [DllImport(Libraries.Radio, EntryPoint = "radio_get_volume")] - internal static extern ErrorCode GetVolume(this RadioHandle /* radio_h */ radio, out float volume); - - internal struct RadioFrequencyRange - { - public int minFreq; - public int maxFreq; - } - - internal class RadioHandle : SafeMultimediaHandle + internal static class Radio { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - internal delegate void SeekCompletedCallback(int frequency, IntPtr /* void */ userData); + internal delegate void SeekCompletedCallback(int frequency, IntPtr userData); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - internal delegate void ScanUpdatedCallback(int frequency, IntPtr /* void */ userData); + internal delegate void ScanUpdatedCallback(int frequency, IntPtr userData); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - internal delegate void ScanStoppedCallback(IntPtr /* void */ userData); + internal delegate void ScanStoppedCallback(IntPtr userData); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - internal delegate void ScanCompletedCallback(IntPtr /* void */ userData); + internal delegate void ScanCompletedCallback(IntPtr userData); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - internal delegate void InterruptedCallback(RadioInterruptedReason /* radio_interrupted_code_e */ code, IntPtr /* void */ userData); + internal delegate void InterruptedCallback(RadioInterruptedReason reason, IntPtr userData); + [DllImport(Libraries.Radio, EntryPoint = "radio_create")] - internal static extern ErrorCode Create(out IntPtr /* radio_h */ radio); + internal static extern RadioError Create(out RadioHandle radio); [DllImport(Libraries.Radio, EntryPoint = "radio_destroy")] - internal static extern ErrorCode Destroy(IntPtr /* radio_h */ radio); + internal static extern RadioError Destroy(IntPtr radio); - internal RadioHandle(IntPtr handle, bool needToRelease) : base(handle, needToRelease) - { - } + [DllImport(Libraries.Radio, EntryPoint = "radio_get_state")] + internal static extern RadioError GetState(RadioHandle radio, out RadioState state); - internal RadioHandle() : this(CreateNativeHandle(), true) - { - } + [DllImport(Libraries.Radio, EntryPoint = "radio_start")] + internal static extern RadioError Start(RadioHandle radio); - internal static IntPtr CreateNativeHandle() - { - IntPtr handle; - Create(out handle).ThrowIfFailed("Failed to create native handle"); - return handle; - } + [DllImport(Libraries.Radio, EntryPoint = "radio_stop")] + internal static extern RadioError Stop(RadioHandle radio); - internal override ErrorCode DisposeNativeHandle() - { - return Destroy(handle); - } + [DllImport(Libraries.Radio, EntryPoint = "radio_seek_up")] + internal static extern RadioError SeekUp(RadioHandle radio, SeekCompletedCallback callback, + IntPtr userData = default(IntPtr)); - internal RadioState State - { - get { return NativeGet(this.GetState); } - } + [DllImport(Libraries.Radio, EntryPoint = "radio_seek_down")] + internal static extern RadioError SeekDown(RadioHandle radio, SeekCompletedCallback callback, + IntPtr userData = default(IntPtr)); - internal int Frequency - { - get { return NativeGet(this.GetFrequency); } - set { NativeSet(this.SetFrequency, value); } - } + [DllImport(Libraries.Radio, EntryPoint = "radio_set_frequency")] + internal static extern RadioError SetFrequency(RadioHandle radio, int frequency); - internal int SignalStrength - { - get { return NativeGet(this.GetSignalStrength); } - } + [DllImport(Libraries.Radio, EntryPoint = "radio_get_frequency")] + internal static extern RadioError GetFrequency(RadioHandle radio, out int frequency); - internal bool IsMuted - { - get { return NativeGet(this.GetMuted); } - set { NativeSet(this.SetMute, value); } - } + [DllImport(Libraries.Radio, EntryPoint = "radio_get_signal_strength")] + internal static extern RadioError GetSignalStrength(RadioHandle radio, out int strength); - internal int ChannelSpacing - { - get { return NativeGet(this.GetChannelSpacing); } - } + [DllImport(Libraries.Radio, EntryPoint = "radio_scan_start")] + internal static extern RadioError ScanStart(RadioHandle radio, ScanUpdatedCallback callback, + IntPtr userData = default(IntPtr)); - internal float Volume - { - get { return NativeGet(this.GetVolume); } - set { NativeSet(this.SetVolume, value); } - } + [DllImport(Libraries.Radio, EntryPoint = "radio_scan_stop")] + internal static extern RadioError ScanStop(RadioHandle radio, ScanStoppedCallback callback, + IntPtr userData = default(IntPtr)); - internal int MinimumFrequency - { - get - { - RadioFrequencyRange range; - this.GetFrequencyRange(out range.minFreq, out range.maxFreq); - return range.minFreq; - } - } + [DllImport(Libraries.Radio, EntryPoint = "radio_set_mute")] + internal static extern RadioError SetMute(RadioHandle radio, bool muted); - internal int MaximumFrequency - { - get - { - RadioFrequencyRange range; - this.GetFrequencyRange(out range.minFreq, out range.maxFreq); - return range.maxFreq; - } - } + [DllImport(Libraries.Radio, EntryPoint = "radio_is_muted")] + internal static extern RadioError GetMuted(RadioHandle radio, out bool muted); - internal ScanCompletedCallback ScanCompleteCb - { - set - { - var err = (value != null) ? this.SetScanCompletedCb(value, IntPtr.Zero) : this.UnsetScanCompletedCb(); - err.ThrowIfFailed("Failed to set/ unset scan complete callback"); - } - } + [DllImport(Libraries.Radio, EntryPoint = "radio_set_scan_completed_cb")] + internal static extern RadioError SetScanCompletedCb(RadioHandle radio, + ScanCompletedCallback callback, IntPtr userData = default(IntPtr)); - internal InterruptedCallback InteruptedCb - { - set - { - var err = (value != null) ? this.SetInterruptedCb(value, IntPtr.Zero) : this.UnsetInterruptedCb(); - err.ThrowIfFailed("Failed to set/ unset interrupted callback"); - } - } + [DllImport(Libraries.Radio, EntryPoint = "radio_unset_scan_completed_cb")] + internal static extern RadioError UnsetScanCompletedCb(RadioHandle radio); - internal void StartPlayback() - { - this.Start().ThrowIfFailed("Failed to start radio"); - } + [DllImport(Libraries.Radio, EntryPoint = "radio_set_interrupted_cb")] + internal static extern RadioError SetInterruptedCb(RadioHandle radio, + InterruptedCallback callback, IntPtr userData = default(IntPtr)); - internal void StopPlayback() - { - this.Stop().ThrowIfFailed("Failed to stop radio"); - } + [DllImport(Libraries.Radio, EntryPoint = "radio_unset_interrupted_cb")] + internal static extern RadioError UnsetInterruptedCb(RadioHandle radio); - internal void StartScan(ScanUpdatedCallback callback) - { - this.ScanStart(callback, IntPtr.Zero).ThrowIfFailed("Failed to start radio"); - } + [DllImport(Libraries.Radio, EntryPoint = "radio_get_frequency_range")] + internal static extern RadioError GetFrequencyRange(RadioHandle radio, out int minFreq, out int maxFreq); - internal void StopScan(ScanStoppedCallback callback) - { - this.ScanStop(callback, IntPtr.Zero).ThrowIfFailed("Failed to stop radio"); - } + [DllImport(Libraries.Radio, EntryPoint = "radio_get_channel_spacing")] + internal static extern RadioError GetChannelSpacing(RadioHandle radio, out int channelSpacing); + + [DllImport(Libraries.Radio, EntryPoint = "radio_set_volume")] + internal static extern RadioError SetVolume(RadioHandle radio, float volume); + + [DllImport(Libraries.Radio, EntryPoint = "radio_get_volume")] + internal static extern RadioError GetVolume(RadioHandle radio, out float volume); + } - internal void SeekUp(SeekCompletedCallback callback) + internal class RadioHandle : SafeHandle + { + protected RadioHandle() : base(IntPtr.Zero, true) { - this.SeekUp(callback, IntPtr.Zero).ThrowIfFailed("Failed to start radio"); } - internal void SeekDown(SeekCompletedCallback callback) + public override bool IsInvalid => handle == IntPtr.Zero; + + protected override bool ReleaseHandle() { - this.SeekDown(callback, IntPtr.Zero).ThrowIfFailed("Failed to stop radio"); + var ret = Radio.Destroy(handle); + if (ret != RadioError.None) + { + Log.Debug(GetType().FullName, $"Failed to release native handle."); + return false; + } + + return true; } } } diff --git a/src/Tizen.Multimedia.Radio/Interop/Interop.SafeMultimediaHandle.cs b/src/Tizen.Multimedia.Radio/Interop/Interop.SafeMultimediaHandle.cs deleted file mode 100644 index 14964b1..0000000 --- a/src/Tizen.Multimedia.Radio/Interop/Interop.SafeMultimediaHandle.cs +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Threading.Tasks; - -namespace Tizen.Multimedia -{ - internal static partial class Interop - { - internal static Task PinnedTask(TaskCompletionSource tcs) - { - var gch = GCHandle.Alloc(tcs); - return tcs.Task.ContinueWith( - t => { gch.Free(); return t; }, - TaskContinuationOptions.ExecuteSynchronously).Unwrap(); - } - - internal abstract class SafeMultimediaHandle : SafeHandle - { - internal delegate ErrorCode GetterMethod(out TProp value); - internal delegate ErrorCode SetterMethod(TProp value); - - protected SafeMultimediaHandle(IntPtr handle, bool needToRelease) : base(handle, true) - { - Debug.Assert(handle != IntPtr.Zero); - HasOwnership = needToRelease; - } - - internal bool HasOwnership { get; set; } - public override bool IsInvalid { get { return handle == IntPtr.Zero; } } - - internal abstract ErrorCode DisposeNativeHandle(); - - internal TProp NativeGet(GetterMethod getter, [CallerMemberName] string propertyName = "") - { - TProp value; getter(out value).ThrowIfFailed($"Failed to get {propertyName}"); - return value; - } - - internal string NativeGet(GetterMethod getter, [CallerMemberName] string propertyName = "") - { - string value; getter(out value).ThrowIfFailed($"Failed to get {propertyName}"); - return value; - } - - internal void NativeSet(SetterMethod setter, TProp value, [CallerMemberName] string propertyName = "") - { - setter(value).ThrowIfFailed($"Failed to set {propertyName}"); - } - - protected override bool ReleaseHandle() - { - var err = ErrorCode.None; - if (HasOwnership) - { - err = DisposeNativeHandle(); - err.WarnIfFailed($"Failed to delete native {GetType()} handle"); - } - - SetHandle(IntPtr.Zero); - return err.IsSuccess(); - } - } - } -} \ No newline at end of file diff --git a/src/Tizen.Multimedia.Radio/Radio/Radio.cs b/src/Tizen.Multimedia.Radio/Radio/Radio.cs index f634861..a732eb2 100644 --- a/src/Tizen.Multimedia.Radio/Radio/Radio.cs +++ b/src/Tizen.Multimedia.Radio/Radio/Radio.cs @@ -15,260 +15,305 @@ */ using System; -using System.Runtime.CompilerServices; +using System.Linq; using System.Threading.Tasks; using Tizen.System; +using static Tizen.Multimedia.Interop.Radio; namespace Tizen.Multimedia { /// - /// Radio class, provides support for using the Radio feature + /// Provides means for using the radio feature. /// public class Radio : IDisposable { - internal Interop.RadioHandle _handle; + private Interop.RadioHandle _handle; private const string FeatureFmRadio = "http://tizen.org/feature/fmradio"; /// - /// Radio constructor + /// Initialize a new instance of the Radio class. /// - /// http://tizen.org/feature/fmradio - /// - /// This is thrown if Radio feature is not supported - /// + /// Radio feature is not supported public Radio() { ValidateFeatureSupported(FeatureFmRadio); - _handle = new Interop.RadioHandle(); - _handle.ScanCompleteCb = ScanCompleteCallback; - _handle.InteruptedCb = PlaybackIntruptedCallback; + + Create(out _handle); + + try + { + SetScanCompletedCb(_handle, ScanCompleteCallback).ThrowIfFailed("Failed to initialize radio"); + SetInterruptedCb(_handle, IntruptedCallback).ThrowIfFailed("Failed to initialize radio"); + } + catch (Exception) + { + _handle.Dispose(); + throw; + } + } + + private Interop.RadioHandle Handle + { + get + { + if (_disposed) + { + throw new ObjectDisposedException(GetType().Name); + } + return _handle; + } } /// - /// Scan update event, to be triggered when radio scan information is updated + /// Occurs when radio scan information is updated. /// - public event EventHandler ScanInformationUpdated; + public event EventHandler ScanUpdated; /// - /// Scan stopped event, to be triggered when radio scanning stops + /// Occurs when radio scanning stops. /// public event EventHandler ScanStopped; /// - /// Scan complete event, to be triggered when radio scan is completed + /// Occurs when radio scan is completed. /// public event EventHandler ScanCompleted; /// - /// Playback interrupted event, to be triggered when radio playback is interrupted + /// Occurs when radio is interrupted /// - public event EventHandler PlaybackInterrupted; + public event EventHandler Interrupted; /// - /// Current state for the radio + /// Gets the current state of the radio. /// public RadioState State { get { - ValidateObjectNotDisposed(); - return (RadioState)_handle.State; + RadioState state; + GetState(Handle, out state); + return state; } } /// - /// Current radio frequency, in [87500 ~ 108000] (kHz) range + /// Gets or sets the radio frequency, in [87500 ~ 108000] (kHz). /// - /// This is thrown if value passed to setter in not in valid range + /// + /// is less than of .\n + /// - or - \n + /// is greater than of .\n + /// public int Frequency { get { - ValidateObjectNotDisposed(); - return _handle.Frequency; + int value = 0; + GetFrequency(Handle, out value).ThrowIfFailed("Failed to get frequency"); + return value; } set { - ValidateObjectNotDisposed(); - ValidateInputRangeForPropertySetter(value, 87500, 108000); - _handle.Frequency = value; + if (value < FrequencyRange.Min || value > FrequencyRange.Max) + { + throw new ArgumentOutOfRangeException(nameof(Frequency), value, "Frequency must be within FrequencyRange."); + } + + SetFrequency(Handle, value).ThrowIfFailed("Failed to set frequency"); } } /// - /// Current signal strength, in [-128 ~ 128] (dBm) range + /// Gets the current signal strength, in [-128 ~ 128] (dBm). /// public int SignalStrength { get { - ValidateObjectNotDisposed(); - return _handle.SignalStrength; + int value = 0; + GetSignalStrength(Handle, out value).ThrowIfFailed("Failed to get signal strength"); + return value; } } /// - /// Indicates if radio is muted. By default radio is not muted. + /// Gets the value indicating if radio is muted. /// + /// + /// true if the radio is muted; otherwise, false. + /// The default is false. + /// public bool IsMuted { get { - ValidateObjectNotDisposed(); - return _handle.IsMuted; + bool value; + GetMuted(Handle, out value).ThrowIfFailed("Failed to get the mute state"); + return value; } set { - ValidateObjectNotDisposed(); - _handle.IsMuted = value; + SetMute(Handle, value).ThrowIfFailed("Failed to set the mute state"); } } /// - /// Channel spacing for current region + /// Gets the channel spacing for current region. /// public int ChannelSpacing { get { - ValidateObjectNotDisposed(); - return _handle.ChannelSpacing; + int value; + GetChannelSpacing(Handle, out value).ThrowIfFailed("Failed to get channel spacing"); + return value; } } /// - /// Current radio volume level, in [0.0 ~ 1.0](1.0 = 100%) range. - /// Default value for volume is 1.0. + /// Gets or sets the radio volume level. /// - /// This is thrown if value passed to setter in not in valid range + /// Valid volume range is from 0 to 1.0(100%), inclusive. + /// The default is 1.0. + /// + /// is less than zero.\n + /// - or -\n + /// is greater than 1.0. + /// public float Volume { get { - ValidateObjectNotDisposed(); - return _handle.Volume; + float value; + GetVolume(Handle, out value).ThrowIfFailed("Failed to get volume level."); + return value; } set { - ValidateObjectNotDisposed(); - ValidateInputRangeForPropertySetter(value, 0.0, 1.0); - _handle.Volume = value; - } - } + if (value < 0F || 1.0F < value) + { + throw new ArgumentOutOfRangeException(nameof(value), value, + $"Valid volume range is 0 <= value <= 1.0, but got { value }."); + } - /// - /// Minimum frequency for the region, in [87500 ~ 108000] (kHz) range - /// - public int MinimumFrequency - { - get - { - ValidateObjectNotDisposed(); - return _handle.MinimumFrequency; + SetVolume(Handle, value).ThrowIfFailed("Failed to set volume level"); } } /// - /// Maximum frequency for the region, in [87500 ~ 108000] (kHz) range + /// Gets the frequency for the region, in [87500 ~ 108000] (kHz). /// - public int MaximumFrequency + public Range FrequencyRange { get { - ValidateObjectNotDisposed(); - return _handle.MaximumFrequency; + int min, max; + + GetFrequencyRange(Handle, out min, out max).ThrowIfFailed("Failed to get frequency range"); + + return new Range(min, max); } } /// - /// Starts radio playback + /// Starts the radio. /// - /// This method can be called if Radio is in Ready state. This method will move Radio to Playing state - /// This is thrown if Radio is not in Ready state - public void StartPlayback() + /// The radio must be in the state. + /// The radio is not in the valid state. + public void Start() { - ValidateObjectNotDisposed(); - ValidateRadioState(() => State == RadioState.Ready); - _handle.StartPlayback(); + ValidateRadioState(RadioState.Ready); + + Interop.Radio.Start(Handle).ThrowIfFailed("Failed to start radio"); } /// - /// Stops radio playback + /// Stops the radio. /// - /// This method can be called if Radio is in Playing state. This method will move Radio to Ready state - /// This is thrown if Radio is not in Playing state - public void StopPlayback() + /// The radio must be in the state. + /// The radio is not in the valid state. + public void Stop() { - ValidateObjectNotDisposed(); - ValidateRadioState(() => State == RadioState.Playing); - _handle.StopPlayback(); + ValidateRadioState(RadioState.Playing); + + Interop.Radio.Stop(Handle).ThrowIfFailed("Failed to stop radio"); } /// /// Starts radio scan, will trigger ScanInformationUpdated event, when scan information is updated /// - /// This method should not be called if Radio is in Scanning state. This method will move Radio to Scanning state - /// This is thrown if Radio is already in Scanning state + /// The radio must be in the or state. + /// The radio is not in the valid state. + /// + /// public void StartScan() { - ValidateObjectNotDisposed(); - ValidateRadioState(() => State != RadioState.Scanning); - _handle.StartScan(ScanUpdateCallback); + ValidateRadioState(RadioState.Ready, RadioState.Playing); + + ScanStart(Handle, ScanUpdatedCallback); } /// - /// Stops radio scan, will trigger ScanStopped event, once complete + /// Stops radio scan. /// - /// This method should be called only if Radio is in Scanning state - /// This is thrown if Radio is not in Scanning state + /// The radio must be in the state. + /// The radio is not in the valid state. + /// public void StopScan() { - ValidateObjectNotDisposed(); - ValidateRadioState(() => State == RadioState.Scanning); - _handle.StopScan(ScanStoppedCallback); + ValidateRadioState(RadioState.Scanning); + + ScanStop(Handle, ScanStoppedCallback); } /// - /// Seeks up the effective frequency of the radio + /// Seeks up the effective frequency of the radio. /// - /// Current frequency, in range [87500 ~ 108000] (kHz) - /// Radio must be in Playing state to use this API - /// This is thrown if Radio is not in Playing state - public Task SeekUpAsync() + /// + /// A task that represents the asynchronous seeking operation. + /// The result value is the current frequency, in range [87500 ~ 108000] (kHz). + /// It can be -1 if the seeking operation has failed. + /// + /// The radio must be in the The radio is not in the valid state. + public async Task SeekUpAsync() { - ValidateObjectNotDisposed(); - ValidateRadioState(() => State == RadioState.Playing); + ValidateRadioState(RadioState.Playing); TaskCompletionSource tcs = new TaskCompletionSource(); - Interop.RadioHandle.SeekCompletedCallback callback = (currentFrequency, userData) => + SeekCompletedCallback callback = (currentFrequency, _) => { tcs.TrySetResult(currentFrequency); }; - _handle.SeekUp(callback); - return Interop.PinnedTask(tcs); + SeekUp(Handle, callback); + return await tcs.Task; } /// - /// Seeks down the effective frequency of the radio + /// Seeks down the effective frequency of the radio. /// - /// Current frequency, in range [87500 ~ 108000] (kHz) - /// Radio must be in Playing state to use this API - /// This is thrown if Radio is not in Playing state - public Task SeekDownAsync() + /// + /// A task that represents the asynchronous seeking operation. + /// The result value is the current frequency, in range [87500 ~ 108000] (kHz). + /// It can be -1 if the seeking operation has failed. + /// + /// The radio must be in the The radio is not in the valid state. + public async Task SeekDownAsync() { - ValidateObjectNotDisposed(); - ValidateRadioState(() => State == RadioState.Playing); + ValidateRadioState(RadioState.Playing); TaskCompletionSource tcs = new TaskCompletionSource(); - Interop.RadioHandle.SeekCompletedCallback callback = (currentFrequency, userData) => + SeekCompletedCallback callback = (currentFrequency, _) => { tcs.TrySetResult(currentFrequency); }; - _handle.SeekDown(callback); - return Interop.PinnedTask(tcs); + SeekDown(Handle, callback); + return await tcs.Task; } private void ValidateFeatureSupported(string featurePath) @@ -283,9 +328,9 @@ namespace Tizen.Multimedia } - private void ScanUpdateCallback(int frequency, IntPtr data) + private void ScanUpdatedCallback(int frequency, IntPtr data) { - ScanInformationUpdated?.Invoke(this, new ScanUpdatedEventArgs(frequency)); + ScanUpdated?.Invoke(this, new ScanUpdatedEventArgs(frequency)); } private void ScanStoppedCallback(IntPtr data) @@ -298,43 +343,43 @@ namespace Tizen.Multimedia ScanCompleted?.Invoke(this, EventArgs.Empty); } - private void PlaybackIntruptedCallback(Interop.RadioInterruptedReason reason, IntPtr data) + private void IntruptedCallback(RadioInterruptedReason reason, IntPtr data) { - PlaybackInterrupted?.Invoke(this, new RadioInterruptedEventArgs((RadioInterruptedReason)reason)); + Interrupted?.Invoke(this, new RadioInterruptedEventArgs(reason)); } - private void ValidateInputRangeForPropertySetter(T input, T min, T max, [CallerMemberName] string member = "") where T : IComparable + private void ValidateRadioState(params RadioState[] reqiured) { - if (min.CompareTo(input) == 1 || max.CompareTo(input) == -1) - { - throw new ArgumentOutOfRangeException(member, input, $"Valid Range [{min} - {max}]"); - } - } + RadioState curState = State; - private void ValidateRadioState(Func stateVerifier, [CallerMemberName] string member = "") - { - if (stateVerifier() == false) + if (reqiured.Contains(curState) == false) { - throw new InvalidOperationException($"{State} is not valid state to call {member}. Please check API documentation"); + throw new InvalidOperationException($"{curState} is not valid state."); } } - private void ValidateObjectNotDisposed() + #region IDisposable Support + private bool _disposed = false; + + protected virtual void Dispose(bool disposing) { - if (_disposedValue) + if (!_disposed) { - throw new ObjectDisposedException(GetType().Name); + if (_handle != null) + { + _handle.Dispose(); + } + _disposed = true; } } - private bool _disposedValue = false; - + /// + /// Releases all resources used by the object. + /// public void Dispose() { - _handle.ScanCompleteCb = null; - _handle.InteruptedCb = null; - _handle.Dispose(); - _disposedValue = true; + Dispose(true); } + #endregion } } diff --git a/src/Tizen.Multimedia.Radio/Radio/RadioError.cs b/src/Tizen.Multimedia.Radio/Radio/RadioError.cs new file mode 100644 index 0000000..d8dc559 --- /dev/null +++ b/src/Tizen.Multimedia.Radio/Radio/RadioError.cs @@ -0,0 +1,69 @@ +/* + * 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 Tizen.Internals.Errors; + +namespace Tizen.Multimedia +{ + + internal enum RadioError + { + None = ErrorCode.None, + OutOfMemory = ErrorCode.OutOfMemory, + InvalidParameter = ErrorCode.InvalidParameter, + InvalidOperation = ErrorCode.InvalidOperation, + PermissionDenied = ErrorCode.PermissionDenied, + NotSupported = ErrorCode.NotSupported, + + InvalidState = -0x019A0000 | 0x01, + SoundPolicy = -0x019A0000 | 0x02, + NoAntenna = -0x019A0000 | 0x03, + } + + internal static class RadioErrorExtesions + { + internal static void ThrowIfFailed(this RadioError err, string message) + { + if (err == RadioError.None) + { + return; + } + + string errMessage = $"{message}; {err}."; + switch (err) + { + case RadioError.PermissionDenied: + throw new UnauthorizedAccessException(errMessage); + + case RadioError.InvalidParameter: + throw new ArgumentException(errMessage); + + case RadioError.OutOfMemory: + throw new OutOfMemoryException(errMessage); + + case RadioError.NotSupported: + case RadioError.NoAntenna: + throw new NotSupportedException(errMessage); + + default: + throw new InvalidOperationException(errMessage); + } + } + + } + +} diff --git a/src/Tizen.Multimedia.Radio/Radio/RadioInterruptedEventArgs.cs b/src/Tizen.Multimedia.Radio/Radio/RadioInterruptedEventArgs.cs index c77e837..b9ba17d 100644 --- a/src/Tizen.Multimedia.Radio/Radio/RadioInterruptedEventArgs.cs +++ b/src/Tizen.Multimedia.Radio/Radio/RadioInterruptedEventArgs.cs @@ -19,7 +19,7 @@ using System; namespace Tizen.Multimedia { /// - /// Arguments for radio Playback Interrupted events + /// Provides data for the event. /// public class RadioInterruptedEventArgs : EventArgs { @@ -29,8 +29,13 @@ namespace Tizen.Multimedia } /// - /// Tuned radio frequency, in range [87500 ~ 108000] (kHz) - /// + /// Gets the reason. + /// - /// Radio Interrupted Reason + /// Specifies interrupted reasons. /// public enum RadioInterruptedReason { /// - /// Playback interrupted by a resource conflict + /// By a resource conflict. /// - ResourceConflict = Interop.RadioInterruptedReason.ResourceConflict, - + ResourceConflict = 4, } -} \ No newline at end of file +} diff --git a/src/Tizen.Multimedia.Radio/Radio/RadioState.cs b/src/Tizen.Multimedia.Radio/Radio/RadioState.cs index a877536..38db7f0 100644 --- a/src/Tizen.Multimedia.Radio/Radio/RadioState.cs +++ b/src/Tizen.Multimedia.Radio/Radio/RadioState.cs @@ -17,21 +17,21 @@ namespace Tizen.Multimedia { /// - /// Radio State + /// Specifies states of the . /// public enum RadioState { /// - /// Ready to play or scan + /// Ready to play or scan. /// - Ready = Interop.RadioState.Ready, + Ready, /// - /// Playing audio from the tuner + /// Playing audio from the tuner. /// - Playing = Interop.RadioState.Playing, + Playing, /// - /// Scanning/ searching for the next station for signal + /// Scanning; searching for the next station for signal. /// - Scanning = Interop.RadioState.Scanning, + Scanning, } -} \ No newline at end of file +} diff --git a/src/Tizen.Multimedia.Radio/Radio/ScanUpdatedEventArgs.cs b/src/Tizen.Multimedia.Radio/Radio/ScanUpdatedEventArgs.cs index 7e82f1e..b4afe78 100644 --- a/src/Tizen.Multimedia.Radio/Radio/ScanUpdatedEventArgs.cs +++ b/src/Tizen.Multimedia.Radio/Radio/ScanUpdatedEventArgs.cs @@ -19,7 +19,7 @@ using System; namespace Tizen.Multimedia { /// - /// Arguments for radio scan update events + /// Provides data for the event. /// public class ScanUpdatedEventArgs : EventArgs { @@ -29,8 +29,14 @@ namespace Tizen.Multimedia } /// - /// Tuned radio frequency, in range [87500 ~ 108000] (kHz) + /// Gets the tuned radio frequency that is scanned, in range [87500 ~ 108000] (kHz). /// public int Frequency { get; } + + + public override string ToString() + { + return $"Frequency={ Frequency.ToString() }"; + } } -} \ No newline at end of file +} diff --git a/src/Tizen.Multimedia.Radio/Tizen.Multimedia.Radio.csproj b/src/Tizen.Multimedia.Radio/Tizen.Multimedia.Radio.csproj index ecf05ef..deff462 100644 --- a/src/Tizen.Multimedia.Radio/Tizen.Multimedia.Radio.csproj +++ b/src/Tizen.Multimedia.Radio/Tizen.Multimedia.Radio.csproj @@ -14,4 +14,8 @@ + + + + diff --git a/src/Tizen.Multimedia.Radio/Tizen.Multimedia.Radio.nuspec b/src/Tizen.Multimedia.Radio/Tizen.Multimedia.Radio.nuspec index f5162ef..d1c9562 100644 --- a/src/Tizen.Multimedia.Radio/Tizen.Multimedia.Radio.nuspec +++ b/src/Tizen.Multimedia.Radio/Tizen.Multimedia.Radio.nuspec @@ -12,6 +12,7 @@ Provides the Multimedia Radio API for Tizen.Net + diff --git a/src/Tizen.Multimedia/Tizen.Multimedia.csproj b/src/Tizen.Multimedia/Tizen.Multimedia.csproj index d9f36b1..1a83918 100755 --- a/src/Tizen.Multimedia/Tizen.Multimedia.csproj +++ b/src/Tizen.Multimedia/Tizen.Multimedia.csproj @@ -13,7 +13,7 @@ - + -- 2.7.4