Skip to content

Commit

Permalink
Rewrite completely the listing of devices
Browse files Browse the repository at this point in the history
Rewrite the caching of the information. Stop using the MMDevice, only use it to gather the needed date.

MMDevice is great to list devices, not to be used everywhere as I was doing since it's a COM Object.

I created a DeviceFullInfo that contains exactly what the app needs to work. This way it's lighter and resolve the lag issues.

Fixes #298
Fixes #293
  • Loading branch information
Antoine Aflalo committed Nov 21, 2018
1 parent b107f27 commit 8fcbd63
Show file tree
Hide file tree
Showing 31 changed files with 696 additions and 430 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
<ItemGroup>
<Reference Include="CommonMark, Version=0.1.0.0, Culture=neutral, PublicKeyToken=001ef8810438905d, processorArchitecture=MSIL">
<HintPath>..\packages\CommonMark.NET.0.15.1\lib\net45\CommonMark.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
Expand Down
3 changes: 3 additions & 0 deletions SoundSwitch.sln
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Audio.Default.Switcher.Wrap
EndProjectSection
EndProject
Global
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
AppVeyor|Any CPU = AppVeyor|Any CPU
AppVeyor|x64 = AppVeyor|x64
Expand Down
8 changes: 6 additions & 2 deletions SoundSwitch/App.config
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
Expand All @@ -19,7 +19,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.InteropServices" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
Expand All @@ -33,6 +33,10 @@
<assemblyIdentity name="System.Runtime.Extensions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Linq" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
47 changes: 0 additions & 47 deletions SoundSwitch/Framework/Audio/Device/DisposableMMDeviceCollection.cs

This file was deleted.

32 changes: 32 additions & 0 deletions SoundSwitch/Framework/Configuration/Device/DeviceFullInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Drawing;
using NAudio.CoreAudioApi;
using SoundSwitch.Util;

namespace SoundSwitch.Framework.Configuration.Device
{
public class DeviceFullInfo : DeviceInfo
{
public string IconPath { get; }
public DeviceState State { get; }

public Icon LargeIcon => AudioDeviceIconExtractor.ExtractIconFromPath(IconPath, Type, true);
public Icon SmallIcon => AudioDeviceIconExtractor.ExtractIconFromPath(IconPath, Type, false);

public DeviceFullInfo(string name, string id, DataFlow type, string iconPath, DeviceState state) : base(name, id, type)
{
IconPath = iconPath;
State = state;
}

public DeviceFullInfo(MMDevice device) : base(device)
{
IconPath = device.IconPath;
State = device.State;
}

public override string ToString()
{
return Name;
}
}
}
15 changes: 10 additions & 5 deletions SoundSwitch/Framework/Configuration/Device/DeviceInfoCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ public DeviceInfoCollection(HashSet<DeviceInfo> devices)
/// </summary>
/// <param name="devices"></param>
/// <returns></returns>
public IEnumerable<MMDevice> IntersectWith(IEnumerable<MMDevice> devices)
public ICollection<DeviceFullInfo> IntersectWith(IEnumerable<DeviceFullInfo> devices)
{
var devicesResult = new Dictionary<string, MMDevice>();
var devicesResult = new Dictionary<string, DeviceFullInfo>();
foreach (var mmDevice in devices)
{
if (devicesResult.ContainsKey(mmDevice.ID))
if (devicesResult.ContainsKey(mmDevice.Id))
continue;

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

devicesResult.Add(mmDevice.ID, mmDevice);
devicesResult.Add(mmDevice.Id, mmDevice);

}

Expand All @@ -62,6 +62,11 @@ public void Add(DeviceInfo item)
AddItem(item, true);
}

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

/// <summary>
/// Add Item and update or not the original
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@
using AudioDefaultSwitcherWrapper;
using NAudio.CoreAudioApi;
using Serilog;
using SoundSwitch.Framework.Configuration.Device;
using SoundSwitch.Model;

