Skip to content

Commit

Permalink
Changing default device in-app or via hotkeys. New settings layout.
Browse files Browse the repository at this point in the history
  • Loading branch information
G-Stas committed Sep 18, 2021
1 parent 9b10d8f commit 9dd64ef
Show file tree
Hide file tree
Showing 50 changed files with 1,630 additions and 487 deletions.
2 changes: 1 addition & 1 deletion Volumey.Package/Package.appxmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<Identity
Name="58593StasG.Volumey"
Publisher="CN=978C2FB1-8A3A-4D5E-BC79-3F2149147466"
Version="1.2.0.0"/>
Version="1.3.0.0"/>

<Properties>
<DisplayName>Volumey</DisplayName>
Expand Down
102 changes: 98 additions & 4 deletions Volumey/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,110 @@
<Thickness x:Key="ComboBoxDropdownBorderThickness">0</Thickness>
<CornerRadius x:Key="OverlayCornerRadius">6</CornerRadius>

<Style TargetType="{x:Type local:HotKeyBox}" BasedOn="{StaticResource DefaultTextBoxStyle}" />
<system:Double x:Key="InputBoxWidth">150</system:Double>
<system:Double x:Key="SliderWidth">265</system:Double>
<system:Double x:Key="InputBoxWidth">180</system:Double>
<system:Double x:Key="SliderWidth">255</system:Double>
<System:Double x:Key="SliderHeight">35</System:Double>
<system:Double x:Key="TextBlockWidth">180</system:Double>
<system:Double x:Key="TextBlockHeaderWidth">200</system:Double>
<system:Double x:Key="GroupBoxHeaderFontSize">17</system:Double>
<system:Double x:Key="ImageSize">24</system:Double>

<converters:MutedToGlyphConverter x:Key="MutedToGlyphConverter" />
<Thickness x:Key="SliderMargin">5, -4, 0, 0</Thickness>
<Thickness x:Key="ImageMargin">7, 3, 8, 0</Thickness>
<Thickness x:Key="ContentMargin">0 5 0 0</Thickness>
<Thickness x:Key="BoxMargin">0 2 0 0</Thickness>
<Thickness x:Key="MuteButtonMargin">0 -3 0 0</Thickness>

<converters:AnyPropertyIsNullToEnabledConverter x:Key="AnyPropertyIsNullToEnabledConverter" />
<converters:PropertyIsNullToEnabledConverter x:Key="PropertyIsNullToEnabledConverter" />
<converters:CollectionCountToVisibilityConverter x:Key="CollectionCountToVisibilityConverter" />
<converters:HotkeysRegisteredToEnabledConverter x:Key="HotkeysRegisteredToEnabledConverter" />
<converters:MutedToGlyphConverter x:Key="MutedToGlyphConverter" />

<Style
x:Key="SettingsComboBoxStyle"
TargetType="{x:Type ComboBox}"
BasedOn="{StaticResource DefaultComboBoxStyle}">
<Setter
Property="Width"
Value="{StaticResource InputBoxWidth}"/>
<Setter
Property="Margin"
Value="{StaticResource BoxMargin}"/>
<Setter
Property="ui:ControlHelper.CornerRadius"
Value="4"/>
</Style>

<Style
TargetType="{x:Type local:HotKeyBox}"
BasedOn="{StaticResource DefaultTextBoxStyle}">
<Setter
Property="ui:ControlHelper.PlaceholderForeground"
Value="{DynamicResource SystemControlHighlightBaseMediumLowBrush}"/>
<Setter
Property="Margin"
Value="{StaticResource BoxMargin}"/>
<Setter
Property="ui:ControlHelper.CornerRadius"
Value="4"/>
</Style>

<Style
TargetType="{x:Type ui:NumberBox}">
<Setter
Property="Margin"
Value="{StaticResource BoxMargin}"/>
<Setter
Property="ui:ControlHelper.CornerRadius"
Value="4"/>
</Style>

<Style
x:Key="SettingsTextBlockStyle"
TargetType="{x:Type TextBlock}">
<Setter
Property="FontSize"
Value="13"/>
<Setter
Property="TextWrapping"
Value="WrapWithOverflow"/>
<Setter
Property="HorizontalAlignment"
Value="Left"/>
<Setter
Property="LineStackingStrategy"
Value="BlockLineHeight"/>
<Setter
Property="LineHeight"
Value="16"/>
<Setter Property="Margin" Value="0 3 0 0"/>
<Style.Triggers>
<Trigger
Property="Text"
Value="">
<Setter
Property="Visibility"
Value="Collapsed"/>
</Trigger>
</Style.Triggers>
</Style>

<Style TargetType="{x:Type Button}" BasedOn="{StaticResource DefaultButtonStyle}">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="{DynamicResource SystemChromeHighColorBrush}"/>
<Setter Property="ui:ControlHelper.CornerRadius" Value="4"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground"
Value="{DynamicResource SystemControlDisabledChromeDisabledLowBrush}" />
</Trigger>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="Foreground" Value="{DynamicResource SystemControlForegroundBaseHighBrush}" />
</Trigger>
</Style.Triggers>
</Style>

