SoundIoContext.cs
1 using System; 2 using System.Runtime.CompilerServices; 3 using System.Runtime.InteropServices; 4 using System.Threading; 5 using static Ryujinx.Audio.Backends.SoundIo.Native.SoundIo; 6 7 namespace Ryujinx.Audio.Backends.SoundIo.Native 8 { 9 public class SoundIoContext : IDisposable 10 { 11 private IntPtr _context; 12 private Action<SoundIoError> _onBackendDisconnect; 13 private OnBackendDisconnectedDelegate _onBackendDisconnectNative; 14 15 public IntPtr Context => _context; 16 17 internal SoundIoContext(IntPtr context) 18 { 19 _context = context; 20 _onBackendDisconnect = null; 21 _onBackendDisconnectNative = null; 22 } 23 24 public SoundIoError Connect() => soundio_connect(_context); 25 public void Disconnect() => soundio_disconnect(_context); 26 27 public void FlushEvents() => soundio_flush_events(_context); 28 29 public int OutputDeviceCount => soundio_output_device_count(_context); 30 31 public int DefaultOutputDeviceIndex => soundio_default_output_device_index(_context); 32 33 public Action<SoundIoError> OnBackendDisconnect 34 { 35 get { return _onBackendDisconnect; } 36 set 37 { 38 _onBackendDisconnect = value; 39 40 if (_onBackendDisconnect == null) 41 { 42 _onBackendDisconnectNative = null; 43 } 44 else 45 { 46 _onBackendDisconnectNative = (ctx, err) => _onBackendDisconnect(err); 47 } 48 49 GetContext().OnBackendDisconnected = Marshal.GetFunctionPointerForDelegate(_onBackendDisconnectNative); 50 } 51 } 52 53 private ref SoundIoStruct GetContext() 54 { 55 unsafe 56 { 57 return ref Unsafe.AsRef<SoundIoStruct>((SoundIoStruct*)_context); 58 } 59 } 60 61 public SoundIoDeviceContext GetOutputDevice(int index) 62 { 63 IntPtr deviceContext = soundio_get_output_device(_context, index); 64 65 if (deviceContext == IntPtr.Zero) 66 { 67 return null; 68 } 69 70 return new SoundIoDeviceContext(deviceContext); 71 } 72 73 public static SoundIoContext Create() 74 { 75 IntPtr context = soundio_create(); 76 77 if (context == IntPtr.Zero) 78 { 79 return null; 80 } 81 82 return new SoundIoContext(context); 83 } 84 85 protected virtual void Dispose(bool disposing) 86 { 87 IntPtr currentContext = Interlocked.Exchange(ref _context, IntPtr.Zero); 88 89 if (currentContext != IntPtr.Zero) 90 { 91 soundio_destroy(currentContext); 92 } 93 } 94 95 public void Dispose() 96 { 97 Dispose(true); 98 GC.SuppressFinalize(this); 99 } 100 101 ~SoundIoContext() 102 { 103 Dispose(false); 104 } 105 } 106 }