fix audiomix

This commit is contained in:
madwind 2025-01-16 17:24:00 +08:00
parent e1cb957d7b
commit 82664ef69b
8 changed files with 88 additions and 133 deletions

View File

@ -48,8 +48,7 @@ namespace Ryujinx.Audio.Backends.SDL3
private static bool IsSupportedInternal() private static bool IsSupportedInternal()
{ {
nint device = OpenStream(SampleFormat.PcmInt16, Constants.TargetSampleRate, Constants.ChannelCountMax, nint device = OpenStream(SampleFormat.PcmInt16, Constants.TargetSampleRate, Constants.ChannelCountMax, null);
Constants.TargetSampleCount, null);
if (device != 0) if (device != 0)
{ {
@ -100,7 +99,7 @@ namespace Ryujinx.Audio.Backends.SDL3
} }
private static SDL_AudioSpec GetSDL3Spec(SampleFormat requestedSampleFormat, uint requestedSampleRate, private static SDL_AudioSpec GetSDL3Spec(SampleFormat requestedSampleFormat, uint requestedSampleRate,
uint requestedChannelCount, uint sampleCount) uint requestedChannelCount)
{ {
return new SDL_AudioSpec return new SDL_AudioSpec
{ {
@ -123,10 +122,9 @@ namespace Ryujinx.Audio.Backends.SDL3
} }
internal static nint OpenStream(SampleFormat requestedSampleFormat, uint requestedSampleRate, internal static nint OpenStream(SampleFormat requestedSampleFormat, uint requestedSampleRate,
uint requestedChannelCount, uint sampleCount, SDL_AudioStreamCallback callback) uint requestedChannelCount, SDL_AudioStreamCallback callback)
{ {
SDL_AudioSpec desired = GetSDL3Spec(requestedSampleFormat, requestedSampleRate, requestedChannelCount, SDL_AudioSpec desired = GetSDL3Spec(requestedSampleFormat, requestedSampleRate, requestedChannelCount);
sampleCount);
nint stream = nint stream =
SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, ref desired, callback, nint.Zero); SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, ref desired, callback, nint.Zero);
@ -139,16 +137,6 @@ namespace Ryujinx.Audio.Backends.SDL3
return 0; return 0;
} }
// bool isValid = got.format == desired.format && got.freq == desired.freq && got.channels == desired.channels;
//
// if (!isValid)
// {
// Logger.Error?.Print(LogClass.Application, "SDL3 open audio device is not valid");
// SDL_DestroyAudioStream(stream);
//
// return 0;
// }
return stream; return stream;
} }

View File

@ -4,7 +4,6 @@ using Ryujinx.Common.Logging;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Memory; using Ryujinx.Memory;
using System; using System;
using System.Buffers;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Threading; using System.Threading;
using static SDL3.SDL; using static SDL3.SDL;
@ -22,7 +21,6 @@ namespace Ryujinx.Audio.Backends.SDL3
private bool _hasSetupError; private bool _hasSetupError;
private readonly SDL_AudioStreamCallback _callbackDelegate; private readonly SDL_AudioStreamCallback _callbackDelegate;
private readonly int _bytesPerFrame; private readonly int _bytesPerFrame;
private uint _sampleCount;
private bool _started; private bool _started;
private float _volume; private float _volume;
private readonly SDL_AudioFormat _nativeSampleFormat; private readonly SDL_AudioFormat _nativeSampleFormat;
@ -38,7 +36,6 @@ namespace Ryujinx.Audio.Backends.SDL3
_callbackDelegate = Update; _callbackDelegate = Update;
_bytesPerFrame = BackendHelper.GetSampleSize(RequestedSampleFormat) * (int)RequestedChannelCount; _bytesPerFrame = BackendHelper.GetSampleSize(RequestedSampleFormat) * (int)RequestedChannelCount;
_nativeSampleFormat = SDL3HardwareDeviceDriver.GetSDL3Format(RequestedSampleFormat); _nativeSampleFormat = SDL3HardwareDeviceDriver.GetSDL3Format(RequestedSampleFormat);
_sampleCount = uint.MaxValue;
_started = false; _started = false;
_volume = 1f; _volume = 1f;
} }
@ -47,15 +44,12 @@ namespace Ryujinx.Audio.Backends.SDL3
{ {
uint bufferSampleCount = (uint)GetSampleCount(buffer); uint bufferSampleCount = (uint)GetSampleCount(buffer);
bool needAudioSetup = (_outputStream == 0 && !_hasSetupError) || bool needAudioSetup = (_outputStream == 0 && !_hasSetupError) ||
(bufferSampleCount >= Constants.TargetSampleCount && (bufferSampleCount >= Constants.TargetSampleCount);
bufferSampleCount < _sampleCount);
if (needAudioSetup) if (needAudioSetup)
{ {
_sampleCount = Math.Max(Constants.TargetSampleCount, bufferSampleCount);
nint newOutputStream = SDL3HardwareDeviceDriver.OpenStream(RequestedSampleFormat, RequestedSampleRate, nint newOutputStream = SDL3HardwareDeviceDriver.OpenStream(RequestedSampleFormat, RequestedSampleRate,
RequestedChannelCount, _sampleCount, _callbackDelegate); RequestedChannelCount, _callbackDelegate);
_hasSetupError = newOutputStream == 0; _hasSetupError = newOutputStream == 0;
@ -68,18 +62,21 @@ namespace Ryujinx.Audio.Backends.SDL3
_outputStream = newOutputStream; _outputStream = newOutputStream;
// SDL_PauseAudioDevice(_outputStream, _started ? 0 : 1); if (_started)
SDL_ResumeAudioStreamDevice(_outputStream);
Logger.Info?.Print(LogClass.Audio,
$"New audio stream setup with a target sample count of {_sampleCount}");
}
}
}
private unsafe void Update(nint userdata, nint stream, int additional_amount, int total_amount)
{ {
int maxFrameCount = (int)GetSampleCount(additional_amount); SDL_ResumeAudioStreamDevice(_outputStream);
}
else
{
SDL_PauseAudioStreamDevice(_outputStream);
}
}
}
}
private unsafe void Update(nint userdata, nint stream, int additionalAmount, int totalAmount)
{
int maxFrameCount = (int)GetSampleCount(additionalAmount);
int bufferedFrames = _ringBuffer.Length / _bytesPerFrame; int bufferedFrames = _ringBuffer.Length / _bytesPerFrame;
int frameCount = Math.Min(bufferedFrames, maxFrameCount); int frameCount = Math.Min(bufferedFrames, maxFrameCount);
@ -90,24 +87,22 @@ namespace Ryujinx.Audio.Backends.SDL3
} }
using SpanOwner<byte> samplesOwner = SpanOwner<byte>.Rent(frameCount * _bytesPerFrame); using SpanOwner<byte> samplesOwner = SpanOwner<byte>.Rent(frameCount * _bytesPerFrame);
using SpanOwner<byte> destinationOwner = SpanOwner<byte>.Rent(frameCount * _bytesPerFrame);
Span<byte> samples = samplesOwner.Span; Span<byte> samples = samplesOwner.Span;
Span<byte> destinationBuffer = destinationOwner.Span; int samplesLength = samples.Length;
_ringBuffer.Read(samples, 0, samplesLength);
_ringBuffer.Read(samples, 0, samples.Length); fixed (byte* p = samples)
fixed (byte* pSrc = samples, pDst = destinationBuffer)
{ {
nint pStreamSrc = (nint)pSrc; nint pStreamSrc = (nint)p;
nint pStreamDst = (nint)pDst; nint pStreamDst = SDL_calloc(1,samplesLength);
// Apply volume to written data // Apply volume to written data
SDL_MixAudio(pStreamDst, pStreamSrc, _nativeSampleFormat, (uint)samples.Length, _driver.Volume); SDL_MixAudio(pStreamDst, pStreamSrc, _nativeSampleFormat, (uint)samplesLength, _driver.Volume);
SDL_PutAudioStreamData(stream, pStreamSrc, samples.Length); SDL_PutAudioStreamData(stream, pStreamDst, samplesLength);
SDL_free(pStreamDst);
} }
ulong sampleCount = GetSampleCount(samples.Length); ulong sampleCount = GetSampleCount(samplesLength);
ulong availaibleSampleCount = sampleCount; ulong availaibleSampleCount = sampleCount;

View File