</ResourceDictionary>
</Application.Resources>
</Application>
77 changes: 77 additions & 0 deletions Volumey/CoreAudioWrapper/CoreAudio/Interfaces/IPolicyConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System;
using System.Runtime.InteropServices;
using Volumey.CoreAudioWrapper.CoreAudio.Enums;
using Volumey.CoreAudioWrapper.Wrapper;

namespace Volumey.CoreAudioWrapper.CoreAudio.Interfaces
{
[Guid(GuidValue.External.IPolicyConfig), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPolicyConfig
{
[PreserveSig]
int GetMixFormat(
[In][MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName,
[In] IntPtr ppFormat);

[PreserveSig]
int GetDeviceFormat(
[In][MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName,
[In][MarshalAs(UnmanagedType.Bool)] bool bDefault,
[In] IntPtr ppFormat);

[PreserveSig]
int ResetDeviceFormat([In][MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName);

[PreserveSig]
int SetDeviceFormat(
[In][MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName,
[In] IntPtr pEndpointFormat,
[In] IntPtr mixFormat);

[PreserveSig]
int GetProcessingPeriod(
[In][MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName,
[In][MarshalAs(UnmanagedType.Bool)] bool bDefault,
[In] IntPtr pmftDefaultPeriod,
[In] IntPtr pmftMinimumPeriod);

[PreserveSig]
int SetProcessingPeriod(
[In][MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName,
[In] IntPtr pmftPeriod);

[PreserveSig]
int GetShareMode(
[In][MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName,
[In] IntPtr pMode);

[PreserveSig]
int SetShareMode(
[In][MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName,
[In] IntPtr mode);

[PreserveSig]
int GetPropertyValue(
[In][MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName,
[In][MarshalAs(UnmanagedType.Bool)] bool bFxStore,
[In] IntPtr key,
[In] IntPtr pv);

[PreserveSig]
int SetPropertyValue(
[In][MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName,
[In][MarshalAs(UnmanagedType.Bool)] bool bFxStore,
[In] IntPtr key,
[In] IntPtr pv);

[PreserveSig]
int SetDefaultEndpoint(
[In][MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName,
[In][MarshalAs(UnmanagedType.U4)] ERole role);

[PreserveSig]
int SetEndpointVisibility(
[In][MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName,
[In][MarshalAs(UnmanagedType.Bool)] bool bVisible);
}
}
2 changes: 2 additions & 0 deletions Volumey/CoreAudioWrapper/Wrapper/GuidValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public static class External
public const string IMMNotificationClient = "7991EEC9-7E89-4D85-8390-6C703CEC60C0";
public const string IPropertyStore = "886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99";
public const string IMMEndpoint = "1BE09788-6894-4089-8586-9A2A6C265AC5";
public const string IPolicyConfig = "F8679F50-850A-41CF-9C72-430F290290C8";
public const string PolicyConfigCOM = "870AF99C-171D-4F9E-AF0D-E63DF40C2BC9";
}

/// <summary>
Expand Down
20 changes: 20 additions & 0 deletions Volumey/CoreAudioWrapper/Wrapper/PolicyClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Runtime.InteropServices;
using Volumey.CoreAudioWrapper.CoreAudio.Enums;
using Volumey.CoreAudioWrapper.CoreAudio.Interfaces;

namespace Volumey.CoreAudioWrapper.Wrapper
{
public class PolicyClient
{
[ComImport, Guid(GuidValue.External.PolicyConfigCOM)]
private class PolicyClientCOM { }

private IPolicyConfig instance = new PolicyClientCOM() as IPolicyConfig;

public void SetDefaultEndpointDevice(string deviceId)
{
this.instance.SetDefaultEndpoint(deviceId, ERole.Console);
this.instance.SetDefaultEndpoint(deviceId, ERole.Multimedia);
}
}
}
44 changes: 44 additions & 0 deletions Volumey/DataProvider/AppSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,12 @@ internal bool HotkeyExists(HotKey key)
if(session.Value.up.ToHotKey().Equals(key) || session.Value.down.ToHotKey().Equals(key))
return true;
}
foreach(var value in this.serializableRegisteredDevices)
{
var hotkey = value.Key.ToHotKey();
if(hotkey.Equals(key))
return true;
}
return false;
}

Expand All @@ -235,6 +241,13 @@ internal bool HotkeysExist(HotKey key, HotKey key2)
if(up.Equals(key) || up.Equals(key2) || down.Equals(key) || down.Equals(key2))
return true;
}

foreach(var value in this.serializableRegisteredDevices)
{
var hotkey = value.Key.ToHotKey();
if(hotkey.Equals(key) || hotkey.Equals(key2))
return true;
}
return false;
}

Expand All @@ -252,6 +265,37 @@ internal void RemoveRegisteredSession(string sessionName)
this.serializableRegisteredSessions.Remove(sessionName);
}

[OptionalField]
private Dictionary<SerializableHotkey, (string id, string name)> serializableRegisteredDevices;

internal ObservableConcurrentDictionary<HotKey, Tuple<string, string>> GetRegisteredDevices()
{
var dict = new ObservableConcurrentDictionary<HotKey, Tuple<string, string>>();
if(this.serializableRegisteredDevices == null)
{
this.serializableRegisteredDevices = new Dictionary<SerializableHotkey, (string id, string name)>();
return dict;
}

if(this.serializableRegisteredDevices.Count == 0)
return dict;

foreach(var tuple in this.serializableRegisteredDevices)
dict.Add(tuple.Key.ToHotKey(), new Tuple<string, string>(tuple.Value.id, tuple.Value.name));

return dict;
}

internal void AddRegisteredDevice(HotKey hotkey, string deviceId, string name)
{
this.serializableRegisteredDevices.Add(hotkey.ToSerializableHotkey(), (deviceId, name));
}

internal void RemoveRegisteredDevice(HotKey hotkey)
{
this.serializableRegisteredDevices.Remove(hotkey.ToSerializableHotkey());
}

[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
Expand Down
24 changes: 24 additions & 0 deletions Volumey/DataProvider/DeviceProvider.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Windows.Threading;
Expand Down Expand Up @@ -30,6 +31,8 @@ public OutputDeviceModel DefaultDevice
OnPropertyChanged();
}
}

private readonly PolicyClient PolicyClient = new PolicyClient();

private bool noOutputDevices;
public bool NoOutputDevices
Expand Down Expand Up @@ -102,6 +105,27 @@ public static IDeviceProvider GetInstance()
return instance;
}

public void SetDefaultDevice(string id)
{
try
{
//Check if the device to set is enabled
if(this.ActiveDevices.Any(device => device.CompareId(id)))
{
//Prevent if it's already the default device
if(DefaultDevice != null && !DefaultDevice.CompareId(id))
{
// Debug.WriteLine($"Activating device {id}");
this.PolicyClient.SetDefaultEndpointDevice(id);
}
}
}
catch(Exception e)
{
Logger.Error("Failed to change default device", e);
}
}

private void OnDeviceDisabled(OutputDeviceModel device)
{
dispatcher.Invoke(() =>
Expand Down
2 changes: 2 additions & 0 deletions Volumey/DataProvider/IDeviceProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@ public interface IDeviceProvider : IDisposable
event Action<OutputDeviceModel> DeviceFormatChanged;

public bool NoOutputDevices { get; set; }

public void SetDefaultDevice(string deviceId);
}
}
2 changes: 1 addition & 1 deletion Volumey/DataProvider/SettingsProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ await using(var fileStream = new FileStream(SettingsFullPath, FileMode.OpenOrCre
}
}

private static AppSettings.SerializableHotkey ToSerializableHotkey(this HotKey hotkey)
internal static AppSettings.SerializableHotkey ToSerializableHotkey(this HotKey hotkey)
{
if(hotkey == null)
return new AppSettings.SerializableHotkey(Key.None, ModifierKeys.None);
Expand Down
4 changes: 2 additions & 2 deletions Volumey/Model/AudioSessionModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public bool SetHotkeys(HotKey volUp, HotKey volDown)
{
try
{
if(volUp != null && volDown != null && HotkeysControl.RegisterVolumeHotkeys(volUp, volDown))
if(volUp != null && volDown != null && HotkeysControl.RegisterHotkeysPair(volUp, volDown))
{
this.volumeUp = volUp;
this.volumeDown = volDown;
Expand All @@ -138,7 +138,7 @@ private void UnregisterHotkeys()
{
try
{
HotkeysControl.UnregisterVolumeHotkeys(this.volumeUp, this.volumeDown);
HotkeysControl.UnregisterHotkeysPair(this.volumeUp, this.volumeDown);
}
catch { }
}
Expand Down
4 changes: 2 additions & 2 deletions Volumey/Model/MasterSessionModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public bool SetHotkeys(HotKey volUp, HotKey volDown)
{
try
{
if(volUp != null && volDown != null && HotkeysControl.RegisterVolumeHotkeys(volUp, volDown))
if(volUp != null && volDown != null && HotkeysControl.RegisterHotkeysPair(volUp, volDown))
{
this.volumeUp = volUp;
this.volumeDown = volDown;
Expand All @@ -136,7 +136,7 @@ internal void ResetHotkeys()
private void UnregisterHotkeys()
{
if(this.volumeUp != null && this.volumeDown != null)
HotkeysControl.UnregisterVolumeHotkeys(this.volumeUp, this.volumeDown);
HotkeysControl.UnregisterHotkeysPair(this.volumeUp, this.volumeDown);
HotkeysControl.HotkeyPressed -= OnHotkeyPressed;
}

Expand Down
Loading

0 comments on commit 9dd64ef

Please sign in to comment.