diff --git a/EonaCat.VolumeMixer.Tester/Program.cs b/EonaCat.VolumeMixer.Tester/Program.cs
index 81b7ab6..a03765c 100644
--- a/EonaCat.VolumeMixer.Tester/Program.cs
+++ b/EonaCat.VolumeMixer.Tester/Program.cs
@@ -16,7 +16,7 @@ class Program
try
{
// Get all audio PLAYBACK devices
- var devices = await volumeMixer.GetAudioDevicesAsync(DataFlow.Output);
+ var devices = await volumeMixer.GetAudioDevicesAsync(DataFlow.Input);
Console.WriteLine($"Found {devices.Count} playback devices:");
foreach (var device in devices)
@@ -36,6 +36,9 @@ class Program
// Get all audio sessions
var sessions = await defaultDevice.GetAudioSessionsAsync();
+ var sessions2 = await defaultDevice.GetAudioSessionsAsync();
+ var sessions3 = await defaultDevice.GetAudioSessionsAsync();
+ var sessions4 = await defaultDevice.GetAudioSessionsAsync();
Console.WriteLine($"Active sessions: {sessions.Count}");
foreach (var session in sessions)
@@ -99,15 +102,11 @@ class Program
{
Console.WriteLine($"Error: {ex.Message}");
}
- }
- // Microphone management example
- using (var micManager = new MicrophoneManager())
- {
try
{
// Get all microphones
- var microphones = await micManager.GetMicrophonesAsync();
+ var microphones = await volumeMixer.GetMicrophonesAsync();
Console.WriteLine($"Found {microphones.Count} microphones:");
foreach (var mic in microphones)
@@ -119,7 +118,7 @@ class Program
}
// Default microphone
- using (var defaultMic = await micManager.GetDefaultMicrophoneAsync())
+ using (var defaultMic = await volumeMixer.GetDefaultMicrophoneAsync())
{
Console.WriteLine($"\nSetting default microphone volume to 1%");
bool success = await defaultMic.SetMasterVolumeAsync(0.1f);
@@ -149,15 +148,15 @@ class Program
}
}
- Console.WriteLine($"Default mic volume: {await micManager.GetMicrophoneVolumeAsync():P0}");
- Console.WriteLine($"Default mic muted: {await micManager.GetMicrophoneMuteAsync()}");
+ Console.WriteLine($"Default mic volume: {await volumeMixer.GetMicrophoneVolumeAsync():P0}");
+ Console.WriteLine($"Default mic muted: {await volumeMixer.GetMicrophoneMuteAsync()}");
// Set microphone volume to 60%
- bool result = await micManager.SetMicrophoneVolumeAsync(0.6f);
+ bool result = await volumeMixer.SetMicrophoneVolumeAsync(0.6f);
Console.WriteLine($"Set microphone volume to 60%: {result}");
// Set specific microphone by name
- result = await micManager.SetMicrophoneVolumeByNameAsync("USB", 0.7f);
+ result = await volumeMixer.SetMicrophoneVolumeByNameAsync("USB", 0.7f);
Console.WriteLine($"Set USB microphone volume to 70%: {result}");
}
diff --git a/EonaCat.VolumeMixer/EonaCat.VolumeMixer.csproj b/EonaCat.VolumeMixer/EonaCat.VolumeMixer.csproj
index 09be1ff..d184bee 100644
--- a/EonaCat.VolumeMixer/EonaCat.VolumeMixer.csproj
+++ b/EonaCat.VolumeMixer/EonaCat.VolumeMixer.csproj
@@ -18,9 +18,9 @@
EonaCat, Audio, Volume, Mixer .NET Standard, Jeroen, Saey
EonaCat VolumeMixer
- 1.0.0
- 1.0.0.0
- 1.0.0.0
+ 1.0.1
+ 1.0.0.1
+ 1.0.0.1
icon.png
diff --git a/EonaCat.VolumeMixer/Managers/MicrophoneManager.cs b/EonaCat.VolumeMixer/Managers/MicrophoneManager.cs
deleted file mode 100644
index b50b1b7..0000000
--- a/EonaCat.VolumeMixer/Managers/MicrophoneManager.cs
+++ /dev/null
@@ -1,146 +0,0 @@
-using EonaCat.VolumeMixer.Models;
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-
-namespace EonaCat.VolumeMixer.Managers
-{
- // This file is part of the EonaCat project(s) which is released under the Apache License.
- // See the LICENSE file or go to https://EonaCat.com/License for full license details.
- public class MicrophoneManager : IDisposable
- {
- private readonly VolumeMixerManager _volumeMixer;
- private readonly object _syncLock = new();
-
- public MicrophoneManager()
- {
- _volumeMixer = new VolumeMixerManager();
- }
-
- public async Task> GetMicrophonesAsync()
- {
- return await _volumeMixer.GetAudioDevicesAsync(DataFlow.Input);
- }
-
- public async Task GetDefaultMicrophoneAsync()
- {
- return await _volumeMixer.GetDefaultAudioDeviceAsync(DataFlow.Input);
- }
-
- public async Task SetMicrophoneVolumeAsync(float volume)
- {
- if (volume < 0f || volume > 1f)
- {
- return false;
- }
-
- AudioDevice defaultMic = await GetDefaultMicrophoneAsync();
-
- if (defaultMic == null)
- {
- return false;
- }
-
- try
- {
- return await defaultMic.SetMasterVolumeAsync(volume);
- }
- finally
- {
- defaultMic.Dispose();
- }
- }
-
- public async Task GetMicrophoneVolumeAsync()
- {
- AudioDevice defaultMic = await GetDefaultMicrophoneAsync();
-
- if (defaultMic == null)
- {
- return 0f;
- }
-
- try
- {
- return await defaultMic.GetMasterVolumeAsync();
- }
- finally
- {
- defaultMic.Dispose();
- }
- }
-
- public async Task SetMicrophoneMuteAsync(bool mute)
- {
- AudioDevice defaultMic = await GetDefaultMicrophoneAsync();
-
- if (defaultMic == null)
- {
- return false;
- }
-
- try
- {
- return await defaultMic.SetMasterMuteAsync(mute);
- }
- finally
- {
- defaultMic.Dispose();
- }
- }
-
- public async Task GetMicrophoneMuteAsync()
- {
- AudioDevice defaultMic = await GetDefaultMicrophoneAsync();
-
- if (defaultMic == null)
- {
- return false;
- }
-
- try
- {
- return await defaultMic.GetMasterMuteAsync();
- }
- finally
- {
- defaultMic.Dispose();
- }
- }
-
- public async Task SetMicrophoneVolumeByNameAsync(string microphoneName, float volume)
- {
- if (string.IsNullOrWhiteSpace(microphoneName) || volume < 0f || volume > 1f)
- {
- return false;
- }
-
- List microphones = await GetMicrophonesAsync();
-
- foreach (var mic in microphones)
- {
- try
- {
- if (mic.Name.IndexOf(microphoneName, StringComparison.OrdinalIgnoreCase) >= 0)
- {
- return await mic.SetMasterVolumeAsync(volume);
- }
- }
- finally
- {
- mic.Dispose();
- }
- }
-
- return false;
- }
-
- public void Dispose()
- {
- lock (_syncLock)
- {
- _volumeMixer?.Dispose();
- }
- }
- }
-}
diff --git a/EonaCat.VolumeMixer/Managers/VolumeMixerManager.cs b/EonaCat.VolumeMixer/Managers/VolumeMixerManager.cs
index ae0040b..bb40db3 100644
--- a/EonaCat.VolumeMixer/Managers/VolumeMixerManager.cs
+++ b/EonaCat.VolumeMixer/Managers/VolumeMixerManager.cs
@@ -92,18 +92,12 @@ namespace EonaCat.VolumeMixer.Managers
}
}
}
- catch
- {
- // Skip individual device on error
- }
+ catch { }
}
ComHelper.ReleaseComObject(deviceCollection);
}
- catch
- {
- // Ignore all and return partial/empty result
- }
+ catch { }
}
return devices;
@@ -132,45 +126,78 @@ namespace EonaCat.VolumeMixer.Managers
var name = GetDeviceName(device);
return new AudioDevice(device, id, name, true, dataFlow);
}
-
ComHelper.ReleaseComObject(device);
}
}
- catch
- {
- // Ignore and return null
- }
+ catch { }
return null;
}
});
}
- private string GetDeviceName(IMultiMediaDevice device)
+ public async Task> GetMicrophonesAsync()
{
- 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.data != IntPtr.Zero)
- {
- string name = Marshal.PtrToStringUni(propVariant.data);
- ComHelper.ReleaseComObject(propertyStore);
- return !string.IsNullOrEmpty(name) ? name : "Unknown Device";
- }
+ return await GetAudioDevicesAsync(DataFlow.Input);
+ }
- ComHelper.ReleaseComObject(propertyStore);
+ public async Task GetDefaultMicrophoneAsync()
+ {
+ return await GetDefaultAudioDeviceAsync(DataFlow.Input);
+ }
+
+ public async Task SetAudioDeviceVolumeByNameAsync(string audioDevice, float volume)
+ {
+ if (string.IsNullOrWhiteSpace(audioDevice) || volume < 0f || volume > 1f)
+ {
+ return false;
+ }
+
+ List audioDevices = await GetAudioDevicesAsync();
+
+ foreach (var mic in audioDevices)
+ {
+ try
+ {
+ if (mic.Name.IndexOf(audioDevice, StringComparison.OrdinalIgnoreCase) >= 0)
+ {
+ return await mic.SetMasterVolumeAsync(volume);
+ }
+ }
+ finally
+ {
+ mic.Dispose();
}
}
- catch
+
+ return false;
+ }
+
+ public async Task SetMicrophoneVolumeByNameAsync(string microphoneName, float volume)
+ {
+ if (string.IsNullOrWhiteSpace(microphoneName) || volume < 0f || volume > 1f)
{
- // Ignore and fall through
+ return false;
}
- return "Unknown Device";
+ List microphones = await GetMicrophonesAsync();
+
+ foreach (var mic in microphones)
+ {
+ try
+ {
+ if (mic.Name.IndexOf(microphoneName, StringComparison.OrdinalIgnoreCase) >= 0)
+ {
+ return await mic.SetMasterVolumeAsync(volume);
+ }
+ }
+ finally
+ {
+ mic.Dispose();
+ }
+ }
+
+ return false;
}
public async Task SetSystemVolumeAsync(float volume)
@@ -254,6 +281,87 @@ namespace EonaCat.VolumeMixer.Managers
}
}
+ public async Task GetMicrophoneVolumeAsync()
+ {
+ AudioDevice defaultMic = await GetDefaultMicrophoneAsync();
+
+ if (defaultMic == null)
+ {
+ return 0f;
+ }
+
+ try
+ {
+ return await defaultMic.GetMasterVolumeAsync();
+ }
+ finally
+ {
+ defaultMic.Dispose();
+ }
+ }
+
+ public async Task SetMicrophoneVolumeAsync(float volume)
+ {
+ if (volume < 0f || volume > 1f)
+ {
+ return false;
+ }
+
+ AudioDevice defaultMic = await GetDefaultMicrophoneAsync();
+
+ if (defaultMic == null)
+ {
+ return false;
+ }
+
+ try
+ {
+ return await defaultMic.SetMasterVolumeAsync(volume);
+ }
+ finally
+ {
+ defaultMic.Dispose();
+ }
+ }
+
+ public async Task SetMicrophoneMuteAsync(bool mute)
+ {
+ AudioDevice defaultMic = await GetDefaultMicrophoneAsync();
+
+ if (defaultMic == null)
+ {
+ return false;
+ }
+
+ try
+ {
+ return await defaultMic.SetMasterMuteAsync(mute);
+ }
+ finally
+ {
+ defaultMic.Dispose();
+ }
+ }
+
+ public async Task GetMicrophoneMuteAsync()
+ {
+ AudioDevice defaultMic = await GetDefaultMicrophoneAsync();
+
+ if (defaultMic == null)
+ {
+ return false;
+ }
+
+ try
+ {
+ return await defaultMic.GetMasterMuteAsync();
+ }
+ finally
+ {
+ defaultMic.Dispose();
+ }
+ }
+
public async Task> GetAllActiveSessionsAsync()
{
return await Task.Run(async () =>
@@ -268,10 +376,7 @@ namespace EonaCat.VolumeMixer.Managers
{
allSessions.AddRange(await device.GetAudioSessionsAsync());
}
- catch
- {
- // Skip device on error
- }
+ catch { }
finally
{
device.Dispose();
@@ -282,6 +387,30 @@ namespace EonaCat.VolumeMixer.Managers
});
}
+ 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.data != IntPtr.Zero)
+ {
+ string name = Marshal.PtrToStringUni(propVariant.data);
+ ComHelper.ReleaseComObject(propertyStore);
+ return !string.IsNullOrEmpty(name) ? name : "Unknown Device";
+ }
+
+ ComHelper.ReleaseComObject(propertyStore);
+ }
+ }
+ catch { }
+
+ return "Unknown Device";
+ }
+
public void Dispose()
{
lock (_syncLock)
diff --git a/EonaCat.VolumeMixer/Models/AudioDevice.cs b/EonaCat.VolumeMixer/Models/AudioDevice.cs
index ec5c711..fd068f4 100644
--- a/EonaCat.VolumeMixer/Models/AudioDevice.cs
+++ b/EonaCat.VolumeMixer/Models/AudioDevice.cs
@@ -79,8 +79,8 @@ namespace EonaCat.VolumeMixer.Models
try
{
- var hr = _endpointVolume.GetMasterVolumeLevelScalar(out var volume);
- return hr == 0 ? volume : 0f;
+ var result = _endpointVolume.GetMasterVolumeLevelScalar(out var volume);
+ return result == 0 ? volume : 0f;
}
catch
{
diff --git a/EonaCat.VolumeMixer/Models/AudioSession.cs b/EonaCat.VolumeMixer/Models/AudioSession.cs
index c25328f..6068cdc 100644
--- a/EonaCat.VolumeMixer/Models/AudioSession.cs
+++ b/EonaCat.VolumeMixer/Models/AudioSession.cs
@@ -10,6 +10,7 @@ namespace EonaCat.VolumeMixer.Models
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
public class AudioSession : IDisposable
{
+ private static Guid SharedAppSessionGuid = new Guid("c0a3a9d0-b4dc-58b7-b95e-dcc407dbd8db");
private readonly IAudioSessionControlExtended _sessionControl;
private IAudioVolume _audioVolume;
private bool _isDisposed = false;
@@ -33,14 +34,11 @@ namespace EonaCat.VolumeMixer.Models
{
try
{
- var result = _sessionControl.GetGroupingParam(out var guid);
- if (result == 0)
+ // Always use the shared static GUID
+ var result = sessionManager.GetAudioVolume(ref SharedAppSessionGuid, 0, out var ptr);
+ if (result == 0 && ptr != IntPtr.Zero)
{
- result = sessionManager.GetAudioVolume(ref guid, 0, out var ptr);
- if (result == 0 && ptr != IntPtr.Zero)
- {
- _audioVolume = ComHelper.GetInterface(ptr);
- }
+ _audioVolume = ComHelper.GetInterface(ptr);
}
}
catch
@@ -126,8 +124,8 @@ namespace EonaCat.VolumeMixer.Models
{
try
{
- var hr = audioVolCopy.SetMasterVolume(volume, ref guid);
- if (hr == 0)
+ var result = audioVolCopy.SetMasterVolume(volume, ref guid);
+ if (result == 0)
{
await Task.Delay(delayMs);
diff --git a/README.md b/README.md
index 36c07de..4f4cf84 100644
--- a/README.md
+++ b/README.md
@@ -88,18 +88,18 @@ using System.Threading.Tasks;
class Program
{
- // This file is part of the EonaCat project(s) which is released under the Apache License.
+ // This file is part of the EonaCat project(s) which is released under the Apache License.
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
[STAThread]
static async Task Main()
{
- // Playback management example
+ // 1. Create the volume mixer manager
using (var volumeMixer = new VolumeMixerManager())
{
try
{
- // Get all audio PLAYBACK devices
- var devices = await volumeMixer.GetAudioDevicesAsync(DataFlow.Output);
+ // 2. Get all audio PLAYBACK devices
+ var devices = await volumeMixer.GetAudioDevicesAsync(DataFlow.Input);
Console.WriteLine($"Found {devices.Count} playback devices:");
foreach (var device in devices)
@@ -119,6 +119,9 @@ class Program
// Get all audio sessions
var sessions = await defaultDevice.GetAudioSessionsAsync();
+ var sessions2 = await defaultDevice.GetAudioSessionsAsync();
+ var sessions3 = await defaultDevice.GetAudioSessionsAsync();
+ var sessions4 = await defaultDevice.GetAudioSessionsAsync();
Console.WriteLine($"Active sessions: {sessions.Count}");
foreach (var session in sessions)
@@ -182,33 +185,11 @@ class Program
{
Console.WriteLine($"Error: {ex.Message}");
}
- }
- }
-}
-```
-
-## Microphone management example:
-```csharp
-using EonaCat.VolumeMixer.Managers;
-using EonaCat.VolumeMixer.Models;
-using System;
-using System.Threading.Tasks;
-
-class Program
-{
- // This file is part of the EonaCat project(s) which is released under the Apache License.
- // See the LICENSE file or go to https://EonaCat.com/License for full license details.
- [STAThread]
- static async Task Main()
- {
- // Microphone management example
- using (var micManager = new MicrophoneManager())
- {
try
{
- // Get all microphones
- var microphones = await micManager.GetMicrophonesAsync();
+ // 3. Get all microphones
+ var microphones = await volumeMixer.GetMicrophonesAsync();
Console.WriteLine($"Found {microphones.Count} microphones:");
foreach (var mic in microphones)
@@ -220,7 +201,7 @@ class Program
}
// Default microphone
- using (var defaultMic = await micManager.GetDefaultMicrophoneAsync())
+ using (var defaultMic = await volumeMixer.GetDefaultMicrophoneAsync())
{
Console.WriteLine($"\nSetting default microphone volume to 1%");
bool success = await defaultMic.SetMasterVolumeAsync(0.1f);
@@ -250,15 +231,15 @@ class Program
}
}
- Console.WriteLine($"Default mic volume: {await micManager.GetMicrophoneVolumeAsync():P0}");
- Console.WriteLine($"Default mic muted: {await micManager.GetMicrophoneMuteAsync()}");
+ Console.WriteLine($"Default mic volume: {await volumeMixer.GetMicrophoneVolumeAsync():P0}");
+ Console.WriteLine($"Default mic muted: {await volumeMixer.GetMicrophoneMuteAsync()}");
// Set microphone volume to 60%
- bool result = await micManager.SetMicrophoneVolumeAsync(0.6f);
+ bool result = await volumeMixer.SetMicrophoneVolumeAsync(0.6f);
Console.WriteLine($"Set microphone volume to 60%: {result}");
// Set specific microphone by name
- result = await micManager.SetMicrophoneVolumeByNameAsync("USB", 0.7f);
+ result = await volumeMixer.SetMicrophoneVolumeByNameAsync("USB", 0.7f);
Console.WriteLine($"Set USB microphone volume to 70%: {result}");
}
@@ -268,5 +249,4 @@ class Program
}
}
}
-}
```
\ No newline at end of file