/*
* Copyright (c) 2018 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.Runtime.InteropServices;
using System.Collections.Generic;
using System.Linq;
namespace Tizen.Multimedia
{
///
/// Provides the ability to query the information of sound devices.
///
/// 3
public class AudioDevice
{
private readonly int _id;
private readonly AudioDeviceType _type;
private readonly AudioDeviceIoDirection _ioDirection;
private const string Tag = "Tizen.Multimedia.AudioDevice";
internal AudioDevice(IntPtr deviceHandle)
{
int ret = Interop.AudioDevice.GetDeviceId(deviceHandle, out _id);
MultimediaDebug.AssertNoError(ret);
ret = Interop.AudioDevice.GetDeviceName(deviceHandle, out var name);
MultimediaDebug.AssertNoError(ret);
Name = Marshal.PtrToStringAnsi(name);
ret = Interop.AudioDevice.GetDeviceType(deviceHandle, out _type);
MultimediaDebug.AssertNoError(ret);
ret = Interop.AudioDevice.GetDeviceIoDirection(deviceHandle, out _ioDirection);
MultimediaDebug.AssertNoError(ret);
}
///
/// Gets the ID of the device.
///
/// The id of the device.
/// 3
public int Id => _id;
///
/// Gets the name of the device.
///
/// The name of the device.
/// 3
public string Name { get; }
///
/// Gets the type of the device.
///
/// The of the device.
/// 3
public AudioDeviceType Type => _type;
///
/// Gets the IO direction of the device.
///
/// The IO direction of the device.
/// 3
public AudioDeviceIoDirection IoDirection => _ioDirection;
///
/// Gets the state of the device.
///
/// The of the device.
/// 3
[Obsolete("Deprecated since API level 5. Please use the IsRunning property instead.")]
public AudioDeviceState State
{
get
{
Interop.AudioDevice.GetDeviceState(Id, out var state).
ThrowIfError("Failed to get the state of the device");
return state;
}
}
///
/// Gets the running state of the device.
///
/// true if the audio stream of device is running actually; otherwise, false.
/// 5
public bool IsRunning
{
get
{
Interop.AudioDevice.IsDeviceRunning(_id, out bool isRunning).
ThrowIfError("Failed to get the running state of the device");
return isRunning;
}
}
///
/// Gets the device's supported sample formats.
///
/// An IEnumerable<AudioSampleFormat> that contains supported sample formats.
///
/// This device should be type and direction.
///
/// This device is not valid or is disconnected.
/// 5
public IEnumerable GetSupportedSampleFormats()
{
Interop.AudioDevice.GetSupportedSampleFormats(_id, out IntPtr formats, out uint numberOfElements).
ThrowIfError("Failed to get supported sample formats");
return RetrieveFormats();
IEnumerable RetrieveFormats()
{
int[] formatsResult = new int[numberOfElements];
Marshal.Copy(formats, formatsResult, 0, (int)numberOfElements);
Interop.Libc.Free(formats);
foreach (int f in formatsResult)
{
Log.Debug(Tag, $"supported sample format:{f}");
}
return formatsResult.Cast();
}
}
///
/// Sets the device's sample format.
///
/// The to set to the device.
///
/// This device should be type and direction.
///
/// This device is not valid or is disconnected.
/// 5
public void SetSampleFormat(AudioSampleFormat format)
{
Interop.AudioDevice.SetSampleFormat(_id, format).
ThrowIfError("Failed to set sample format of the device");
}
///
/// Gets the device's sample format.
///
/// The of the device.
///
/// This device should be type and direction.
///
/// This device is not valid or is disconnected.
/// 5
public AudioSampleFormat GetSampleFormat()
{
Interop.AudioDevice.GetSampleFormat(_id, out AudioSampleFormat format).
ThrowIfError("Failed to get sample format of the device");
return format;
}
private uint ConvertCoreRateValToUint(int value)
{
switch (value)
{
case 0: return 8000;
case 1: return 16000;
case 2: return 22050;
case 3: return 44100;
case 4: return 48000;
case 5: return 88200;
case 6: return 96000;
case 7: return 192000;
default:
Log.Error(Tag, $"unknown value from core:{value}");
return 0;
}
}
private uint ConvertRateToCoreValue(uint rate)
{
switch (rate)
{
case 8000: return 0;
case 16000: return 1;
case 22050: return 2;
case 44100: return 3;
case 48000: return 4;
case 88200: return 5;
case 96000: return 6;
case 192000: return 7;
default:
Log.Error(Tag, $"not supported rate:{rate}");
return 0;
}
}
///
/// Gets the device's supported sample rates.
///
/// An IEnumerable<uint> that contains supported sample rates.
///
/// This device should be type and direction.
///
/// This device is not valid or is disconnected.
/// 5
public IEnumerable GetSupportedSampleRates()
{
Interop.AudioDevice.GetSupportedSampleRates(_id, out IntPtr rates, out uint numberOfElements).
ThrowIfError("Failed to get supported sample formats");
return RetrieveRates();
IEnumerable RetrieveRates()
{
int[] ratesResult = new int[numberOfElements];
uint[] convertedRates = new uint[numberOfElements];
Marshal.Copy(rates, ratesResult, 0, (int)numberOfElements);
Interop.Libc.Free(rates);
for (int i = 0; i < ratesResult.Length; i++)
{
convertedRates[i] = ConvertCoreRateValToUint(ratesResult[i]);
Log.Debug(Tag, $"supported sample rate:{convertedRates[i]}");
}
return convertedRates;
}
}
///
/// Sets the device's sample rate.
///
/// The sample rate to set to the device.
///
/// This device should be type and direction.
///
/// This device is not valid or is disconnected.
/// 5
public void SetSampleRate(uint rate)
{
Interop.AudioDevice.SetSampleRate(_id, ConvertRateToCoreValue(rate)).
ThrowIfError("Failed to set sample rate of the device");
}
///
/// Gets the device's sample rate.
///
/// The sample rate of the device.
///
/// This device should be type and direction.
///
/// This device is not valid or is disconnected.
/// 5
public uint GetSampleRate()
{
Interop.AudioDevice.GetSampleRate(_id, out uint rate).
ThrowIfError("Failed to get sample rate of the device");
return ConvertCoreRateValToUint((int)rate);
}
///
/// Sets the device's 'avoid resampling' property.
///
/// The 'avoid resampling' value to set to the device.
///
/// This device should be type and direction.
/// This property is not enabled as default. With this enabled, this device will use the first stream's original sample format
/// and rate without resampling if supported.
///
/// This device is not valid or is disconnected.
/// 5
public void SetAvoidResampling(bool enable)
{
Interop.AudioDevice.SetAvoidResampling(_id, enable).
ThrowIfError("Failed to set avoid-resampling property of the device");
}
///
/// Gets the device's 'avoid resampling' property.
///
/// The 'avoid resampling' property of the device.
///
/// This device should be type and direction.
/// This property is not enabled as default. With this enabled, this device will use the first stream's original sample format
/// and rate without resampling if supported.
///
/// This device is not valid or is disconnected.
/// 5
public bool GetAvoidResampling()
{
Interop.AudioDevice.GetAvoidResampling(_id, out bool enabled).
ThrowIfError("Failed to get avoid-resampling property of the device");
return enabled;
}
///
/// Sets the restriction of stream type only for media.
///
/// The 'media stream only' value to set to the device.
///
/// This device should be type and direction.
/// This property is not enabled as default. With this enabled, no other stream types except
/// are not allowed to this device.
///
/// This device is not valid or is disconnected.
/// 5
public void SetMediaStreamOnly(bool enable)
{
Interop.AudioDevice.SetMediaStreamOnly(_id, enable).
ThrowIfError("Failed to set media-stream-only property of the device");
}
///
/// Gets the restriction of stream type only for media.
///
/// The 'media stream only' property of the device.
///
/// This device should be type and direction.
/// This property is not enabled as default. With this enabled, no other stream types except
/// are not allowed to this device.
///
/// This device is not valid or is disconnected.
/// 5
public bool GetMediaStreamOnly()
{
Interop.AudioDevice.GetMediaStreamOnly(_id, out bool enabled).
ThrowIfError("Failed to get media-stream-only property of the device");
return enabled;
}
///
/// Returns a string that represents the current object.
///
/// A string that represents the current object.
/// 4
public override string ToString() =>
$"Id={Id}, Name={Name}, Type={Type}, IoDirection={IoDirection}, IsRunning={IsRunning}";
///
/// Compares an object to an instance of for equality.
///
/// A to compare.
/// true if the two devices are equal; otherwise, false.
/// 4
public override bool Equals(object obj)
{
var rhs = obj as AudioDevice;
if (rhs == null)
{
return false;
}
return Id == rhs.Id;
}
///
/// Gets the hash code for this instance of .
///
/// The hash code for this instance of .
/// 4
public override int GetHashCode()
{
return Id.GetHashCode();
}
}
}