namespace SoundSwitch.Framework.DeviceCyclerManager.DeviceCycler
{
public abstract class ADeviceCycler : IDeviceCycler
{
private readonly IDictionary<DeviceType, String> _lastDevices = new Dictionary<DeviceType, String>();
private readonly IDictionary<DeviceType, DeviceFullInfo> _lastDevices = new Dictionary<DeviceType, DeviceFullInfo>();

public abstract DeviceCyclerTypeEnum TypeEnum { get; }
public abstract string Label { get; }
Expand All @@ -41,29 +42,14 @@ public abstract class ADeviceCycler : IDeviceCycler
/// <param name="audioDevices"></param>
/// <param name="type"></param>
/// <returns></returns>
protected MMDevice GetNextDevice(ICollection<MMDevice> audioDevices, DeviceType type)
protected DeviceFullInfo GetNextDevice(ICollection<DeviceFullInfo> audioDevices, DeviceType type)
{
_lastDevices.TryGetValue(type, out var lastDeviceId);
MMDevice lastDevice = null;
if (lastDeviceId != null)
{
using (var enumerator = new MMDeviceEnumerator())
{
try
{
lastDevice = enumerator.GetDevice(lastDeviceId);
}
catch (Exception)
{
// ignored
}
}
}
_lastDevices.TryGetValue(type, out var lastDevice);

var defaultDev = lastDevice ??
audioDevices.FirstOrDefault(device => AudioController.IsDefault(device.ID, type, DeviceRole.Console)) ??
audioDevices.FirstOrDefault(device => AudioController.IsDefault(device.Id, type, DeviceRole.Console)) ??
audioDevices.Last();
var next = audioDevices.SkipWhile((device, i) => device.ID != defaultDev.ID).Skip(1).FirstOrDefault() ??
var next = audioDevices.SkipWhile((device, i) => device.Id != defaultDev.Id).Skip(1).FirstOrDefault() ??
audioDevices.ElementAt(0);
return next;
}
Expand All @@ -72,21 +58,21 @@ protected MMDevice GetNextDevice(ICollection<MMDevice> audioDevices, DeviceType
/// Attempts to set active device to the specified name
/// </summary>
/// <param name="device"></param>
public bool SetActiveDevice(MMDevice device)
public bool SetActiveDevice(DeviceFullInfo device)
{

Log.Information("Set Default device: {Device}", device);
if (!AppModel.Instance.SetCommunications)
{
AudioController.SwitchTo(device.ID, DeviceRole.Console);
AudioController.SwitchTo(device.ID, DeviceRole.Multimedia);
AudioController.SwitchTo(device.Id, DeviceRole.Console);
AudioController.SwitchTo(device.Id, DeviceRole.Multimedia);
}
else
{
Log.Information("Set Default Communication device: {Device}", device);
AudioController.SwitchTo(device.ID, DeviceRole.All);
AudioController.SwitchTo(device.Id, DeviceRole.All);
}
_lastDevices[(DeviceType)device.DataFlow] = device.ID;
_lastDevices[(DeviceType)device.Type] = device;
return true;

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
using System.Linq;
using AudioDefaultSwitcherWrapper;
using NAudio.CoreAudioApi;
using SoundSwitch.Framework.Audio.Device;
using SoundSwitch.Framework.Configuration.Device;
using SoundSwitch.Model;
using SoundSwitch.Localization;

Expand All @@ -34,7 +34,7 @@ public class DeviceCyclerAll : ADeviceCycler
/// <param name="type"></param>
public override bool CycleAudioDevice(DeviceType type)
{
DisposableMMDeviceCollection audioDevices;
ICollection<DeviceFullInfo> audioDevices;
switch (type)
{
case DeviceType.Playback:
Expand All @@ -54,10 +54,8 @@ public override bool CycleAudioDevice(DeviceType type)
case 1:
return false;
}
using (audioDevices)
{
return SetActiveDevice(GetNextDevice(audioDevices.ToList(), type));
}

return SetActiveDevice(GetNextDevice(audioDevices.ToList(), type));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using System.Collections.Generic;
using AudioDefaultSwitcherWrapper;
using NAudio.CoreAudioApi;
using SoundSwitch.Framework.Configuration.Device;
using SoundSwitch.Model;
using SoundSwitch.Localization;

Expand All @@ -32,7 +33,7 @@ public class DeviceCyclerAvailable : ADeviceCycler
/// <param name="type"></param>
public override bool CycleAudioDevice(DeviceType type)
{
ICollection<MMDevice> audioDevices;
ICollection<DeviceFullInfo> audioDevices;
switch (type)
{
case DeviceType.Playback:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

using AudioDefaultSwitcherWrapper;
using NAudio.CoreAudioApi;
using SoundSwitch.Framework.Configuration.Device;
using SoundSwitch.Framework.Factory;

namespace SoundSwitch.Framework.DeviceCyclerManager.DeviceCycler
Expand All @@ -30,6 +31,6 @@ public interface IDeviceCycler : IEnumImpl<DeviceCyclerTypeEnum>
/// Attempts to set active device to the specified name
/// </summary>
/// <param name="device"></param>
bool SetActiveDevice(MMDevice device);
bool SetActiveDevice(DeviceFullInfo device);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using AudioDefaultSwitcherWrapper;
using NAudio.CoreAudioApi;
using SoundSwitch.Framework.Configuration;
using SoundSwitch.Framework.Configuration.Device;

namespace SoundSwitch.Framework.DeviceCyclerManager
{
Expand Down Expand Up @@ -51,7 +52,7 @@ public bool CycleDevice(DeviceType type)
/// </summary>
/// <param name="device"></param>
/// <returns></returns>
public bool SetAsDefault(MMDevice device)
public bool SetAsDefault(DeviceFullInfo device)
{
return _deviceCyclerFactory.Get(CurrentCycler).SetActiveDevice(device);
}
Expand Down
28 changes: 13 additions & 15 deletions SoundSwitch/Framework/NotificationManager/MMNotificationClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,57 +9,55 @@ namespace SoundSwitch.Framework.NotificationManager
public class MMNotificationClient : IMMNotificationClient
{
public static MMNotificationClient Instance { get; } = new MMNotificationClient();
private MMDeviceEnumerator _enumerator;

public event EventHandler<DeviceDefaultChangedEvent> DefaultDeviceChanged;
public event EventHandler<DeviceChangedEventBase> DevicesChanged;

/// <summary>
/// Register the notification client in the Enumerator
/// </summary>
public void Register()
{
using (var enumerator = new MMDeviceEnumerator())
{
enumerator.RegisterEndpointNotificationCallback(this);
}
_enumerator = new MMDeviceEnumerator();
_enumerator.RegisterEndpointNotificationCallback(this);
}

/// <summary>
/// Unregister the notification client in the Enumerator
/// </summary>
public void UnRegister()
{
using (var enumerator = new MMDeviceEnumerator())
using (_enumerator)
{
enumerator.UnregisterEndpointNotificationCallback(this);
_enumerator.UnregisterEndpointNotificationCallback(this);
}
}

public void OnDeviceStateChanged(string deviceId, DeviceState newState)
{
//ignored
DevicesChanged?.Invoke(this, new DeviceChangedEventBase(deviceId));
}

public void OnDeviceAdded(string pwstrDeviceId)
{
//ignored
DevicesChanged?.Invoke(this, new DeviceChangedEventBase(pwstrDeviceId));
}

public void OnDeviceRemoved(string deviceId)
{
//ignored
DevicesChanged?.Invoke(this, new DeviceChangedEventBase(deviceId));
}

public void OnDefaultDeviceChanged(DataFlow flow, Role role, string defaultDeviceId)
{
using (var enumerator = new MMDeviceEnumerator())
{
var device = enumerator.GetDevice(defaultDeviceId);
DefaultDeviceChanged?.Invoke(this, new DeviceDefaultChangedEvent(device, (DeviceRole)role));
}
var device = _enumerator.GetDevice(defaultDeviceId);
DefaultDeviceChanged?.Invoke(this, new DeviceDefaultChangedEvent(device, (DeviceRole) role));
}

public void OnPropertyValueChanged(string pwstrDeviceId, PropertyKey key)
{
//ignored
DevicesChanged?.Invoke(this, new DeviceChangedEventBase(pwstrDeviceId));
}
}
}
Loading

0 comments on commit 8fcbd63

Please sign in to comment.