[.NET/AudioUnit] Use [UnmanagedCallersOnly] instead of [MonoPInvokeCallback] Partial Fix for #10470 (#15808)

This commit is contained in:
Steve Hawley 2022-09-06 10:24:55 -04:00 коммит произвёл GitHub
Родитель ea6048686a
Коммит 1efe5ff6a3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 116 добавлений и 5 удалений

Просмотреть файл

@ -140,8 +140,15 @@ namespace AudioUnit
ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (callback));
AudioUnitStatus error = AudioUnitStatus.OK;
#if NET
unsafe {
if (graphUserCallbacks.Count == 0)
error = (AudioUnitStatus) AUGraphAddRenderNotify (Handle, &renderCallback, GCHandle.ToIntPtr (gcHandle));
}
#else
if (graphUserCallbacks.Count == 0)
error = (AudioUnitStatus) AUGraphAddRenderNotify (Handle, renderCallback, GCHandle.ToIntPtr (gcHandle));
#endif
if (error == AudioUnitStatus.OK)
graphUserCallbacks.Add (callback);
@ -156,8 +163,15 @@ namespace AudioUnit
throw new ArgumentException ("Cannot unregister a callback that has not been registered");
AudioUnitStatus error = AudioUnitStatus.OK;
#if NET
unsafe {
if (graphUserCallbacks.Count == 0)
error = (AudioUnitStatus)AUGraphRemoveRenderNotify (Handle, &renderCallback, GCHandle.ToIntPtr (gcHandle));
}
#else
if (graphUserCallbacks.Count == 0)
error = (AudioUnitStatus)AUGraphRemoveRenderNotify (Handle, renderCallback, GCHandle.ToIntPtr (gcHandle));
#endif
graphUserCallbacks.Remove (callback); // Remove from list even if there is an error
return error;
@ -165,6 +179,26 @@ namespace AudioUnit
HashSet<RenderDelegate> graphUserCallbacks = new HashSet<RenderDelegate> ();
#if !NET
static CallbackShared? _static_CallbackShared;
static CallbackShared static_CallbackShared {
get {
if (_static_CallbackShared is null)
_static_CallbackShared = new CallbackShared (renderCallback);
return _static_CallbackShared;
}
}
#endif
#if NET
[UnmanagedCallersOnly]
static unsafe AudioUnitStatus renderCallback(IntPtr inRefCon,
AudioUnitRenderActionFlags* _ioActionFlags,
AudioTimeStamp* _inTimeStamp,
uint _inBusNumber,
uint _inNumberFrames,
IntPtr _ioData)
#else
[MonoPInvokeCallback (typeof(CallbackShared))]
static AudioUnitStatus renderCallback(IntPtr inRefCon,
ref AudioUnitRenderActionFlags _ioActionFlags,
@ -172,6 +206,7 @@ namespace AudioUnit
uint _inBusNumber,
uint _inNumberFrames,
IntPtr _ioData)
#endif
{
// getting audiounit instance
var handler = GCHandle.FromIntPtr (inRefCon);
@ -183,8 +218,13 @@ namespace AudioUnit
if (renderers.Count != 0) {
using (var buffers = new AudioBuffers (_ioData)) {
foreach (RenderDelegate renderer in renderers)
foreach (RenderDelegate renderer in renderers) {
#if NET
renderer (*_ioActionFlags, *_inTimeStamp, _inBusNumber, _inNumberFrames, buffers);
#else
renderer (_ioActionFlags, _inTimeStamp, _inBusNumber, _inNumberFrames, buffers);
#endif
}
return AudioUnitStatus.OK;
}
}
@ -313,7 +353,9 @@ namespace AudioUnit
}
Dictionary<uint, RenderDelegate>? nodesCallbacks;
#if !NET
static readonly CallbackShared CreateRenderCallback = RenderCallbackImpl;
#endif
public AUGraphError SetNodeInputCallback (int destNode, uint destInputNumber, RenderDelegate renderDelegate)
{
@ -323,17 +365,27 @@ namespace AudioUnit
nodesCallbacks [destInputNumber] = renderDelegate;
var cb = new AURenderCallbackStruct ();
#if NET
unsafe {
cb.Proc = &RenderCallbackImpl;
}
#else
cb.Proc = CreateRenderCallback;
#endif
cb.ProcRefCon = GCHandle.ToIntPtr (gcHandle);
return AUGraphSetNodeInputCallback (Handle, destNode, destInputNumber, ref cb);
}
#if NET
[UnmanagedCallersOnly]
static unsafe AudioUnitStatus RenderCallbackImpl (IntPtr clientData, AudioUnitRenderActionFlags* actionFlags, AudioTimeStamp* timeStamp, uint busNumber, uint numberFrames, IntPtr data)
#else
[MonoPInvokeCallback (typeof (CallbackShared))]
static AudioUnitStatus RenderCallbackImpl (IntPtr clientData, ref AudioUnitRenderActionFlags actionFlags, ref AudioTimeStamp timeStamp, uint busNumber, uint numberFrames, IntPtr data)
#endif
{
GCHandle gch = GCHandle.FromIntPtr (clientData);
var au = gch.Target as AUGraph;
if (au?.nodesCallbacks is null)
return AudioUnitStatus.InvalidParameter;
@ -341,7 +393,11 @@ namespace AudioUnit
return AudioUnitStatus.InvalidParameter;
using (var buffers = new AudioBuffers (data)) {
#if NET
return callback (*actionFlags, *timeStamp, busNumber, numberFrames, buffers);
#else
return callback (actionFlags, timeStamp, busNumber, numberFrames, buffers);
#endif
}
}
@ -435,10 +491,19 @@ namespace AudioUnit
static extern AUGraphError AUGraphInitialize (IntPtr inGraph);
[DllImport (Constants.AudioToolboxLibrary)]
#if NET
static unsafe extern int AUGraphAddRenderNotify (IntPtr inGraph, delegate* unmanaged<IntPtr, AudioUnitRenderActionFlags*, AudioTimeStamp*, uint, uint, IntPtr, AudioUnitStatus> inCallback, IntPtr inRefCon );
#else
static extern int AUGraphAddRenderNotify (IntPtr inGraph, CallbackShared inCallback, IntPtr inRefCon );
#endif
#if NET
[DllImport (Constants.AudioToolboxLibrary)]
static unsafe extern int AUGraphRemoveRenderNotify (IntPtr inGraph, delegate* unmanaged<IntPtr, AudioUnitRenderActionFlags*, AudioTimeStamp*, uint, uint, IntPtr, AudioUnitStatus> inCallback, IntPtr inRefCon );
#else
[DllImport (Constants.AudioToolboxLibrary)]
static extern int AUGraphRemoveRenderNotify (IntPtr inGraph, CallbackShared inCallback, IntPtr inRefCon );
#endif
[DllImport (Constants.AudioToolboxLibrary)]
static extern AUGraphError AUGraphStart (IntPtr inGraph);

