Skip to content

Commit

Permalink
Prepare the application for Recording devices.
Browse files Browse the repository at this point in the history
Change the Model to work with recording devies. See #19
  • Loading branch information
Antoine Aflalo committed Sep 2, 2015
1 parent 709e5c2 commit 9b1e5a3
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 43 deletions.
29 changes: 19 additions & 10 deletions SoundSwitch.Tests/AppModelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ private static void SetConfigurationMoq(IMock<ISoundSwitchConfiguration> configu
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)");

//Setup
configurationMoq.Setup(c => c.SelectedPlaybackDeviceList).Returns(new HashSet<string>());
Expand All @@ -44,32 +46,36 @@ public void TestAddingPlaybackDeviceToSelected()
//Action
var eventCalled = false;
AppModel.Instance.SelectedPlaybackDeviceChanged += (sender, changed) => eventCalled = true;
Assert.True(AppModel.Instance.AddPlaybackDevice("test"));
Assert.True(AppModel.Instance.SelectDevice(audioMoqI.Object));

//Asserts
configurationMoq.VerifyGet(c => c.SelectedPlaybackDeviceList);
configurationMoq.Verify(c => c.Save());
audioMoqI.VerifyGet(a => a.FriendlyName);
Assert.That(configurationMoq.Object.SelectedPlaybackDeviceList.Count == 1);
Assert.That(configurationMoq.Object.SelectedPlaybackDeviceList.Contains("test"));
Assert.That(configurationMoq.Object.SelectedPlaybackDeviceList.Contains("Speakers (Test device)"));
Assert.That(eventCalled, "SelectedPlaybackDeviceChanged not called");
}

[Test]
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)");

//Setup
configurationMoq.Setup(c => c.SelectedPlaybackDeviceList).Returns(new HashSet<string> {"test"});
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;
Assert.False(AppModel.Instance.AddPlaybackDevice("test"));
Assert.False(AppModel.Instance.SelectDevice(audioMoqI.Object));

//Asserts
configurationMoq.VerifyGet(c => c.SelectedPlaybackDeviceList);
audioMoqI.VerifyGet(a => a.FriendlyName);
Assert.That(configurationMoq.Object.SelectedPlaybackDeviceList.Count == 1);
Assert.That(!eventCalled, "SelectedPlaybackDeviceChanged called");
}
Expand All @@ -78,40 +84,43 @@ public void TestAddingAlreadyPresentPlaybackDeviceToSelected()
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)");
//Setup
configurationMoq.Setup(c => c.SelectedPlaybackDeviceList).Returns(new HashSet<string> {"test"});
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;
Assert.True(AppModel.Instance.RemovePlaybackDevice("test"));
Assert.True(AppModel.Instance.UnselectDevice(audioMoqI.Object));

//Asserts
configurationMoq.VerifyGet(c => c.SelectedPlaybackDeviceList);
configurationMoq.Verify(c => c.Save());
audioMoqI.VerifyGet(a => a.FriendlyName);
Assert.That(configurationMoq.Object.SelectedPlaybackDeviceList.Count == 0);
Assert.That(!configurationMoq.Object.SelectedPlaybackDeviceList.Contains("test"));
Assert.That(eventCalled, "SelectedPlaybackDeviceChanged not called");
}

[Test]
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)");
//Setup
configurationMoq.Setup(c => c.SelectedPlaybackDeviceList).Returns(new HashSet<string>());
SetConfigurationMoq(configurationMoq);

//Action
var eventCalled = false;
AppModel.Instance.SelectedPlaybackDeviceChanged += (sender, changed) => eventCalled = true;
Assert.False(AppModel.Instance.RemovePlaybackDevice("test"));
Assert.False(AppModel.Instance.UnselectDevice(audioMoqI.Object));

//Asserts
configurationMoq.VerifyGet(c => c.SelectedPlaybackDeviceList);
audioMoqI.VerifyGet(a => a.FriendlyName);
Assert.That(!eventCalled, "SelectedPlaybackDeviceChanged called");
}

