Beispiel #1
0
        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);
            }
        }
Beispiel #2
0
 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);
             }
         }
     }
 }
Beispiel #3
0
            void IMMNotificationClient.OnDeviceRemoved(string deviceId)
            {
                AudioInterface audioInterface = GetAudioInterfaceById(deviceId);

                mContext.Send(
                    x => Devices.Remove(GetAudioInterfaceById(deviceId))
                    , null);
                if (audioInterface.IsActive)
                {
                    mContext.Send(
                        x => ActiveDevices.Remove(audioInterface),
                        null);
                }
            }
Beispiel #4
0
            void IMMNotificationClient.OnDeviceAdded(string pwstrDeviceId)
            {
                AudioInterface device = new AudioInterface
                {
                    Device = _Enumerator.GetDevice(pwstrDeviceId)
                };

                mContext.Send(
                    x => Devices.Add(device)
                    , null);
                if (device.IsActive)
                {
                    mContext.Send(
                        x => ActiveDevices.Add(device),
                        null);
                }
            }
Beispiel #5
0
        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);
        }
Beispiel #6
0
 private void AddDeviceApplicationPreference(AudioInterface audioInterface, ObservableProcess process)
 {
     SharedModels.DeviceApplicationPreference deviceApplicationPreference = deviceApplicationPreferences.Devices.FirstOrDefault(x => x.Id == audioInterface.ID);
     if (deviceApplicationPreference == default)
     {
         deviceApplicationPreference = new SharedModels.DeviceApplicationPreference()
         {
             Id           = audioInterface.ID,
             Applications = new List <string>()
         };
         deviceApplicationPreferences.Devices.Add(deviceApplicationPreference);
     }
     if (!deviceApplicationPreference.Applications.Contains(process.ProcessName))
     {
         deviceApplicationPreference.Applications.Add(process.ProcessName);
     }
     jsonDataDirty = true;
 }
Beispiel #7
0
 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;
 }
Beispiel #8
0
        private void DevicesEnumerated(MMDeviceCollection collection)
        {
            _Enumerator.RegisterEndpointNotificationCallback(_NotificationClient);
            foreach (MMDevice device in collection)
            {
                AudioInterface audioDevice = new AudioInterface
                {
                    Device = device
                };
                _Context.Send(
                    x => Devices.Add(audioDevice),
                    null);
                if (audioDevice.IsActive)
                {
                    _Context.Send(
                        x => ActiveDevices.Add(audioDevice),
                        null);
                }
            }
            UpdateDefaultDevice(DataFlow.Render, _Enumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Console).ID);
            UpdateDefaultDevice(DataFlow.Capture, _Enumerator.GetDefaultAudioEndpoint(DataFlow.Capture, Role.Console).ID);
            DevicesAreEnumerated = true;
            NotifyCollectionEnumerated();
            RestoreDeviceApplicationPreferences();
            bool processesEnumerated = false;

            _Context.Send(
                x => processesEnumerated = ProcessCollection.Instance.ProcessesAreEnumerated,
                null);
            if (!processesEnumerated)
            {
                ProcessCollection.Instance.CollectionEnumerated += Processes_CollectionEnumerated;
            }
            else
            {
                Processes_CollectionEnumerated(this, EventArgs.Empty);
            }

            ProcessCollection.Instance.CollectionChanged += Processes_CollectionChanged;
        }
Beispiel #9
0
            void IMMNotificationClient.OnDeviceStateChanged(string deviceId, DeviceState newState)
            {
                AudioInterface audioInterface = GetAudioInterfaceById(deviceId);

                if (audioInterface != null)
                {
                    audioInterface.SetProperties(newState);
                }

                if (newState != DeviceState.Active)
                {
                    if (ActiveDevices.Contains(audioInterface))
                    {
                        mContext.Send(
                            x => ActiveDevices.Remove(audioInterface),
                            null);
                    }
                    return;
                }

                mContext.Send(
                    x => ActiveDevices.Add(audioInterface),
                    null);

                SharedModels.DeviceApplicationPreference deviceApplicationPreference = Instance.deviceApplicationPreferences.Devices.FirstOrDefault(x => x.Id == deviceId);
                if (deviceApplicationPreference == default)
                {
                    return;
                }

                foreach (string applicationName in deviceApplicationPreference.Applications)
                {
                    ObservableProcess[] processes = ProcessCollection.Processes.Where(x => x.ProcessName == applicationName).ToArray();
                    foreach (ObservableProcess process in processes)
                    {
                        ChangeDefaultApplicationDevice(audioInterface, process);
                    }
                }
            }
Beispiel #10
0
        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);
            }
        }
Beispiel #11
0
        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);
        }
Beispiel #12
0
        public static void ToggleDefaultApplicationDevice(ObservableProcess process)
        {
            if (process == null)
            {
                throw new ArgumentNullException(nameof(process));
            }

            AudioInterface renderDevice = GetDefaultApplicationDevice(DataFlow.Render, process);

            if (renderDevice != null)
            {
                Trace.WriteLine($"Toggling PID {process.Id} render device to default and back to {renderDevice.FriendlyName}.");
                ChangeDefaultApplicationDevice(Instance.DefaultRender, process);
                ChangeDefaultApplicationDevice(renderDevice, process);
            }
            AudioInterface captureDevice = GetDefaultApplicationDevice(DataFlow.Capture, process);

            if (captureDevice != null)
            {
                Trace.WriteLine($"Toggling PID {process.Id} capture device to default and back to {captureDevice.FriendlyName}.");
                ChangeDefaultApplicationDevice(Instance.DefaultCapture, process);
                ChangeDefaultApplicationDevice(captureDevice, process);
            }
        }
Beispiel #13
0
        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);
        }