diff --git a/App.xaml.cs b/App.xaml.cs
index c70f6fb..ebe3bff 100644
--- a/App.xaml.cs
+++ b/App.xaml.cs
@@ -37,7 +37,7 @@ namespace unison
{
_systray.Dispose();
_snapcast.LaunchOrExit(true);
- _hotkeys.RemoveHotKeys();
+ _hotkeys.RemoveHotkeys();
base.OnExit(e);
}
}
diff --git a/Handlers/HotkeyHandler.cs b/Handlers/HotkeyHandler.cs
index c0680a2..3d57eb2 100644
--- a/Handlers/HotkeyHandler.cs
+++ b/Handlers/HotkeyHandler.cs
@@ -15,21 +15,168 @@ namespace unison
private const int HOTKEY_ID = 9000;
- // modifiers
- private const uint MOD_NONE = 0x0000;
- private const uint MOD_ALT = 0x0001;
- private const uint MOD_CONTROL = 0x0002;
- private const uint MOD_SHIFT = 0x0004;
- private const uint MOD_WIN = 0x0008;
+ public enum MOD : int
+ {
+ None = 0x0000,
+ Alt = 0x0001,
+ Control = 0x0002,
+ Shift = 0x0004,
+ //Win = 0x0008
+ };
// reference => https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
- private const uint VK_MEDIA_PREV_TRACK = 0xB1;
- private const uint VK_MEDIA_NEXT_TRACK = 0xB0;
- private const uint VK_MEDIA_PLAY_PAUSE = 0xB3;
- private const uint VK_VOLUME_UP = 0xAF;
- private const uint VK_VOLUME_DOWN = 0xAE;
- private const uint VK_VOLUME_MUTE = 0xAD;
- private const uint VK_ENTER = 0x0D;
+ public enum VK : int
+ {
+ None = 0x00,
+ Back = 0x08,
+ Tab = 0x09,
+ Clear = 0x0c,
+ Return = 0x0d,
+ Menu = 0x12,
+ Pause = 0x13,
+ Capital = 0x14,
+ Kana = 0x15,
+ Hangul = 0x15,
+ Junja = 0x17,
+ Final = 0x18,
+ Hanja = 0x19,
+ Kanji = 0x19,
+ Escape = 0x1b,
+ Convert = 0x1c,
+ NonConvert = 0x1d,
+ Accept = 0x1e,
+ ModeChange = 0x1f,
+ Space = 0x20,
+ Prior = 0x21,
+ Next = 0x22,
+ End = 0x23,
+ Home = 0x24,
+ Left = 0x25,
+ Up = 0x26,
+ Right = 0x27,
+ Down = 0x28,
+ Select = 0x29,
+ Print = 0x2a,
+ Execute = 0x2b,
+ Snapshot = 0x2c,
+ Insert = 0x2d,
+ Delete = 0x2e,
+ Help = 0x2f,
+ NumRow0 = 0x30,
+ NumRow1 = 0x31,
+ NumRow2 = 0x32,
+ NumRow3 = 0x33,
+ NumRow4 = 0x34,
+ NumRow5 = 0x35,
+ NumRow6 = 0x36,
+ NumRow7 = 0x37,
+ NumRow8 = 0x38,
+ NumRow9 = 0x39,
+ A = 0x41,
+ B = 0x42,
+ C = 0x43,
+ D = 0x44,
+ E = 0x45,
+ F = 0x46,
+ G = 0x47,
+ H = 0x48,
+ I = 0x49,
+ J = 0x4a,
+ K = 0x4b,
+ L = 0x4c,
+ M = 0x4d,
+ N = 0x4e,
+ O = 0x4f,
+ P = 0x50,
+ Q = 0x51,
+ R = 0x52,
+ S = 0x53,
+ T = 0x54,
+ U = 0x55,
+ V = 0x56,
+ W = 0x57,
+ X = 0x58,
+ Y = 0x59,
+ Z = 0x5a,
+ Apps = 0x5d,
+ Sleep = 0x5f,
+ NumPad0 = 0x60,
+ NumPad1 = 0x61,
+ NumPad2 = 0x62,
+ NumPad3 = 0x63,
+ NumPad4 = 0x64,
+ NumPad5 = 0x65,
+ NumPad6 = 0x66,
+ NumPad7 = 0x67,
+ NumPad8 = 0x68,
+ NumPad9 = 0x69,
+ Multiply = 0x6a,
+ Add = 0x6b,
+ Separator = 0x6c,
+ Subtract = 0x6d,
+ Decimal = 0x6e,
+ Divide = 0x6f,
+ F1 = 0x70,
+ F2 = 0x71,
+ F3 = 0x72,
+ F4 = 0x73,
+ F5 = 0x74,
+ F6 = 0x75,
+ F7 = 0x76,
+ F8 = 0x77,
+ F9 = 0x78,
+ F10 = 0x79,
+ F11 = 0x7a,
+ F12 = 0x7b,
+ F13 = 0x7c,
+ F14 = 0x7d,
+ F15 = 0x7e,
+ F16 = 0x7f,
+ F17 = 0x80,
+ F18 = 0x81,
+ F19 = 0x82,
+ F20 = 0x83,
+ F21 = 0x84,
+ F22 = 0x85,
+ F23 = 0x86,
+ F24 = 0x87,
+ NumLock = 0x90,
+ Scroll = 0x91,
+ LMenu = 0xa4,
+ RMenu = 0xa5,
+ BrowserBack = 0xa6,
+ BrowserForward = 0xa7,
+ BrowserRefresh = 0xa8,
+ BrowserStop = 0xa9,
+ BrowserSearch = 0xaa,
+ BrowserFavorites = 0xab,
+ BrowserHome = 0xac,
+ VolumeMute = 0xad,
+ VolumeDown = 0xae,
+ VolumeUp = 0xaf,
+ MediaNextTrack = 0xb0,
+ MediaPreviousTrack = 0xb1,
+ MediaStop = 0xb2,
+ MediaPlayPause = 0xb3,
+ LaunchMail = 0xb4,
+ LaunchMediaSelect = 0xb5,
+ LaunchApp1 = 0xb6,
+ LaunchApp2 = 0xb7,
+ };
+
+ public struct HotkeyPair
+ {
+ public MOD mod;
+ public VK vk;
+
+ public HotkeyPair(MOD _mod, VK _vk) { mod = _mod; vk = _vk; }
+
+ public uint GetMOD() { return (uint)mod; }
+ public uint GetVK() { return (uint)vk; }
+
+ public void SetMOD(MOD modmod) { mod = modmod; }
+ public void SetVK(VK vkvk) { vk = vkvk; }
+ }
private MainWindow _appWindow;
private readonly MPDHandler _mpd;
@@ -37,9 +184,26 @@ namespace unison
private IntPtr _windowHandle;
private HwndSource _source;
+ public HotkeyPair _NextTrack;
+ public HotkeyPair _PreviousTrack;
+ public HotkeyPair _PlayPause;
+ public HotkeyPair _VolumeUp;
+ public HotkeyPair _VolumeDown;
+ public HotkeyPair _VolumeMute;
+ public HotkeyPair _ShowWindow;
+
public HotkeyHandler()
{
_mpd = (MPDHandler)Application.Current.Properties["mpd"];
+
+ // get shortcuts from settings
+ _NextTrack = new HotkeyPair((MOD)Properties.Settings.Default.nextTrack_mod, (VK)Properties.Settings.Default.nextTrack_vk);
+ _PreviousTrack = new HotkeyPair((MOD)Properties.Settings.Default.previousTrack_mod, (VK)Properties.Settings.Default.previousTrack_vk);
+ _PlayPause = new HotkeyPair((MOD)Properties.Settings.Default.playPause_mod, (VK)Properties.Settings.Default.playPause_vk);
+ _VolumeUp = new HotkeyPair((MOD)Properties.Settings.Default.volumeUp_mod, (VK)Properties.Settings.Default.volumeUp_vk);
+ _VolumeDown = new HotkeyPair((MOD)Properties.Settings.Default.volumeDown_mod, (VK)Properties.Settings.Default.volumeDown_vk);
+ _VolumeMute = new HotkeyPair((MOD)Properties.Settings.Default.volumeMute_mod, (VK)Properties.Settings.Default.volumeMute_vk);
+ _ShowWindow = new HotkeyPair((MOD)Properties.Settings.Default.showWindow_mod, (VK)Properties.Settings.Default.showWindow_vk);
}
public void Activate(Window win)
@@ -48,18 +212,28 @@ namespace unison
{
_windowHandle = new WindowInteropHelper(win).Handle;
_source = HwndSource.FromHwnd(_windowHandle);
- _source.AddHook(HwndHook);
-
- RegisterHotKey(_windowHandle, HOTKEY_ID, MOD_CONTROL, VK_MEDIA_PREV_TRACK);
- RegisterHotKey(_windowHandle, HOTKEY_ID, MOD_CONTROL, VK_MEDIA_NEXT_TRACK);
- RegisterHotKey(_windowHandle, HOTKEY_ID, MOD_CONTROL, VK_MEDIA_PLAY_PAUSE);
- RegisterHotKey(_windowHandle, HOTKEY_ID, MOD_CONTROL, VK_VOLUME_UP);
- RegisterHotKey(_windowHandle, HOTKEY_ID, MOD_CONTROL, VK_VOLUME_DOWN);
- RegisterHotKey(_windowHandle, HOTKEY_ID, MOD_CONTROL, VK_VOLUME_MUTE);
- RegisterHotKey(_windowHandle, HOTKEY_ID, MOD_CONTROL | MOD_ALT, VK_ENTER);
+ AddHotkeys();
}
}
+ public void AddHotkeys()
+ {
+ _source.AddHook(HwndHook);
+ RegisterHotKey(_windowHandle, HOTKEY_ID, _NextTrack.GetMOD(), _NextTrack.GetVK());
+ RegisterHotKey(_windowHandle, HOTKEY_ID, _PreviousTrack.GetMOD(), _PreviousTrack.GetVK());
+ RegisterHotKey(_windowHandle, HOTKEY_ID, _PlayPause.GetMOD(), _PlayPause.GetVK());
+ RegisterHotKey(_windowHandle, HOTKEY_ID, _VolumeUp.GetMOD(), _VolumeUp.GetVK());
+ RegisterHotKey(_windowHandle, HOTKEY_ID, _VolumeDown.GetMOD(), _VolumeDown.GetVK());
+ RegisterHotKey(_windowHandle, HOTKEY_ID, _VolumeMute.GetMOD(), _VolumeMute.GetVK());
+ RegisterHotKey(_windowHandle, HOTKEY_ID, _ShowWindow.GetMOD(), _ShowWindow.GetVK());
+ }
+
+ public void RemoveHotkeys()
+ {
+ _source.RemoveHook(HwndHook);
+ UnregisterHotKey(_windowHandle, HOTKEY_ID);
+ }
+
private IntPtr HwndHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
const int WM_HOTKEY = 0x0312;
@@ -67,61 +241,48 @@ namespace unison
if (msg == WM_HOTKEY && wParam.ToInt32() == HOTKEY_ID)
{
uint vkey = ((uint)lParam >> 16) & 0xFFFF;
- switch (vkey)
- {
- case VK_MEDIA_NEXT_TRACK:
- _mpd.Next();
- break;
- case VK_MEDIA_PREV_TRACK:
- _mpd.Prev();
- break;
- case VK_VOLUME_DOWN:
- _mpd.VolumeDown();
- break;
- case VK_VOLUME_UP:
- _mpd.VolumeUp();
- break;
- case VK_VOLUME_MUTE:
- _mpd.VolumeMute();
- break;
- case VK_MEDIA_PLAY_PAUSE:
- _mpd.PlayPause();
- break;
- case VK_ENTER:
- if (_appWindow == null)
- _appWindow = (MainWindow)Application.Current.MainWindow;
- if (_appWindow.WindowState == WindowState.Minimized)
+ if (vkey == _NextTrack.GetVK())
+ _mpd.Next();
+ else if (vkey == _PreviousTrack.GetVK())
+ _mpd.Prev();
+ else if (vkey == _PlayPause.GetVK())
+ _mpd.PlayPause();
+ else if (vkey == _VolumeUp.GetVK())
+ _mpd.VolumeUp();
+ else if (vkey == _VolumeDown.GetVK())
+ _mpd.VolumeDown();
+ else if (vkey == _VolumeMute.GetVK())
+ _mpd.VolumeMute();
+ else if (vkey == _ShowWindow.GetVK())
+ {
+ if (_appWindow == null)
+ _appWindow = (MainWindow)Application.Current.MainWindow;
+
+ if (_appWindow.WindowState == WindowState.Minimized)
+ {
+ _appWindow.Show();
+ _appWindow.Activate();
+ _appWindow.WindowState = WindowState.Normal;
+ }
+ else
+ {
+ if (_appWindow.IsActive)
+ {
+ _appWindow.Hide();
+ _appWindow.WindowState = WindowState.Minimized;
+ }
+ else // not minimized but not in front
{
_appWindow.Show();
_appWindow.Activate();
_appWindow.WindowState = WindowState.Normal;
}
- else
- {
- if (_appWindow.IsActive)
- {
- _appWindow.Hide();
- _appWindow.WindowState = WindowState.Minimized;
- }
- else // not minimized but not in front
- {
- _appWindow.Show();
- _appWindow.Activate();
- _appWindow.WindowState = WindowState.Normal;
- }
- }
- break;
+ }
}
handled = true;
}
return IntPtr.Zero;
}
-
- public void RemoveHotKeys()
- {
- _source.RemoveHook(HwndHook);
- UnregisterHotKey(_windowHandle, HOTKEY_ID);
- }
}
}
\ No newline at end of file
diff --git a/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs
index 35adc82..03b9275 100644
--- a/Properties/Settings.Designer.cs
+++ b/Properties/Settings.Designer.cs
@@ -118,5 +118,173 @@ namespace unison.Properties {
this["volume_offset"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("2")]
+ public uint nextTrack_mod {
+ get {
+ return ((uint)(this["nextTrack_mod"]));
+ }
+ set {
+ this["nextTrack_mod"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("176")]
+ public uint nextTrack_vk {
+ get {
+ return ((uint)(this["nextTrack_vk"]));
+ }
+ set {
+ this["nextTrack_vk"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("2")]
+ public uint previousTrack_mod {
+ get {
+ return ((uint)(this["previousTrack_mod"]));
+ }
+ set {
+ this["previousTrack_mod"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("177")]
+ public uint previousTrack_vk {
+ get {
+ return ((uint)(this["previousTrack_vk"]));
+ }
+ set {
+ this["previousTrack_vk"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("2")]
+ public uint playPause_mod {
+ get {
+ return ((uint)(this["playPause_mod"]));
+ }
+ set {
+ this["playPause_mod"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("179")]
+ public uint playPause_vk {
+ get {
+ return ((uint)(this["playPause_vk"]));
+ }
+ set {
+ this["playPause_vk"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("2")]
+ public uint volumeUp_mod {
+ get {
+ return ((uint)(this["volumeUp_mod"]));
+ }
+ set {
+ this["volumeUp_mod"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("175")]
+ public uint volumeUp_vk {
+ get {
+ return ((uint)(this["volumeUp_vk"]));
+ }
+ set {
+ this["volumeUp_vk"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("2")]
+ public uint volumeDown_mod {
+ get {
+ return ((uint)(this["volumeDown_mod"]));
+ }
+ set {
+ this["volumeDown_mod"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("174")]
+ public uint volumeDown_vk {
+ get {
+ return ((uint)(this["volumeDown_vk"]));
+ }
+ set {
+ this["volumeDown_vk"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("2")]
+ public uint volumeMute_mod {
+ get {
+ return ((uint)(this["volumeMute_mod"]));
+ }
+ set {
+ this["volumeMute_mod"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("173")]
+ public uint volumeMute_vk {
+ get {
+ return ((uint)(this["volumeMute_vk"]));
+ }
+ set {
+ this["volumeMute_vk"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("3")]
+ public uint showWindow_mod {
+ get {
+ return ((uint)(this["showWindow_mod"]));
+ }
+ set {
+ this["showWindow_mod"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("13")]
+ public uint showWindow_vk {
+ get {
+ return ((uint)(this["showWindow_vk"]));
+ }
+ set {
+ this["showWindow_vk"] = value;
+ }
+ }
}
}
diff --git a/Properties/Settings.settings b/Properties/Settings.settings
index 4a045b9..89920b8 100644
--- a/Properties/Settings.settings
+++ b/Properties/Settings.settings
@@ -26,5 +26,47 @@
5
+
+ 2
+
+
+ 176
+
+
+ 2
+
+
+ 177
+
+
+ 2
+
+
+ 179
+
+
+ 2
+
+
+ 175
+
+
+ 2
+
+
+ 174
+
+
+ 2
+
+
+ 173
+
+
+ 3
+
+
+ 13
+
\ No newline at end of file
diff --git a/README.md b/README.md
index df02576..d217ea4 100644
--- a/README.md
+++ b/README.md
@@ -37,13 +37,12 @@ Through [Radio-Browser](https://www.radio-browser.info), a community database, y
### Missing features
-* Custom shortcuts.
* MPD passwords: I don't really see the point, but if asked, I will integrate them.
-* Any sort of playlist and queue management. I use other software to do it, but I might implement them at some point.
### Wanted features
* A complete shuffle system based on set criteria, aka a smart playlist.
+* Any sort of playlist and queue management. I use other software to do it, but I will implement them at some point.
## Translations
diff --git a/Views/Settings.xaml b/Views/Settings.xaml
index f612775..61bf055 100644
--- a/Views/Settings.xaml
+++ b/Views/Settings.xaml
@@ -109,11 +109,12 @@
-
+
-
+
+
@@ -126,23 +127,79 @@
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Views/Settings.xaml.cs b/Views/Settings.xaml.cs
index ac98bcd..386bade 100644
--- a/Views/Settings.xaml.cs
+++ b/Views/Settings.xaml.cs
@@ -2,9 +2,11 @@
using System.Diagnostics;
using System.Globalization;
using System.IO;
+using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Windows;
+using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Navigation;
@@ -13,6 +15,8 @@ namespace unison
{
public partial class Settings : Window
{
+ Key _pressedKey = Key.None;
+
public static string GetVersion => Assembly.GetEntryAssembly().GetCustomAttribute().InformationalVersion;
public static string GetLicense
@@ -49,6 +53,52 @@ namespace unison
SnapcastPath.Text = Properties.Settings.Default.snapcast_path;
SnapcastPort.Text = Properties.Settings.Default.snapcast_port.ToString();
VolumeOffset.Text = Properties.Settings.Default.volume_offset.ToString();
+
+ SetupShortcuts();
+ }
+
+ private void SetupShortcuts()
+ {
+ var MODValues = System.Enum.GetValues(typeof(HotkeyHandler.MOD));
+
+ System.Collections.Generic.IEnumerable stackPanelCollection = RebindKeyWrapper.Children.OfType();
+ foreach (StackPanel stackPanel in stackPanelCollection)
+ {
+ if (stackPanel.Name.Contains("Shortcut"))
+ {
+ HotkeyHandler.HotkeyPair hotkey = GetHotkeyVariable(stackPanel.Name);
+ System.Collections.Generic.IEnumerable comboBoxCollection = stackPanel.Children.OfType();
+
+ HotkeyHandler.MOD[] MODList = System.Enum.GetValues(typeof(HotkeyHandler.MOD))
+ .OfType()
+ .Select(x => x & (HotkeyHandler.MOD)hotkey.GetMOD())
+ .Where(x => x != HotkeyHandler.MOD.None)
+ .ToArray();
+
+ foreach (ComboBox comboBox in comboBoxCollection)
+ {
+ foreach (var value in MODValues)
+ {
+ comboBox.Items.Add(value.ToString().ToLower());
+ comboBox.SelectedItem = comboBox.Items[0];
+ comboBox.FontWeight = FontWeights.Light;
+ }
+ }
+
+ for (int i = 0; i < comboBoxCollection.ToArray().Length; i++)
+ {
+ if (i < MODList.Length)
+ {
+ comboBoxCollection.ToArray()[i].SelectedItem = MODList[i].ToString().ToLower();
+ comboBoxCollection.ToArray()[i].FontWeight = FontWeights.Bold;
+ }
+ }
+
+ System.Collections.Generic.IEnumerable