Expand Down
43 changes: 33 additions & 10 deletions SoundSwitch/Model/AppModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,21 @@ public ICollection<IAudioDevice> AvailablePlaybackDevices
}
}

public HashSet<string> SelectedRecordingDevicesList { get; }

public ICollection<IAudioDevice> AvailableRecordingDevices
{
get
{
return ActiveAudioDeviceLister.GetRecordingDevices()
.Join(SelectedRecordingDevicesList,
a => a.FriendlyName,
selected => selected,
(a, selected) => a)
.ToList();
}
}

public bool SetCommunications
{
get { return AppConfigs.Configuration.ChangeCommunications; }
Expand All @@ -64,7 +79,8 @@ public bool SetCommunications
}
}

public string HotKeysString => AppConfigs.Configuration.HotKeysCombinaison.ToString();
public string PlaybackHotKeysString => AppConfigs.Configuration.HotKeysCombinaison.ToString();
public string RecordingHotKeysString { get; }

#region Misc settings

Expand Down Expand Up @@ -108,7 +124,7 @@ public void InitializeMain()
{
throw new InvalidOperationException("Already initialized");
}
SetHotkeyCombination(AppConfigs.Configuration.HotKeysCombinaison);
SetPlaybackHotkeyCombination(AppConfigs.Configuration.HotKeysCombinaison);
InitUpdateChecker();
_initialized = true;
}
Expand All @@ -125,8 +141,10 @@ private void InitUpdateChecker()
}

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

