Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix performance #290

Merged
merged 3 commits into from
Jun 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions SoundSwitch/Framework/Configuration/Device/DeviceInfoCollection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using NAudio.CoreAudioApi;

namespace SoundSwitch.Framework.Configuration.Device
{
public class DeviceInfoCollection : ICollection<DeviceInfo>
{
private readonly Dictionary<string, DeviceInfo> _deviceByName = new Dictionary<string, DeviceInfo>();
private readonly Dictionary<string, DeviceInfo> _deviceById = new Dictionary<string, DeviceInfo>();

private readonly HashSet<DeviceInfo> _original;

public DeviceInfoCollection(HashSet<DeviceInfo> devices)
{
_original = devices;
foreach (var deviceInfo in devices)
{
AddItem(deviceInfo);
}
}

/// <summary>
/// Intersect with MMDevices
/// </summary>
/// <param name="devices"></param>
/// <returns></returns>
public IEnumerable<MMDevice> IntersectWith(IEnumerable<MMDevice> devices)
{
var devicesResult = new Dictionary<string, MMDevice>();
foreach (var mmDevice in devices)
{
if (devicesResult.ContainsKey(mmDevice.ID))
continue;

if (!_deviceById.ContainsKey(mmDevice.ID) && !_deviceByName.ContainsKey(mmDevice.FriendlyName))
continue;

devicesResult.Add(mmDevice.ID, mmDevice);

}

return devicesResult.Values;

}

public IEnumerator<DeviceInfo> GetEnumerator()
{
return _deviceById.Values.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

public void Add(DeviceInfo item)
{
AddItem(item, true);
}

/// <summary>
/// Add Item and update or not the original
/// </summary>
/// <param name="item"></param>
/// <param name="updateOriginal"></param>
private void AddItem(DeviceInfo item, bool updateOriginal = false)
{
if (item == null)
{
return;
}

try
{
_deviceById.Add(item.Id, item);
}
catch (ArgumentException)
{
}

try
{
_deviceByName.Add(item.Name, item);
}
catch (ArgumentException)
{
}

if (updateOriginal)
{
_original.Add(item);
}
}

public void Clear()
{
_deviceById.Clear();
_deviceByName.Clear();
_original.Clear();
}

public bool Contains(DeviceInfo item)
{
return item != null && (_deviceById.ContainsKey(item.Id) || _deviceByName.ContainsKey(item.Name));
}

public void CopyTo(DeviceInfo[] array, int arrayIndex)
{
throw new System.NotImplementedException();
}

public bool Remove(DeviceInfo item)
{
if (item == null)
{
return false;
}

var result = _original.RemoveWhere((info => info?.Id == item.Id || info?.Name == item.Name)) > 0;

try
{
result &= _deviceById.Remove(item.Id);
}
catch (ArgumentException)
{

}

try
{
result &= _deviceByName.Remove(item.Name);
}
catch (ArgumentException)
{

}

return result;
}

public int Count => _deviceById.Count;

public bool IsReadOnly => false;
}
}
55 changes: 37 additions & 18 deletions SoundSwitch/Model/AppModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ private AppModel()
public TrayIcon TrayIcon { get; set; }
private CachedSound _customNotificationCachedSound;
private readonly DeviceCyclerManager _deviceCyclerManager;
private DeviceInfoCollection _deviceSelectedList;



public CachedSound CustomNotificationSound
{
Expand Down Expand Up @@ -102,15 +105,23 @@ public bool IncludeBetaVersions
}


public HashSet<DeviceInfo> SelectedDevices { get; } = AppConfigs.Configuration.SelectedDevices;
public DeviceInfoCollection SelectedDevices
{
get
{
if (_deviceSelectedList != null)
return _deviceSelectedList;
return _deviceSelectedList = new DeviceInfoCollection(AppConfigs.Configuration.SelectedDevices);
}
}

public ICollection<MMDevice> AvailablePlaybackDevices
{
get
{
using (var devices = ActiveAudioDeviceLister.GetPlaybackDevices())
{
return devices.Where((device) => SelectedDevices.Any((info => new DeviceInfo(device).Equals(info)))).ToList();
return SelectedDevices.IntersectWith(devices).ToList();
}
}
}
Expand All @@ -123,7 +134,7 @@ public ICollection<MMDevice> AvailableRecordingDevices
{
using (var devices = ActiveAudioDeviceLister.GetRecordingDevices())
{
return devices.Where((device) => SelectedDevices.Any((info => new DeviceInfo(device).Equals(info)))).ToList();
return SelectedDevices.IntersectWith(devices).ToList();
}
}
}
Expand Down Expand Up @@ -288,17 +299,19 @@ private int SaveState(object state)
/// <returns></returns>
public bool SelectDevice(MMDevice device)
{
var result = false;
DeviceListChanged eventChanged = null;
result = SelectedDevices.Add(new DeviceInfo(device));
eventChanged = new DeviceListChanged(SelectedDevices, (DeviceType)device.DataFlow);

if (result)
try
{
SelectedDeviceChanged?.Invoke(this, eventChanged);
AppConfigs.Configuration.Save();
SelectedDevices.Add(new DeviceInfo(device));
}
return result;
catch (ArgumentException)
{
return false;
}

SelectedDeviceChanged?.Invoke(this, new DeviceListChanged(SelectedDevices, (DeviceType)device.DataFlow));
AppConfigs.Configuration.Save();

return true;
}

