[AudioUnit] Create a GCHandle when AudioUnit.SetInputCallback is called. Fixes #13637. (#13673)

AudioUnit needs a GCHandle in the input callback, which means we have to create it
when SetInputCallback is called (like we already do for SetRenderCallback).

Fixes https://github.com/xamarin/xamarin-macios/issues/13637.
This commit is contained in:
Rolf Bjarne Kvinge 2022-01-12 20:52:03 +01:00 коммит произвёл GitHub
Родитель 677b45b91c
Коммит 10ad084ec3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 56 добавлений и 0 удалений

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

@ -642,6 +642,9 @@ namespace AudioUnit
inputs [audioUnitElement] = inputDelegate; inputs [audioUnitElement] = inputDelegate;
if (!gcHandle.IsAllocated)
gcHandle = GCHandle.Alloc (this);
var cb = new AURenderCallbackStruct (); var cb = new AURenderCallbackStruct ();
cb.Proc = CreateInputCallback; cb.Proc = CreateInputCallback;
cb.ProcRefCon = GCHandle.ToIntPtr (gcHandle); cb.ProcRefCon = GCHandle.ToIntPtr (gcHandle);

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

@ -0,0 +1,53 @@
//
// Unit tests for AudioUnit
//
// Authors:
// Rolf Bjarne Kvinge (rolf@xamarin.com)
//
// Copyright 2022 Microsoft Corp. All rights reserved.
//
#if __MACOS__ && NET
using System;
using System.Threading;
using Foundation;
using AudioToolbox;
using AudioUnit;
using NUnit.Framework;
namespace MonoTouchFixtures.AudioToolbox {
[TestFixture]
[Preserve (AllMembers = true)]
public class AudioUnitTest
{
ManualResetEvent inputCallbackEvent = new ManualResetEvent (false);
// This test currently only works on macOS, probably due to missing microphone entitlements/permissions for mobile platforms.
[Test]
public void Callbacks ()
{
var audioComponent = AudioComponent.FindComponent (AudioTypeOutput.VoiceProcessingIO);
using var audioUnit = new global::AudioUnit.AudioUnit (audioComponent);
audioUnit.SetInputCallback (InputCallback, AudioUnitScopeType.Input, 1);
audioUnit.Initialize ();
try {
audioUnit.Start ();
Assert.IsTrue (inputCallbackEvent.WaitOne (TimeSpan.FromSeconds (1)), "No input callback for 1 second");
} finally {
audioUnit.Stop ();
}
}
AudioUnitStatus InputCallback (AudioUnitRenderActionFlags actionFlags, AudioTimeStamp timeStamp, uint busNumber, uint numberFrames, global::AudioUnit.AudioUnit audioUnit)
{
inputCallbackEvent.Set ();
return AudioUnitStatus.NoError;
}
}
}
#endif // __MACOS__ && NET