Migrate Audio service to new IPC (#6285)
* Migrate audren to new IPC * Migrate audout * Migrate audin * Migrate hwopus * Bye bye old audio service * Switch volume control to IHardwareDeviceDriver * Somewhat unrelated changes * Remove Concentus reference from HLE * Implement OpenAudioRendererForManualExecution * Remove SetVolume/GetVolume methods that are not necessary * Remove SetVolume/GetVolume methods that are not necessary (2) * Fix incorrect volume update * PR feedback * PR feedback * Stub audrec * Init outParameter * Make FinalOutputRecorderParameter/Internal readonly * Make FinalOutputRecorder IDisposable * Fix HardwareOpusDecoderManager parameter buffers * Opus work buffer size and error handling improvements * Add AudioInProtocolName enum * Fix potential divisions by zero
This commit is contained in:
parent
57d8afd0c9
commit
d4d0a48bfe
130 changed files with 3096 additions and 3174 deletions
252
src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioDevice.cs
Normal file
252
src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioDevice.cs
Normal file
|
@ -0,0 +1,252 @@
|
|||
using Ryujinx.Audio.Renderer.Device;
|
||||
using Ryujinx.Audio.Renderer.Server;
|
||||
using Ryujinx.Horizon.Common;
|
||||
using Ryujinx.Horizon.Sdk.Applet;
|
||||
using Ryujinx.Horizon.Sdk.OsTypes;
|
||||
using Ryujinx.Horizon.Sdk.Sf;
|
||||
using Ryujinx.Horizon.Sdk.Sf.Hipc;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Horizon.Sdk.Audio.Detail
|
||||
{
|
||||
partial class AudioDevice : IAudioDevice, IDisposable
|
||||
{
|
||||
private readonly VirtualDeviceSessionRegistry _registry;
|
||||
private readonly VirtualDeviceSession[] _sessions;
|
||||
private readonly bool _isUsbDeviceSupported;
|
||||
|
||||
private SystemEventType _audioEvent;
|
||||
private SystemEventType _audioInputEvent;
|
||||
private SystemEventType _audioOutputEvent;
|
||||
|
||||
public AudioDevice(VirtualDeviceSessionRegistry registry, AppletResourceUserId appletResourceId, uint revision)
|
||||
{
|
||||
_registry = registry;
|
||||
|
||||
BehaviourContext behaviourContext = new();
|
||||
behaviourContext.SetUserRevision((int)revision);
|
||||
|
||||
_isUsbDeviceSupported = behaviourContext.IsAudioUsbDeviceOutputSupported();
|
||||
_sessions = registry.GetSessionByAppletResourceId(appletResourceId.Id);
|
||||
|
||||
Os.CreateSystemEvent(out _audioEvent, EventClearMode.AutoClear, interProcess: true);
|
||||
Os.CreateSystemEvent(out _audioInputEvent, EventClearMode.AutoClear, interProcess: true);
|
||||
Os.CreateSystemEvent(out _audioOutputEvent, EventClearMode.AutoClear, interProcess: true);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
[CmifCommand(0)]
|
||||
public Result ListAudioDeviceName([Buffer(HipcBufferFlags.Out | HipcBufferFlags.MapAlias)] Span<DeviceName> names, out int nameCount)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
foreach (VirtualDeviceSession session in _sessions)
|
||||
{
|
||||
if (!_isUsbDeviceSupported && session.Device.IsUsbDevice())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (count >= names.Length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
names[count] = new DeviceName(session.Device.Name);
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
nameCount = count;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
[CmifCommand(1)]
|
||||
public Result SetAudioDeviceOutputVolume([Buffer(HipcBufferFlags.In | HipcBufferFlags.MapAlias)] ReadOnlySpan<DeviceName> name, float volume)
|
||||
{
|
||||
if (name.Length > 0 && TryGetDeviceByName(out VirtualDeviceSession result, name[0].ToString(), ignoreRevLimitation: true))
|
||||
{
|
||||
if (!_isUsbDeviceSupported && result.Device.IsUsbDevice())
|
||||
{
|
||||
result = _sessions[0];
|
||||
}
|
||||
|
||||
result.Volume = volume;
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
[CmifCommand(2)]
|
||||
public Result GetAudioDeviceOutputVolume([Buffer(HipcBufferFlags.In | HipcBufferFlags.MapAlias)] ReadOnlySpan<DeviceName> name, out float volume)
|
||||
{
|
||||
if (name.Length > 0 && TryGetDeviceByName(out VirtualDeviceSession result, name[0].ToString()))
|
||||
{
|
||||
volume = result.Volume;
|
||||
}
|
||||
else
|
||||
{
|
||||
volume = 0f;
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
[CmifCommand(3)]
|
||||
public Result GetActiveAudioDeviceName([Buffer(HipcBufferFlags.Out | HipcBufferFlags.MapAlias)] Span<DeviceName> name)
|
||||
{
|
||||
VirtualDevice device = _registry.ActiveDevice;
|
||||
|
||||
if (!_isUsbDeviceSupported && device.IsUsbDevice())
|
||||
{
|
||||
device = _registry.DefaultDevice;
|
||||
}
|
||||
|
||||
if (name.Length > 0)
|
||||
{
|
||||
name[0] = new DeviceName(device.Name);
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
[CmifCommand(4)]
|
||||
public Result QueryAudioDeviceSystemEvent([CopyHandle] out int eventHandle)
|
||||
{
|
||||
eventHandle = Os.GetReadableHandleOfSystemEvent(ref _audioEvent);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
[CmifCommand(5)]
|
||||
public Result GetActiveChannelCount(out int channelCount)
|
||||
{
|
||||
VirtualDevice device = _registry.ActiveDevice;
|
||||
|
||||
if (!_isUsbDeviceSupported && device.IsUsbDevice())
|
||||
{
|
||||
device = _registry.DefaultDevice;
|
||||
}
|
||||
|
||||
channelCount = (int)device.ChannelCount;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
[CmifCommand(6)] // 3.0.0+
|
||||
public Result ListAudioDeviceNameAuto([Buffer(HipcBufferFlags.Out | HipcBufferFlags.AutoSelect)] Span<DeviceName> names, out int nameCount)
|
||||
{
|
||||
return ListAudioDeviceName(names, out nameCount);
|
||||
}
|
||||
|
||||
[CmifCommand(7)] // 3.0.0+
|
||||
public Result SetAudioDeviceOutputVolumeAuto([Buffer(HipcBufferFlags.In | HipcBufferFlags.AutoSelect)] ReadOnlySpan<DeviceName> name, float volume)
|
||||
{
|
||||
return SetAudioDeviceOutputVolume(name, volume);
|
||||
}
|
||||
|
||||
[CmifCommand(8)] // 3.0.0+
|
||||
public Result GetAudioDeviceOutputVolumeAuto([Buffer(HipcBufferFlags.In | HipcBufferFlags.AutoSelect)] ReadOnlySpan<DeviceName> name, out float volume)
|
||||
{
|
||||
return GetAudioDeviceOutputVolume(name, out volume);
|
||||
}
|
||||
|
||||
[CmifCommand(10)] // 3.0.0+
|
||||
public Result GetActiveAudioDeviceNameAuto([Buffer(HipcBufferFlags.Out | HipcBufferFlags.AutoSelect)] Span<DeviceName> name)
|
||||
{
|
||||
return GetActiveAudioDeviceName(name);
|
||||
}
|
||||
|
||||
[CmifCommand(11)] // 3.0.0+
|
||||
public Result QueryAudioDeviceInputEvent([CopyHandle] out int eventHandle)
|
||||
{
|
||||
eventHandle = Os.GetReadableHandleOfSystemEvent(ref _audioInputEvent);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
[CmifCommand(12)] // 3.0.0+
|
||||
public Result QueryAudioDeviceOutputEvent([CopyHandle] out int eventHandle)
|
||||
{
|
||||
eventHandle = Os.GetReadableHandleOfSystemEvent(ref _audioOutputEvent);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
[CmifCommand(13)] // 13.0.0+
|
||||
public Result GetActiveAudioOutputDeviceName([Buffer(HipcBufferFlags.Out | HipcBufferFlags.MapAlias)] Span<DeviceName> name)
|
||||
{
|
||||
if (name.Length > 0)
|
||||
{
|
||||
name[0] = new DeviceName(_registry.ActiveDevice.GetOutputDeviceName());
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
[CmifCommand(14)] // 13.0.0+
|
||||
public Result ListAudioOutputDeviceName([Buffer(HipcBufferFlags.Out | HipcBufferFlags.MapAlias)] Span<DeviceName> names, out int nameCount)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
foreach (VirtualDeviceSession session in _sessions)
|
||||
{
|
||||
if (!_isUsbDeviceSupported && session.Device.IsUsbDevice())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (count >= names.Length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
names[count] = new DeviceName(session.Device.GetOutputDeviceName());
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
nameCount = count;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
Os.DestroySystemEvent(ref _audioEvent);
|
||||
Os.DestroySystemEvent(ref _audioInputEvent);
|
||||
Os.DestroySystemEvent(ref _audioOutputEvent);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue