Skip to content

Commit

Permalink
fix(AudioSwitcher): Properly use the right audio client for Windows p…
Browse files Browse the repository at this point in the history
…ost 21H2 (like Windows 11)
  • Loading branch information
Belphemur committed Oct 21, 2021
1 parent 5e0a985 commit 7324b15
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 28 deletions.
12 changes: 5 additions & 7 deletions SoundSwitch.Audio.Manager/Interop/Client/ExtendedPolicyClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.Runtime.InteropServices;
using Serilog;
using SoundSwitch.Audio.Manager.Interop.Client.ClientException;
using SoundSwitch.Audio.Manager.Interop.Com.Base;
using SoundSwitch.Audio.Manager.Interop.Enum;
using SoundSwitch.Audio.Manager.Interop.Factory;
using SoundSwitch.Audio.Manager.Interop.Interface.Policy.Extended;
Expand All @@ -16,15 +15,15 @@ internal class ExtendedPolicyClient
private const string DEVINTERFACE_AUDIO_CAPTURE = "#{2eef81be-33fa-4800-9670-1cd474972c3f}";
private const string MMDEVAPI_TOKEN = @"\\?\SWD#MMDEVAPI#";

private IAudioPolicyConfigFactory _sharedPolicyConfig;
private IAudioPolicyConfig _sharedPolicyConfig;
private readonly ILogger _log;

public ExtendedPolicyClient()
{
_log = Log.ForContext(GetType());
}

private IAudioPolicyConfigFactory PolicyConfig
private IAudioPolicyConfig PolicyConfig
{
get
{
Expand All @@ -33,7 +32,7 @@ private IAudioPolicyConfigFactory PolicyConfig
return _sharedPolicyConfig;
}

return _sharedPolicyConfig = AudioPolicyConfigFactory.Create();
return _sharedPolicyConfig = AudioPolicyConfigFactory.CreatePre21H2();
}
}

Expand All @@ -60,7 +59,7 @@ public void SetDefaultEndPoint(string deviceId, EDataFlow flow, IEnumerable<ERol
return;
}

using var deviceIdStr = HSTRING.FromString(GenerateDeviceId(deviceId, flow));
var deviceIdStr = GenerateDeviceId(deviceId, flow);
foreach (var eRole in roles)
{
PolicyConfig.SetPersistedDefaultAudioEndpoint(processId, flow, eRole, deviceIdStr);
Expand All @@ -83,9 +82,8 @@ public string GetDefaultEndPoint(EDataFlow flow, ERole role, uint processId)
{
try
{
PolicyConfig.GetPersistedDefaultAudioEndpoint(processId, flow, role, out var deviceId);
var deviceId = PolicyConfig.GetPersistedDefaultAudioEndpoint(processId, flow, role);
var unpacked = UnpackDeviceId(deviceId);
deviceId.Dispose();
return unpacked;
}
catch (Exception ex)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
using System;
using SoundSwitch.Audio.Manager.Interop.Com.Base;
using SoundSwitch.Audio.Manager.Interop.Interface.Policy.Extended;
using WinRT;
using SoundSwitch.Audio.Manager.Interop.Interface.Policy.Extended.Client;

namespace SoundSwitch.Audio.Manager.Interop.Factory
{
internal sealed class AudioPolicyConfigFactory
{
private const int OS_21H2_VERSION = 21390;

public static IAudioPolicyConfigFactory Create()
public static IAudioPolicyConfig CreatePre21H2()
{
using var name = HSTRING.FromString("Windows.Media.Internal.AudioPolicyConfig");

if (Environment.OSVersion.Version.Build >= OS_21H2_VERSION)
{
var iid21H2 = GuidGenerator.CreateIID(typeof(IAudioPolicyConfigFactoryVariant21H2Windows11));
ComBase.RoGetActivationFactory(name, ref iid21H2, out object factory21H2);
return factory21H2.As<IAudioPolicyConfigFactoryVariant21H2Windows11>();
return new Post21H2AudioPolicyConfig();
}

var iid = GuidGenerator.CreateIID(typeof(IAudioPolicyConfigFactoryWindows10Pre21H2));
ComBase.RoGetActivationFactory(name, ref iid, out object factory);
return factory.As<IAudioPolicyConfigFactoryWindows10Pre21H2>();
return new Pre21H2AudioPolicyConfig();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Runtime.InteropServices;
using SoundSwitch.Audio.Manager.Interop.Com.Base;
using SoundSwitch.Audio.Manager.Interop.Enum;
using WinRT;

namespace SoundSwitch.Audio.Manager.Interop.Interface.Policy.Extended.Client;

public class Post21H2AudioPolicyConfig : IAudioPolicyConfig
{
private readonly IAudioPolicyConfigFactoryVariant21H2Windows11 _factory;

public Post21H2AudioPolicyConfig()
{
using var name = HSTRING.FromString("Windows.Media.Internal.AudioPolicyConfig");

var iid = GuidGenerator.CreateIID(typeof(IAudioPolicyConfigFactoryVariant21H2Windows11));
ComBase.RoGetActivationFactory(name, ref iid, out object factory);
_factory = factory.As<IAudioPolicyConfigFactoryVariant21H2Windows11>();
}

public void SetPersistedDefaultAudioEndpoint(uint processId, EDataFlow flow, ERole role, string deviceId)
{
using var deviceIdHString = HSTRING.FromString(deviceId);
Marshal.ThrowExceptionForHR((int)_factory.SetPersistedDefaultAudioEndpoint(processId, flow, role, deviceIdHString));
}

public string GetPersistedDefaultAudioEndpoint(uint processId, EDataFlow flow, ERole role)
{
_factory.GetPersistedDefaultAudioEndpoint(processId, flow, role, out var deviceId);
var deviceIdStr = deviceId.ToString();
deviceId.Dispose();
return deviceIdStr;
}

public void ClearAllPersistedApplicationDefaultEndpoints()
{
Marshal.ThrowExceptionForHR((int)_factory.ClearAllPersistedApplicationDefaultEndpoints());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Runtime.InteropServices;
using SoundSwitch.Audio.Manager.Interop.Com.Base;
using SoundSwitch.Audio.Manager.Interop.Enum;
using WinRT;

namespace SoundSwitch.Audio.Manager.Interop.Interface.Policy.Extended.Client;

public class Pre21H2AudioPolicyConfig : IAudioPolicyConfig
{
private readonly IAudioPolicyConfigFactoryWindows10Pre21H2 _factory;

public Pre21H2AudioPolicyConfig()
{
using var name = HSTRING.FromString("Windows.Media.Internal.AudioPolicyConfig");

var iid = GuidGenerator.CreateIID(typeof(IAudioPolicyConfigFactoryWindows10Pre21H2));
ComBase.RoGetActivationFactory(name, ref iid, out object factory);
_factory = factory.As<IAudioPolicyConfigFactoryWindows10Pre21H2>();
}

public void SetPersistedDefaultAudioEndpoint(uint processId, EDataFlow flow, ERole role, string deviceId)
{
using var deviceIdHString = HSTRING.FromString(deviceId);
Marshal.ThrowExceptionForHR((int)_factory.SetPersistedDefaultAudioEndpoint(processId, flow, role, deviceIdHString));
}

public string GetPersistedDefaultAudioEndpoint(uint processId, EDataFlow flow, ERole role)
{
_factory.GetPersistedDefaultAudioEndpoint(processId, flow, role, out var deviceId);
var deviceIdStr = deviceId.ToString();
deviceId.Dispose();
return deviceIdStr;
}

public void ClearAllPersistedApplicationDefaultEndpoints()
{
Marshal.ThrowExceptionForHR((int)_factory.ClearAllPersistedApplicationDefaultEndpoints());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using SoundSwitch.Audio.Manager.Interop.Enum;

namespace SoundSwitch.Audio.Manager.Interop.Interface.Policy.Extended;

public interface IAudioPolicyConfig
{
/// <summary>
/// Set the audio enpoint for this device
/// </summary>
/// <param name="processId"></param>
/// <param name="flow"></param>
/// <param name="role"></param>
/// <param name="deviceId"></param>
void SetPersistedDefaultAudioEndpoint(uint processId, EDataFlow flow, ERole role, string deviceId);

/// <summary>
/// Get Audio enpoint of the device
/// </summary>
/// <param name="processId"></param>
/// <param name="flow"></param>
/// <param name="role"></param>
string GetPersistedDefaultAudioEndpoint(uint processId, EDataFlow flow, ERole role);

/// <summary>
/// Clear all set audio enpoint
/// </summary>
void ClearAllPersistedApplicationDefaultEndpoints();
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,10 @@

namespace SoundSwitch.Audio.Manager.Interop.Interface.Policy.Extended
{
public interface IAudioPolicyConfigFactory
{
HRESULT SetPersistedDefaultAudioEndpoint(uint processId, EDataFlow flow, ERole role, HSTRING deviceId);
HRESULT GetPersistedDefaultAudioEndpoint(uint processId, EDataFlow flow, ERole role, [Out, MarshalAs(UnmanagedType.HString)] out HSTRING deviceId);
HRESULT ClearAllPersistedApplicationDefaultEndpoints();
}

[Guid("ab3d4648-e242-459f-b02f-541c70306324")]
[InterfaceType(ComInterfaceType.InterfaceIsIInspectable)]
public interface IAudioPolicyConfigFactoryVariant21H2Windows11 : IAudioPolicyConfigFactory
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAudioPolicyConfigFactoryVariant21H2Windows11
{
int __incomplete__add_CtxVolumeChange();
int __incomplete__remove_CtxVolumeChanged();
Expand Down Expand Up @@ -47,9 +41,9 @@ public interface IAudioPolicyConfigFactoryVariant21H2Windows11 : IAudioPolicyCon
}

[Guid("2a59116d-6c4f-45e0-a74f-707e3fef9258")]
[InterfaceType(ComInterfaceType.InterfaceIsIInspectable)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface IAudioPolicyConfigFactoryWindows10Pre21H2 : IAudioPolicyConfigFactory
public interface IAudioPolicyConfigFactoryWindows10Pre21H2
{
void GetIids(out int iidCount, out IntPtr iids);
void GetRuntimeClassName(out IntPtr className);
Expand Down

0 comments on commit 7324b15

Please sign in to comment.