Merge branch '#21-media-commands' into develop

#6-gpu-reporting
sleevezipper 4 years ago
commit 8a237de0a7

@ -190,6 +190,21 @@ This command allows you to run any Windows Commands. The command will be run in
|shutdown /s /t 300|Shuts the PC down after 5 minutes (300 seconds).|
|C:\path\to\your\batchfile.bat|Run the specified batch file.|
### KeyCommand
Sends a keystroke with the specified key. You can pick [any of these](https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes) key codes.
### Media Commands
There's several media commands available which are very self exlanatory.
- Play/Pause
- Next
- Previous
- Volume up
- Volume down
- Mute (toggle)
## Credits
This project depends on work done by others and they should at least get a mention. Please note that this list is not complete yet.

@ -13,9 +13,11 @@ namespace UserInterface.ViewModels
public string Description { get => description; set => this.RaiseAndSetIfChanged(ref description, value); }
public bool ShowCommandInput { get => showCommandInput; set => this.RaiseAndSetIfChanged(ref showCommandInput, value); }
public bool ShowKeyInput { get => showKeyInput; set => this.RaiseAndSetIfChanged(ref showKeyInput, value); }
private string moreInfoLink;
private bool showCommandInput;
private bool showKeyInput;
public string MoreInfoLink
{
@ -27,5 +29,6 @@ namespace UserInterface.ViewModels
public string Name { get; set; }
public string Command { get; set; }
public string Key { get; set; }
}
}

@ -20,6 +20,8 @@
<TextBlock Text="{Binding UpdateInterval, StringFormat= Update every {0} seconds}" HorizontalAlignment="Left" MinWidth="150"/>
<ContentControl IsVisible="{Binding ShowCommandInput}" Margin="0 20 0 10">Command</ContentControl>
<TextBox IsVisible="{Binding ShowCommandInput}" Text="{Binding Command}" Watermark="Rundll32.exe user32.dll,LockWorkStation" HorizontalAlignment="Left" MinWidth="300"/>
<ContentControl IsVisible="{Binding ShowKeyInput}" Margin="0 20 0 10">Key</ContentControl>
<TextBox IsVisible="{Binding ShowKeyInput}" Text="{Binding Key}" Watermark="0xAD" HorizontalAlignment="Left" MinWidth="300"/>
<Button IsVisible="{Binding ShowCommandInput}" Width="75" HorizontalAlignment="Right" Margin="0 40 0 10" Click="Test">Test</Button>
<Button Width="75" HorizontalAlignment="Right" Margin="0 40 0 10" Click="Save">Save</Button>
</StackPanel>

@ -47,7 +47,7 @@ namespace UserInterface.Views
public async void Save(object sender, RoutedEventArgs args)
{
var item = ((AddCommandViewModel)this.DataContext);
dynamic model = new { item.Name, item.Command};
dynamic model = new { item.Name, item.Command, item.Key};
string json = JsonSerializer.Serialize(model);
await this.client.InvokeAsync(x => x.AddCommand(item.SelectedType, json));
Close();
@ -62,30 +62,77 @@ namespace UserInterface.Views
item.Description = "This command lets you execute any command you want. It will run in a Windows Command Prompt silently. ";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#customcommand";
item.ShowCommandInput = true;
item.ShowKeyInput = false;
break;
case AvailableCommands.ShutdownCommand:
item.Description = "This command shuts down the PC immediately. ";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#shutdowncommand";
item.ShowCommandInput = false;
item.ShowKeyInput = false;
break;
case AvailableCommands.RestartCommand:
item.Description = "This command restarts the PC immediately. ";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#restartcommand";
item.ShowCommandInput = false;
item.ShowKeyInput = false;
break;
case AvailableCommands.LogOffCommand:
item.Description = "This command logs the current user off immediately. ";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#logoffcommand";
item.ShowCommandInput = false;
item.ShowKeyInput = false;
break;
case AvailableCommands.KeyCommand:
item.Description = "This command can be used to emulate a keystroke. It requires a key code which you can find by clicking the info button below.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#keycommand";
item.ShowCommandInput = false;
item.ShowKeyInput = true;
break;
case AvailableCommands.PlayPauseCommand:
item.Description = "This command plays or pauses currently playing media.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#media-commands";
item.ShowCommandInput = false;
item.ShowKeyInput = false;
break;
case AvailableCommands.NextCommand:
item.Description = "This command skips to the next media.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#media-commands";
item.ShowCommandInput = false;
item.ShowKeyInput = false;
break;
case AvailableCommands.PreviousCommand:
item.Description = "This command plays previous media.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#media-commands";
item.ShowCommandInput = false;
item.ShowKeyInput = false;
break;
case AvailableCommands.VolumeDownCommand:
item.Description = "Lowers the system volume.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#media-commands";
item.ShowCommandInput = false;
item.ShowKeyInput = false;
break;
case AvailableCommands.VolumeUpCommand:
item.Description = "Raises the system volume.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#media-commands";
item.ShowCommandInput = false;
item.ShowKeyInput = false;
break;
case AvailableCommands.MuteCommand:
item.Description = "Toggles muting the system volume.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#media-commands";
item.ShowCommandInput = false;
item.ShowKeyInput = false;
break;
default:
item.Description = null;
item.MoreInfoLink = null;
item.ShowCommandInput = false;
item.ShowKeyInput = false;
break;
}
}
public void OpenInfo(object sender, RoutedEventArgs args)
public void OpenInfo(object sender, RoutedEventArgs args)
{
var item = ((AddCommandViewModel)this.DataContext);
BrowserUtil.OpenBrowser(item.MoreInfoLink);

@ -188,6 +188,27 @@ namespace hass_workstation_service.Communication.InterProcesCommunication
case AvailableCommands.CustomCommand:
commandToCreate = new CustomCommand(this._publisher, model.Command, model.Name);
break;
case AvailableCommands.PlayPauseCommand:
commandToCreate = new MediaPlayPauseCommand(this._publisher, model.Name);
break;
case AvailableCommands.NextCommand:
commandToCreate = new MediaNextCommand(this._publisher, model.Name);
break;
case AvailableCommands.PreviousCommand:
commandToCreate = new MediaPreviousCommand(this._publisher, model.Name);
break;
case AvailableCommands.VolumeUpCommand:
commandToCreate = new MediaVolumeUpCommand(this._publisher, model.Name);
break;
case AvailableCommands.VolumeDownCommand:
commandToCreate = new MediaVolumeDownCommand(this._publisher, model.Name);
break;
case AvailableCommands.MuteCommand:
commandToCreate = new MediaMuteCommand(this._publisher, model.Name);
break;
case AvailableCommands.KeyCommand:
commandToCreate = new KeyCommand(this._publisher, Convert.ToByte(model.Key, 16), model.Name);
break;
default:
Log.Logger.Error("Unknown sensortype");
break;

@ -60,5 +60,12 @@ namespace hass_workstation_service.Communication.InterProcesCommunication.Models
ShutdownCommand,
LogOffCommand,
RestartCommand,
KeyCommand,
PlayPauseCommand,
NextCommand,
PreviousCommand,
VolumeUpCommand,
VolumeDownCommand,
MuteCommand
}
}