/// <summary>
Expand All @@ -309,17 +322,23 @@ public bool SelectDevice(MMDevice device)
public bool UnselectDevice(MMDevice device)
{
var result = false;
var deviceToRemove = new DeviceInfo(device);
DeviceListChanged eventChanged = null;
result = SelectedDevices.RemoveWhere((info => info.Equals(deviceToRemove))) > 0;
eventChanged = new DeviceListChanged(SelectedDevices, (DeviceType)device.DataFlow);
try
{
result = SelectedDevices.Remove(new DeviceInfo(device));
}
catch (ArgumentException)
{
return false;
}

if (result)
{
SelectedDeviceChanged?.Invoke(this, eventChanged);
SelectedDeviceChanged?.Invoke(this,
new DeviceListChanged(SelectedDevices, (DeviceType) device.DataFlow));
AppConfigs.Configuration.Save();
}
return result;

return true;
}

#endregion
Expand Down
2 changes: 1 addition & 1 deletion SoundSwitch/Model/IAppModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public interface IAppModel
/// <summary>
/// Devices selected for Switching
/// </summary>
HashSet<DeviceInfo> SelectedDevices { get; }
DeviceInfoCollection SelectedDevices { get; }
/// <summary>
/// An union between the Active <see cref="IAudioDevice" /> of Windows and <see cref="SelectedPlaybackDevicesList" />
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions SoundSwitch/SoundSwitch.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@
<Compile Include="Framework\Banner\BannerData.cs" />
<Compile Include="Framework\Banner\BannerManager.cs" />
<Compile Include="Framework\Configuration\Device\DeviceInfo.cs" />
<Compile Include="Framework\Configuration\Device\DeviceInfoCollection.cs" />
<Compile Include="Framework\Configuration\IPCConfiguration.cs" />
<Compile Include="Framework\Configuration\AppConfigs.cs" />
<Compile Include="Framework\Configuration\ConfigurationManager.cs" />
Expand Down
8 changes: 4 additions & 4 deletions SoundSwitch/UI/Forms/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ public SettingsForm()

// Playback and Recording
var audioDeviceLister = new AudioDeviceLister(DeviceState.All);
PopulateAudioList(playbackListView, AppModel.Instance.SelectedDevices.Where((device) => device.Type == DataFlow.Render), audioDeviceLister.GetPlaybackDevices());
PopulateAudioList(recordingListView, AppModel.Instance.SelectedDevices.Where((device) => device.Type == DataFlow.Capture), audioDeviceLister.GetRecordingDevices());
PopulateAudioList(playbackListView, AppModel.Instance.SelectedDevices, audioDeviceLister.GetPlaybackDevices());
PopulateAudioList(recordingListView, AppModel.Instance.SelectedDevices, audioDeviceLister.GetRecordingDevices());

_loaded = true;
}
Expand Down Expand Up @@ -479,7 +479,7 @@ private ListViewItem GenerateListViewItem(MMDevice device, IEnumerable<DeviceInf
Tag = device
};
var selectedDevice = new DeviceInfo(device);
if (selected.Any((info => selectedDevice.Equals(info))))
if (selected.Contains(selectedDevice))
{
listViewItem.Checked = true;
listViewItem.Group = listView.Groups["selectedGroup"];
Expand Down Expand Up @@ -522,7 +522,7 @@ private void ListViewItemChecked(object sender, ItemCheckEventArgs e)
throw new ArgumentOutOfRangeException();
}
}
catch (Exception)
catch (Exception exception)
{
e.NewValue = e.CurrentValue;
}
Expand Down