 9cb57fb4bb
			
		
	
	
		9cb57fb4bb
		
	
	
	
	
		
			
			* Change naming convention for Ryujinx project * Change naming convention for ChocolArm64 project * Fix NaN * Remove unneeded this. from Ryujinx project * Adjust naming from new PRs * Name changes based on feedback * How did this get removed? * Rebasing fix * Change FP enum case * Remove prefix from ChocolArm64 classes - Part 1 * Remove prefix from ChocolArm64 classes - Part 2 * Fix alignment from last commit's renaming * Rename namespaces * Rename stragglers * Fix alignment * Rename OpCode class * Missed a few * Adjust alignment
		
			
				
	
	
		
			170 lines
		
	
	
	
		
			5.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
	
		
			5.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using ChocolArm64.Memory;
 | |
| using Ryujinx.Audio;
 | |
| using Ryujinx.Common.Logging;
 | |
| using Ryujinx.HLE.HOS.Ipc;
 | |
| using Ryujinx.HLE.HOS.Kernel;
 | |
| using Ryujinx.HLE.HOS.Services.Aud.AudioOut;
 | |
| using System.Collections.Generic;
 | |
| using System.Text;
 | |
| 
 | |
| using static Ryujinx.HLE.HOS.ErrorCode;
 | |
| 
 | |
| namespace Ryujinx.HLE.HOS.Services.Aud
 | |
