Skip to content

Commit

Permalink
fix(Device): Fix issue with device having the same name not being sho…
Browse files Browse the repository at this point in the history
…w as different device in the UI
  • Loading branch information
Belphemur committed Jun 26, 2022
1 parent de9628b commit 2249ed0
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 16 deletions.
84 changes: 84 additions & 0 deletions SoundSwitch.Common/Framework/Audio/Collection/DeviceCollection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System;
using System.Collections;
using System.Collections.Generic;
using SoundSwitch.Common.Framework.Audio.Device;

namespace SoundSwitch.Common.Framework.Audio.Collection;

public class DeviceCollection<T> : ICollection<T> where T : DeviceInfo
{
private readonly Dictionary<string, T> _byId = new();
private readonly Dictionary<string, T> _byName = new();

public DeviceCollection(IEnumerable<T> deviceInfos)
{
foreach (var item in deviceInfos)
{
if (item == null)
{
return;
}

_byId[item.Id] = item;
_byName[item.NameClean] = item;
}
}

public IEnumerator<T> GetEnumerator()
{
return _byId.Values.GetEnumerator();
}

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

public void Add(T item)
{
if (item == null)
{
throw new ArgumentNullException();
}

_byId.TryAdd(item.Id, item);
_byName.TryAdd(item.NameClean, item);
}

public void Clear()
{
_byId.Clear();
_byName.Clear();
}

public bool Contains(T item)
{
if (item == null)
{
throw new ArgumentNullException();
}

return _byId.ContainsKey(item.Id) || _byName.ContainsKey(item.NameClean);
}

public void CopyTo(T[] array, int arrayIndex)
{
_byId.Values.CopyTo(array, arrayIndex);
}

public bool Remove(T item)
{
if (item == null)
{
throw new ArgumentNullException();
}

var removeId = _byId.Remove(item.Id);
var removeName = _byName.Remove(item.NameClean);

return removeId || removeName;
}

public int Count => _byId.Count;
public bool IsReadOnly => false;
}
26 changes: 18 additions & 8 deletions SoundSwitch.Common/Framework/Audio/Device/DeviceInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,20 +94,30 @@ public bool Equals(DeviceInfo other)
//help recognizing the same device
return NameClean == other.NameClean;
}

public override bool Equals(object obj)
{
return ReferenceEquals(this, obj) || obj is DeviceInfo other && Equals(other);
if (ReferenceEquals(null, obj))
{
return false;
}

if (ReferenceEquals(this, obj))
{
return true;
}

if (obj.GetType() != GetType())
{
return false;
}

return Equals((DeviceInfo)obj);
}

