diff --git a/SoundSwitch.Tests/AppModelTests.cs b/SoundSwitch.Tests/AppModelTests.cs index fd0d55f5d8..841c0f7077 100644 --- a/SoundSwitch.Tests/AppModelTests.cs +++ b/SoundSwitch.Tests/AppModelTests.cs @@ -38,6 +38,7 @@ public void TestAddingPlaybackDeviceToSelected() var configurationMoq = new Mock {Name = "Configuration mock"}; var audioMoqI = new Mock { Name = "first audio dev" }; audioMoqI.SetupGet(a => a.FriendlyName).Returns("Speakers (Test device)"); + audioMoqI.SetupGet(a => a.Type).Returns(AudioDeviceType.Playback); //Setup configurationMoq.Setup(c => c.SelectedPlaybackDeviceList).Returns(new HashSet()); @@ -45,16 +46,17 @@ public void TestAddingPlaybackDeviceToSelected() //Action var eventCalled = false; - AppModel.Instance.SelectedPlaybackDeviceChanged += (sender, changed) => eventCalled = true; + AppModel.Instance.SelectedDeviceChanged += (sender, changed) => eventCalled = true; Assert.True(AppModel.Instance.SelectDevice(audioMoqI.Object)); //Asserts configurationMoq.VerifyGet(c => c.SelectedPlaybackDeviceList); configurationMoq.Verify(c => c.Save()); audioMoqI.VerifyGet(a => a.FriendlyName); + audioMoqI.VerifyGet(a => a.Type); Assert.That(configurationMoq.Object.SelectedPlaybackDeviceList.Count == 1); Assert.That(configurationMoq.Object.SelectedPlaybackDeviceList.Contains("Speakers (Test device)")); - Assert.That(eventCalled, "SelectedPlaybackDeviceChanged not called"); + Assert.That(eventCalled, "SelectedDeviceChanged not called"); } [Test] @@ -63,6 +65,7 @@ public void TestAddingAlreadyPresentPlaybackDeviceToSelected() var configurationMoq = new Mock {Name = "Configuration mock"}; var audioMoqI = new Mock { Name = "first audio dev" }; audioMoqI.SetupGet(a => a.FriendlyName).Returns("Speakers (Test device)"); + audioMoqI.SetupGet(a => a.Type).Returns(AudioDeviceType.Playback); //Setup configurationMoq.Setup(c => c.SelectedPlaybackDeviceList).Returns(new HashSet { "Speakers (Test device)" }); @@ -70,14 +73,15 @@ public void TestAddingAlreadyPresentPlaybackDeviceToSelected() //Action var eventCalled = false; - AppModel.Instance.SelectedPlaybackDeviceChanged += (sender, changed) => eventCalled = true; + AppModel.Instance.SelectedDeviceChanged += (sender, changed) => eventCalled = true; Assert.False(AppModel.Instance.SelectDevice(audioMoqI.Object)); //Asserts configurationMoq.VerifyGet(c => c.SelectedPlaybackDeviceList); audioMoqI.VerifyGet(a => a.FriendlyName); + audioMoqI.VerifyGet(a => a.Type); Assert.That(configurationMoq.Object.SelectedPlaybackDeviceList.Count == 1); - Assert.That(!eventCalled, "SelectedPlaybackDeviceChanged called"); + Assert.That(!eventCalled, "SelectedDeviceChanged called"); } [Test] @@ -86,21 +90,24 @@ public void TestRemovePresentPlaybackDevice() var configurationMoq = new Mock {Name = "Configuration mock"}; var audioMoqI = new Mock { Name = "first audio dev" }; audioMoqI.SetupGet(a => a.FriendlyName).Returns("Speakers (Test device)"); + audioMoqI.SetupGet(a => a.Type).Returns(AudioDeviceType.Playback); + //Setup configurationMoq.Setup(c => c.SelectedPlaybackDeviceList).Returns(new HashSet { "Speakers (Test device)" }); SetConfigurationMoq(configurationMoq); //Action var eventCalled = false; - AppModel.Instance.SelectedPlaybackDeviceChanged += (sender, changed) => eventCalled = true; + AppModel.Instance.SelectedDeviceChanged += (sender, changed) => eventCalled = true; Assert.True(AppModel.Instance.UnselectDevice(audioMoqI.Object)); //Asserts configurationMoq.VerifyGet(c => c.SelectedPlaybackDeviceList); configurationMoq.Verify(c => c.Save()); audioMoqI.VerifyGet(a => a.FriendlyName); + audioMoqI.VerifyGet(a => a.Type); Assert.That(configurationMoq.Object.SelectedPlaybackDeviceList.Count == 0); - Assert.That(eventCalled, "SelectedPlaybackDeviceChanged not called"); + Assert.That(eventCalled, "SelectedDeviceChanged not called"); } [Test] @@ -109,19 +116,22 @@ public void TestRemoveNotPresentPlaybackDevice() var configurationMoq = new Mock {Name = "Configuration mock"}; var audioMoqI = new Mock { Name = "first audio dev" }; audioMoqI.SetupGet(a => a.FriendlyName).Returns("Speakers (Test device)"); + audioMoqI.SetupGet(a => a.Type).Returns(AudioDeviceType.Playback); + //Setup configurationMoq.Setup(c => c.SelectedPlaybackDeviceList).Returns(new HashSet()); SetConfigurationMoq(configurationMoq); //Action var eventCalled = false; - AppModel.Instance.SelectedPlaybackDeviceChanged += (sender, changed) => eventCalled = true; + AppModel.Instance.SelectedDeviceChanged += (sender, changed) => eventCalled = true; Assert.False(AppModel.Instance.UnselectDevice(audioMoqI.Object)); //Asserts configurationMoq.VerifyGet(c => c.SelectedPlaybackDeviceList); audioMoqI.VerifyGet(a => a.FriendlyName); - Assert.That(!eventCalled, "SelectedPlaybackDeviceChanged called"); + audioMoqI.VerifyGet(a => a.Type); + Assert.That(!eventCalled, "SelectedDeviceChanged called"); } [Test] @@ -175,7 +185,7 @@ public void TestCycleConsoleAudioDevice() SetConfigurationMoq(configurationMoq); AppModel.Instance.ActiveAudioDeviceLister = listerMoq.Object; IAudioDevice audioDevice = null; - AppModel.Instance.DefaultPlaybackDeviceChanged += (sender, @event) => audioDevice = @event.AudioDevice; + AppModel.Instance.DefaultDeviceChanged += (sender, @event) => audioDevice = @event.AudioDevice; //Action Assert.That(AppModel.Instance.CycleActiveDevice()); @@ -214,7 +224,7 @@ public void TestCycleCommunicationsAudioDevice() SetConfigurationMoq(configurationMoq); AppModel.Instance.ActiveAudioDeviceLister = listerMoq.Object; IAudioDevice audioDevice = null; - AppModel.Instance.DefaultPlaybackDeviceChanged += (sender, @event) => audioDevice = @event.AudioDevice; + AppModel.Instance.DefaultDeviceChanged += (sender, @event) => audioDevice = @event.AudioDevice; //Action Assert.That(AppModel.Instance.CycleActiveDevice()); @@ -252,7 +262,7 @@ public void TestCycleAudioDeviceIsACycleThatReturnToFirstWhenReachEnd() SetConfigurationMoq(configurationMoq); AppModel.Instance.ActiveAudioDeviceLister = listerMoq.Object; IAudioDevice audioDevice = null; - AppModel.Instance.DefaultPlaybackDeviceChanged += (sender, @event) => audioDevice = @event.AudioDevice; + AppModel.Instance.DefaultDeviceChanged += (sender, @event) => audioDevice = @event.AudioDevice; //Action Assert.That(AppModel.Instance.CycleActiveDevice()); @@ -279,7 +289,7 @@ public void TestSetActiveDeviceNull() SetConfigurationMoq(configurationMoq); bool deviceChangeEventCalled = false; bool errorTriggeredEventCalled = false; - AppModel.Instance.DefaultPlaybackDeviceChanged += (sender, @event) => deviceChangeEventCalled = true; + AppModel.Instance.DefaultDeviceChanged += (sender, @event) => deviceChangeEventCalled = true; AppModel.Instance.ErrorTriggered += (sender, @event) => errorTriggeredEventCalled = @event.Exception is NullReferenceException; @@ -303,13 +313,14 @@ public void TestSetAudioDeviceSetAudioDeviceAsDefault() //Setup SetConfigurationMoq(configurationMoq); IAudioDevice audioDevice = null; - AppModel.Instance.DefaultPlaybackDeviceChanged += (sender, @event) => audioDevice = @event.AudioDevice; + AppModel.Instance.DefaultDeviceChanged += (sender, @event) => audioDevice = @event.AudioDevice; //Action AppModel.Instance.SetActiveDevice(audioMoqI.Object); //Asserts configurationMoq.VerifySet(config => config.LastPlaybackActive = "Speakers (Test device)"); + audioMoqI.VerifyGet(a => a.Type); audioMoqI.Verify(a => a.SetAsDefault(It.Is(role => role == Role.Console))); Assert.That(audioMoqI.Object.Equals(audioDevice)); } diff --git a/SoundSwitch/Model/AppModel.cs b/SoundSwitch/Model/AppModel.cs index d2824f8909..52df87956a 100644 --- a/SoundSwitch/Model/AppModel.cs +++ b/SoundSwitch/Model/AppModel.cs @@ -140,11 +140,9 @@ private void InitUpdateChecker() updateChecker.CheckForUpdate(); } - public event EventHandler SelectedPlaybackDeviceChanged; - public event EventHandler DefaultRecordingDeviceChanged; + public event EventHandler SelectedDeviceChanged; public event EventHandler ErrorTriggered; - public event EventHandler DefaultPlaybackDeviceChanged; - public event EventHandler SelectedRecordingDeviceChanged; + public event EventHandler DefaultDeviceChanged; public event EventHandler NewVersionReleased; private void RegisterRecovery() @@ -193,10 +191,25 @@ private int SaveState(object state) /// public bool SelectDevice(IAudioDevice device) { - var result = SelectedPlaybackDevicesList.Add(device.FriendlyName); + var result = false; + DeviceListChanged eventChanged = null; + switch (device.Type) + { + case AudioDeviceType.Playback: + result = SelectedPlaybackDevicesList.Add(device.FriendlyName); + eventChanged = new DeviceListChanged(SelectedPlaybackDevicesList, device.Type); + break; + case AudioDeviceType.Recording: + result = SelectedRecordingDevicesList.Add(device.FriendlyName); + eventChanged = new DeviceListChanged(SelectedRecordingDevicesList, device.Type); + break; + default: + throw new ArgumentOutOfRangeException(); + } + if (result) { - SelectedPlaybackDeviceChanged?.Invoke(this, new DeviceListChanged(SelectedPlaybackDevicesList)); + SelectedDeviceChanged?.Invoke(this, eventChanged); AppConfigs.Configuration.Save(); } return result; @@ -212,10 +225,25 @@ public bool SelectDevice(IAudioDevice device) /// public bool UnselectDevice(IAudioDevice device) { - var result = SelectedPlaybackDevicesList.Remove(device.FriendlyName); + var result = false; + DeviceListChanged eventChanged = null; + switch (device.Type) + { + case AudioDeviceType.Playback: + result = SelectedPlaybackDevicesList.Remove(device.FriendlyName); + eventChanged = new DeviceListChanged(SelectedPlaybackDevicesList, device.Type); + break; + case AudioDeviceType.Recording: + result = SelectedRecordingDevicesList.Remove(device.FriendlyName); + eventChanged = new DeviceListChanged(SelectedRecordingDevicesList, device.Type); + break; + default: + throw new ArgumentOutOfRangeException(); + } + if (result) { - SelectedPlaybackDeviceChanged?.Invoke(this, new DeviceListChanged(SelectedPlaybackDevicesList)); + SelectedDeviceChanged?.Invoke(this, eventChanged); AppConfigs.Configuration.Save(); } return result; @@ -223,7 +251,6 @@ public bool UnselectDevice(IAudioDevice device) #endregion - #region Hot keys /// @@ -240,8 +267,7 @@ public void SetPlaybackHotkeyCombination(HotKeys hotkeys) if (!WindowsAPIAdapter.RegisterHotKey(hotkeys)) { AppLogger.Log.Warn("Can't register new hotkeys", hotkeys); - ErrorTriggered?.Invoke(this, - new ExceptionEvent(new Exception("Impossible to register HotKey: " + PlaybackHotKeysString))); + ErrorTriggered?.Invoke(this, new ExceptionEvent(new Exception("Impossible to register HotKey: " + PlaybackHotKeysString))); } else { @@ -300,8 +326,19 @@ public bool SetActiveDevice(IAudioDevice device) AppLogger.Log.Info("Set Default Communication device", device); device.SetAsDefault(Role.Communications); } - DefaultPlaybackDeviceChanged?.Invoke(this, new AudioChangeEvent(device)); - AppConfigs.Configuration.LastPlaybackActive = device.FriendlyName; + DefaultDeviceChanged?.Invoke(this, new AudioChangeEvent(device)); + switch (device.Type) + { + case AudioDeviceType.Playback: + AppConfigs.Configuration.LastPlaybackActive = device.FriendlyName; + break; + case AudioDeviceType.Recording: + AppConfigs.Configuration.LastRecordingActive = device.FriendlyName; + break; + default: + throw new ArgumentOutOfRangeException(); + } + AppConfigs.Configuration.Save(); return true; } @@ -318,11 +355,26 @@ public bool SetActiveDevice(IAudioDevice device) /// as far as we can tell), returns false if could not successfully switch. Throws NoDevicesException /// if there are no devices configured. /// - public bool CycleActiveDevice() + public bool CycleActiveDevice(AudioDeviceType type = AudioDeviceType.Playback) { using (AppLogger.Log.InfoCall()) { - var list = AvailablePlaybackDevices; + ICollection list = null; + string lastActive = null; + switch (type) + { + case AudioDeviceType.Playback: + list = AvailablePlaybackDevices; + lastActive = AppConfigs.Configuration.LastPlaybackActive; + break; + case AudioDeviceType.Recording: + list = AvailableRecordingDevices; + lastActive = AppConfigs.Configuration.LastRecordingActive; + break; + default: + throw new ArgumentOutOfRangeException(nameof(type), type, null); + } + switch (list.Count) { case 0: @@ -332,12 +384,7 @@ public bool CycleActiveDevice() return false; } AppLogger.Log.Info("Cycle Audio Devices", list); - var defaultDev = - list.FirstOrDefault(device => device.FriendlyName == AppConfigs.Configuration.LastPlaybackActive) ?? - list.FirstOrDefault(device => device.IsDefault(Role.Console)) ?? - list.ElementAt(0); - - + var defaultDev = list.FirstOrDefault(device => device.FriendlyName == lastActive) ?? list.FirstOrDefault(device => device.IsDefault(Role.Console)) ?? list.ElementAt(0); var next = list.SkipWhile((device, i) => device != defaultDev).Skip(1).FirstOrDefault() ?? list.ElementAt(0); AppLogger.Log.Info("Select AudioDevice", next); return SetActiveDevice(next); diff --git a/SoundSwitch/Model/Events.cs b/SoundSwitch/Model/Events.cs index 52b4717bf0..56791ede80 100644 --- a/SoundSwitch/Model/Events.cs +++ b/SoundSwitch/Model/Events.cs @@ -40,11 +40,13 @@ public ExceptionEvent(Exception exception) public class DeviceListChanged : EventArgs { - public DeviceListChanged(IEnumerable seletedDevicesList) + public DeviceListChanged(IEnumerable seletedDevicesList, AudioDeviceType type) { SeletedDevicesList = seletedDevicesList; + Type = type; } public IEnumerable SeletedDevicesList { get; private set; } + public AudioDeviceType Type { get; private set; } } } \ No newline at end of file diff --git a/SoundSwitch/Model/IAppModel.cs b/SoundSwitch/Model/IAppModel.cs index a6ce1431c5..6a4cbd93a8 100644 --- a/SoundSwitch/Model/IAppModel.cs +++ b/SoundSwitch/Model/IAppModel.cs @@ -77,22 +77,12 @@ public interface IAppModel /// /// When the selected list of device to switch from is changed (new device added or removed). /// - event EventHandler SelectedPlaybackDeviceChanged; + event EventHandler SelectedDeviceChanged; /// /// The Default Playback device has been changed. /// - event EventHandler DefaultPlaybackDeviceChanged; - - /// - /// When the selected list of device to switch from is changed (new device added or removed). - /// - event EventHandler SelectedRecordingDeviceChanged; - - /// - /// The Default Recording device has been changed. - /// - event EventHandler DefaultRecordingDeviceChanged; + event EventHandler DefaultDeviceChanged; /// /// If an exception happened in the @@ -157,7 +147,7 @@ public interface IAppModel /// as far as we can tell), returns false if could not successfully switch. Throws NoDevicesException /// if there are no devices configured. /// - bool CycleActiveDevice(); + bool CycleActiveDevice(AudioDeviceType type = AudioDeviceType.Playback); #endregion } diff --git a/SoundSwitch/Util/TrayIcon.cs b/SoundSwitch/Util/TrayIcon.cs index 6769fe647e..824d5ff3d5 100644 --- a/SoundSwitch/Util/TrayIcon.cs +++ b/SoundSwitch/Util/TrayIcon.cs @@ -118,7 +118,7 @@ private void SetEventHandlers() } } }; - AppModel.Instance.DefaultPlaybackDeviceChanged += + AppModel.Instance.DefaultDeviceChanged += (sender, audioChangeEvent) => { ShowAudioChanged(audioChangeEvent.AudioDevice.FriendlyName); @@ -129,7 +129,7 @@ private void SetEventHandlers() : null; } }; - AppModel.Instance.SelectedPlaybackDeviceChanged += (sender, deviceListChanged) => { UpdateAvailableDeviceList(); }; + AppModel.Instance.SelectedDeviceChanged += (sender, deviceListChanged) => { UpdateAvailableDeviceList(); }; AppModel.Instance.NewVersionReleased += (sender, @event) => { if (_settingsMenu.IsHandleCreated)