[AVFoundation] Fix a few issues with AudioUnit. (#12954)

* Add an (IntPtr, bool) constructor so that AudioUnit works with Runtime.GetINativeObject.
* Keep track of ownership, so that AudioUnit doesn't free the native resources
  when it doesn't own them.
* Update a test to verify that calling 'AVAudioIONode.AudioUnit' multiple
  times and disposing the result between them works (this fails if AudioUnit
  doesn't keep track of ownership).
This commit is contained in:
Rolf Bjarne Kvinge 2021-10-08 07:52:40 +02:00 коммит произвёл GitHub
Родитель da9c95d604
Коммит 6d8ef62705
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 24 добавлений и 8 удалений

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

@ -298,7 +298,7 @@ namespace AudioUnit
public class AudioUnit : IDisposable, ObjCRuntime.INativeObject
{
#pragma warning disable 649 // Field 'AudioUnit.handle' is never assigned to, and will always have its default value
internal IntPtr handle;
IntPtr handle;
#pragma warning restore 649
public IntPtr Handle {
get {
@ -314,14 +314,21 @@ namespace AudioUnit
GCHandle gcHandle;
bool _isPlaying;
bool owns;
Dictionary<uint, RenderDelegate> renderer;
Dictionary<uint, InputDelegate> inputs;
internal AudioUnit (IntPtr ptr)
: this (ptr, false)
{
}
internal AudioUnit (IntPtr ptr, bool owns)
{
handle = ptr;
gcHandle = GCHandle.Alloc(this);
this.owns = owns;
}
public AudioUnit (AudioComponent component)
@ -336,6 +343,7 @@ namespace AudioUnit
throw new AudioUnitException (err);
gcHandle = GCHandle.Alloc(this);
owns = true;
}
public AudioComponent Component {
@ -795,9 +803,11 @@ namespace AudioUnit
protected virtual void Dispose (bool disposing)
{
if (handle != IntPtr.Zero){
Stop ();
AudioUnitUninitialize (handle);
AudioComponentInstanceDispose (handle);
if (owns) {
Stop ();
AudioUnitUninitialize (handle);
AudioComponentInstanceDispose (handle);
}
gcHandle.Free();
handle = IntPtr.Zero;
}

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

@ -21,10 +21,16 @@ namespace Xamarin.Mac.Tests
Asserts.EnsureYosemite ();
AVAudioEngine eng = new AVAudioEngine();
AVAudioIONode node = eng.OutputNode;
AUUnit unit = node.AudioUnit;
unit.GetElementCount (AudioUnitScopeType.Global);
using (AVAudioEngine eng = new AVAudioEngine ()) {
using (AVAudioIONode node = eng.OutputNode) {
using (AUUnit unit = node.AudioUnit)
unit.GetElementCount (AudioUnitScopeType.Global);
using (AUUnit unit = node.AudioUnit)
unit.GetElementCount (AudioUnitScopeType.Global);
using (AUUnit unit = node.AudioUnit)
unit.GetElementCount (AudioUnitScopeType.Global);
}
}
// Make sure this doens't crash.
}
}