AudioOutServer.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. using Ryujinx.Audio.Common;
  2. using Ryujinx.Cpu;
  3. using Ryujinx.HLE.HOS.Ipc;
  4. using Ryujinx.HLE.HOS.Kernel.Common;
  5. using Ryujinx.HLE.HOS.Kernel.Threading;
  6. using Ryujinx.Memory;
  7. using System;
  8. using System.Runtime.InteropServices;
  9. namespace Ryujinx.HLE.HOS.Services.Audio.AudioOut
  10. {
  11. class AudioOutServer : DisposableIpcService
  12. {
  13. private IAudioOut _impl;
  14. public AudioOutServer(IAudioOut impl)
  15. {
  16. _impl = impl;
  17. }
  18. [CommandHipc(0)]
  19. // GetAudioOutState() -> u32 state
  20. public ResultCode GetAudioOutState(ServiceCtx context)
  21. {
  22. context.ResponseData.Write((uint)_impl.GetState());
  23. return ResultCode.Success;
  24. }
  25. [CommandHipc(1)]
  26. // Start()
  27. public ResultCode Start(ServiceCtx context)
  28. {
  29. return _impl.Start();
  30. }
  31. [CommandHipc(2)]
  32. // Stop()
  33. public ResultCode Stop(ServiceCtx context)
  34. {
  35. return _impl.Stop();
  36. }
  37. [CommandHipc(3)]
  38. // AppendAudioOutBuffer(u64 bufferTag, buffer<nn::audio::AudioOutBuffer, 5> buffer)
  39. public ResultCode AppendAudioOutBuffer(ServiceCtx context)
  40. {
  41. ulong position = context.Request.SendBuff[0].Position;
  42. ulong bufferTag = context.RequestData.ReadUInt64();
  43. AudioUserBuffer data = MemoryHelper.Read<AudioUserBuffer>(context.Memory, position);
  44. return _impl.AppendBuffer(bufferTag, ref data);
  45. }
  46. [CommandHipc(4)]
  47. // RegisterBufferEvent() -> handle<copy>
  48. public ResultCode RegisterBufferEvent(ServiceCtx context)
  49. {
  50. KEvent bufferEvent = _impl.RegisterBufferEvent();
  51. if (context.Process.HandleTable.GenerateHandle(bufferEvent.ReadableEvent, out int handle) != KernelResult.Success)
  52. {
  53. throw new InvalidOperationException("Out of handles!");
  54. }
  55. context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
  56. return ResultCode.Success;
  57. }
  58. [CommandHipc(5)]
  59. // GetReleasedAudioOutBuffers() -> (u32 count, buffer<u64, 6> tags)
  60. public ResultCode GetReleasedAudioOutBuffers(ServiceCtx context)
  61. {
  62. ulong position = context.Request.ReceiveBuff[0].Position;
  63. ulong size = context.Request.ReceiveBuff[0].Size;
  64. using (WritableRegion outputRegion = context.Memory.GetWritableRegion(position, (int)size))
  65. {
  66. ResultCode result = _impl.GetReleasedBuffers(MemoryMarshal.Cast<byte, ulong>(outputRegion.Memory.Span), out uint releasedCount);
  67. context.ResponseData.Write(releasedCount);
  68. return result;
  69. }
  70. }
  71. [CommandHipc(6)]
  72. // ContainsAudioOutBuffer(u64 tag) -> b8
  73. public ResultCode ContainsAudioOutBuffer(ServiceCtx context)
  74. {
  75. ulong bufferTag = context.RequestData.ReadUInt64();
  76. context.ResponseData.Write(_impl.ContainsBuffer(bufferTag));
  77. return ResultCode.Success;
  78. }
  79. [CommandHipc(7)] // 3.0.0+
  80. // AppendAudioOutBufferAuto(u64 tag, buffer<nn::audio::AudioOutBuffer, 0x21>)
  81. public ResultCode AppendAudioOutBufferAuto(ServiceCtx context)
  82. {
  83. (ulong position, _) = context.Request.GetBufferType0x21();
  84. ulong bufferTag = context.RequestData.ReadUInt64();
  85. AudioUserBuffer data = MemoryHelper.Read<AudioUserBuffer>(context.Memory, position);
  86. return _impl.AppendBuffer(bufferTag, ref data);
  87. }
  88. [CommandHipc(8)] // 3.0.0+
  89. // GetReleasedAudioOutBuffersAuto() -> (u32 count, buffer<u64, 0x22> tags)
  90. public ResultCode GetReleasedAudioOutBuffersAuto(ServiceCtx context)
  91. {
  92. (ulong position, ulong size) = context.Request.GetBufferType0x22();
  93. using (WritableRegion outputRegion = context.Memory.GetWritableRegion(position, (int)size))
  94. {
  95. ResultCode result = _impl.GetReleasedBuffers(MemoryMarshal.Cast<byte, ulong>(outputRegion.Memory.Span), out uint releasedCount);
  96. context.ResponseData.Write(releasedCount);
  97. return result;
  98. }
  99. }
  100. [CommandHipc(9)] // 4.0.0+
  101. // GetAudioOutBufferCount() -> u32
  102. public ResultCode GetAudioOutBufferCount(ServiceCtx context)
  103. {
  104. context.ResponseData.Write(_impl.GetBufferCount());
  105. return ResultCode.Success;
  106. }
  107. [CommandHipc(10)] // 4.0.0+
  108. // GetAudioOutPlayedSampleCount() -> u64
  109. public ResultCode GetAudioOutPlayedSampleCount(ServiceCtx context)
  110. {
  111. context.ResponseData.Write(_impl.GetPlayedSampleCount());
  112. return ResultCode.Success;
  113. }
  114. [CommandHipc(11)] // 4.0.0+
  115. // FlushAudioOutBuffers() -> b8
  116. public ResultCode FlushAudioOutBuffers(ServiceCtx context)
  117. {
  118. context.ResponseData.Write(_impl.FlushBuffers());
  119. return ResultCode.Success;
  120. }
  121. [CommandHipc(12)] // 6.0.0+
  122. // SetAudioOutVolume(s32)
  123. public ResultCode SetAudioOutVolume(ServiceCtx context)
  124. {
  125. float volume = context.RequestData.ReadSingle();
  126. _impl.SetVolume(volume);
  127. return ResultCode.Success;
  128. }
  129. [CommandHipc(13)] // 6.0.0+
  130. // GetAudioOutVolume() -> s32
  131. public ResultCode GetAudioOutVolume(ServiceCtx context)
  132. {
  133. context.ResponseData.Write(_impl.GetVolume());
  134. return ResultCode.Success;
  135. }
  136. protected override void Dispose(bool isDisposing)
  137. {
  138. if (isDisposing)
  139. {
  140. _impl.Dispose();
  141. }
  142. }
  143. }
  144. }