@ -174,6 +174,27 @@ namespace hass_workstation_service.Data
case "CustomCommand":
command = new CustomCommand(publisher, configuredCommand.Command, configuredCommand.Name, configuredCommand.Id);
break;
case "MediaPlayPauseCommand":
command = new MediaPlayPauseCommand(publisher, configuredCommand.Name, configuredCommand.Id);
break;
case "MediaNextCommand":
command = new MediaNextCommand(publisher, configuredCommand.Name, configuredCommand.Id);
break;
case "MediaPreviousCommand":
command = new MediaPreviousCommand(publisher, configuredCommand.Name, configuredCommand.Id);
break;
case "MediaVolumeUpCommand":
command = new MediaVolumeUpCommand(publisher, configuredCommand.Name, configuredCommand.Id);
break;
case "MediaVolumeDownCommand":
command = new MediaVolumeDownCommand(publisher, configuredCommand.Name, configuredCommand.Id);
break;
case "MediaMuteCommand":
command = new MediaMuteCommand(publisher, configuredCommand.Name, configuredCommand.Id);
break;
case "KeyCommand":
command = new KeyCommand(publisher, configuredCommand.KeyCode, configuredCommand.Name, configuredCommand.Id);
break;
default:
Log.Logger.Error("unsupported command type in config");
break;
@ -292,9 +313,13 @@ namespace hass_workstation_service.Data
Log.Logger.Information($"writing configured commands to: {stream.Name}");
foreach (AbstractCommand command in this.ConfiguredCommands)
{
if (command is CustomCommand customcommand)
if (command is CustomCommand customCommand)
{
configuredCommandsToSave.Add(new ConfiguredCommand() { Id = customCommand.Id, Name = customCommand.Name, Type = customCommand.GetType().Name, Command = customCommand.Command });
}
if (command is KeyCommand customKeyCommand)
{
configuredCommandsToSave.Add(new ConfiguredCommand() { Id = customcommand.Id, Name = customcommand.Name, Type = customcommand.GetType().Name, Command = customcommand.Command });
configuredCommandsToSave.Add(new ConfiguredCommand() { Id = customKeyCommand.Id, Name = customKeyCommand.Name, Type = customKeyCommand.GetType().Name, KeyCode = customKeyCommand.KeyCode });
}
}

@ -9,5 +9,6 @@ namespace hass_workstation_service.Data
public Guid Id { get; set; }
public string Name { get; set; }
public string Command { get; set; }
public byte KeyCode { get; set; }
}
}