@ -60,7 +60,7 @@ namespace Ryujinx.Input.SDL3
private float _triggerThreshold; private float _triggerThreshold;
public SDL3Gamepad(SDL_JoystickID joystickId, string driverId) public SDL3Gamepad(uint joystickId, string driverId)
{ {
_gamepadHandle = SDL_OpenGamepad(joystickId); _gamepadHandle = SDL_OpenGamepad(joystickId);
_buttonsUserMapping = new List<ButtonMappingEntry>(20); _buttonsUserMapping = new List<ButtonMappingEntry>(20);

View File

@ -12,7 +12,7 @@ namespace Ryujinx.Input.SDl3
{ {
public class SDL3GamepadDriver : IGamepadDriver public class SDL3GamepadDriver : IGamepadDriver
{ {
private readonly Dictionary<SDL_JoystickID, string> _gamepadsInstanceIdsMapping; private readonly Dictionary<uint, string> _gamepadsInstanceIdsMapping;
private readonly List<string> _gamepadsIds; private readonly List<string> _gamepadsIds;
private readonly Lock _lock = new(); private readonly Lock _lock = new();
@ -34,7 +34,7 @@ namespace Ryujinx.Input.SDl3
public SDL3GamepadDriver() public SDL3GamepadDriver()
{ {
_gamepadsInstanceIdsMapping = new Dictionary<SDL_JoystickID, string>(); _gamepadsInstanceIdsMapping = new Dictionary<uint, string>();
_gamepadsIds = new List<string>(); _gamepadsIds = new List<string>();
SDL3Driver.Instance.Initialize(); SDL3Driver.Instance.Initialize();
@ -43,7 +43,7 @@ namespace Ryujinx.Input.SDl3
SDL3Driver.Instance.OnJoyBatteryUpdated += HandleJoyBatteryUpdated; SDL3Driver.Instance.OnJoyBatteryUpdated += HandleJoyBatteryUpdated;
} }
private string GenerateGamepadId(SDL_JoystickID joystickId) private string GenerateGamepadId(uint joystickId)
{ {
int bufferSize = 33; int bufferSize = 33;
Span<byte> pszGuid = stackalloc byte[bufferSize]; Span<byte> pszGuid = stackalloc byte[bufferSize];
@ -65,7 +65,7 @@ namespace Ryujinx.Input.SDl3
return id; return id;
} }
private KeyValuePair<SDL_JoystickID,string> GetGamepadInfoByGamepadId(string id) private KeyValuePair<uint,string> GetGamepadInfoByGamepadId(string id)
{ {
lock (_lock) lock (_lock)
{ {
@ -73,7 +73,7 @@ namespace Ryujinx.Input.SDl3
} }
} }
private void HandleJoyStickDisconnected(SDL_JoystickID joystickId) private void HandleJoyStickDisconnected(uint joystickId)
{ {
bool joyConPairDisconnected = false; bool joyConPairDisconnected = false;
if (!_gamepadsInstanceIdsMapping.Remove(joystickId, out string id)) if (!_gamepadsInstanceIdsMapping.Remove(joystickId, out string id))
@ -96,7 +96,7 @@ namespace Ryujinx.Input.SDl3
} }
} }
private void HandleJoyStickConnected(SDL_JoystickID joystickId) private void HandleJoyStickConnected(uint joystickId)
{ {
bool joyConPairConnected = false; bool joyConPairConnected = false;
@ -135,7 +135,7 @@ namespace Ryujinx.Input.SDl3
} }
} }
private void HandleJoyBatteryUpdated(SDL_JoystickID joystickId, SDL_JoyBatteryEvent joyBatteryEvent) private void HandleJoyBatteryUpdated(uint joystickId, SDL_JoyBatteryEvent joyBatteryEvent)
{ {
Logger.Info?.Print(LogClass.Hid, Logger.Info?.Print(LogClass.Hid,
$"{SDL_GetGamepadNameForID(joystickId)}, Battery percent: {joyBatteryEvent.percent}"); $"{SDL_GetGamepadNameForID(joystickId)}, Battery percent: {joyBatteryEvent.percent}");

View File

@ -63,17 +63,9 @@ namespace Ryujinx.Input.SDL3
private nint _gamepadHandle; private nint _gamepadHandle;
private enum JoyConType private readonly SDL_GamepadType _gamepadType;
{
Left, Right
}
public const string LeftName = "Nintendo Switch Joy-Con (L)"; public SDL3JoyCon(uint joystickId, string driverId)
public const string RightName = "Nintendo Switch Joy-Con (R)";
private readonly JoyConType _joyConType;
public SDL3JoyCon(SDL_JoystickID joystickId, string driverId)
{ {
_gamepadHandle = SDL_OpenGamepad(joystickId); _gamepadHandle = SDL_OpenGamepad(joystickId);
_buttonsUserMapping = new List<ButtonMappingEntry>(10); _buttonsUserMapping = new List<ButtonMappingEntry>(10);
@ -98,24 +90,15 @@ namespace Ryujinx.Input.SDL3
} }
} }
switch (Name) _gamepadType = SDL_GetGamepadType(_gamepadHandle);
_buttonsDriverMapping = _gamepadType switch
{ {
case LeftName: SDL_GamepadType.SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT => ToSDLButtonMapping(
{ _leftButtonsDriverMapping),
_buttonsDriverMapping = ToSDLButtonMapping(_leftButtonsDriverMapping); SDL_GamepadType.SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT => ToSDLButtonMapping(
_joyConType = JoyConType.Left; _rightButtonsDriverMapping),
break; _ => throw new InvalidOperationException($"Unexpected JoyConType value: {_gamepadType}")
} };
case RightName:
{
_buttonsDriverMapping = ToSDLButtonMapping(_rightButtonsDriverMapping);
_joyConType = JoyConType.Right;
break;
}
default:
throw new InvalidOperationException(
$"Unexpected Name: {Name}. Expected '{LeftName}' or '{RightName}'.");
}
} }
private static SDL_GamepadButton[] ToSDLButtonMapping( private static SDL_GamepadButton[] ToSDLButtonMapping(
@ -205,11 +188,11 @@ namespace Ryujinx.Input.SDL3
return Vector3.Zero; return Vector3.Zero;
} }
Vector3 value = _joyConType switch Vector3 value = _gamepadType switch
{ {
JoyConType.Left => new Vector3(-values[2], values[1], values[0]), SDL_GamepadType.SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT => new Vector3(-values[2], values[1], values[0]),
JoyConType.Right => new Vector3(values[2], values[1], -values[0]), SDL_GamepadType.SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT => new Vector3(values[2], values[1], -values[0]),
_ => throw new ArgumentOutOfRangeException($"Unexpected JoyConType value: {_joyConType}") _ => throw new ArgumentOutOfRangeException($"Unexpected JoyConType value: {_gamepadType}")
}; };
return inputId switch return inputId switch
@ -237,9 +220,9 @@ namespace Ryujinx.Input.SDL3
_stickUserMapping[(int)StickInputId.Right] = (StickInputId)_configuration.RightJoyconStick.Joystick; _stickUserMapping[(int)StickInputId.Right] = (StickInputId)_configuration.RightJoyconStick.Joystick;
switch (_joyConType) switch (_gamepadType)
{ {
case JoyConType.Left: case SDL_GamepadType.SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT:
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftStick, _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftStick,
(GamepadButtonInputId)_configuration.LeftJoyconStick.StickButton)); (GamepadButtonInputId)_configuration.LeftJoyconStick.StickButton));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadUp, _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadUp,
@ -261,7 +244,7 @@ namespace Ryujinx.Input.SDL3
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger0, _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger0,
(GamepadButtonInputId)_configuration.LeftJoycon.ButtonSl)); (GamepadButtonInputId)_configuration.LeftJoycon.ButtonSl));
break; break;
case JoyConType.Right: case SDL_GamepadType.SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT:
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightStick, _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightStick,
(GamepadButtonInputId)_configuration.RightJoyconStick.StickButton)); (GamepadButtonInputId)_configuration.RightJoyconStick.StickButton));
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.A, _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.A,
@ -316,7 +299,6 @@ namespace Ryujinx.Input.SDL3
// Do not touch state of button already pressed // Do not touch state of button already pressed
if (!result.IsPressed(entry.To)) if (!result.IsPressed(entry.To))
{ {
result.SetPressed(entry.To, rawState.IsPressed(entry.From)); result.SetPressed(entry.To, rawState.IsPressed(entry.From));
} }
} }
@ -367,8 +349,8 @@ namespace Ryujinx.Input.SDL3
if (inputId == StickInputId.Unbound) if (inputId == StickInputId.Unbound)
return (0.0f, 0.0f); return (0.0f, 0.0f);
if (inputId == StickInputId.Left && _joyConType == JoyConType.Right || if (inputId == StickInputId.Left && _gamepadType == SDL_GamepadType.SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT ||
inputId == StickInputId.Right && _joyConType == JoyConType.Left) inputId == StickInputId.Right && _gamepadType == SDL_GamepadType.SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT)
{ {
return (0.0f, 0.0f); return (0.0f, 0.0f);
} }
@ -401,8 +383,8 @@ namespace Ryujinx.Input.SDL3
return inputId switch return inputId switch
{ {
StickInputId.Left when _joyConType == JoyConType.Left => (resultY, -resultX), StickInputId.Left when _gamepadType == SDL_GamepadType.SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT => (resultY, -resultX),
StickInputId.Right when _joyConType == JoyConType.Right => (-resultY, resultX), StickInputId.Right when _gamepadType == SDL_GamepadType.SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT => (-resultY, resultX),
_ => (0.0f, 0.0f) _ => (0.0f, 0.0f)
}; };
} }
@ -421,18 +403,14 @@ namespace Ryujinx.Input.SDL3
{ {
return false; return false;
} }
// if (SDL_GetGamepadButton(_gamepadHandle, button))
// {
// Console.WriteLine(inputId+", "+button);
// }
return SDL_GetGamepadButton(_gamepadHandle, button); return SDL_GetGamepadButton(_gamepadHandle, button);
} }
public static bool IsJoyCon(SDL_JoystickID joystickId) public static bool IsJoyCon(uint joystickId)
{ {
var gamepadName = SDL_GetGamepadNameForID(joystickId); var gamepadName = SDL_GetGamepadTypeForID(joystickId);
return gamepadName is LeftName or RightName; return gamepadName is SDL_GamepadType.SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT
or SDL_GamepadType.SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT;
} }
} }
} }