Просмотреть файл

@ -135,12 +135,25 @@ namespace AudioUnit
delegate AudioUnitStatus CallbackShared (IntPtr /* void* */ clientData, ref AudioUnitRenderActionFlags /* AudioUnitRenderActionFlags* */ actionFlags, ref AudioTimeStamp /* AudioTimeStamp* */ timeStamp, uint /* UInt32 */ busNumber, uint /* UInt32 */ numberFrames, IntPtr /* AudioBufferList* */ data);
#endif // !COREBUILD
#if NET
[StructLayout (LayoutKind.Sequential)]
unsafe struct AURenderCallbackStruct
{
#if COREBUILD
public delegate* unmanaged<IntPtr, int*, AudioTimeStamp*, uint, uint, IntPtr, int> Proc;
#else
public delegate* unmanaged<IntPtr, AudioUnitRenderActionFlags*, AudioTimeStamp*, uint, uint, IntPtr, AudioUnitStatus> Proc;
#endif
public IntPtr ProcRefCon;
}
#else
[StructLayout (LayoutKind.Sequential)]
struct AURenderCallbackStruct
{
public Delegate Proc;
public IntPtr ProcRefCon;
}
#endif
[StructLayout (LayoutKind.Sequential)]
struct AudioUnitConnection
@ -349,8 +362,10 @@ namespace AudioUnit
public class AudioUnit : DisposableObject
{
#if !COREBUILD
#if !NET
static readonly CallbackShared CreateRenderCallback = RenderCallbackImpl;
static readonly CallbackShared CreateInputCallback = InputCallbackImpl;
#endif
GCHandle gcHandle;
bool _isPlaying;
@ -657,18 +672,28 @@ namespace AudioUnit
gcHandle = GCHandle.Alloc (this);
var cb = new AURenderCallbackStruct ();
#if NET
unsafe {
cb.Proc = &RenderCallbackImpl;
}
#else
cb.Proc = CreateRenderCallback;
#endif
cb.ProcRefCon = GCHandle.ToIntPtr (gcHandle);
return AudioUnitSetProperty (Handle, AudioUnitPropertyIDType.SetRenderCallback, scope, audioUnitElement, ref cb, Marshal.SizeOf (cb));
}
#if NET
[UnmanagedCallersOnly]
static unsafe AudioUnitStatus RenderCallbackImpl (IntPtr clientData, AudioUnitRenderActionFlags* actionFlags, AudioTimeStamp* timeStamp, uint busNumber, uint numberFrames, IntPtr data)
#else
[MonoPInvokeCallback (typeof (CallbackShared))]
static AudioUnitStatus RenderCallbackImpl (IntPtr clientData, ref AudioUnitRenderActionFlags actionFlags, ref AudioTimeStamp timeStamp, uint busNumber, uint numberFrames, IntPtr data)
#endif
{
GCHandle gch = GCHandle.FromIntPtr (clientData);
var au = (AudioUnit?) gch.Target;
var renderer = au?.renderer;
if (renderer is null)
return AudioUnitStatus.Uninitialized;
@ -676,7 +701,13 @@ namespace AudioUnit
return AudioUnitStatus.Uninitialized;
using (var buffers = new AudioBuffers (data)) {
#if NET
unsafe {
return render (*actionFlags, *timeStamp, busNumber, numberFrames, buffers);
}
#else
return render (actionFlags, timeStamp, busNumber, numberFrames, buffers);
#endif
}
}
@ -695,13 +726,23 @@ namespace AudioUnit
gcHandle = GCHandle.Alloc (this);
var cb = new AURenderCallbackStruct ();
#if NET
unsafe {
cb.Proc = &InputCallbackImpl;
}
#else
cb.Proc = CreateInputCallback;
#endif
cb.ProcRefCon = GCHandle.ToIntPtr (gcHandle);
return AudioUnitSetProperty (Handle, AudioUnitPropertyIDType.SetInputCallback, scope, audioUnitElement, ref cb, Marshal.SizeOf (cb));
}
#if NET
[UnmanagedCallersOnly]
static unsafe AudioUnitStatus InputCallbackImpl (IntPtr clientData, AudioUnitRenderActionFlags* actionFlags, AudioTimeStamp* timeStamp, uint busNumber, uint numberFrames, IntPtr data)
#else
[MonoPInvokeCallback (typeof (CallbackShared))]
static AudioUnitStatus InputCallbackImpl (IntPtr clientData, ref AudioUnitRenderActionFlags actionFlags, ref AudioTimeStamp timeStamp, uint busNumber, uint numberFrames, IntPtr data)
#endif
{
GCHandle gch = GCHandle.FromIntPtr (clientData);
var au = gch.Target as AudioUnit;
@ -714,8 +755,13 @@ namespace AudioUnit
if (!inputs.TryGetValue (busNumber, out var input))
return AudioUnitStatus.Uninitialized;
#if NET
unsafe {
return input (*actionFlags, *timeStamp, busNumber, numberFrames, au);
}
#else
return input (actionFlags, timeStamp, busNumber, numberFrames, au);
#endif
}
#endregion