Fixed memory leak

This commit is contained in:
Jeroen Saey 2025-09-01 11:54:28 +02:00
parent faf091ac2c
commit a0df126bcf
3 changed files with 104 additions and 48 deletions

View File

@ -19,6 +19,14 @@ class Program
var devices = await volumeMixer.GetAudioDevicesAsync(DataFlow.Output);
Console.WriteLine($"Found {devices.Count} playback devices:");
while (true)
{
var test = await volumeMixer.GetDefaultAudioDeviceAsync(DataFlow.Output);
devices = await volumeMixer.GetAudioDevicesAsync(DataFlow.Output);
devices = await volumeMixer.GetAudioDevicesAsync(DataFlow.Input);
await Task.Delay(1000);
}
foreach (var device in devices)
{
Console.WriteLine($"- {device.Name} (Default: {device.IsDefault})");

View File

@ -18,9 +18,9 @@
<PackageTags>EonaCat, Audio, Volume, Mixer .NET Standard, Jeroen, Saey</PackageTags>
<PackageReleaseNotes></PackageReleaseNotes>
<Description>EonaCat VolumeMixer</Description>
<Version>1.0.5</Version>
<AssemblyVersion>1.0.0.5</AssemblyVersion>
<FileVersion>1.0.0.5</FileVersion>
<Version>1.0.6</Version>
<AssemblyVersion>1.0.0.6</AssemblyVersion>
<FileVersion>1.0.0.6</FileVersion>
<PackageIcon>icon.png</PackageIcon>
<RepositoryUrl>https://git.saey.me/EonaCat/EonaCat.VolumeMixer</RepositoryUrl>
<RepositoryType>git</RepositoryType>

View File

@ -49,9 +49,12 @@ namespace EonaCat.VolumeMixer.Managers
lock (_syncLock)
{
IMultiMediaDeviceCollection deviceCollection = null;
IMultiMediaDevice defaultDevice = null;
try
{
var result = _deviceEnumerator.EnumAudioEndpoints(dataFlow, DeviceState.Active, out var deviceCollection);
var result = _deviceEnumerator.EnumAudioEndpoints(dataFlow, DeviceState.Active, out deviceCollection);
if (result != 0 || deviceCollection == null)
{
return devices;
@ -60,18 +63,16 @@ namespace EonaCat.VolumeMixer.Managers
result = deviceCollection.GetCount(out var count);
if (result != 0)
{
ComHelper.ReleaseComObject(deviceCollection);
return devices;
}
string defaultId = "";
try
{
result = _deviceEnumerator.GetDefaultAudioEndpoint(dataFlow, Role.Multimedia, out var defaultDevice);
result = _deviceEnumerator.GetDefaultAudioEndpoint(dataFlow, Role.Multimedia, out defaultDevice);
if (result == 0 && defaultDevice != null)
{
defaultDevice.GetId(out defaultId);
ComHelper.ReleaseComObject(defaultDevice);
}
}
catch
@ -81,9 +82,11 @@ namespace EonaCat.VolumeMixer.Managers
for (uint i = 0; i < count; i++)
{
IMultiMediaDevice device = null;
try
{
result = deviceCollection.Item(i, out var device);
result = deviceCollection.Item(i, out device);
if (result == 0 && device != null)
{
result = device.GetId(out var id);
@ -94,24 +97,37 @@ namespace EonaCat.VolumeMixer.Managers
bool isDefault = id == defaultId;
devices.Add(new AudioDevice(device, id, name, isDefault, dataFlow, type));
}
else
{
ComHelper.ReleaseComObject(device);
}
}
}
catch
{
// Do nothing
}
finally
{
if (device != null)
{
ComHelper.ReleaseComObject(device);
}
}
}
ComHelper.ReleaseComObject(deviceCollection);
}
catch
{
// Do nothing
}
finally
{
if (deviceCollection != null)
{
ComHelper.ReleaseComObject(deviceCollection);
}
if (defaultDevice != null)
{
ComHelper.ReleaseComObject(defaultDevice);
}
}
}
return devices;
@ -129,9 +145,11 @@ namespace EonaCat.VolumeMixer.Managers
lock (_syncLock)
{
IMultiMediaDevice device = null;
try
{
var result = _deviceEnumerator.GetDefaultAudioEndpoint(dataFlow, Role.Multimedia, out var device);
var result = _deviceEnumerator.GetDefaultAudioEndpoint(dataFlow, Role.Multimedia, out device);
if (result == 0 && device != null)
{
result = device.GetId(out var id);
@ -141,58 +159,81 @@ namespace EonaCat.VolumeMixer.Managers
var type = GetDeviceType(device);
return new AudioDevice(device, id, name, true, dataFlow, type);
}
ComHelper.ReleaseComObject(device);
}
}
catch
{
// Do nothing
}
finally
{
if (device != null)
{
ComHelper.ReleaseComObject(device);
}
}
return null;
}
});
}
}
[DllImport("ole32.dll")]
private static extern int PropVariantClear(ref PropVariant pvar);
private string GetDeviceName(IMultiMediaDevice device)
{
IPropertyStore? propertyStore = null;
PropVariant propVariant = new PropVariant();
try
{
var result = device.OpenPropertyStore(0, out propertyStore);
if (result == 0 && propertyStore != null)
{
var propertyKey = PKEY_Device_FriendlyName;
result = propertyStore.GetValue(ref propertyKey, out propVariant);
if (result == 0)
{
// Get string
string name = Marshal.PtrToStringUni(propVariant.data1);
return !string.IsNullOrEmpty(name) ? name : "Unknown Device";
}
}
}
catch
{
// Do nothing
}
finally
{
// Clear memory
PropVariantClear(ref propVariant);
if (propertyStore != null)
{
ComHelper.ReleaseComObject(propertyStore);
}
}
return "Unknown Device";
}
private string GetDeviceName(IMultiMediaDevice device)
{
try
{
var result = device.OpenPropertyStore(0, out var propertyStore);
if (result == 0 && propertyStore != null)
{
var propertyKey = PKEY_Device_FriendlyName;
result = propertyStore.GetValue(ref propertyKey, out var propVariant);
if (result == 0 && propVariant.data1 != IntPtr.Zero)
{
string name = Marshal.PtrToStringUni(propVariant.data1);
ComHelper.ReleaseComObject(propertyStore);
return !string.IsNullOrEmpty(name) ? name : "Unknown Device";
}
ComHelper.ReleaseComObject(propertyStore);
}
}
catch
{
// Do nothing
}
return "Unknown Device";
}
private DeviceType GetDeviceType(IMultiMediaDevice device)
{
IPropertyStore propertyStore = null;
PropVariant propVariant = new PropVariant();
try
{
int result = device.OpenPropertyStore(0, out var propertyStore);
int result = device.OpenPropertyStore(0, out propertyStore);
if (result == 0 && propertyStore != null)
{
try
{
var propertyKey = PKEY_AudioEndpoint_FormFactor;
result = propertyStore.GetValue(ref propertyKey, out var propVariant);
result = propertyStore.GetValue(ref propertyKey, out propVariant);
// 0x13 == VT_UI4
if (result == 0 && propVariant.vt == 0x13)
@ -227,7 +268,7 @@ namespace EonaCat.VolumeMixer.Managers
}
finally
{
ComHelper.ReleaseComObject(propertyStore);
}
}
}
@ -235,7 +276,14 @@ namespace EonaCat.VolumeMixer.Managers
{
// Do nothing
}
finally
{
PropVariantClear(ref propVariant);
if (propertyStore != null)
{
ComHelper.ReleaseComObject(propertyStore);
}
}
return DeviceType.Unknown;
}