View File

@ -11,14 +11,17 @@ namespace Ryujinx.Input.SDL3
class SDL3JoyConPair(SDL3JoyCon left, SDL3JoyCon right) : IGamepad class SDL3JoyConPair(SDL3JoyCon left, SDL3JoyCon right) : IGamepad
{ {
private StandardControllerInputConfig _configuration; private StandardControllerInputConfig _configuration;
private readonly record struct ButtonMappingEntry(GamepadButtonInputId To, GamepadButtonInputId From) private readonly record struct ButtonMappingEntry(GamepadButtonInputId To, GamepadButtonInputId From)
{ {
public bool IsValid => To is not GamepadButtonInputId.Unbound && From is not GamepadButtonInputId.Unbound; public bool IsValid => To is not GamepadButtonInputId.Unbound && From is not GamepadButtonInputId.Unbound;
} }
private readonly StickInputId[] _stickUserMapping = new StickInputId[(int)StickInputId.Count] private readonly StickInputId[] _stickUserMapping = new StickInputId[(int)StickInputId.Count]
{ {
StickInputId.Unbound, StickInputId.Left, StickInputId.Right, StickInputId.Unbound, StickInputId.Left, StickInputId.Right,
}; };
public GamepadFeaturesFlag Features => (left?.Features ?? GamepadFeaturesFlag.None) | public GamepadFeaturesFlag Features => (left?.Features ?? GamepadFeaturesFlag.None) |
(right?.Features ?? GamepadFeaturesFlag.None); (right?.Features ?? GamepadFeaturesFlag.None);
@ -185,20 +188,21 @@ namespace Ryujinx.Input.SDL3
{ {
} }
public static bool IsCombinable(Dictionary<SDL_JoystickID, string> gamepadsInstanceIdsMapping) public static bool IsCombinable(Dictionary<uint, string> gamepadsInstanceIdsMapping)
{ {
var gamepadNames = gamepadsInstanceIdsMapping.Keys.Select(id => SDL_GetGamepadNameForID(id)).ToArray(); var gamepadTypes = gamepadsInstanceIdsMapping.Keys.Select(SDL_GetGamepadTypeForID).ToArray();
return gamepadNames.Contains(SDL3JoyCon.LeftName) && gamepadNames.Contains(SDL3JoyCon.RightName); return gamepadTypes.Contains(SDL_GamepadType.SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT) &&
gamepadTypes.Contains(SDL_GamepadType.SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT);
} }
public static IGamepad GetGamepad(Dictionary<SDL_JoystickID, string> gamepadsInstanceIdsMapping) public static IGamepad GetGamepad(Dictionary<uint, string> gamepadsInstanceIdsMapping)
{ {
var leftPair = var leftPair =
gamepadsInstanceIdsMapping.FirstOrDefault(pair => gamepadsInstanceIdsMapping.FirstOrDefault(pair =>
SDL_GetGamepadNameForID(pair.Key) == SDL3JoyCon.LeftName); SDL_GetGamepadTypeForID(pair.Key) == SDL_GamepadType.SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT);
var rightPair = var rightPair =
gamepadsInstanceIdsMapping.FirstOrDefault(pair => gamepadsInstanceIdsMapping.FirstOrDefault(pair =>
SDL_GetGamepadNameForID(pair.Key) == SDL3JoyCon.RightName); SDL_GetGamepadTypeForID(pair.Key) == SDL_GamepadType.SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT);
if (leftPair.Key == 0 || rightPair.Key == 0) if (leftPair.Key == 0 || rightPair.Key == 0)
{ {
return null; return null;

View File

@ -83,6 +83,10 @@ public static unsafe partial class SDL
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial IntPtr SDL_malloc(UIntPtr size); public static partial IntPtr SDL_malloc(UIntPtr size);
[LibraryImport(nativeLibName)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial IntPtr SDL_calloc(int nmemb, int size);
[LibraryImport(nativeLibName)] [LibraryImport(nativeLibName)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial void SDL_free(IntPtr mem); public static partial void SDL_free(IntPtr mem);
@ -752,6 +756,7 @@ public static unsafe partial class SDL
public static partial SDLBool SDL_WriteS64BE(IntPtr dst, long value); public static partial SDLBool SDL_WriteS64BE(IntPtr dst, long value);
// /usr/local/include/SDL3/SDL_audio.h // /usr/local/include/SDL3/SDL_audio.h
public const uint SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK = 0xFFFFFFFFu;
public enum SDL_AudioFormat public enum SDL_AudioFormat
{ {
@ -2615,6 +2620,7 @@ public static unsafe partial class SDL
public static partial SDL_PowerState SDL_GetPowerInfo(out int seconds, out int percent); public static partial SDL_PowerState SDL_GetPowerInfo(out int seconds, out int percent);
// /usr/local/include/SDL3/SDL_sensor.h // /usr/local/include/SDL3/SDL_sensor.h
public const float SDL_STANDARD_GRAVITY = 9.80665f;
public enum SDL_SensorType public enum SDL_SensorType
{ {
@ -2749,7 +2755,7 @@ public static unsafe partial class SDL
[LibraryImport(nativeLibName)] [LibraryImport(nativeLibName)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial SDL_GUID SDL_GetJoystickGUIDForID(SDL_JoystickID instance_id); public static partial SDL_GUID SDL_GetJoystickGUIDForID(uint instance_id);
[LibraryImport(nativeLibName)] [LibraryImport(nativeLibName)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
@ -4620,7 +4626,7 @@ public static unsafe partial class SDL
public SDL_EventType type; public SDL_EventType type;
public uint reserved; public uint reserved;
public ulong timestamp; public ulong timestamp;
public SDL_JoystickID which; public uint which;
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
@ -4629,7 +4635,7 @@ public static unsafe partial class SDL
public SDL_EventType type; public SDL_EventType type;
public uint reserved; public uint reserved;
public ulong timestamp; public ulong timestamp;
public SDL_JoystickID which; public uint which;
public SDL_PowerState state; public SDL_PowerState state;
public int percent; public int percent;
} }
@ -8048,19 +8054,4 @@ public static unsafe partial class SDL
[LibraryImport(nativeLibName)] [LibraryImport(nativeLibName)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial int SDL_EnterAppMainCallbacks(int argc, IntPtr argv, SDL_AppInit_func appinit, SDL_AppIterate_func appiter, SDL_AppEvent_func appevent, SDL_AppQuit_func appquit); public static partial int SDL_EnterAppMainCallbacks(int argc, IntPtr argv, SDL_AppInit_func appinit, SDL_AppIterate_func appiter, SDL_AppEvent_func appevent, SDL_AppQuit_func appquit);
public const uint SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK = 0xFFFFFFFFu;
public const float SDL_STANDARD_GRAVITY = 9.80665f;
public record struct SDL_JoystickID
{
public uint Value;
public SDL_JoystickID(uint value)
{
Value = value;
}
public static implicit operator uint(SDL_JoystickID id) => id.Value;
public static implicit operator SDL_JoystickID(uint value) => new SDL_JoystickID(value);
}
} }

View File

@ -33,9 +33,9 @@ namespace Ryujinx.SDL3.Common
private uint _refereceCount; private uint _refereceCount;
private Thread _worker; private Thread _worker;
public event Action<SDL_JoystickID> OnJoyStickConnected; public event Action<uint> OnJoyStickConnected;
public event Action<SDL_JoystickID> OnJoystickDisconnected; public event Action<uint> OnJoystickDisconnected;
public event Action<SDL_JoystickID, SDL_JoyBatteryEvent> OnJoyBatteryUpdated; public event Action<uint, SDL_JoyBatteryEvent> OnJoyBatteryUpdated;
private ConcurrentDictionary<uint, Action<SDL_Event>> _registeredWindowHandlers; private ConcurrentDictionary<uint, Action<SDL_Event>> _registeredWindowHandlers;
@ -123,8 +123,7 @@ namespace Ryujinx.SDL3.Common
private void HandleSDLEvent(ref SDL_Event evnt) private void HandleSDLEvent(ref SDL_Event evnt)
{ {
var type = (SDL_EventType)evnt.type; if (evnt.type == (uint)SDL_EventType.SDL_EVENT_GAMEPAD_ADDED)
if (type == SDL_EventType.SDL_EVENT_GAMEPAD_ADDED)
{ {
var instanceId = evnt.jdevice.which; var instanceId = evnt.jdevice.which;
@ -132,7 +131,7 @@ namespace Ryujinx.SDL3.Common
OnJoyStickConnected?.Invoke(instanceId); OnJoyStickConnected?.Invoke(instanceId);
} }
else if (type == SDL_EventType.SDL_EVENT_GAMEPAD_REMOVED) else if (evnt.type == (uint)SDL_EventType.SDL_EVENT_GAMEPAD_REMOVED)
{ {
var instanceId = evnt.jdevice.which; var instanceId = evnt.jdevice.which;
@ -140,13 +139,13 @@ namespace Ryujinx.SDL3.Common
OnJoystickDisconnected?.Invoke(instanceId); OnJoystickDisconnected?.Invoke(instanceId);
} }
else if (type == SDL_EventType.SDL_EVENT_JOYSTICK_BATTERY_UPDATED) else if (evnt.type == (uint)SDL_EventType.SDL_EVENT_JOYSTICK_BATTERY_UPDATED)
{ {
OnJoyBatteryUpdated?.Invoke(evnt.jbattery.which, evnt.jbattery); OnJoyBatteryUpdated?.Invoke(evnt.jbattery.which, evnt.jbattery);
} }
else if (type is >= SDL_EventType.SDL_EVENT_WINDOW_FIRST and <= SDL_EventType.SDL_EVENT_WINDOW_LAST else if (evnt.type is >= (uint)SDL_EventType.SDL_EVENT_WINDOW_FIRST and <= (uint)SDL_EventType.SDL_EVENT_WINDOW_LAST
or SDL_EventType.SDL_EVENT_MOUSE_BUTTON_DOWN or (uint)SDL_EventType.SDL_EVENT_MOUSE_BUTTON_DOWN
or SDL_EventType.SDL_EVENT_MOUSE_BUTTON_UP) or (uint)SDL_EventType.SDL_EVENT_MOUSE_BUTTON_UP)
{ {
if (_registeredWindowHandlers.TryGetValue(evnt.window.windowID, out Action<SDL_Event> handler)) if (_registeredWindowHandlers.TryGetValue(evnt.window.windowID, out Action<SDL_Event> handler))
{ {