diff options
Diffstat (limited to 'Ryujinx.HLE/OsHle/Services/Aud/IAudioOutManager.cs')
| -rw-r--r-- | Ryujinx.HLE/OsHle/Services/Aud/IAudioOutManager.cs | 115 |
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 |
