IAudioOutManager.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. using ChocolArm64.Memory;
  2. using Ryujinx.Audio;
  3. using Ryujinx.Core.Logging;
  4. using Ryujinx.Core.OsHle.Handles;
  5. using Ryujinx.Core.OsHle.Ipc;
  6. using System.Collections.Generic;
  7. using System.Text;
  8. namespace Ryujinx.Core.OsHle.Services.Aud
  9. {
  10. class IAudioOutManager : IpcService
  11. {
  12. private const string DefaultAudioOutput = "DeviceOut";
  13. private Dictionary<int, ServiceProcessRequest> m_Commands;
  14. public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
  15. public IAudioOutManager()
  16. {
  17. m_Commands = new Dictionary<int, ServiceProcessRequest>()
  18. {
  19. { 0, ListAudioOuts },
  20. { 1, OpenAudioOut }
  21. };
  22. }
  23. public long ListAudioOuts(ServiceCtx Context)
  24. {
  25. long Position = Context.Request.ReceiveBuff[0].Position;
  26. long Size = Context.Request.ReceiveBuff[0].Size;
  27. int NameCount = 0;
  28. byte[] DeviceNameBuffer = Encoding.ASCII.GetBytes(DefaultAudioOutput + "\0");
  29. if ((ulong)DeviceNameBuffer.Length <= (ulong)Size)
  30. {
  31. AMemoryHelper.WriteBytes(Context.Memory, Position, DeviceNameBuffer);
  32. NameCount++;
  33. }
  34. else
  35. {
  36. Context.Ns.Log.PrintError(LogClass.ServiceAudio, $"Output buffer size {Size} too small!");
  37. }
  38. Context.ResponseData.Write(NameCount);
  39. return 0;
  40. }
  41. public long OpenAudioOut(ServiceCtx Context)
  42. {
  43. IAalOutput AudioOut = Context.Ns.AudioOut;
  44. string DeviceName = AMemoryHelper.ReadAsciiString(
  45. Context.Memory,
  46. Context.Request.SendBuff[0].Position,
  47. Context.Request.SendBuff[0].Size);
  48. if (DeviceName == string.Empty)
  49. {
  50. DeviceName = DefaultAudioOutput;
  51. }
  52. long Position = Context.Request.ReceiveBuff[0].Position;
  53. long Size = Context.Request.ReceiveBuff[0].Size;
  54. byte[] DeviceNameBuffer = Encoding.ASCII.GetBytes(DeviceName + "\0");
  55. if ((ulong)DeviceNameBuffer.Length <= (ulong)Size)
  56. {
  57. AMemoryHelper.WriteBytes(Context.Memory, Position, DeviceNameBuffer);
  58. }
  59. else
  60. {
  61. Context.Ns.Log.PrintError(LogClass.ServiceAudio, $"Output buffer size {Size} too small!");
  62. }
  63. int SampleRate = Context.RequestData.ReadInt32();
  64. int Channels = Context.RequestData.ReadInt32();
  65. Channels = (ushort)(Channels >> 16);
  66. if (SampleRate == 0)
  67. {
  68. SampleRate = 48000;
  69. }
  70. if (Channels < 1 || Channels > 2)
  71. {
  72. Channels = 2;
  73. }
  74. KEvent ReleaseEvent = new KEvent();
  75. ReleaseCallback Callback = () =>
  76. {
  77. ReleaseEvent.WaitEvent.Set();
  78. };
  79. int Track = AudioOut.OpenTrack(SampleRate, Channels, Callback, out AudioFormat Format);
  80. MakeObject(Context, new IAudioOut(AudioOut, ReleaseEvent, Track));
  81. Context.ResponseData.Write(SampleRate);
  82. Context.ResponseData.Write(Channels);
  83. Context.ResponseData.Write((int)Format);
  84. Context.ResponseData.Write((int)PlaybackState.Stopped);
  85. return 0;
  86. }
  87. }
  88. }