2020-08-18 03:49:37 +02:00
|
|
|
|
using Ryujinx.Audio.Renderer.Device;
|
|
|
|
|
using Ryujinx.Audio.Renderer.Server;
|
|
|
|
|
using Ryujinx.HLE.HOS.Kernel;
|
|
|
|
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
|
|
|
|
|
|
|
|
|
namespace Ryujinx.HLE.HOS.Services.Audio.AudioRenderer
|
|
|
|
|
{
|
|
|
|
|
class AudioDevice : IAudioDevice
|
|
|
|
|
{
|
|
|
|
|
private VirtualDeviceSession[] _sessions;
|
|
|
|
|
private ulong _appletResourceId;
|
|
|
|
|
private int _revision;
|
|
|
|
|
private bool _isUsbDeviceSupported;
|
|
|
|
|
|
|
|
|
|
private VirtualDeviceSessionRegistry _registry;
|
|
|
|
|
private KEvent _systemEvent;
|
|
|
|
|
|
|
|
|
|
public AudioDevice(VirtualDeviceSessionRegistry registry, KernelContext context, ulong appletResourceId, int revision)
|
|
|
|
|
{
|
|
|
|
|
_registry = registry;
|
|
|
|
|
_appletResourceId = appletResourceId;
|
|
|
|
|
_revision = revision;
|
|
|
|
|
|
|
|
|
|
BehaviourContext behaviourContext = new BehaviourContext();
|
|
|
|
|
behaviourContext.SetUserRevision(revision);
|
|
|
|
|
|
|
|
|
|
_isUsbDeviceSupported = behaviourContext.IsAudioUsbDeviceOutputSupported();
|
|
|
|
|
_sessions = _registry.GetSessionByAppletResourceId(appletResourceId);
|
|
|
|
|
|
|
|
|
|
// TODO: support the 3 different events correctly when we will have hot plugable audio devices.
|
|
|
|
|
_systemEvent = new KEvent(context);
|
|
|
|
|
_systemEvent.ReadableEvent.Signal();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool TryGetDeviceByName(out VirtualDeviceSession result, string name, bool ignoreRevLimitation = false)
|
|
|
|
|
{
|
|
|
|
|
result = null;
|
|
|
|
|
|
|
|
|
|
foreach (VirtualDeviceSession session in _sessions)
|
|
|
|
|
{
|
|
|
|
|
if (session.Device.Name.Equals(name))
|
|
|
|
|
{
|
|
|
|
|
if (!ignoreRevLimitation && !_isUsbDeviceSupported && session.Device.IsUsbDevice())
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = session;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string GetActiveAudioDeviceName()
|
|
|
|
|
{
|
|
|
|
|
VirtualDevice device = _registry.ActiveDevice;
|
|
|
|
|
|
|
|
|
|
if (!_isUsbDeviceSupported && device.IsUsbDevice())
|
|
|
|
|
{
|
|
|
|
|
device = _registry.DefaultDevice;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return device.Name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public uint GetActiveChannelCount()
|
|
|
|
|
{
|
|
|
|
|
VirtualDevice device = _registry.ActiveDevice;
|
|
|
|
|
|
|
|
|
|
if (!_isUsbDeviceSupported && device.IsUsbDevice())
|
|
|
|
|
{
|
|
|
|
|
device = _registry.DefaultDevice;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return device.ChannelCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ResultCode GetAudioDeviceOutputVolume(string name, out float volume)
|
|
|
|
|
{
|
|
|
|
|
if (TryGetDeviceByName(out VirtualDeviceSession result, name))
|
|
|
|
|
{
|
|
|
|
|
volume = result.Volume;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
volume = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ResultCode.Success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ResultCode SetAudioDeviceOutputVolume(string name, float volume)
|
|
|
|
|
{
|
|
|
|
|
if (TryGetDeviceByName(out VirtualDeviceSession result, name, true))
|
|
|
|
|
{
|
|
|
|
|
if (!_isUsbDeviceSupported && result.Device.IsUsbDevice())
|
|
|
|
|
{
|
|
|
|
|
result = _sessions[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result.Volume = volume;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ResultCode.Success;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-19 12:29:19 +02:00
|
|
|
|
public string GetActiveAudioOutputDeviceName()
|
2020-08-18 03:49:37 +02:00
|
|
|
|
{
|
2021-09-19 12:29:19 +02:00
|
|
|
|
return _registry.ActiveDevice.GetOutputDeviceName();
|
2020-08-18 03:49:37 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string[] ListAudioDeviceName()
|
|
|
|
|
{
|
|
|
|
|
int deviceCount = _sessions.Length;
|
|
|
|
|
|
|
|
|
|
if (!_isUsbDeviceSupported)
|
|
|
|
|
{
|
|
|
|
|
deviceCount--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string[] result = new string[deviceCount];
|
|
|
|
|
|
2021-09-19 12:29:19 +02:00
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
foreach (VirtualDeviceSession session in _sessions)
|
2020-08-18 03:49:37 +02:00
|
|
|
|
{
|
2021-09-19 13:42:16 +02:00
|
|
|
|
if (!_isUsbDeviceSupported && session.Device.IsUsbDevice())
|
2021-09-19 12:29:19 +02:00
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-19 13:42:16 +02:00
|
|
|
|
result[i] = session.Device.Name;
|
2021-09-19 12:29:19 +02:00
|
|
|
|
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string[] ListAudioOutputDeviceName()
|
|
|
|
|
{
|
|
|
|
|
int deviceCount = _sessions.Length;
|
|
|
|
|
|
|
|
|
|
string[] result = new string[deviceCount];
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < deviceCount; i++)
|
|
|
|
|
{
|
|
|
|
|
result[i] = _sessions[i].Device.GetOutputDeviceName();
|
2020-08-18 03:49:37 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public KEvent QueryAudioDeviceInputEvent()
|
|
|
|
|
{
|
|
|
|
|
return _systemEvent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public KEvent QueryAudioDeviceOutputEvent()
|
|
|
|
|
{
|
|
|
|
|
return _systemEvent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public KEvent QueryAudioDeviceSystemEvent()
|
|
|
|
|
{
|
|
|
|
|
return _systemEvent;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|