Skip to content

Commit

Permalink
Use the AudioDeviceType as much as possible to avoid duplication of m…
Browse files Browse the repository at this point in the history
…ethod and code. See #19
  • Loading branch information
Antoine Aflalo committed Sep 2, 2015
1 parent c92865c commit 59db284
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 50 deletions.
37 changes: 24 additions & 13 deletions SoundSwitch.Tests/AppModelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,25 @@ public void TestAddingPlaybackDeviceToSelected()
var configurationMoq = new Mock<ISoundSwitchConfiguration> {Name = "Configuration mock"};
var audioMoqI = new Mock<IAudioDevice> { 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<string>());
SetConfigurationMoq(configurationMoq);

//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]
Expand All @@ -63,21 +65,23 @@ public void TestAddingAlreadyPresentPlaybackDeviceToSelected()
var configurationMoq = new Mock<ISoundSwitchConfiguration> {Name = "Configuration mock"};
var audioMoqI = new Mock<IAudioDevice> { 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<string> { "Speakers (Test device)" });
SetConfigurationMoq(configurationMoq);

//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]
Expand All @@ -86,21 +90,24 @@ public void TestRemovePresentPlaybackDevice()
var configurationMoq = new Mock<ISoundSwitchConfiguration> {Name = "Configuration mock"};
var audioMoqI = new Mock<IAudioDevice> { 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<string> { "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]
Expand All @@ -109,19 +116,22 @@ public void TestRemoveNotPresentPlaybackDevice()
var configurationMoq = new Mock<ISoundSwitchConfiguration> {Name = "Configuration mock"};
var audioMoqI = new Mock<IAudioDevice> { 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<string>());
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]
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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());
Expand All @@ -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;

Expand All @@ -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 == Role.Console)));
Assert.That(audioMoqI.Object.Equals(audioDevice));
}
Expand Down
89 changes: 68 additions & 21 deletions SoundSwitch/Model/AppModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,9 @@ private void InitUpdateChecker()
updateChecker.CheckForUpdate();
}

public event EventHandler<DeviceListChanged> SelectedPlaybackDeviceChanged;
public event EventHandler<AudioChangeEvent> DefaultRecordingDeviceChanged;
public event EventHandler<DeviceListChanged> SelectedDeviceChanged;
public event EventHandler<ExceptionEvent> ErrorTriggered;
public event EventHandler<AudioChangeEvent> DefaultPlaybackDeviceChanged;
public event EventHandler<DeviceListChanged> SelectedRecordingDeviceChanged;
public event EventHandler<AudioChangeEvent> DefaultDeviceChanged;
public event EventHandler<UpdateChecker.NewReleaseEvent> NewVersionReleased;

private void RegisterRecovery()
Expand Down Expand Up @@ -193,10 +191,25 @@ private int SaveState(object state)
/// </returns>
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;
Expand All @@ -212,18 +225,32 @@ public bool SelectDevice(IAudioDevice device)
/// </returns>
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;
}

#endregion


#region Hot keys

/// <summary>
Expand All @@ -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
{
Expand Down Expand Up @@ -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;
}
Expand All @@ -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.
/// </summary>
public bool CycleActiveDevice()
public bool CycleActiveDevice(AudioDeviceType type = AudioDeviceType.Playback)
{
using (AppLogger.Log.InfoCall())
{
var list = AvailablePlaybackDevices;
ICollection<IAudioDevice> 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:
Expand All @@ -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);
Expand Down
4 changes: 3 additions & 1 deletion SoundSwitch/Model/Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@ public ExceptionEvent(Exception exception)

public class DeviceListChanged : EventArgs
{
public DeviceListChanged(IEnumerable<string> seletedDevicesList)
public DeviceListChanged(IEnumerable<string> seletedDevicesList, AudioDeviceType type)
{
SeletedDevicesList = seletedDevicesList;
Type = type;
}

public IEnumerable<string> SeletedDevicesList { get; private set; }
public AudioDeviceType Type { get; private set; }
}
}
16 changes: 3 additions & 13 deletions SoundSwitch/Model/IAppModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,22 +77,12 @@ public interface IAppModel
/// <summary>
/// When the selected list of device to switch from is changed (new device added or removed).
/// </summary>
event EventHandler<DeviceListChanged> SelectedPlaybackDeviceChanged;
event EventHandler<DeviceListChanged> SelectedDeviceChanged;

/// <summary>
/// The Default Playback device has been changed.
/// </summary>
event EventHandler<AudioChangeEvent> DefaultPlaybackDeviceChanged;

/// <summary>
/// When the selected list of device to switch from is changed (new device added or removed).
/// </summary>
event EventHandler<DeviceListChanged> SelectedRecordingDeviceChanged;

/// <summary>
/// The Default Recording device has been changed.
/// </summary>
event EventHandler<AudioChangeEvent> DefaultRecordingDeviceChanged;
event EventHandler<AudioChangeEvent> DefaultDeviceChanged;

/// <summary>
/// If an exception happened in the <see cref="IAppModel" />
Expand Down Expand Up @@ -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.
/// </summary>
bool CycleActiveDevice();
bool CycleActiveDevice(AudioDeviceType type = AudioDeviceType.Playback);

#endregion
}
Expand Down
4 changes: 2 additions & 2 deletions SoundSwitch/Util/TrayIcon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ private void SetEventHandlers()
}
}
};
AppModel.Instance.DefaultPlaybackDeviceChanged +=
AppModel.Instance.DefaultDeviceChanged +=
(sender, audioChangeEvent) =>
{
ShowAudioChanged(audioChangeEvent.AudioDevice.FriendlyName);
Expand All @@ -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)
Expand Down

0 comments on commit 59db284

Please sign in to comment.