IAudioDevice.cs 6.8 KB

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