From 499e77df96054156420c823e3d80266ac886bdcc Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 15 Jan 2026 10:39:01 +0100 Subject: [PATCH] [AudioUnit] Simplify code and fix leak in AudioComponent.ComponentList. Contributes towards https://github.com/dotnet/macios/issues/17285. --- src/AudioUnit/AudioComponent.cs | 64 ++++++------------- .../AudioToolbox/AudioComponentTest.cs | 2 +- 2 files changed, 21 insertions(+), 45 deletions(-) diff --git a/src/AudioUnit/AudioComponent.cs b/src/AudioUnit/AudioComponent.cs index 4a5254a9c830..03ec43c23177 100644 --- a/src/AudioUnit/AudioComponent.cs +++ b/src/AudioUnit/AudioComponent.cs @@ -648,64 +648,40 @@ public void ValidateAsync (NSDictionary? validationParameters, [SupportedOSPlatform ("maccatalyst")] [UnsupportedOSPlatform ("tvos")] [DllImport (Constants.AudioUnitLibrary)] - static extern int /* OSStatus */ AudioUnitExtensionSetComponentList (IntPtr /* CFString */ extensionIdentifier, /* CFArrayRef */ IntPtr audioComponentInfo); + static extern int /* OSStatus */ AudioUnitExtensionSetComponentList (IntPtr /* CFString */ extensionIdentifier, /* __nullable CFArrayRef */ IntPtr audioComponentInfo); [SupportedOSPlatform ("macos")] [SupportedOSPlatform ("ios")] [SupportedOSPlatform ("maccatalyst")] [UnsupportedOSPlatform ("tvos")] [DllImport (Constants.AudioUnitLibrary)] - static extern /* CFArrayRef */ IntPtr AudioUnitExtensionCopyComponentList (IntPtr /* CFString */ extensionIdentifier); - - /// To be added. - /// To be added. - /// To be added. + static extern /* __nullable CFArrayRef */ IntPtr AudioUnitExtensionCopyComponentList (IntPtr /* CFString */ extensionIdentifier); + + /// Gets or sets the component list for this audio unit extension. + /// An array of objects describing the audio components, or if no components are available. + /// + /// This property allows you to get or set the list of audio components associated with this audio unit extension. + /// When setting this property, an will be thrown if the operation fails. + /// [SupportedOSPlatform ("macos")] [SupportedOSPlatform ("ios")] [SupportedOSPlatform ("maccatalyst")] [UnsupportedOSPlatform ("tvos")] public AudioComponentInfo []? ComponentList { get { - var nameHandle = CFString.CreateNative (Name); - try { - var cHandle = AudioUnitExtensionCopyComponentList (nameHandle); - if (cHandle == IntPtr.Zero) - return null; - using (var nsArray = Runtime.GetNSObject (cHandle, owns: true)) { - if (nsArray is null) - return null; - // make things easier for developers since we do not know how to have an implicit conversion from NSObject to AudioComponentInfo - var dics = NSArray.FromArray (nsArray); - var result = new AudioComponentInfo [dics.Length]; - for (var i = 0; i < result.Length; i++) { - result [i] = new AudioComponentInfo (dics [i]); - } - return result; - } - } finally { - CFString.ReleaseNative (nameHandle); - } + using var nameHandle = new TransientCFString (Name); + var cHandle = AudioUnitExtensionCopyComponentList (nameHandle); + return NSArray.ArrayFromHandle (cHandle, h => new AudioComponentInfo (Runtime.GetNSObject (h)!), releaseHandle: true); } set { - if (value is null) - ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (value)); - var nameHandle = CFString.CreateNative (Name); - try { - var dics = new NSDictionary [value.Length]; - for (var i = 0; i < value.Length; i++) { - dics [i] = value [i].Dictionary; - } - using (var array = NSArray.FromNSObjects (dics)) { - var result = (AudioConverterError) AudioUnitExtensionSetComponentList (nameHandle, array.Handle); - switch (result) { - case AudioConverterError.None: - return; - default: - throw new InvalidOperationException ($"ComponentList could not be set, error {result.ToString ()}"); - } - } - } finally { - CFString.ReleaseNative (nameHandle); + using var nameHandle = new TransientCFString (Name); + using var array = NSArray.FromNSObjects (h => h.Dictionary, value); + var result = (AudioConverterError) AudioUnitExtensionSetComponentList (nameHandle, array.GetHandle ()); + switch (result) { + case AudioConverterError.None: + return; + default: + throw new InvalidOperationException ($"ComponentList could not be set, error {result.ToString ()}"); } } } diff --git a/tests/monotouch-test/AudioToolbox/AudioComponentTest.cs b/tests/monotouch-test/AudioToolbox/AudioComponentTest.cs index 08741c8d35aa..1653026b0562 100644 --- a/tests/monotouch-test/AudioToolbox/AudioComponentTest.cs +++ b/tests/monotouch-test/AudioToolbox/AudioComponentTest.cs @@ -73,7 +73,7 @@ public void GetSetNullComponentList () if (component is null) continue; //monotouchtests does not have permissions to deal with the hwd. - Assert.Throws (() => component.ComponentList = null); + Assert.Throws (() => component.ComponentList = null); } }