public override int GetHashCode()
{
unchecked
{
var hashCode = (NameClean != null ? NameClean.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (int) Type;
return hashCode;
}
return HashCode.Combine(NameClean, Id);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public interface ISoundSwitchConfiguration : IConfiguration
[Obsolete]
HashSet<string> SelectedRecordingDeviceListId { get; }

HashSet<DeviceInfo> SelectedDevices { get; }
HashSet<DeviceInfo> SelectedDevices { get; set; }

bool FirstRun { get; set; }
HotKey PlaybackHotKey { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public SoundSwitchConfiguration()

public HashSet<string> SelectedPlaybackDeviceListId { get; }
public HashSet<string> SelectedRecordingDeviceListId { get; }
public HashSet<DeviceInfo> SelectedDevices { get; }
public HashSet<DeviceInfo> SelectedDevices { get; set; }
public bool FirstRun { get; set; }
public HotKey PlaybackHotKey { get; set; }
public HotKey RecordingHotKey { get; set; }
Expand Down
23 changes: 19 additions & 4 deletions SoundSwitch/Model/AppModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
using RailSharp;
using Serilog;
using SoundSwitch.Audio.Manager;
using SoundSwitch.Common.Framework.Audio.Collection;
using SoundSwitch.Common.Framework.Audio.Device;
using SoundSwitch.Framework;
using SoundSwitch.Framework.Audio;
Expand All @@ -50,6 +51,7 @@ public class AppModel : IAppModel
private bool _initialized;
private readonly NotificationManager _notificationManager;
private UpdateChecker _updateChecker;
private DeviceCollection<DeviceInfo> _selectedDevices;

private class DefaultDeviceChangedJob : IDebounceJob
{
Expand Down Expand Up @@ -88,6 +90,7 @@ private AppModel()
_notificationManager = new NotificationManager(this);

_deviceCyclerManager = new DeviceCyclerManager();
_selectedDevices = null;
MMNotificationClient.Instance.DefaultDeviceChanged += (sender, @event) => { JobScheduler.Instance.ScheduleJob(new DefaultDeviceChangedJob(this, @event.Device, @event.Role), @event.Token); };
_microphoneMuteToggler = new MicrophoneMuteToggler(AudioSwitcher.Instance, _notificationManager);
_updateScheduler = new LimitedConcurrencyLevelTaskScheduler(1);
Expand Down Expand Up @@ -168,7 +171,18 @@ public bool QuickMenuEnabled
}


public IEnumerable<DeviceInfo> SelectedDevices => AppConfigs.Configuration.SelectedDevices.OrderBy(info => info.DiscoveredAt);
public DeviceCollection<DeviceInfo> SelectedDevices
{
get
{
if (_selectedDevices != null)
{
return _selectedDevices;
}

return _selectedDevices = new DeviceCollection<DeviceInfo>(AppConfigs.Configuration.SelectedDevices.OrderBy(info => info.DiscoveredAt));
}
}

public IEnumerable<DeviceFullInfo> AvailablePlaybackDevices => ActiveAudioDeviceLister.PlaybackDevices.IntersectWith(SelectedDevices);

Expand Down Expand Up @@ -387,7 +401,8 @@ public bool SelectDevice(DeviceFullInfo device)
try
{
device.DiscoveredAt = DateTime.UtcNow;
AppConfigs.Configuration.SelectedDevices.Add(device);
SelectedDevices.Add(device);
AppConfigs.Configuration.SelectedDevices = SelectedDevices.ToHashSet();
}
catch (ArgumentException)
{
Expand All @@ -410,8 +425,8 @@ public bool UnselectDevice(DeviceFullInfo device)
bool result;
try
{
var list = AppConfigs.Configuration.SelectedDevices.Where(device.Equals).ToArray();
result = list.Aggregate(true, (b, info) => b & AppConfigs.Configuration.SelectedDevices.Remove(info));
result = SelectedDevices.Remove(device);
AppConfigs.Configuration.SelectedDevices = SelectedDevices.ToHashSet();
}
catch (ArgumentException)
{
Expand Down
3 changes: 2 additions & 1 deletion SoundSwitch/Model/IAppModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using System;
using System.Collections.Generic;
using NAudio.CoreAudioApi;
using SoundSwitch.Common.Framework.Audio.Collection;
using SoundSwitch.Common.Framework.Audio.Device;
using SoundSwitch.Framework.Audio;
using SoundSwitch.Framework.NotificationManager;
Expand All @@ -34,7 +35,7 @@ public interface IAppModel : IDisposable
/// <summary>
/// Devices selected for Switching
/// </summary>
IEnumerable<DeviceInfo> SelectedDevices { get; }
DeviceCollection<DeviceInfo> SelectedDevices { get; }

/// <summary>
/// An union between the Active <see cref="IAudioDevice" /> of Windows and <see cref="SelectedPlaybackDevicesList" />
Expand Down
2 changes: 1 addition & 1 deletion SoundSwitch/UI/Forms/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ ListViewItem ProfileToListViewItem(Profile profile)

private void PopulateAudioDevices()
{
var selectedDevices = AppModel.Instance.SelectedDevices.ToArray();
var selectedDevices = AppModel.Instance.SelectedDevices;
PopulateAudioList(playbackListView, selectedDevices, _audioDeviceLister.PlaybackDevices);
PopulateAudioList(recordingListView, selectedDevices, _audioDeviceLister.RecordingDevices);
}
Expand Down

0 comments on commit 2249ed0

Please sign in to comment.