890c319327244b183c60cfb741bed051c1f5fa95
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia / AudioManager / AudioManager.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 using System;
18 using System.Collections.Generic;
19
20 namespace Tizen.Multimedia
21 {
22     /// <summary>
23     /// Provides the ability to control volume levels and monitor audio devices.
24     /// </summary>
25     /// <since_tizen> 3 </since_tizen>
26     public static class AudioManager
27     {
28         static AudioManager()
29         {
30             VolumeController = new AudioVolume();
31         }
32
33         /// <summary>
34         /// Gets the volume controller.
35         /// </summary>
36         /// <value>The <see cref="AudioVolume"/>.</value>
37         /// <since_tizen> 3 </since_tizen>
38         public static AudioVolume VolumeController { get; }
39
40         /// <summary>
41         /// Gets the all devices currently connected.
42         /// </summary>
43         /// <returns>An IEnumerable&lt;AudioDevice&gt; that contains connected devices.</returns>
44         /// <since_tizen> 4 </since_tizen>
45         public static IEnumerable<AudioDevice> GetConnectedDevices()
46         {
47             IntPtr deviceListHandle = IntPtr.Zero;
48
49             try
50             {
51                 var ret = Interop.AudioDevice.GetDeviceList(AudioDeviceOptions.All, out deviceListHandle);
52
53                 if (ret == AudioManagerError.NoData)
54                 {
55                     return new List<AudioDevice>();
56                 }
57
58                 ret.ThrowIfError("Failed to get connected devices");
59
60                 return RetrieveDevices();
61             }
62             finally
63             {
64                 Interop.AudioDevice.FreeDeviceList(deviceListHandle);
65             }
66
67             IEnumerable<AudioDevice> RetrieveDevices()
68             {
69                 var result = new List<AudioDevice>();
70
71                 while (true)
72                 {
73                     var ret = Interop.AudioDevice.GetNextDevice(deviceListHandle, out var deviceHandle);
74
75                     if (ret == AudioManagerError.NoData)
76                     {
77                         break;
78                     }
79
80                     ret.ThrowIfError("Failed to get connected devices");
81
82                     result.Add(new AudioDevice(deviceHandle));
83                 }
84                 return result;
85             }
86         }
87
88         #region DeviceConnectionChanged event
89         private static int _deviceConnectionChangedCallbackId = -1;
90
91         private static Interop.AudioDevice.ConnectionChangedCallback _audioDeviceConnectionChangedCallback;
92         private static EventHandler<AudioDeviceConnectionChangedEventArgs> _audioDeviceConnectionChanged;
93         private static readonly object _audioDeviceConnectionLock = new object();
94
95         /// <summary>
96         /// Occurs when the state of a connection of an audio device changes.
97         /// </summary>
98         /// <since_tizen> 3 </since_tizen>
99         public static event EventHandler<AudioDeviceConnectionChangedEventArgs> DeviceConnectionChanged
100         {
101             add
102             {
103                 if (value == null)
104                 {
105                     return;
106                 }
107
108                 lock (_audioDeviceConnectionLock)
109                 {
110                     if (_audioDeviceConnectionChanged == null)
111                     {
112                         RegisterAudioDeviceEvent();
113                     }
114                     _audioDeviceConnectionChanged += value;
115                 }
116             }
117             remove
118             {
119                 if (value == null)
120                 {
121                     return;
122                 }
123
124                 lock (_audioDeviceConnectionLock)
125                 {
126                     if (_audioDeviceConnectionChanged == value)
127                     {
128                         UnregisterDeviceConnectionChangedEvent();
129                     }
130                     _audioDeviceConnectionChanged -= value;
131                 }
132             }
133         }
134
135         private static void RegisterAudioDeviceEvent()
136         {
137             _audioDeviceConnectionChangedCallback = (device, isConnected, _) =>
138             {
139                 _audioDeviceConnectionChanged?.Invoke(null,
140                     new AudioDeviceConnectionChangedEventArgs(new AudioDevice(device), isConnected));
141             };
142
143             Interop.AudioDevice.AddDeviceConnectionChangedCallback(AudioDeviceOptions.All,
144                 _audioDeviceConnectionChangedCallback, IntPtr.Zero, out _deviceConnectionChangedCallbackId).
145                 ThrowIfError("Unable to add device connection changed callback");
146         }
147
148         private static void UnregisterDeviceConnectionChangedEvent()
149         {
150             Interop.AudioDevice.RemoveDeviceConnectionChangedCallback(_deviceConnectionChangedCallbackId).
151                 ThrowIfError("Unable to remove device connection changed callback");
152         }
153         #endregion
154
155         #region DeviceStateChanged event
156         private static int _deviceStateChangedCallbackId = -1;
157
158 #pragma warning disable CS0618 // Type or member is obsolete
159
160         private static Interop.AudioDevice.StateChangedCallback _audioDeviceStateChangedCallback;
161         private static EventHandler<AudioDeviceStateChangedEventArgs> _audioDeviceStateChanged;
162         private static readonly object _audioDeviceStateLock = new object();
163
164         /// <summary>
165         /// Occurs when the state of an audio device changes.
166         /// </summary>
167         /// <since_tizen> 3 </since_tizen>
168         [Obsolete("Deprecated since API level 5. Please use the DeviceRunningStateChanged property instead.")]
169         public static event EventHandler<AudioDeviceStateChangedEventArgs> DeviceStateChanged
170         {
171             add
172             {
173                 if (value == null)
174                 {
175                     return;
176                 }
177
178                 lock (_audioDeviceStateLock)
179                 {
180                     if (_audioDeviceStateChanged == null)
181                     {
182                         RegisterDeviceStateChangedEvent();
183                     }
184                     _audioDeviceStateChanged += value;
185                 }
186             }
187             remove
188             {
189                 if (value == null)
190                 {
191                     return;
192                 }
193
194                 lock (_audioDeviceStateLock)
195                 {
196                     if (_audioDeviceStateChanged == value)
197                     {
198                         UnregisterDeviceStateChangedEvent();
199                     }
200                     _audioDeviceStateChanged -= value;
201                 }
202             }
203         }
204
205         private static void RegisterDeviceStateChangedEvent()
206         {
207             _audioDeviceStateChangedCallback = (device, changedState, _) =>
208             {
209                 _audioDeviceStateChanged?.Invoke(null,
210                     new AudioDeviceStateChangedEventArgs(new AudioDevice(device), changedState));
211             };
212
213             Interop.AudioDevice.AddDeviceStateChangedCallback(AudioDeviceOptions.All,
214                 _audioDeviceStateChangedCallback, IntPtr.Zero, out _deviceStateChangedCallbackId).
215                 ThrowIfError("Failed to add device state changed event");
216         }
217
218 #pragma warning restore CS0618 // Type or member is obsolete
219
220         private static void UnregisterDeviceStateChangedEvent()
221         {
222             Interop.AudioDevice.RemoveDeviceStateChangedCallback(_deviceStateChangedCallbackId).
223                 ThrowIfError("Failed to remove device state changed event");
224         }
225         #endregion
226
227         #region DeviceRunningStateChanged event
228         private static int _deviceRunningChangedCallbackId = -1;
229         private static Interop.AudioDevice.RunningChangedCallback _audioDeviceRunningChangedCallback;
230         private static EventHandler<AudioDeviceRunningChangedEventArgs> _audioDeviceRunningChanged;
231         private static readonly object _audioDeviceRunningLock = new object();
232
233         /// <summary>
234         /// Occurs when the audio stream started actually to run on the device.
235         /// </summary>
236         /// <remarks>
237         /// If this event is invoked once and the audio stream is still running on the device,<br/>
238         /// this event will not be invoked anymore, even if there are more audio streams to run.<br/>
239         /// This event is invoked only when all streams are stopped and a new stream starts to run.
240         /// </remarks>
241         /// <exception cref="InvalidOperationException">
242         /// AudioManager failed to communicate internally or allocate memory.
243         /// </exception>
244         /// <since_tizen> 5 </since_tizen>
245         public static event EventHandler<AudioDeviceRunningChangedEventArgs> DeviceRunningChanged
246         {
247             add
248             {
249                 if (value == null)
250                 {
251                     return;
252                 }
253                 lock (_audioDeviceRunningLock)
254                 {
255                     if (_audioDeviceRunningChanged == null)
256                     {
257                         RegisterDeviceRunningChangedEvent();
258                     }
259                     _audioDeviceRunningChanged += value;
260                 }
261             }
262             remove
263             {
264                 if (value == null)
265                 {
266                     return;
267                 }
268                 lock (_audioDeviceRunningLock)
269                 {
270                     _audioDeviceRunningChanged -= value;
271                     if (_audioDeviceRunningChanged == null)
272                     {
273                         UnregisterDeviceRunningChangedEvent();
274                     }
275                 }
276             }
277         }
278
279         private static void RegisterDeviceRunningChangedEvent()
280         {
281             _audioDeviceRunningChangedCallback = (device, isRunning, _) =>
282             {
283                 _audioDeviceRunningChanged?.Invoke(null,
284                     new AudioDeviceRunningChangedEventArgs(new AudioDevice(device), isRunning));
285             };
286             Interop.AudioDevice.AddDeviceRunningChangedCallback(AudioDeviceOptions.All,
287                _audioDeviceRunningChangedCallback, IntPtr.Zero, out _deviceRunningChangedCallbackId).
288                ThrowIfError("Failed to add DeviceRunningChanged event");
289         }
290
291         private static void UnregisterDeviceRunningChangedEvent()
292         {
293             Interop.AudioDevice.RemoveDeviceRunningChangedCallback(_deviceRunningChangedCallbackId).
294                 ThrowIfError("Failed to remove DeviceRunningChanged event");
295         }
296         #endregion
297     }
298 }