@ -0,0 +1,60 @@
using hass_workstation_service.Communication;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace hass_workstation_service.Domain.Commands
{
public class KeyCommand : AbstractCommand
{
public const int KEYEVENTF_EXTENTEDKEY = 1;
public const int KEYEVENTF_KEYUP = 0;
public const int VK_MEDIA_NEXT_TRACK = 0xB0;
public const int VK_MEDIA_PLAY_PAUSE = 0xB3;
public const int VK_MEDIA_PREV_TRACK = 0xB1;
public const int VK_VOLUME_MUTE = 0xAD;
public const int VK_VOLUME_UP = 0xAF;
public const int VK_VOLUME_DOWN = 0xAE;
public byte KeyCode { get; protected set; }
public KeyCommand(MqttPublisher publisher, byte keyCode, string name = "Key", Guid id = default(Guid)) : base(publisher, name ?? "Key", id) {
this.KeyCode = keyCode;
}
public override CommandDiscoveryConfigModel GetAutoDiscoveryConfig()
{
return new CommandDiscoveryConfigModel()
{
Name = this.Name,
Unique_id = this.Id.ToString(),
Availability_topic = $"homeassistant/sensor/{Publisher.DeviceConfigModel.Name}/availability",
Command_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/set",
State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/state",
Device = this.Publisher.DeviceConfigModel,
};
}
[DllImport("user32.dll")]
public static extern void keybd_event(byte virtualKey, byte scanCode, uint flags, IntPtr extraInfo);
public override string GetState()
{
return "OFF";
}
public override void TurnOff()
{
}
public override void TurnOn()
{
keybd_event(this.KeyCode, 0, KEYEVENTF_EXTENTEDKEY, IntPtr.Zero);
}
}
}

@ -0,0 +1,14 @@
using hass_workstation_service.Communication;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace hass_workstation_service.Domain.Commands
{
public class MediaMuteCommand : KeyCommand
{
public MediaMuteCommand(MqttPublisher publisher, string name = "Mute", Guid id = default(Guid)) : base(publisher, KeyCommand.VK_VOLUME_MUTE, name ?? "Mute", id) { }
}
}

@ -0,0 +1,14 @@
using hass_workstation_service.Communication;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace hass_workstation_service.Domain.Commands
{
public class MediaNextCommand : KeyCommand
{
public MediaNextCommand(MqttPublisher publisher, string name = "Next", Guid id = default(Guid)) : base(publisher, KeyCommand.VK_MEDIA_NEXT_TRACK, name ?? "Next", id) { }
}
}

@ -0,0 +1,14 @@
using hass_workstation_service.Communication;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace hass_workstation_service.Domain.Commands
{
public class MediaPlayPauseCommand : KeyCommand
{
public MediaPlayPauseCommand(MqttPublisher publisher, string name = "PlayPause", Guid id = default(Guid)) : base(publisher, KeyCommand.VK_MEDIA_PLAY_PAUSE, name ?? "PlayPause", id) { }
}
}

@ -0,0 +1,14 @@
using hass_workstation_service.Communication;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace hass_workstation_service.Domain.Commands
{
public class MediaPreviousCommand : KeyCommand
{
public MediaPreviousCommand(MqttPublisher publisher, string name = "Previous", Guid id = default(Guid)) : base(publisher, KeyCommand.VK_MEDIA_PREV_TRACK, name ?? "Previous", id) { }
}
}

@ -0,0 +1,14 @@
using hass_workstation_service.Communication;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace hass_workstation_service.Domain.Commands
{
public class MediaVolumeDownCommand : KeyCommand
{
public MediaVolumeDownCommand(MqttPublisher publisher, string name = "VolumeDown", Guid id = default(Guid)) : base(publisher, KeyCommand.VK_VOLUME_DOWN, name ?? "VolumeDown", id) { }
}
}

@ -0,0 +1,14 @@
using hass_workstation_service.Communication;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace hass_workstation_service.Domain.Commands
{
public class MediaVolumeUpCommand : KeyCommand
{
public MediaVolumeUpCommand(MqttPublisher publisher, string name = "VolumeUp", Guid id = default(Guid)) : base(publisher, KeyCommand.VK_VOLUME_UP, name ?? "VolumeUp", id) { }
}
}

@ -12,8 +12,10 @@ namespace hass_workstation_service.Domain.Sensors
{
public class CurrentVolumeSensor : AbstractSensor
{
public CurrentVolumeSensor(MqttPublisher publisher, int? updateInterval = null, string name = "CurrentVolume", Guid id = default(Guid)) : base(publisher, name ?? "CurrentVolume", updateInterval ?? 10, id) { }
private MMDeviceEnumerator DevEnum;
public CurrentVolumeSensor(MqttPublisher publisher, int? updateInterval = null, string name = "CurrentVolume", Guid id = default(Guid)) : base(publisher, name ?? "CurrentVolume", updateInterval ?? 10, id) {
this.DevEnum = new MMDeviceEnumerator();
}
public override SensorDiscoveryConfigModel GetAutoDiscoveryConfig()
{
return this._autoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel()
@ -33,8 +35,6 @@ namespace hass_workstation_service.Domain.Sensors
public override string GetState()
{
MMDeviceEnumerator DevEnum = new MMDeviceEnumerator();
var collection = DevEnum.EnumerateAudioEndPoints(EDataFlow.eRender, DEVICE_STATE.DEVICE_STATE_ACTIVE);
List<float> peaks = new List<float>();

Loading…
Cancel
Save