private void RegisterRecovery()
Expand Down Expand Up @@ -168,14 +186,14 @@ private int SaveState(object state)
/// <summary>
/// Add a playback device into the Set.
/// </summary>
/// <param name="deviceName"></param>
/// <param name="device"></param>
/// <returns>
/// true if the element is added to the <see cref="T:System.Collections.Generic.HashSet`1" /> object; false if
/// the element is already present.
/// </returns>
public bool AddPlaybackDevice(string deviceName)
public bool SelectDevice(IAudioDevice device)
{
var result = SelectedPlaybackDevicesList.Add(deviceName);
var result = SelectedPlaybackDevicesList.Add(device.FriendlyName);
if (result)
{
SelectedPlaybackDeviceChanged?.Invoke(this, new DeviceListChanged(SelectedPlaybackDevicesList));
Expand All @@ -187,14 +205,14 @@ public bool AddPlaybackDevice(string deviceName)
/// <summary>
/// Remove a device from the Set.
/// </summary>
/// <param name="deviceName"></param>
/// <param name="device"></param>
/// <returns>
/// true if the element is successfully found and removed; otherwise, false. This method returns false if
/// <paramref name="deviceName" /> is not found in the <see cref="T:System.Collections.Generic.HashSet`1" /> object.
/// </returns>
public bool RemovePlaybackDevice(string deviceName)
public bool UnselectDevice(IAudioDevice device)
{
var result = SelectedPlaybackDevicesList.Remove(deviceName);
var result = SelectedPlaybackDevicesList.Remove(device.FriendlyName);
if (result)
{
SelectedPlaybackDeviceChanged?.Invoke(this, new DeviceListChanged(SelectedPlaybackDevicesList));
Expand All @@ -212,7 +230,7 @@ public bool RemovePlaybackDevice(string deviceName)
/// Sets the hotkey combination
/// </summary>
/// <param name="hotkeys"></param>
public void SetHotkeyCombination(HotKeys hotkeys)
public void SetPlaybackHotkeyCombination(HotKeys hotkeys)
{
using (AppLogger.Log.InfoCall())
{
Expand All @@ -223,7 +241,7 @@ public void SetHotkeyCombination(HotKeys hotkeys)
{
AppLogger.Log.Warn("Can't register new hotkeys", hotkeys);
ErrorTriggered?.Invoke(this,
new ExceptionEvent(new Exception("Impossible to register HotKey: " + HotKeysString)));
new ExceptionEvent(new Exception("Impossible to register HotKey: " + PlaybackHotKeysString)));
}
else
{
Expand All @@ -234,6 +252,11 @@ public void SetHotkeyCombination(HotKeys hotkeys)
}
}

public void SetRecordingHotkeyCombination(HotKeys hotkeys)
{
throw new NotImplementedException();
}


private void HandleHotkeyPress(object sender, WindowsAPIAdapter.KeyPressedEventArgs e)
{
Expand Down
56 changes: 44 additions & 12 deletions SoundSwitch/Model/IAppModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,31 @@ public interface IAppModel
/// </summary>
ICollection<IAudioDevice> AvailablePlaybackDevices { get; }

/// <summary>
/// The list of Recording device selected to be used for Switching default devices.
/// </summary>
HashSet<string> SelectedRecordingDevicesList { get; }

/// <summary>
/// An union between the Active <see cref="IAudioDevice" /> of Windows and <see cref="SelectedRecordingDevicesList" />
/// </summary>
ICollection<IAudioDevice> AvailableRecordingDevices { get; }

/// <summary>
/// If the Playback device need also to be set for Communications.
/// </summary>
bool SetCommunications { get; set; }

/// <summary>
/// A string repsenting the set Keyboard shortcut for Switch default devices.
/// A string repsenting the set Keyboard shortcut for Switch default Playback devices.
/// </summary>
string PlaybackHotKeysString { get; }


/// <summary>
/// A string repsenting the set Keyboard shortcut for Switch default Playback devices.
/// </summary>
string HotKeysString { get; }
string RecordingHotKeysString { get; }

/// <summary>
/// If the application runs at windows startup
Expand All @@ -64,14 +80,24 @@ public interface IAppModel
event EventHandler<DeviceListChanged> SelectedPlaybackDeviceChanged;

/// <summary>
/// If an exception happened in the <see cref="IAppModel" />
/// The Default Playback device has been changed.
/// </summary>
event EventHandler<ExceptionEvent> ErrorTriggered;
event EventHandler<AudioChangeEvent> DefaultPlaybackDeviceChanged;

/// <summary>
/// The Default Playback device has been changed.
/// When the selected list of device to switch from is changed (new device added or removed).
/// </summary>
event EventHandler<AudioChangeEvent> DefaultPlaybackDeviceChanged;
event EventHandler<DeviceListChanged> SelectedRecordingDeviceChanged;

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

/// <summary>
/// If an exception happened in the <see cref="IAppModel" />
/// </summary>
event EventHandler<ExceptionEvent> ErrorTriggered;

/// <summary>
/// The update checker found a newer release than the installed version.
Expand All @@ -91,28 +117,34 @@ public interface IAppModel
/// <summary>
/// Add a playback device into the Set.
/// </summary>
/// <param name="deviceName"></param>
/// <param name="device"></param>
/// <returns>
/// true if the element is added to the <see cref="T:System.Collections.Generic.HashSet`1" /> object; false if
/// the element is already present.
/// </returns>
bool AddPlaybackDevice(string deviceName);
bool SelectDevice(IAudioDevice device);

/// <summary>
/// Remove a device from the Set.
/// </summary>
/// <param name="deviceName"></param>
/// <param name="device"></param>
/// <returns>
/// true if the element is successfully found and removed; otherwise, false. This method returns false if
/// <paramref name="deviceName" /> is not found in the <see cref="T:System.Collections.Generic.HashSet`1" /> object.
/// <paramref name="device" /> is not found in the <see cref="T:System.Collections.Generic.HashSet`1" /> object.
/// </returns>
bool RemovePlaybackDevice(string deviceName);
bool UnselectDevice(IAudioDevice device);

/// <summary>
/// Sets the hotkey combination
/// </summary>
/// <param name="hotkeys"></param>
void SetPlaybackHotkeyCombination(HotKeys hotkeys);

/// <summary>
/// Sets the hotkey combination
/// </summary>
/// <param name="hotkeys"></param>
void SetHotkeyCombination(HotKeys hotkeys);
void SetRecordingHotkeyCombination(HotKeys hotkeys);

/// <summary>
/// Attempts to set active device to the specified name
Expand Down
21 changes: 10 additions & 11 deletions SoundSwitch/UI/Forms/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ namespace SoundSwitch.UI.Forms
{
public partial class Settings : Form
{
public const string DevicesDelimiter = ";;;";

public Settings()
{
InitializeComponent();
Expand All @@ -40,7 +38,7 @@ public Settings()
toolTipComm.SetToolTip(communicationCheckbox, "When checked, switch also the default Communications device");

txtHotkey.KeyDown += TxtHotkey_KeyDown;
txtHotkey.Text = AppModel.Instance.HotKeysString;
txtHotkey.Text = AppModel.Instance.PlaybackHotKeysString;


RunAtStartup.Checked = AppModel.Instance.RunAtStartup;
Expand Down Expand Up @@ -79,7 +77,7 @@ private void TxtHotkey_KeyDown(object sender, KeyEventArgs e)
if (!string.IsNullOrEmpty(keyCode))
{
txtHotkey.ForeColor = Color.Green;
AppModel.Instance.SetHotkeyCombination(new HotKeys(e.KeyCode, modifierKeys));
AppModel.Instance.SetPlaybackHotkeyCombination(new HotKeys(e.KeyCode, modifierKeys));
}
}

Expand Down Expand Up @@ -137,7 +135,7 @@ private void PopulateAudioList()
deviceListView.Columns.Add("Device", -3, HorizontalAlignment.Center);
foreach (var device in audioDeviceWrappers)
{
AddDeviceIconSmallImage(device);
AddDeviceIconSmallImage(device, deviceListView);

var listViewItem = GenerateListViewItem(device, selected);

Expand All @@ -161,7 +159,8 @@ private ListViewItem GenerateListViewItem(IAudioDevice device, ICollection<strin
var listViewItem = new ListViewItem
{
Text = device.FriendlyName,
ImageKey = device.DeviceClassIconPath
ImageKey = device.DeviceClassIconPath,
Tag = device
};

if (selected.Contains(device.FriendlyName))
Expand All @@ -181,11 +180,11 @@ private ListViewItem GenerateListViewItem(IAudioDevice device, ICollection<strin
/// Using the DeviceClassIconPath, get the Icon
/// </summary>
/// <param name="device"></param>
private void AddDeviceIconSmallImage(IAudioDevice device)
private void AddDeviceIconSmallImage(IAudioDevice device, ListView listView)
{
if (!deviceListView.SmallImageList.Images.ContainsKey(device.DeviceClassIconPath))
if (!listView.SmallImageList.Images.ContainsKey(device.DeviceClassIconPath))
{
deviceListView.SmallImageList.Images.Add(device.DeviceClassIconPath,
listView.SmallImageList.Images.Add(device.DeviceClassIconPath,
AudioDeviceIconExtractor.ExtractIconFromAudioDevice(device, false));
}
}
Expand All @@ -197,10 +196,10 @@ private void LstDevicesItemChecked(object sender, ItemCheckEventArgs e)
switch (e.NewValue)
{
case CheckState.Checked:
AppModel.Instance.AddPlaybackDevice(deviceListView.Items[e.Index].Text);
AppModel.Instance.SelectDevice((IAudioDevice)deviceListView.Items[e.Index].Tag);
break;
case CheckState.Unchecked:
AppModel.Instance.RemovePlaybackDevice(deviceListView.Items[e.Index].Text);
AppModel.Instance.UnselectDevice((IAudioDevice)deviceListView.Items[e.Index].Tag);
break;
}
}
Expand Down

0 comments on commit 9b1e5a3

Please sign in to comment.