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.
18 using System.Diagnostics;
20 namespace Tizen.Multimedia
23 /// Provides the ability to control a sound stream.
25 public class AudioStreamPolicy : IDisposable
27 private AudioStreamPolicyHandle _handle;
28 private bool _disposed = false;
29 private Interop.AudioStreamPolicy.FocusStateChangedCallback _focusStateChangedCallback;
32 /// Initializes a new instance of the <see cref="AudioStreamPolicy"/> class with <see cref="AudioStreamType"/>
35 /// To apply the stream policy according to this stream information, the AudioStreamPolicy should
36 /// be passed to other APIs related to playback or recording. (e.g., <see cref="Player"/>, <see cref="WavPlayer"/> , etc.)
38 /// <param name="streamType">Type of sound stream for which policy needs to be created.</param>
39 public AudioStreamPolicy(AudioStreamType streamType)
41 ValidationUtil.ValidateEnum(typeof(AudioStreamType), streamType, nameof(streamType));
43 _focusStateChangedCallback = (IntPtr streamInfo, AudioStreamFocusOptions focusMask,
44 AudioStreamFocusState state, AudioStreamFocusChangedReason reason, AudioStreamBehaviors behaviors,
45 string extraInfo, IntPtr userData) =>
47 FocusStateChanged?.Invoke(this,
48 new AudioStreamPolicyFocusStateChangedEventArgs(focusMask, state, reason, behaviors, extraInfo));
51 Interop.AudioStreamPolicy.Create(streamType, _focusStateChangedCallback,
52 IntPtr.Zero, out _handle).Validate("Unable to create stream information");
54 Debug.Assert(_handle != null);
58 /// Occurs when the state of focus that belongs to the current AudioStreamPolicy is changed.
61 /// The event is raised in the internal thread.
63 public event EventHandler<AudioStreamPolicyFocusStateChangedEventArgs> FocusStateChanged;
66 /// Gets the <see cref="AudioVolumeType"/>.
69 /// If the <see cref="AudioStreamType"/> of the current AudioStreamPolicy is <see cref="AudioStreamType.Emergency"/>,
70 /// it returns <see cref="AudioVolumeType.None"/>.
72 /// <value>The <see cref="AudioVolumeType"/> of the policy instance.</value>
73 public AudioVolumeType VolumeType
78 var ret = Interop.AudioStreamPolicy.GetSoundType(Handle, out type);
79 if (ret == AudioManagerError.NoData)
81 return AudioVolumeType.None;
84 ret.Validate("Failed to get volume type");
90 private AudioStreamFocusState GetFocusState(bool playback)
92 int ret = Interop.AudioStreamPolicy.GetFocusState(Handle, out var stateForPlayback, out var stateForRecording);
93 MultimediaDebug.AssertNoError(ret);
95 return playback ? stateForPlayback : stateForRecording;
99 /// Gets the state of focus for playback.
101 /// <value>The state of focus for playback.</value>
102 public AudioStreamFocusState PlaybackFocusState => GetFocusState(true);
105 /// Gets the state of focus for recording.
107 /// <value>The state of focus for recording.</value>
108 public AudioStreamFocusState RecordingFocusState => GetFocusState(false);
111 /// Gets or sets the auto focus reacquisition.
114 /// true if the auto focus reacquisition is enabled; otherwise, false.\n
115 /// The default is true.
118 /// If you don't want to reacquire the focus you've lost automatically,
119 /// disable the focus reacquisition.
121 public bool FocusReacquisitionEnabled
125 Interop.AudioStreamPolicy.GetFocusReacquisition(Handle, out var enabled).
126 Validate("Failed to get focus reacquisition state");
132 Interop.AudioStreamPolicy.SetFocusReacquisition(Handle, value).
133 Validate("Failed to set focus reacquisition");
137 internal AudioStreamPolicyHandle Handle
143 throw new ObjectDisposedException(nameof(AudioStreamPolicy));
150 /// Acquires the stream focus.
152 /// <param name="options">The focuses that you want to acquire.</param>
153 /// <param name="behaviors">The requesting behaviors.</param>
154 /// <param name="extraInfo">The extra information for this request. This value can be null.</param>
155 public void AcquireFocus(AudioStreamFocusOptions options, AudioStreamBehaviors behaviors, string extraInfo)
159 throw new ArgumentException("options can't be zero.", nameof(options));
162 if (options.IsValid() == false)
164 throw new ArgumentOutOfRangeException(nameof(options), options, "options contains a invalid bit.");
167 if (behaviors.IsValid() == false)
169 throw new ArgumentOutOfRangeException(nameof(behaviors), behaviors, "behaviors contains a invalid bit.");
172 Interop.AudioStreamPolicy.AcquireFocus(Handle, options, behaviors, extraInfo).
173 Validate("Failed to acquire focus");
177 /// Releases the acquired focus.
179 /// <param name="options">The focus mask that you want to release.</param>
180 /// <param name="behaviors">The requesting behaviors.</param>
181 /// <param name="extraInfo">The extra information for this request. This value can be null.</param>
182 public void ReleaseFocus(AudioStreamFocusOptions options, AudioStreamBehaviors behaviors, string extraInfo)
186 throw new ArgumentException("options can't be zero.", nameof(options));
189 if (options.IsValid() == false)
191 throw new ArgumentOutOfRangeException(nameof(options), options, "options contains a invalid bit.");
194 if (behaviors.IsValid() == false)
196 throw new ArgumentOutOfRangeException(nameof(behaviors), behaviors, "behaviors contains a invalid bit.");
199 Interop.AudioStreamPolicy.ReleaseFocus(Handle, options, behaviors, extraInfo).
200 Validate("Failed to release focus");
204 /// Applies the stream routing.
207 /// If the stream has not been made yet, this will be applied when the stream starts to play.
209 /// <seealso cref="AddDeviceForStreamRouting(AudioDevice)"/>
210 /// <seealso cref="RemoveDeviceForStreamRouting(AudioDevice)"/>
211 public void ApplyStreamRouting()
213 Interop.AudioStreamPolicy.ApplyStreamRouting(Handle).Validate("Failed to apply stream routing");
217 /// Adds a device for the stream routing.
219 /// <param name="device">The device to add.</param>
221 /// The available <see cref="AudioStreamType"/> is <see cref="AudioStreamType.Voip"/> and <see cref="AudioStreamType.MediaExternalOnly"/>.
223 /// <seealso cref="AudioManager.GetConnectedDevices()"/>
224 /// <seealso cref="ApplyStreamRouting"/>
225 public void AddDeviceForStreamRouting(AudioDevice device)
229 throw new ArgumentNullException(nameof(device));
231 var ret = Interop.AudioStreamPolicy.AddDeviceForStreamRouting(Handle, device.Id);
233 if (ret == AudioManagerError.NoData)
235 throw new ArgumentException("The device seems not connected.", nameof(device));
238 ret.Validate("Failed to add device for stream routing");
242 /// Removes the device for the stream routing.
244 /// <param name="device">The device to remove.</param>
246 /// The available <see cref="AudioStreamType"/> is <see cref="AudioStreamType.Voip"/> and <see cref="AudioStreamType.MediaExternalOnly"/>.
248 public void RemoveDeviceForStreamRouting(AudioDevice device)
252 throw new ArgumentNullException(nameof(device));
255 Interop.AudioStreamPolicy.RemoveDeviceForStreamRouting(Handle, device.Id).
256 Validate("Failed to remove device for stream routing");
260 /// Releases all resources used by the <see cref="AudioStreamPolicy"/>.
262 public void Dispose()
268 /// Releases the unmanaged resources used by the <see cref="AudioStreamPolicy"/>.
270 /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
271 protected virtual void Dispose(bool disposing)
283 #region Static events
285 private static bool _isWatchCallbackRegistered;
286 private static EventHandler<StreamFocusStateChangedEventArgs> _streamFocusStateChanged;
287 private static Interop.AudioStreamPolicy.FocusStateWatchCallback _focusStateWatchCallback;
288 private static object _streamFocusEventLock = new object();
291 /// Occurs when the focus state for stream types is changed regardless of the process.
293 public static event EventHandler<StreamFocusStateChangedEventArgs> StreamFocusStateChanged
297 lock (_streamFocusEventLock)
299 if (_isWatchCallbackRegistered == false)
301 RegisterFocusStateWatch();
302 _isWatchCallbackRegistered = true;
304 _streamFocusStateChanged += value;
309 lock (_streamFocusEventLock)
311 _streamFocusStateChanged -= value;
316 private static void RegisterFocusStateWatch()
318 _focusStateWatchCallback = (int id, AudioStreamFocusOptions options, AudioStreamFocusState focusState,
319 AudioStreamFocusChangedReason reason, string extraInfo, IntPtr userData) =>
321 _streamFocusStateChanged?.Invoke(null,
322 new StreamFocusStateChangedEventArgs(options, focusState, reason, extraInfo));
325 Interop.AudioStreamPolicy.AddFocusStateWatchCallback(
326 AudioStreamFocusOptions.Playback | AudioStreamFocusOptions.Recording,
327 _focusStateWatchCallback, IntPtr.Zero, out var cbId).
328 Validate("Failed to initialize focus state event");