bf4ec2491fcda0b86aaf94d422bc30c31bd3e127
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia / AudioManager / AudioDevice.cs
1 /*
2  * Copyright (c) 2018 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.Runtime.InteropServices;
19 using System.Collections.Generic;
20 using System.Linq;
21
22 namespace Tizen.Multimedia
23 {
24     /// <summary>
25     /// Provides the ability to query the information of sound devices.
26     /// </summary>
27     /// <since_tizen> 3 </since_tizen>
28     public class AudioDevice
29     {
30         private readonly int _id;
31         private readonly AudioDeviceType _type;
32         private readonly AudioDeviceIoDirection _ioDirection;
33         private const string Tag = "Tizen.Multimedia.AudioDevice";
34
35         internal AudioDevice(IntPtr deviceHandle)
36         {
37             int ret = Interop.AudioDevice.GetDeviceId(deviceHandle, out _id);
38             MultimediaDebug.AssertNoError(ret);
39
40             ret = Interop.AudioDevice.GetDeviceName(deviceHandle, out var name);
41             MultimediaDebug.AssertNoError(ret);
42
43             Name = Marshal.PtrToStringAnsi(name);
44
45             ret = Interop.AudioDevice.GetDeviceType(deviceHandle, out _type);
46             MultimediaDebug.AssertNoError(ret);
47
48             ret = Interop.AudioDevice.GetDeviceIoDirection(deviceHandle, out _ioDirection);
49             MultimediaDebug.AssertNoError(ret);
50         }
51
52         /// <summary>
53         /// Gets the ID of the device.
54         /// </summary>
55         /// <value>The id of the device.</value>
56         /// <since_tizen> 3 </since_tizen>
57         public int Id => _id;
58
59         /// <summary>
60         /// Gets the name of the device.
61         /// </summary>
62         /// <value>The name of the device.</value>
63         /// <since_tizen> 3 </since_tizen>
64         public string Name { get; }
65
66         /// <summary>
67         /// Gets the type of the device.
68         /// </summary>
69         /// <value>The <see cref="AudioDeviceType"/> of the device.</value>
70         /// <since_tizen> 3 </since_tizen>
71         public AudioDeviceType Type => _type;
72
73         /// <summary>
74         /// Gets the IO direction of the device.
75         /// </summary>
76         /// <value>The IO direction of the device.</value>
77         /// <since_tizen> 3 </since_tizen>
78         public AudioDeviceIoDirection IoDirection => _ioDirection;
79
80         /// <summary>
81         /// Gets the state of the device.
82         /// </summary>
83         /// <value>The <see cref="AudioDeviceState"/> of the device.</value>
84         /// <since_tizen> 3 </since_tizen>
85         [Obsolete("Deprecated since API level 5. Please use the IsRunning property instead.")]
86         public AudioDeviceState State
87         {
88             get
89             {
90                 Interop.AudioDevice.GetDeviceState(Id, out var state).
91                     ThrowIfError("Failed to get the state of the device");
92
93                 return state;
94             }
95         }
96
97         /// <summary>
98         /// Gets the running state of the device.
99         /// </summary>
100         /// <value>true if the audio stream of device is running actually; otherwise, false.</value>
101         /// <since_tizen> 5 </since_tizen>
102         public bool IsRunning
103         {
104             get
105             {
106                 Interop.AudioDevice.IsDeviceRunning(_id, out bool isRunning).
107                     ThrowIfError("Failed to get the running state of the device");
108
109                 return isRunning;
110                         }
111         }
112
113         /// <summary>
114         /// Gets the device's supported sample formats.
115         /// </summary>
116         /// <returns>An IEnumerable&lt;AudioSampleFormat&gt; that contains supported sample formats.</returns>
117         /// <remarks>
118         /// This device should be <see cref="AudioDeviceType.UsbAudio"/> type and <see cref="AudioDeviceIoDirection.Output"/> direction.
119         /// </remarks>
120         /// <exception cref="InvalidOperationException">This device is not valid or is disconnected.</exception>
121         /// <since_tizen> 5 </since_tizen>
122         public IEnumerable<AudioSampleFormat> GetSupportedSampleFormats()
123         {
124             Interop.AudioDevice.GetSupportedSampleFormats(_id, out IntPtr formats, out uint numberOfElements).
125                 ThrowIfError("Failed to get supported sample formats");
126
127             return RetrieveFormats();
128
129             IEnumerable<AudioSampleFormat> RetrieveFormats()
130             {
131                 int[] formatsResult = new int[numberOfElements];
132
133                 Marshal.Copy(formats, formatsResult, 0, (int)numberOfElements);
134                 Interop.Libc.Free(formats);
135
136                 foreach (int f in formatsResult)
137                 {
138                     Log.Debug(Tag, $"supported sample format:{f}");
139                 }
140
141                 return formatsResult.Cast<AudioSampleFormat>();
142             }
143         }
144
145         /// <summary>
146         /// Sets the device's sample format.
147         /// </summary>
148         /// <param name="format">The <see cref="AudioSampleFormat"/> to set to the device.</param>
149         /// <remarks>
150         /// This device should be <see cref="AudioDeviceType.UsbAudio"/> type and <see cref="AudioDeviceIoDirection.Output"/> direction.
151         /// </remarks>
152         /// <exception cref="InvalidOperationException">This device is not valid or is disconnected.</exception>
153         /// <since_tizen> 5 </since_tizen>
154         public void SetSampleFormat(AudioSampleFormat format)
155         {
156             Interop.AudioDevice.SetSampleFormat(_id, format).
157                     ThrowIfError("Failed to set sample format of the device");
158         }
159
160         /// <summary>
161         /// Gets the device's sample format.
162         /// </summary>
163         /// <returns>The <see cref="AudioSampleFormat"/> of the device.</returns>
164         /// <remarks>
165         /// This device should be <see cref="AudioDeviceType.UsbAudio"/> type and <see cref="AudioDeviceIoDirection.Output"/> direction.
166         /// </remarks>
167         /// <exception cref="InvalidOperationException">This device is not valid or is disconnected.</exception>
168         /// <since_tizen> 5 </since_tizen>
169         public AudioSampleFormat GetSampleFormat()
170         {
171             Interop.AudioDevice.GetSampleFormat(_id, out AudioSampleFormat format).
172                 ThrowIfError("Failed to get sample format of the device");
173
174             return format;
175         }
176
177         private uint ConvertCoreRateValToUint(int value)
178         {
179             switch (value)
180             {
181                 case 0: return 8000;
182                 case 1: return 16000;
183                 case 2: return 22050;
184                 case 3: return 44100;
185                 case 4: return 48000;
186                 case 5: return 88200;
187                 case 6: return 96000;
188                 case 7: return 192000;
189                 default:
190                     Log.Error(Tag, $"unknown value from core:{value}");
191                     return 0;
192             }
193         }
194
195         private uint ConvertRateToCoreValue(uint rate)
196         {
197             switch (rate)
198             {
199                 case 8000: return 0;
200                 case 16000: return 1;
201                 case 22050: return 2;
202                 case 44100: return 3;
203                 case 48000: return 4;
204                 case 88200: return 5;
205                 case 96000: return 6;
206                 case 192000: return 7;
207                 default:
208                     Log.Error(Tag, $"not supported rate:{rate}");
209                     return 0;
210             }
211         }
212
213         /// <summary>
214         /// Gets the device's supported sample rates.
215         /// </summary>
216         /// <returns>An IEnumerable&lt;uint&gt; that contains supported sample rates.</returns>
217         /// <remarks>
218         /// This device should be <see cref="AudioDeviceType.UsbAudio"/> type and <see cref="AudioDeviceIoDirection.Output"/> direction.
219         /// </remarks>
220         /// <exception cref="InvalidOperationException">This device is not valid or is disconnected.</exception>
221         /// <since_tizen> 5 </since_tizen>
222         public IEnumerable<uint> GetSupportedSampleRates()
223         {
224             Interop.AudioDevice.GetSupportedSampleRates(_id, out IntPtr rates, out uint numberOfElements).
225                 ThrowIfError("Failed to get supported sample formats");
226
227             return RetrieveRates();
228
229             IEnumerable<uint> RetrieveRates()
230             {
231                 int[] ratesResult = new int[numberOfElements];
232                 uint[] convertedRates = new uint[numberOfElements];
233
234                 Marshal.Copy(rates, ratesResult, 0, (int)numberOfElements);
235                 Interop.Libc.Free(rates);
236
237                 for (int i = 0; i < ratesResult.Length; i++)
238                 {
239                     convertedRates[i] = ConvertCoreRateValToUint(ratesResult[i]);
240                     Log.Debug(Tag, $"supported sample rate:{convertedRates[i]}");
241                 }
242
243                 return convertedRates;
244             }
245         }
246
247         /// <summary>
248         /// Sets the device's sample rate.
249         /// </summary>
250         /// <param name="rate">The sample rate to set to the device.</param>
251         /// <remarks>
252         /// This device should be <see cref="AudioDeviceType.UsbAudio"/> type and <see cref="AudioDeviceIoDirection.Output"/> direction.
253         /// </remarks>
254         /// <exception cref="InvalidOperationException">This device is not valid or is disconnected.</exception>
255         /// <since_tizen> 5 </since_tizen>
256         public void SetSampleRate(uint rate)
257         {
258             Interop.AudioDevice.SetSampleRate(_id, ConvertRateToCoreValue(rate)).
259                 ThrowIfError("Failed to set sample rate of the device");
260         }
261
262         /// <summary>
263         /// Gets the device's sample rate.
264         /// </summary>
265         /// <returns>The sample rate of the device.</returns>
266         /// <remarks>
267         /// This device should be <see cref="AudioDeviceType.UsbAudio"/> type and <see cref="AudioDeviceIoDirection.Output"/> direction.
268         /// </remarks>
269         /// <exception cref="InvalidOperationException">This device is not valid or is disconnected.</exception>
270         /// <since_tizen> 5 </since_tizen>
271         public uint GetSampleRate()
272         {
273             Interop.AudioDevice.GetSampleRate(_id, out uint rate).
274                 ThrowIfError("Failed to get sample rate of the device");
275
276             return ConvertCoreRateValToUint((int)rate);
277         }
278
279         /// <summary>
280         /// Sets the device's 'avoid resampling' property.
281         /// </summary>
282         /// <param name="enable">The 'avoid resampling' value to set to the device.</param>
283         /// <remarks>
284         /// This device should be <see cref="AudioDeviceType.UsbAudio"/> type and <see cref="AudioDeviceIoDirection.Output"/> direction.
285         /// This property is not enabled as default. With this enabled, this device will use the first stream's original sample format
286         /// and rate without resampling if supported.
287         /// </remarks>
288         /// <exception cref="InvalidOperationException">This device is not valid or is disconnected.</exception>
289         /// <since_tizen> 5 </since_tizen>
290         public void SetAvoidResampling(bool enable)
291         {
292             Interop.AudioDevice.SetAvoidResampling(_id, enable).
293                 ThrowIfError("Failed to set avoid-resampling property of the device");
294
295         }
296
297         /// <summary>
298         /// Gets the device's 'avoid resampling' property.
299         /// </summary>
300         /// <returns>The 'avoid resampling' property of the device.</returns>
301         /// <remarks>
302         /// This device should be <see cref="AudioDeviceType.UsbAudio"/> type and <see cref="AudioDeviceIoDirection.Output"/> direction.
303         /// This property is not enabled as default. With this enabled, this device will use the first stream's original sample format
304         /// and rate without resampling if supported.
305         /// </remarks>
306         /// <exception cref="InvalidOperationException">This device is not valid or is disconnected.</exception>
307         /// <since_tizen> 5 </since_tizen>
308         public bool GetAvoidResampling()
309         {
310             Interop.AudioDevice.GetAvoidResampling(_id, out bool enabled).
311                 ThrowIfError("Failed to get avoid-resampling property of the device");
312
313             return enabled;
314         }
315
316         /// <summary>
317         /// Sets the restriction of stream type only for media.
318         /// </summary>
319         /// <param name="enable">The 'media stream only' value to set to the device.</param>
320         /// <remarks>
321         /// This device should be <see cref="AudioDeviceType.UsbAudio"/> type and <see cref="AudioDeviceIoDirection.Output"/> direction.
322         ///     This property is not enabled as default. With this enabled, no other stream types except <see cref="AudioStreamType.Media"/>
323         ///     are not allowed to this device.
324         /// </remarks>
325         /// <exception cref="InvalidOperationException">This device is not valid or is disconnected.</exception>
326         /// <since_tizen> 5 </since_tizen>
327         public void SetMediaStreamOnly(bool enable)
328         {
329             Interop.AudioDevice.SetMediaStreamOnly(_id, enable).
330                 ThrowIfError("Failed to set media-stream-only property of the device");
331         }
332
333         /// <summary>
334         /// Gets the restriction of stream type only for media.
335         /// </summary>
336         /// <returns>The 'media stream only' property of the device.</returns>
337         /// <remarks>
338         /// This device should be <see cref="AudioDeviceType.UsbAudio"/> type and <see cref="AudioDeviceIoDirection.Output"/> direction.
339         ///     This property is not enabled as default. With this enabled, no other stream types except <see cref="AudioStreamType.Media"/>
340         ///     are not allowed to this device.
341         /// </remarks>
342         /// <exception cref="InvalidOperationException">This device is not valid or is disconnected.</exception>
343         /// <since_tizen> 5 </since_tizen>
344         public bool GetMediaStreamOnly()
345         {
346             Interop.AudioDevice.GetMediaStreamOnly(_id, out bool enabled).
347                 ThrowIfError("Failed to get media-stream-only property of the device");
348
349             return enabled;
350         }
351
352         /// <summary>
353         /// Returns a string that represents the current object.
354         /// </summary>
355         /// <returns>A string that represents the current object.</returns>
356         /// <since_tizen> 4 </since_tizen>
357         public override string ToString() =>
358             $"Id={Id}, Name={Name}, Type={Type}, IoDirection={IoDirection}, IsRunning={IsRunning}";
359
360         /// <summary>
361         /// Compares an object to an instance of <see cref="AudioDevice"/> for equality.
362         /// </summary>
363         /// <param name="obj">A <see cref="Object"/> to compare.</param>
364         /// <returns>true if the two devices are equal; otherwise, false.</returns>
365         /// <since_tizen> 4 </since_tizen>
366         public override bool Equals(object obj)
367         {
368             var rhs = obj as AudioDevice;
369             if (rhs == null)
370             {
371                 return false;
372             }
373
374             return Id == rhs.Id;
375         }
376
377         /// <summary>
378         /// Gets the hash code for this instance of <see cref="AudioDevice"/>.
379         /// </summary>
380         /// <returns>The hash code for this instance of <see cref="AudioDevice"/>.</returns>
381         /// <since_tizen> 4 </since_tizen>
382         public override int GetHashCode()
383         {
384             return Id.GetHashCode();
385         }
386     }
387 }