diff options
Diffstat (limited to 'src/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs')
| -rw-r--r-- | src/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/src/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs b/src/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs new file mode 100644 index 00000000..a137c413 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs @@ -0,0 +1,217 @@ +using Ryujinx.Common.Logging; +using Ryujinx.Common.Memory; +using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.HLE.HOS.Kernel.Threading; +using Ryujinx.Horizon.Common; +using System; +using System.Buffers; + +namespace Ryujinx.HLE.HOS.Services.Audio.AudioRenderer +{ + class AudioRendererServer : DisposableIpcService + { + private IAudioRenderer _impl; + + public AudioRendererServer(IAudioRenderer impl) + { + _impl = impl; + } + + [CommandCmif(0)] + // GetSampleRate() -> u32 + public ResultCode GetSampleRate(ServiceCtx context) + { + context.ResponseData.Write(_impl.GetSampleRate()); + + return ResultCode.Success; + } + + [CommandCmif(1)] + // GetSampleCount() -> u32 + public ResultCode GetSampleCount(ServiceCtx context) + { + context.ResponseData.Write(_impl.GetSampleCount()); + + return ResultCode.Success; + } + + [CommandCmif(2)] + // GetMixBufferCount() -> u32 + public ResultCode GetMixBufferCount(ServiceCtx context) + { + context.ResponseData.Write(_impl.GetMixBufferCount()); + + return ResultCode.Success; + } + + [CommandCmif(3)] + // GetState() -> u32 + public ResultCode GetState(ServiceCtx context) + { + context.ResponseData.Write(_impl.GetState()); + + return ResultCode.Success; + } + + [CommandCmif(4)] + // RequestUpdate(buffer<nn::audio::detail::AudioRendererUpdateDataHeader, 5> input) + // -> (buffer<nn::audio::detail::AudioRendererUpdateDataHeader, 6> output, buffer<nn::audio::detail::AudioRendererUpdateDataHeader, 6> performanceOutput) + public ResultCode RequestUpdate(ServiceCtx context) + { + ulong inputPosition = context.Request.SendBuff[0].Position; + ulong inputSize = context.Request.SendBuff[0].Size; + + ulong outputPosition = context.Request.ReceiveBuff[0].Position; + ulong outputSize = context.Request.ReceiveBuff[0].Size; + + ulong performanceOutputPosition = context.Request.ReceiveBuff[1].Position; + ulong performanceOutputSize = context.Request.ReceiveBuff[1].Size; + + ReadOnlyMemory<byte> input = context.Memory.GetSpan(inputPosition, (int)inputSize).ToArray(); + + using (IMemoryOwner<byte> outputOwner = ByteMemoryPool.Shared.RentCleared(outputSize)) + using (IMemoryOwner<byte> performanceOutputOwner = ByteMemoryPool.Shared.RentCleared(performanceOutputSize)) + { + Memory<byte> output = outputOwner.Memory; + Memory<byte> performanceOutput = performanceOutputOwner.Memory; + + using MemoryHandle outputHandle = output.Pin(); + using MemoryHandle performanceOutputHandle = performanceOutput.Pin(); + + ResultCode result = _impl.RequestUpdate(output, performanceOutput, input); + + if (result == ResultCode.Success) + { + context.Memory.Write(outputPosition, output.Span); + context.Memory.Write(performanceOutputPosition, performanceOutput.Span); + } + else + { + Logger.Error?.Print(LogClass.ServiceAudio, $"Error while processing renderer update: 0x{(int)result:X}"); + } + + return result; + } + } + + [CommandCmif(5)] + // Start() + public ResultCode Start(ServiceCtx context) + { + return _impl.Start(); + } + + [CommandCmif(6)] + // Stop() + public ResultCode Stop(ServiceCtx context) + { + return _impl.Stop(); + } + + [CommandCmif(7)] + // QuerySystemEvent() -> handle<copy, event> + public ResultCode QuerySystemEvent(ServiceCtx context) + { + ResultCode result = _impl.QuerySystemEvent(out KEvent systemEvent); + + if (result == ResultCode.Success) + { + if (context.Process.HandleTable.GenerateHandle(systemEvent.ReadableEvent, out int handle) != Result.Success) + { + throw new InvalidOperationException("Out of handles!"); + } + + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle); + } + + return result; + } + + [CommandCmif(8)] + // SetAudioRendererRenderingTimeLimit(u32 limit) + public ResultCode SetAudioRendererRenderingTimeLimit(ServiceCtx context) + { + uint limit = context.RequestData.ReadUInt32(); + + _impl.SetRenderingTimeLimit(limit); + + return ResultCode.Success; + } + + [CommandCmif(9)] + // GetAudioRendererRenderingTimeLimit() -> u32 limit + public ResultCode GetAudioRendererRenderingTimeLimit(ServiceCtx context) + { + uint limit = _impl.GetRenderingTimeLimit(); + + context.ResponseData.Write(limit); + + return ResultCode.Success; + } + + [CommandCmif(10)] // 3.0.0+ + // RequestUpdateAuto(buffer<nn::audio::detail::AudioRendererUpdateDataHeader, 0x21> input) + // -> (buffer<nn::audio::detail::AudioRendererUpdateDataHeader, 0x22> output, buffer<nn::audio::detail::AudioRendererUpdateDataHeader, 0x22> performanceOutput) + public ResultCode RequestUpdateAuto(ServiceCtx context) + { + (ulong inputPosition, ulong inputSize) = context.Request.GetBufferType0x21(); + (ulong outputPosition, ulong outputSize) = context.Request.GetBufferType0x22(0); + (ulong performanceOutputPosition, ulong performanceOutputSize) = context.Request.GetBufferType0x22(1); + + ReadOnlyMemory<byte> input = context.Memory.GetSpan(inputPosition, (int)inputSize).ToArray(); + + Memory<byte> output = new byte[outputSize]; + Memory<byte> performanceOutput = new byte[performanceOutputSize]; + + using MemoryHandle outputHandle = output.Pin(); + using MemoryHandle performanceOutputHandle = performanceOutput.Pin(); + + ResultCode result = _impl.RequestUpdate(output, performanceOutput, input); + + if (result == ResultCode.Success) + { + context.Memory.Write(outputPosition, output.Span); + context.Memory.Write(performanceOutputPosition, performanceOutput.Span); + } + + return result; + } + + [CommandCmif(11)] // 3.0.0+ + // ExecuteAudioRendererRendering() + public ResultCode ExecuteAudioRendererRendering(ServiceCtx context) + { + return _impl.ExecuteAudioRendererRendering(); + } + + [CommandCmif(12)] // 15.0.0+ + // SetVoiceDropParameter(f32 voiceDropParameter) + public ResultCode SetVoiceDropParameter(ServiceCtx context) + { + float voiceDropParameter = context.RequestData.ReadSingle(); + + _impl.SetVoiceDropParameter(voiceDropParameter); + + return ResultCode.Success; + } + + [CommandCmif(13)] // 15.0.0+ + // GetVoiceDropParameter() -> f32 voiceDropParameter + public ResultCode GetVoiceDropParameter(ServiceCtx context) + { + float voiceDropParameter = _impl.GetVoiceDropParameter(); + + context.ResponseData.Write(voiceDropParameter); + + return ResultCode.Success; + } + + protected override void Dispose(bool isDisposing) + { + if (isDisposing) + { + _impl.Dispose(); + } + } + } +}
\ No newline at end of file |
