2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 using System.Threading.Tasks;
21 using static Tizen.Multimedia.Interop.Radio;
23 namespace Tizen.Multimedia
26 /// Provides a means for using the radio feature.
28 public class Radio : IDisposable
30 private Interop.RadioHandle _handle;
32 private const string FeatureFmRadio = "http://tizen.org/feature/fmradio";
35 /// Initialize a new instance of the Radio class.
37 /// <exception cref="NotSupportedException">Radio feature is not supported</exception>
40 ValidateFeatureSupported(FeatureFmRadio);
46 SetScanCompletedCb(_handle, ScanCompleteCallback).ThrowIfFailed("Failed to initialize radio");
47 SetInterruptedCb(_handle, InterruptedCallback).ThrowIfFailed("Failed to initialize radio");
56 private Interop.RadioHandle Handle
62 throw new ObjectDisposedException(GetType().Name);
69 /// Occurs when radio scan information is updated.
71 public event EventHandler<ScanUpdatedEventArgs> ScanUpdated;
74 /// Occurs when radio scanning stops.
76 public event EventHandler ScanStopped;
79 /// Occurs when radio scan is completed.
81 public event EventHandler ScanCompleted;
84 /// Occurs when radio is interrupted
86 public event EventHandler<RadioInterruptedEventArgs> Interrupted;
89 /// Gets the current state of the radio.
91 public RadioState State
96 GetState(Handle, out state);
102 /// Gets or sets the radio frequency, in [87500 ~ 108000] (kHz).
104 /// <exception cref="ArgumentOutOfRangeException">
105 /// <paramref name="value"/> is less than <see cref="Range.Min"/> of <see cref="FrequencyRange"/>.\n
107 /// <paramref name="value"/> is greater than <see cref="Range.Max"/> of <see cref="FrequencyRange"/>.\n
114 GetFrequency(Handle, out value).ThrowIfFailed("Failed to get frequency");
119 if (value < FrequencyRange.Min || value > FrequencyRange.Max)
121 throw new ArgumentOutOfRangeException(nameof(Frequency), value, "Frequency must be within FrequencyRange.");
124 SetFrequency(Handle, value).ThrowIfFailed("Failed to set frequency");
129 /// Gets the current signal strength, in [-128 ~ 128] (dBm).
131 public int SignalStrength
136 GetSignalStrength(Handle, out value).ThrowIfFailed("Failed to get signal strength");
142 /// Gets the value indicating if radio is muted.
145 /// true if the radio is muted; otherwise, false.
146 /// The default is false.
153 GetMuted(Handle, out value).ThrowIfFailed("Failed to get the mute state");
158 SetMute(Handle, value).ThrowIfFailed("Failed to set the mute state");
163 /// Gets the channel spacing for current region.
165 public int ChannelSpacing
170 GetChannelSpacing(Handle, out value).ThrowIfFailed("Failed to get channel spacing");
176 /// Gets or sets the radio volume level.
178 /// <remarks>Valid volume range is from 0 to 1.0(100%), inclusive.</remarks>
179 /// <value>The default is 1.0.</value>
180 /// <exception cref="ArgumentOutOfRangeException">
181 /// <paramref name="value"/> is less than zero.\n
183 /// <paramref name="value"/> is greater than 1.0.
190 GetVolume(Handle, out value).ThrowIfFailed("Failed to get volume level.");
195 if (value < 0F || 1.0F < value)
197 throw new ArgumentOutOfRangeException(nameof(value), value,
198 $"Valid volume range is 0 <= value <= 1.0, but got { value }.");
201 SetVolume(Handle, value).ThrowIfFailed("Failed to set volume level");
206 /// Gets the frequency for the region, in [87500 ~ 108000] (kHz).
208 public Range FrequencyRange
214 GetFrequencyRange(Handle, out min, out max).ThrowIfFailed("Failed to get frequency range");
216 return new Range(min, max);
221 /// Starts the radio.
223 /// <remarks>The radio must be in the <see cref="RadioState.Ready"/> state.</remarks>
224 /// <exception cref="InvalidOperationException">The radio is not in the valid state.</exception>
227 ValidateRadioState(RadioState.Ready);
229 Interop.Radio.Start(Handle).ThrowIfFailed("Failed to start radio");
235 /// <remarks>The radio must be in the <see cref="RadioState.Playing"/> state.</remarks>
236 /// <exception cref="InvalidOperationException">The radio is not in the valid state.</exception>
239 ValidateRadioState(RadioState.Playing);
241 Interop.Radio.Stop(Handle).ThrowIfFailed("Failed to stop radio");
245 /// Starts radio scan, will trigger ScanInformationUpdated event, when scan information is updated
247 /// <remarks>The radio must be in the <see cref="RadioState.Ready"/> or <see cref="RadioState.Playing"/> state.</remarks>
248 /// <exception cref="InvalidOperationException">The radio is not in the valid state.</exception>
249 /// <seealso cref="ScanUpdated"/>
250 /// <seealso cref="ScanCompleted"/>
251 public void StartScan()
253 ValidateRadioState(RadioState.Ready, RadioState.Playing);
255 ScanStart(Handle, ScanUpdatedCallback);
259 /// Stops radio scan.
261 /// <remarks>The radio must be in the <see cref="RadioState.Scanning"/> state.</remarks>
262 /// <exception cref="InvalidOperationException">The radio is not in the valid state.</exception>
263 /// <seealso cref="ScanStopped"/>
264 public void StopScan()
266 ValidateRadioState(RadioState.Scanning);
268 ScanStop(Handle, ScanStoppedCallback);
272 /// Seeks up the effective frequency of the radio.
275 /// A task that represents the asynchronous seeking operation.
276 /// The result value is the current frequency, in range [87500 ~ 108000] (kHz).
277 /// It can be -1 if the seeking operation has failed.
279 /// <remarks>The radio must be in the <see cref="RadioState.Playing"/> state.</remarks>
280 /// <exception cref="InvalidOperationException">The radio is not in the valid state.</exception>
281 public async Task<int> SeekUpAsync()
283 ValidateRadioState(RadioState.Playing);
285 TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
286 SeekCompletedCallback callback = (currentFrequency, _) =>
288 tcs.TrySetResult(currentFrequency);
291 SeekUp(Handle, callback);
292 return await tcs.Task;
296 /// Seeks down the effective frequency of the radio.
299 /// A task that represents the asynchronous seeking operation.
300 /// The result value is the current frequency, in range [87500 ~ 108000] (kHz).
301 /// It can be -1 if the seeking operation has failed.
303 /// <remarks>The radio must be in the <see cref="RadioState.Playing"/> state.</remarks>
304 /// <exception cref="InvalidOperationException">The radio is not in the valid state.</exception>
305 public async Task<int> SeekDownAsync()
307 ValidateRadioState(RadioState.Playing);
309 TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
310 SeekCompletedCallback callback = (currentFrequency, _) =>
312 tcs.TrySetResult(currentFrequency);
315 SeekDown(Handle, callback);
316 return await tcs.Task;
319 private void ValidateFeatureSupported(string featurePath)
321 bool supported = false;
322 SystemInfo.TryGetValue(featurePath, out supported);
324 if (supported == false)
326 throw new NotSupportedException($"The feature({featurePath}) is not supported.");
331 private void ScanUpdatedCallback(int frequency, IntPtr data)
333 ScanUpdated?.Invoke(this, new ScanUpdatedEventArgs(frequency));
336 private void ScanStoppedCallback(IntPtr data)
338 ScanStopped?.Invoke(this, EventArgs.Empty);
341 private void ScanCompleteCallback(IntPtr data)
343 ScanCompleted?.Invoke(this, EventArgs.Empty);
346 private void InterruptedCallback(RadioInterruptedReason reason, IntPtr data)
348 Interrupted?.Invoke(this, new RadioInterruptedEventArgs(reason));
351 private void ValidateRadioState(params RadioState[] required)
353 RadioState curState = State;
355 if (required.Contains(curState) == false)
357 throw new InvalidOperationException($"{curState} is not valid state.");
361 #region IDisposable Support
362 private bool _disposed = false;
365 /// Releases the resources used by the Radio.
367 /// <param name="disposing">
368 /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
370 protected virtual void Dispose(bool disposing)
383 /// Releases all resources used by the <see cref="Radio"/> object.
385 public void Dispose()