IAudioDevice.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. using Ryujinx.HLE.HOS.Ipc;
  2. using Ryujinx.HLE.HOS.Kernel;
  3. using Ryujinx.HLE.HOS.SystemState;
  4. using Ryujinx.HLE.Logging;
  5. using System.Collections.Generic;
  6. using System.Text;
  7. namespace Ryujinx.HLE.HOS.Services.Aud
  8. {
  9. class IAudioDevice : IpcService
  10. {
  11. private Dictionary<int, ServiceProcessRequest> m_Commands;
  12. public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
  13. private KEvent SystemEvent;
  14. public IAudioDevice()
  15. {
  16. m_Commands = new Dictionary<int, ServiceProcessRequest>()
  17. {
  18. { 0, ListAudioDeviceName },
  19. { 1, SetAudioDeviceOutputVolume },
  20. { 3, GetActiveAudioDeviceName },
  21. { 4, QueryAudioDeviceSystemEvent },
  22. { 5, GetActiveChannelCount },
  23. { 6, ListAudioDeviceNameAuto },
  24. { 7, SetAudioDeviceOutputVolumeAuto },
  25. { 8, GetAudioDeviceOutputVolumeAuto },
  26. { 10, GetActiveAudioDeviceNameAuto },
  27. { 11, QueryAudioDeviceInputEvent },
  28. { 12, QueryAudioDeviceOutputEvent }
  29. };
  30. SystemEvent = new KEvent();
  31. //TODO: We shouldn't be signaling this here.
  32. SystemEvent.WaitEvent.Set();
  33. }
  34. public long ListAudioDeviceName(ServiceCtx Context)
  35. {
  36. string[] DeviceNames = SystemStateMgr.AudioOutputs;
  37. Context.ResponseData.Write(DeviceNames.Length);
  38. long Position = Context.Request.ReceiveBuff[0].Position;
  39. long Size = Context.Request.ReceiveBuff[0].Size;
  40. long BasePosition = Position;
  41. foreach (string Name in DeviceNames)
  42. {
  43. byte[] Buffer = Encoding.ASCII.GetBytes(Name + "\0");
  44. if ((Position - BasePosition) + Buffer.Length > Size)
  45. {
  46. Context.Device.Log.PrintError(LogClass.ServiceAudio, $"Output buffer size {Size} too small!");
  47. break;
  48. }
  49. Context.Memory.WriteBytes(Position, Buffer);
  50. Position += Buffer.Length;
  51. }
  52. return 0;
  53. }
  54. public long SetAudioDeviceOutputVolume(ServiceCtx Context)
  55. {
  56. float Volume = Context.RequestData.ReadSingle();
  57. long Position = Context.Request.SendBuff[0].Position;
  58. long Size = Context.Request.SendBuff[0].Size;
  59. byte[] DeviceNameBuffer = Context.Memory.ReadBytes(Position, Size);
  60. string DeviceName = Encoding.ASCII.GetString(DeviceNameBuffer);
  61. Context.Device.Log.PrintStub(LogClass.ServiceAudio, "Stubbed.");
  62. return 0;
  63. }
  64. public long GetActiveAudioDeviceName(ServiceCtx Context)
  65. {
  66. string Name = Context.Device.System.State.ActiveAudioOutput;
  67. long Position = Context.Request.ReceiveBuff[0].Position;
  68. long Size = Context.Request.ReceiveBuff[0].Size;
  69. byte[] DeviceNameBuffer = Encoding.ASCII.GetBytes(Name + "\0");
  70. if ((ulong)DeviceNameBuffer.Length <= (ulong)Size)
  71. {
  72. Context.Memory.WriteBytes(Position, DeviceNameBuffer);
  73. }
  74. else
  75. {
  76. Context.Device.Log.PrintError(LogClass.ServiceAudio, $"Output buffer size {Size} too small!");
  77. }
  78. return 0;
  79. }
  80. public long QueryAudioDeviceSystemEvent(ServiceCtx Context)
  81. {
  82. int Handle = Context.Process.HandleTable.OpenHandle(SystemEvent);
  83. Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
  84. Context.Device.Log.PrintStub(LogClass.ServiceAudio, "Stubbed.");
  85. return 0;
  86. }
  87. public long GetActiveChannelCount(ServiceCtx Context)
  88. {
  89. Context.ResponseData.Write(2);
  90. Context.Device.Log.PrintStub(LogClass.ServiceAudio, "Stubbed.");
  91. return 0;
  92. }
  93. public long ListAudioDeviceNameAuto(ServiceCtx Context)
  94. {
  95. string[] DeviceNames = SystemStateMgr.AudioOutputs;
  96. Context.ResponseData.Write(DeviceNames.Length);
  97. (long Position, long Size) = Context.Request.GetBufferType0x22();
  98. long BasePosition = Position;
  99. foreach (string Name in DeviceNames)
  100. {
  101. byte[] Buffer = Encoding.UTF8.GetBytes(Name + '\0');
  102. if ((Position - BasePosition) + Buffer.Length > Size)
  103. {
  104. Context.Device.Log.PrintError(LogClass.ServiceAudio, $"Output buffer size {Size} too small!");
  105. break;
  106. }
  107. Context.Memory.WriteBytes(Position, Buffer);
  108. Position += Buffer.Length;
  109. }
  110. return 0;
  111. }
  112. public long SetAudioDeviceOutputVolumeAuto(ServiceCtx Context)
  113. {
  114. float Volume = Context.RequestData.ReadSingle();
  115. (long Position, long Size) = Context.Request.GetBufferType0x21();
  116. byte[] DeviceNameBuffer = Context.Memory.ReadBytes(Position, Size);
  117. string DeviceName = Encoding.UTF8.GetString(DeviceNameBuffer);
  118. Context.Device.Log.PrintStub(LogClass.ServiceAudio, "Stubbed.");
  119. return 0;
  120. }
  121. public long GetAudioDeviceOutputVolumeAuto(ServiceCtx Context)
  122. {
  123. Context.ResponseData.Write(1f);
  124. Context.Device.Log.PrintStub(LogClass.ServiceAudio, "Stubbed.");
  125. return 0;
  126. }
  127. public long GetActiveAudioDeviceNameAuto(ServiceCtx Context)
  128. {
  129. string Name = Context.Device.System.State.ActiveAudioOutput;
  130. (long Position, long Size) = Context.Request.GetBufferType0x22();
  131. byte[] DeviceNameBuffer = Encoding.UTF8.GetBytes(Name + '\0');
  132. if ((ulong)DeviceNameBuffer.Length <= (ulong)Size)
  133. {
  134. Context.Memory.WriteBytes(Position, DeviceNameBuffer);
  135. }
  136. else
  137. {
  138. Context.Device.Log.PrintError(LogClass.ServiceAudio, $"Output buffer size {Size} too small!");
  139. }
  140. return 0;
  141. }
  142. public long QueryAudioDeviceInputEvent(ServiceCtx Context)
  143. {
  144. int Handle = Context.Process.HandleTable.OpenHandle(SystemEvent);
  145. Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
  146. Context.Device.Log.PrintStub(LogClass.ServiceAudio, "Stubbed.");
  147. return 0;
  148. }
  149. public long QueryAudioDeviceOutputEvent(ServiceCtx Context)
  150. {
  151. int Handle = Context.Process.HandleTable.OpenHandle(SystemEvent);
  152. Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
  153. Context.Device.Log.PrintStub(LogClass.ServiceAudio, "Stubbed.");
  154. return 0;
  155. }
  156. }
  157. }