private void ProcessAdded(ObservableProcess process) { if (process == null) { throw new ArgumentNullException(nameof(process)); } while (applicationDevicePreferences == null) { Task.Delay(250); } SharedModels.ApplicationDevicePreference applicationDevicePreference = applicationDevicePreferences.Applications.FirstOrDefault(x => x.Name == process.ProcessName); if (applicationDevicePreference == null) { applicationDevicePreference = new SharedModels.ApplicationDevicePreference(); } AudioInterface preferredRender = GetApplicationDevicePreference(DataFlow.Render, applicationDevicePreference, process); if (preferredRender != null) { ChangeDefaultApplicationDevice(preferredRender, process); } AudioInterface preferredCapture = GetApplicationDevicePreference(DataFlow.Capture, applicationDevicePreference, process); if (preferredCapture != null) { ChangeDefaultApplicationDevice(preferredCapture, process); } }
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); } } } }
private void AddApplicationDevicePreference(ObservableProcess process, AudioInterface audioInterface) { SharedModels.ApplicationDevicePreference applicationDevicePreference = applicationDevicePreferences.Applications.FirstOrDefault(x => x.Name == process.ProcessName); if (applicationDevicePreference == default) { applicationDevicePreference = new SharedModels.ApplicationDevicePreference() { Name = process.ProcessName, Devices = new SharedModels.DefaultDevicePreference() }; applicationDevicePreferences.Applications.Add(applicationDevicePreference); } _ = audioInterface.DataFlow switch { DataFlow.Render => applicationDevicePreference.Devices.RenderDeviceId = audioInterface.ID, DataFlow.Capture => applicationDevicePreference.Devices.CaptureDeviceId = audioInterface.ID, _ => null }; jsonDataDirty = true; }
private void RemoveOldApplicationDevicePreference(ObservableProcess process, AudioInterface audioInterface) { SharedModels.ApplicationDevicePreference applicationDevicePreference = applicationDevicePreferences.Applications.FirstOrDefault(x => x.Name == process.ProcessName); if (applicationDevicePreference == default) { return; } string previousPreferredInterface = null; switch (audioInterface.DataFlow) { case DataFlow.Render: previousPreferredInterface = applicationDevicePreference.Devices.RenderDeviceId; applicationDevicePreference.Devices.RenderDeviceId = null; break; case DataFlow.Capture: previousPreferredInterface = applicationDevicePreference.Devices.CaptureDeviceId; applicationDevicePreference.Devices.CaptureDeviceId = null; break; default: return; } if (applicationDevicePreference.Devices.RenderDeviceId == null && applicationDevicePreference.Devices.CaptureDeviceId == null) { applicationDevicePreferences.Applications.Remove(applicationDevicePreference); } SharedModels.DeviceApplicationPreference deviceApplicationPreference = deviceApplicationPreferences.Devices.FirstOrDefault(x => x.Id == previousPreferredInterface); if (deviceApplicationPreference == default) { return; } deviceApplicationPreference.Applications.Remove(process.ProcessName); if (deviceApplicationPreference.Applications.Count == 0) { deviceApplicationPreferences.Devices.Remove(deviceApplicationPreference); } }
private AudioInterface GetApplicationDevicePreference(DataFlow dataFlow, SharedModels.ApplicationDevicePreference applicationDevicePreference, ObservableProcess process) { string preferredInterfaceId = dataFlow switch { DataFlow.Render => applicationDevicePreference?.Devices?.RenderDeviceId, DataFlow.Capture => applicationDevicePreference?.Devices?.CaptureDeviceId, _ => null }; if (preferredInterfaceId != null) { return(GetAudioInterfaceById(preferredInterfaceId)); } AudioInterface audioInterface = GetDefaultApplicationDevice(dataFlow, process); if (audioInterface != null) { RemoveOldApplicationDevicePreference(process, audioInterface); AddApplicationDevicePreference(process, audioInterface); AddDeviceApplicationPreference(audioInterface, process); return(audioInterface); } return(null); }