Skip to content

Commit

Permalink
feat(Notification::DeviceMenu): First version of the new device menu …
Browse files Browse the repository at this point in the history
…triggered by device changed.
  • Loading branch information
Belphemur committed Aug 24, 2021
1 parent 7ba1d18 commit ee6f2c5
Show file tree
Hide file tree
Showing 9 changed files with 264 additions and 27 deletions.
17 changes: 17 additions & 0 deletions SoundSwitch/Framework/Banner/BannerManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
********************************************************************/

using System;
using System.Linq;
using SoundSwitch.Audio.Manager;
using SoundSwitch.Audio.Manager.Interop.Enum;
using SoundSwitch.Model;
using SoundSwitch.UI.Forms;
using SoundSwitch.UI.Forms.Components;

namespace SoundSwitch.Framework.Banner
{
Expand All @@ -23,21 +29,32 @@ public class BannerManager
{
private static System.Threading.SynchronizationContext syncContext;
private static BannerForm banner;
private static DeviceSelectorMenu menu;

/// <summary>
/// Show a banner notification with the given data
/// </summary>
/// <param name="data"></param>
public void ShowNotification(BannerData data)
{
var defaultDevice = AudioSwitcher.Instance.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eConsole);

// Execute the banner in the context of the UI thread
syncContext.Post((d) =>
{
if (menu == null)
{
menu = new DeviceSelectorMenu();
menu.Disposed += (sender, args) => menu = null;
}

menu.SetData(AppModel.Instance.AvailablePlaybackDevices.Select(info => new AudioDeviceBox.Payload(info.LargeIcon.ToBitmap(), info.NameClean, defaultDevice.Id == info.Id)));
if (banner == null)
{
banner = new BannerForm();
banner.Disposed += (s, e) => banner = null;
}

banner.SetData(data);
}, null);
}
Expand Down
4 changes: 2 additions & 2 deletions SoundSwitch/Model/AppModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,9 @@ public bool Telemetry

public IEnumerable<DeviceInfo> SelectedDevices => AppConfigs.Configuration.SelectedDevices.OrderBy(info => info.DiscoveredAt);

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

public IEnumerable<DeviceInfo> AvailableRecordingDevices => ActiveAudioDeviceLister.RecordingDevices.IntersectWith(SelectedDevices);
public IEnumerable<DeviceFullInfo> AvailableRecordingDevices => ActiveAudioDeviceLister.RecordingDevices.IntersectWith(SelectedDevices);

public bool SetCommunications
{
Expand Down
4 changes: 2 additions & 2 deletions SoundSwitch/Model/IAppModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ public interface IAppModel : IDisposable
/// <summary>
/// An union between the Active <see cref="IAudioDevice" /> of Windows and <see cref="SelectedPlaybackDevicesList" />
/// </summary>
IEnumerable<DeviceInfo> AvailablePlaybackDevices { get; }
IEnumerable<DeviceFullInfo> AvailablePlaybackDevices { get; }

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

/// <summary>
/// If the Playback device need also to be set for Communications.
Expand Down
3 changes: 2 additions & 1 deletion SoundSwitch/UI/Forms/Components/AudioDeviceBox.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 6 additions & 22 deletions SoundSwitch/UI/Forms/Components/AudioDeviceBox.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.ComponentModel;
using System.Drawing;
using System.Drawing;
using System.Windows.Forms;

namespace SoundSwitch.UI.Forms.Components
Expand All @@ -8,34 +7,19 @@ public partial class AudioDeviceBox : UserControl
{
private bool _selected;

public record Payload(Image Image, string Label, bool Selected);

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[DefaultValue(false)]
public bool Selected
public record Payload(Image Image, string Label, bool Selected)
{
get => _selected;
set
{
var oldValue = _selected;
_selected = value;
OnSelectedChanged(oldValue, _selected);
}
public Color Color => Selected ? Color.Teal : Color.Black;
}


public AudioDeviceBox(Payload payload)
{
InitializeComponent();

iconBox.DataBindings.Add(nameof(PictureBox.Image), payload, nameof(payload.Image), false, DataSourceUpdateMode.OnPropertyChanged);
deviceName.DataBindings.Add(nameof(Label.Text), payload, nameof(payload.Label), false, DataSourceUpdateMode.OnPropertyChanged);
Selected = payload.Selected;

InitializeComponent();
}

protected void OnSelectedChanged(bool oldValue, bool newValue)
{
ForeColor = newValue ? Color.Teal : Color.Black;
DataBindings.Add(nameof(BackColor), payload, nameof(payload.Color), false, DataSourceUpdateMode.OnPropertyChanged);
}
}
}
60 changes: 60 additions & 0 deletions SoundSwitch/UI/Forms/Components/AudioDeviceBox.resx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
60 changes: 60 additions & 0 deletions SoundSwitch/UI/Forms/DeviceSelectorMenu.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 55 additions & 0 deletions SoundSwitch/UI/Forms/DeviceSelectorMenu.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System.Collections.Generic;
using System.Windows.Forms;
using SoundSwitch.UI.Forms.Components;

namespace SoundSwitch.UI.Forms
{
public partial class DeviceSelectorMenu : Form
{
protected override bool ShowWithoutActivation => true;

/// <summary>
/// Override the parameters used to create the window handle.
/// Ensure that the window will be top-most and do not activate or take focus.
/// </summary>
protected override CreateParams CreateParams
{
get
{
CreateParams p = base.CreateParams;
p.ExStyle |= 0x08000000; // WS_EX_NOACTIVATE
p.ExStyle |= 0x00000008; // WS_EX_TOPMOST
return p;
}
}

public DeviceSelectorMenu()
{
InitializeComponent();
SetLocationToCursor();
}

public void SetData(IEnumerable<AudioDeviceBox.Payload> payloads)
{
Hide();
SetLocationToCursor();
Controls.Clear();
Height = 0;
var top = 5;
foreach (var payload in payloads)
{
var control = new AudioDeviceBox(payload);
control.Top = top;
Controls.Add(control);
top += control.Height;
}
Show();
}

private void SetLocationToCursor()
{
SetDesktopLocation(Cursor.Position.X, Cursor.Position.Y);
Location = Cursor.Position;
}
}
}
60 changes: 60 additions & 0 deletions SoundSwitch/UI/Forms/DeviceSelectorMenu.resx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

0 comments on commit ee6f2c5

Please sign in to comment.