[.NET/AudioUnit] Use [UnmanagedCallersOnly] instead of [MonoPInvokeCallback] Partial Fix for #10470 (#15808)
This commit is contained in:
Родитель
ea6048686a
Коммит
1efe5ff6a3
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче