private void CheckApplicationDeviceChanges() { foreach (ObservableProcess process in ProcessCollection.Processes) { AudioInterface windowsPreferredRender = GetDefaultApplicationDevice(DataFlow.Render, process); AudioInterface windowsPreferredCapture = GetDefaultApplicationDevice(DataFlow.Capture, process); SharedModels.ApplicationDevicePreference applicationDevicePreference = applicationDevicePreferences.Applications.FirstOrDefault(x => x.Name == process.ProcessName); string preferredRenderId = applicationDevicePreference?.Devices?.RenderDeviceId; string preferredCaptureId = applicationDevicePreference?.Devices?.CaptureDeviceId; bool windowsThinksDefault = windowsPreferredRender == null && windowsPreferredCapture == null; bool noPreferences = preferredRenderId == null && preferredCaptureId == null; // There is agreement that this process uses the default devices. if (noPreferences && windowsThinksDefault) { continue; } // Windows doesn't think this process uses the default device and we don't have any preferences for the process. if (applicationDevicePreference == default && !windowsThinksDefault) { ChangeDefaultApplicationDevice(windowsPreferredRender, process); ChangeDefaultApplicationDevice(windowsPreferredCapture, process); } // Windows doesn't think this process uses the default device. We agree, but we disagree on the preferred audio device. else if (!windowsThinksDefault) { bool changeNeeded = preferredRenderId != windowsPreferredRender?.ID; changeNeeded = changeNeeded || preferredCaptureId != windowsPreferredCapture?.ID; if (changeNeeded) { Trace.WriteLine($"Preference conflict detected between Windows Settings and Stream Controller for process {process.ProcessName}."); } if (process.AudioDeviceTogglingNeeded) { ToggleDefaultApplicationDevice(process); process.AudioDeviceTogglingNeeded = false; } } // Windows thinks the process uses the default device. We disagree and are waiting for the process to make a sound. else if (windowsThinksDefault) { EarTrumpet.DataModel.WindowsAudio.Internal.AudioPolicyConfig audioPolicyConfig; if (preferredRenderId != null) { audioPolicyConfig = new EarTrumpet.DataModel.WindowsAudio.Internal.AudioPolicyConfig(DataFlow.Render); audioPolicyConfig.SetDefaultEndPoint(preferredRenderId, process.Id); } if (preferredCaptureId != null) { audioPolicyConfig = new EarTrumpet.DataModel.WindowsAudio.Internal.AudioPolicyConfig(DataFlow.Capture); audioPolicyConfig.SetDefaultEndPoint(preferredCaptureId, process.Id); } } } }
public static void ChangeDefaultApplicationDevice(AudioInterface audioInterface, ObservableProcess process) { if (audioInterface == null) { throw new ArgumentNullException(nameof(audioInterface)); } if (process == null) { throw new ArgumentNullException(nameof(process)); } EarTrumpet.DataModel.WindowsAudio.Internal.AudioPolicyConfig audioPolicyConfig = new EarTrumpet.DataModel.WindowsAudio.Internal.AudioPolicyConfig(audioInterface.DataFlow); audioPolicyConfig.SetDefaultEndPoint(audioInterface.ID, process.Id); Instance.RemoveOldApplicationDevicePreference(process, audioInterface); Instance.AddDeviceApplicationPreference(audioInterface, process); Instance.AddApplicationDevicePreference(process, audioInterface); }
public static void ClearApplicationDefaultDevice(DataFlow dataFlow, ObservableProcess process) { if (process == null) { throw new ArgumentNullException(nameof(process)); } AudioInterface dataFlowInterface = dataFlow switch { DataFlow.Render => Instance.DefaultRender, DataFlow.Capture => Instance.DefaultCapture, _ => null }; if (dataFlowInterface == null) { throw new ArgumentException($"{Enum.GetName(typeof(DataFlow),dataFlow)} is not {Enum.GetName(typeof(DataFlow), DataFlow.Render)} or {Enum.GetName(typeof(DataFlow), DataFlow.Capture)}.", nameof(dataFlow)); } EarTrumpet.DataModel.WindowsAudio.Internal.AudioPolicyConfig audioPolicyConfig = new EarTrumpet.DataModel.WindowsAudio.Internal.AudioPolicyConfig(dataFlow); audioPolicyConfig.SetDefaultEndPoint(String.Empty, process.Id); Instance.RemoveOldApplicationDevicePreference(process, dataFlowInterface); }