diff --git a/SoundSwitch.Common/Framework/Audio/Collection/DeviceReadOnlyCollection.cs b/SoundSwitch.Common/Framework/Audio/Collection/DeviceReadOnlyCollection.cs new file mode 100644 index 0000000000..ccce0e5830 --- /dev/null +++ b/SoundSwitch.Common/Framework/Audio/Collection/DeviceReadOnlyCollection.cs @@ -0,0 +1,65 @@ +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using SoundSwitch.Common.Framework.Audio.Device; + +namespace SoundSwitch.Common.Framework.Audio.Collection +{ + public class DeviceReadOnlyCollection : IReadOnlyCollection where T : DeviceInfo + { + private readonly Dictionary _byId = new(); + private readonly Dictionary _byName = new(); + + public DeviceReadOnlyCollection(IEnumerable deviceInfos) + { + foreach (var item in deviceInfos) + { + if (item == null) + { + return; + } + + _byId[item.Id] = item; + _byName[item.NameClean] = item; + } + } + + public IEnumerator GetEnumerator() + { + return _byId.Values.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// Intersect with another list of + /// + /// + /// + public IEnumerable IntersectWith(IEnumerable second) + { + return second + .Select(info => + { + if (_byId.TryGetValue(info.Id, out var found)) + { + return found; + } + + if (_byId.TryGetValue(info.NameClean, out found)) + { + return found; + } + + return null; + }) + .Where(info => info != null) + .Distinct(); + } + + public int Count => _byId.Count; + } +} \ No newline at end of file diff --git a/SoundSwitch/Framework/Audio/Lister/CachedAudioDeviceLister.cs b/SoundSwitch/Framework/Audio/Lister/CachedAudioDeviceLister.cs index 794a5822de..8537902eef 100644 --- a/SoundSwitch/Framework/Audio/Lister/CachedAudioDeviceLister.cs +++ b/SoundSwitch/Framework/Audio/Lister/CachedAudioDeviceLister.cs @@ -17,6 +17,7 @@ using System.Linq; using NAudio.CoreAudioApi; using Serilog; +using SoundSwitch.Common.Framework.Audio.Collection; using SoundSwitch.Common.Framework.Audio.Device; using SoundSwitch.Framework.NotificationManager; using SoundSwitch.Model; @@ -27,10 +28,10 @@ namespace SoundSwitch.Framework.Audio.Lister public class CachedAudioDeviceLister : IAudioDeviceLister { /// - public IReadOnlyCollection PlaybackDevices { get; private set; } = new DeviceFullInfo[0]; + public DeviceReadOnlyCollection PlaybackDevices { get; private set; } = new(Enumerable.Empty()); /// - public IReadOnlyCollection RecordingDevices { get; private set; } = new DeviceFullInfo[0]; + public DeviceReadOnlyCollection RecordingDevices { get; private set; } = new(Enumerable.Empty()); private readonly DeviceState _state; private readonly DebounceDispatcher _dispatcher = new(); @@ -86,8 +87,8 @@ public void Refresh() } } - PlaybackDevices = playbackDevices.Values.ToArray(); - RecordingDevices = recordingDevices.Values.ToArray(); + PlaybackDevices = new DeviceReadOnlyCollection(playbackDevices.Values); + RecordingDevices = new DeviceReadOnlyCollection(recordingDevices.Values); Log.Information("[{@State}] Refreshed all devices. {@Recording}/rec, {@Playback}/play", _state, recordingDevices.Count, playbackDevices.Count); diff --git a/SoundSwitch/Model/AppModel.cs b/SoundSwitch/Model/AppModel.cs index 477447c033..054405eb24 100644 --- a/SoundSwitch/Model/AppModel.cs +++ b/SoundSwitch/Model/AppModel.cs @@ -39,7 +39,6 @@ using SoundSwitch.Localization; using SoundSwitch.Localization.Factory; using SoundSwitch.UI.Component; -using SoundSwitch.Util.Extension; using SoundSwitch.Util.Timer; namespace SoundSwitch.Model @@ -124,9 +123,9 @@ public bool IncludeBetaVersions public IEnumerable SelectedDevices => AppConfigs.Configuration.SelectedDevices.OrderBy(info => info.DiscoveredAt); - public IEnumerable AvailablePlaybackDevices => SelectedDevices.IntersectInverse(ActiveAudioDeviceLister.PlaybackDevices); + public IEnumerable AvailablePlaybackDevices => ActiveAudioDeviceLister.PlaybackDevices.IntersectWith(SelectedDevices); - public IEnumerable AvailableRecordingDevices => SelectedDevices.IntersectInverse(ActiveAudioDeviceLister.RecordingDevices); + public IEnumerable AvailableRecordingDevices => ActiveAudioDeviceLister.RecordingDevices.IntersectWith(SelectedDevices); public bool SetCommunications { @@ -354,8 +353,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)); + var list = AppConfigs.Configuration.SelectedDevices.Where(device.Equals).ToArray(); + result = list.Aggregate(true, (b, info) => b & AppConfigs.Configuration.SelectedDevices.Remove(info)); } catch (ArgumentException) { diff --git a/SoundSwitch/Model/IAudioDeviceLister.cs b/SoundSwitch/Model/IAudioDeviceLister.cs index 469de9a9da..277ebd959f 100644 --- a/SoundSwitch/Model/IAudioDeviceLister.cs +++ b/SoundSwitch/Model/IAudioDeviceLister.cs @@ -13,9 +13,7 @@ ********************************************************************/ using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using NAudio.CoreAudioApi; +using SoundSwitch.Common.Framework.Audio.Collection; using SoundSwitch.Common.Framework.Audio.Device; namespace SoundSwitch.Model @@ -26,13 +24,13 @@ public interface IAudioDeviceLister : IDisposable /// Get the playback device in the set state /// /// - IReadOnlyCollection PlaybackDevices { get; } + DeviceReadOnlyCollection PlaybackDevices { get; } /// /// Get the recording device in the set state /// /// - IReadOnlyCollection RecordingDevices { get; } + DeviceReadOnlyCollection RecordingDevices { get; } void Refresh(); } diff --git a/SoundSwitch/UI/Forms/Settings.cs b/SoundSwitch/UI/Forms/Settings.cs index 26ff5c40cd..cf22eda941 100644 --- a/SoundSwitch/UI/Forms/Settings.cs +++ b/SoundSwitch/UI/Forms/Settings.cs @@ -209,7 +209,7 @@ public void RefreshProfiles() { ListViewItem ProfileToListViewItem(Profile profile) { - var listViewItem = new ListViewItem(profile.Name) { Tag = profile }; + var listViewItem = new ListViewItem(profile.Name) {Tag = profile}; Icon appIcon = null; DeviceFullInfo recording = null; DeviceFullInfo playback = null; @@ -284,10 +284,8 @@ ListViewItem ProfileToListViewItem(Profile profile) private void PopulateAudioDevices() { var selectedDevices = AppModel.Instance.SelectedDevices.ToArray(); - PopulateAudioList(playbackListView, selectedDevices, - _audioDeviceLister.PlaybackDevices); - PopulateAudioList(recordingListView, selectedDevices, - _audioDeviceLister.RecordingDevices); + PopulateAudioList(playbackListView, selectedDevices, _audioDeviceLister.PlaybackDevices); + PopulateAudioList(recordingListView, selectedDevices, _audioDeviceLister.RecordingDevices); } private void LocalizeForm() @@ -359,7 +357,7 @@ private void closeButton_Click(object sender, EventArgs e) private void tabControl_SelectedIndexChanged(object sender, EventArgs e) { - var tabControlSender = (TabControl)sender; + var tabControlSender = (TabControl) sender; if (tabControlSender.SelectedTab == playbackTabPage) { SetHotkeysFieldsVisibility(true); @@ -402,7 +400,7 @@ private void notificationComboBox_SelectedValueChanged(object sender, EventArgs { if (!_loaded) return; - var value = (DisplayEnumObject)((ComboBox)sender).SelectedItem; + var value = (DisplayEnumObject) ((ComboBox) sender).SelectedItem; if (value == null) return; @@ -437,7 +435,7 @@ private void tooltipInfoComboBox_SelectedValueChanged(object sender, EventArgs e { if (!_loaded) return; - var value = (DisplayEnumObject)((ComboBox)sender).SelectedItem; + var value = (DisplayEnumObject) ((ComboBox) sender).SelectedItem; if (value == null) return; @@ -450,7 +448,7 @@ private void cyclerComboBox_SelectedValueChanged(object sender, EventArgs e) { if (!_loaded) return; - var value = (DisplayEnumObject)((ComboBox)sender).SelectedItem; + var value = (DisplayEnumObject) ((ComboBox) sender).SelectedItem; if (value == null) return; @@ -463,7 +461,7 @@ private void languageComboBox_SelectedIndexChanged(object sender, EventArgs e) if (!_loaded) return; - var value = (DisplayEnumObject)((ComboBox)sender).SelectedItem; + var value = (DisplayEnumObject) ((ComboBox) sender).SelectedItem; if (value == null) return; @@ -543,8 +541,7 @@ private void betaVersionCheckbox_CheckedChanged(object sender, EventArgs e) #region Device List Playback - private void PopulateAudioList(ListView listView, IEnumerable selectedDevices, - IEnumerable audioDevices) + private void PopulateAudioList(ListView listView, IEnumerable selectedDevices, IEnumerable audioDevices) { try { @@ -579,8 +576,7 @@ private void PopulateAudioList(ListView listView, IEnumerable select /// /// /// - private ListViewItem GenerateListViewItem(DeviceFullInfo device, IEnumerable selected, - ListView listView) + private ListViewItem GenerateListViewItem(DeviceFullInfo device, IEnumerable selected, ListView listView) { var listViewItem = new ListViewItem { @@ -588,9 +584,8 @@ private ListViewItem GenerateListViewItem(DeviceFullInfo device, IEnumerable)iconChangeChoicesComboBox.SelectedItem; + var item = (DisplayEnumObject) iconChangeChoicesComboBox.SelectedItem; AppConfigs.Configuration.SwitchIcon = item.Enum; AppConfigs.Configuration.Save(); @@ -745,7 +740,7 @@ private void deleteProfileButton_Click(object sender, EventArgs e) } var profiles = profilesListView.SelectedItems.Cast() - .Select(item => (Profile)item.Tag); + .Select(item => (Profile) item.Tag); AppModel.Instance.ProfileManager.DeleteProfiles(profiles); deleteProfileButton.Enabled = false; editProfileButton.Enabled = false; @@ -755,7 +750,7 @@ private void deleteProfileButton_Click(object sender, EventArgs e) private void hotKeyControl_HotKeyChanged(object sender, HotKeyTextBox.Event e) { var control = (HotKeyTextBox) sender; - var tuple = (Tuple)control.Tag; + var tuple = (Tuple) control.Tag; if (tuple == null) return; @@ -772,7 +767,7 @@ private void editProfileButton_Click(object sender, EventArgs e) return; } - var profile = (Profile)profilesListView.SelectedItems[0].Tag; + var profile = (Profile) profilesListView.SelectedItems[0].Tag; var form = new UpsertProfileExtended(profile, _audioDeviceLister.PlaybackDevices, _audioDeviceLister.RecordingDevices, this, true); form.Show(this); } diff --git a/SoundSwitch/Util/Extension/EnumerableExtension.cs b/SoundSwitch/Util/Extension/EnumerableExtension.cs deleted file mode 100644 index c6e76435d4..0000000000 --- a/SoundSwitch/Util/Extension/EnumerableExtension.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace SoundSwitch.Util.Extension -{ - public static class EnumerableExtension - { - public static IEnumerable IntersectInverse(this IEnumerable first, IEnumerable second) - { - - return IntersectIteratorInverse(first, second, null); - } - - public static IEnumerable IntersectInverse(this IEnumerable first, IEnumerable second, IEqualityComparer? comparer) - { - - return IntersectIteratorInverse(first, second, comparer); - } - - private static IEnumerable IntersectIteratorInverse(IEnumerable first, IEnumerable second, IEqualityComparer? comparer) - { - var set = second.ToDictionary(source => source, comparer); - - foreach (var element in first) - { - if (set.TryGetValue(element, out var secondElement)) - { - yield return secondElement; - } - } - } - } -} \ No newline at end of file