aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/OsHle/Services/Aud/IAudioOutManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.HLE/OsHle/Services/Aud/IAudioOutManager.cs')
-rw-r--r--Ryujinx.HLE/OsHle/Services/Aud/IAudioOutManager.cs115
1 files changed, 115 insertions, 0 deletions
diff --git a/Ryujinx.HLE/OsHle/Services/Aud/IAudioOutManager.cs b/Ryujinx.HLE/OsHle/Services/Aud/IAudioOutManager.cs
new file mode 100644
index 00000000..a6b30835
--- /dev/null
+++ b/Ryujinx.HLE/OsHle/Services/Aud/IAudioOutManager.cs
@@ -0,0 +1,115 @@
+using ChocolArm64.Memory;
+using Ryujinx.Audio;
+using Ryujinx.HLE.Logging;
+using Ryujinx.HLE.OsHle.Handles;
+using Ryujinx.HLE.OsHle.Ipc;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Ryujinx.HLE.OsHle.Services.Aud
+{
+ class IAudioOutManager : IpcService
+ {
+ private const string DefaultAudioOutput = "DeviceOut";
+
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ public IAudioOutManager()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 0, ListAudioOuts },
+ { 1, OpenAudioOut }
+ };
+ }
+
+ public long ListAudioOuts(ServiceCtx Context)
+ {
+ long Position = Context.Request.ReceiveBuff[0].Position;
+ long Size = Context.Request.ReceiveBuff[0].Size;
+
+ int NameCount = 0;
+
+ byte[] DeviceNameBuffer = Encoding.ASCII.GetBytes(DefaultAudioOutput + "\0");
+
+ if ((ulong)DeviceNameBuffer.Length <= (ulong)Size)
+ {
+ Context.Memory.WriteBytes(Position, DeviceNameBuffer);
+
+ NameCount++;
+ }
+ else
+ {
+ Context.Ns.Log.PrintError(LogClass.ServiceAudio, $"Output buffer size {Size} too small!");
+ }
+
+ Context.ResponseData.Write(NameCount);
+
+ return 0;
+ }
+
+ public long OpenAudioOut(ServiceCtx Context)
+ {
+ IAalOutput AudioOut = Context.Ns.AudioOut;
+
+ string DeviceName = AMemoryHelper.ReadAsciiString(
+ Context.Memory,
+ Context.Request.SendBuff[0].Position,
+ Context.Request.SendBuff[0].Size);
+
+ if (DeviceName == string.Empty)
+ {
+ DeviceName = DefaultAudioOutput;
+ }
+
+ long Position = Context.Request.ReceiveBuff[0].Position;
+ long Size = Context.Request.ReceiveBuff[0].Size;
+
+ byte[] DeviceNameBuffer = Encoding.ASCII.GetBytes(DeviceName + "\0");
+
+ if ((ulong)DeviceNameBuffer.Length <= (ulong)Size)
+ {
+ Context.Memory.WriteBytes(Position, DeviceNameBuffer);
+ }
+ else
+ {
+ Context.Ns.Log.PrintError(LogClass.ServiceAudio, $"Output buffer size {Size} too small!");
+ }
+
+ int SampleRate = Context.RequestData.ReadInt32();
+ int Channels = Context.RequestData.ReadInt32();
+
+ Channels = (ushort)(Channels >> 16);
+
+ if (SampleRate == 0)
+ {
+ SampleRate = 48000;
+ }
+
+ if (Channels < 1 || Channels > 2)
+ {
+ Channels = 2;
+ }
+
+ KEvent ReleaseEvent = new KEvent();
+
+ ReleaseCallback Callback = () =>
+ {
+ ReleaseEvent.WaitEvent.Set();
+ };
+
+ int Track = AudioOut.OpenTrack(SampleRate, Channels, Callback, out AudioFormat Format);
+
+ MakeObject(Context, new IAudioOut(AudioOut, ReleaseEvent, Track));
+
+ Context.ResponseData.Write(SampleRate);
+ Context.ResponseData.Write(Channels);
+ Context.ResponseData.Write((int)Format);
+ Context.ResponseData.Write((int)PlaybackState.Stopped);
+
+ return 0;
+ }
+ }
+} \ No newline at end of file