| {
 | |
|     class IAudioOutManager : IpcService
 | |
|     {
 | |
|         private const string DefaultAudioOutput = "DeviceOut";
 | |
| 
 | |
|         private const int DefaultSampleRate = 48000;
 | |
| 
 | |
|         private const int DefaultChannelsCount = 2;
 | |
| 
 | |
|         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      },
 | |
|                 { 2, ListAudioOutsAuto },
 | |
|                 { 3, OpenAudioOutAuto  }
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         public long ListAudioOuts(ServiceCtx Context)
 | |
|         {
 | |
|             return ListAudioOutsImpl(
 | |
|                 Context,
 | |
|                 Context.Request.ReceiveBuff[0].Position,
 | |
|                 Context.Request.ReceiveBuff[0].Size);
 | |
|         }
 | |
| 
 | |
|         public long OpenAudioOut(ServiceCtx Context)
 | |
|         {
 | |
|             return OpenAudioOutImpl(
 | |
|                 Context,
 | |
|                 Context.Request.SendBuff[0].Position,
 | |
|                 Context.Request.SendBuff[0].Size,
 | |
|                 Context.Request.ReceiveBuff[0].Position,
 | |
|                 Context.Request.ReceiveBuff[0].Size);
 | |
|         }
 | |
| 
 | |
|         public long ListAudioOutsAuto(ServiceCtx Context)
 | |
|         {
 | |
|             (long RecvPosition, long RecvSize) = Context.Request.GetBufferType0x22();
 | |
| 
 | |
|             return ListAudioOutsImpl(Context, RecvPosition, RecvSize);
 | |
|         }
 | |
| 
 | |
|         public long OpenAudioOutAuto(ServiceCtx Context)
 | |
|         {
 | |
|             (long SendPosition, long SendSize) = Context.Request.GetBufferType0x21();
 | |
|             (long RecvPosition, long RecvSize) = Context.Request.GetBufferType0x22();
 | |
| 
 | |
|             return OpenAudioOutImpl(
 | |
|                 Context,
 | |
|                 SendPosition,
 | |
|                 SendSize,
 | |
|                 RecvPosition,
 | |
|                 RecvSize);
 | |
|         }
 | |
| 
 | |
|         private long ListAudioOutsImpl(ServiceCtx Context, long Position, long Size)
 | |
|         {
 | |
|             int NameCount = 0;
 | |
| 
 | |
|             byte[] DeviceNameBuffer = Encoding.ASCII.GetBytes(DefaultAudioOutput + "\0");
 | |
| 
 | |
|             if ((ulong)DeviceNameBuffer.Length <= (ulong)Size)
 | |
|             {
 | |
|                 Context.Memory.WriteBytes(Position, DeviceNameBuffer);
 | |
| 
 | |
|                 NameCount++;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 Logger.PrintError(LogClass.ServiceAudio, $"Output buffer size {Size} too small!");
 | |
|             }
 | |
| 
 | |
|             Context.ResponseData.Write(NameCount);
 | |
| 
 | |
|             return 0;
 | |
|         }
 | |
| 
 | |
|         private long OpenAudioOutImpl(ServiceCtx Context, long SendPosition, long SendSize, long ReceivePosition, long ReceiveSize)
 | |
|         {
 | |
|             string DeviceName = MemoryHelper.ReadAsciiString(
 | |
|                 Context.Memory,
 | |
|                 SendPosition,
 | |
|                 SendSize);
 | |
| 
 | |
|             if (DeviceName == string.Empty)
 | |
|             {
 | |
|                 DeviceName = DefaultAudioOutput;
 | |
|             }
 | |
| 
 | |
|             if (DeviceName != DefaultAudioOutput)
 | |
|             {
 | |
|                 Logger.PrintWarning(LogClass.Audio, "Invalid device name!");
 | |
| 
 | |
|                 return MakeError(ErrorModule.Audio, AudErr.DeviceNotFound);
 | |
|             }
 | |
| 
 | |
|             byte[] DeviceNameBuffer = Encoding.ASCII.GetBytes(DeviceName + "\0");
 | |
| 
 | |
|             if ((ulong)DeviceNameBuffer.Length <= (ulong)ReceiveSize)
 | |
|             {
 | |
|                 Context.Memory.WriteBytes(ReceivePosition, DeviceNameBuffer);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 Logger.PrintError(LogClass.ServiceAudio, $"Output buffer size {ReceiveSize} too small!");
 | |
|             }
 | |
| 
 | |
|             int SampleRate = Context.RequestData.ReadInt32();
 | |
|             int Channels   = Context.RequestData.ReadInt32();
 | |
| 
 | |
|             if (SampleRate == 0)
 | |
|             {
 | |
|                 SampleRate = DefaultSampleRate;
 | |
|             }
 | |
| 
 | |
|             if (SampleRate != DefaultSampleRate)
 | |
|             {
 | |
|                 Logger.PrintWarning(LogClass.Audio, "Invalid sample rate!");
 | |
| 
 | |
|                 return MakeError(ErrorModule.Audio, AudErr.UnsupportedSampleRate);
 | |
|             }
 | |
| 
 | |
|             Channels = (ushort)Channels;
 | |
| 
 | |
|             if (Channels == 0)
 | |
|             {
 | |
|                 Channels = DefaultChannelsCount;
 | |
|             }
 | |
| 
 | |
|             KEvent ReleaseEvent = new KEvent(Context.Device.System);
 | |
| 
 | |
|             ReleaseCallback Callback = () =>
 | |
|             {
 | |
|                 ReleaseEvent.ReadableEvent.Signal();
 | |
|             };
 | |
| 
 | |
|             IAalOutput AudioOut = Context.Device.AudioOut;
 | |
| 
 | |
|             int Track = AudioOut.OpenTrack(SampleRate, Channels, Callback);
 | |
| 
 | |
|             MakeObject(Context, new IAudioOut(AudioOut, ReleaseEvent, Track));
 | |
| 
 | |
|             Context.ResponseData.Write(SampleRate);
 | |
|             Context.ResponseData.Write(Channels);
 | |
|             Context.ResponseData.Write((int)SampleFormat.PcmInt16);
 | |
|             Context.ResponseData.Write((int)PlaybackState.Stopped);
 | |
| 
 | |
|             return 0;
 | |
|         }
 | |
|     }
 | |
| }
 |