Last active
June 28, 2018 22:18
-
-
Save lbehm/38f960e40cba6f2595c8e770a4b433b0 to your computer and use it in GitHub Desktop.
First try on working with Saitek X52Pro MFD
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[string]$dll = (gi HKLM:\SOFTWARE\Saitek\DirectOutput).GetValue('DirectOutput_Saitek').Replace('\', '\\') | |
Add-Type -Namespace Saitek -Name "DirectOutput" -UsingNamespace "System.Collections.Generic" -MemberDefinition @" | |
[UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate void Pfn_DirectOutput_EnumerateCallback(IntPtr hDevice, IntPtr pCtxt); | |
[UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate void Pfn_DirectOutput_DeviceChange(IntPtr hDevice, bool bAdded, IntPtr pCtxt); | |
[UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate void Pfn_DirectOutput_PageChange(IntPtr hDevice, uint dwPage, bool bSetActive, IntPtr pCtxt); | |
[UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate void Pfn_DirectOutput_SoftButtonChange(IntPtr hDevice, uint dwButtons, IntPtr pCtxt); | |
[DllImport("$dll", SetLastError = true, CharSet = CharSet.Ansi)] public static extern IntPtr DirectOutput_Initialize([MarshalAs(UnmanagedType.LPWStr)]System.Text.StringBuilder wszPluginName); | |
[DllImport("$dll", SetLastError = true)] public static extern IntPtr DirectOutput_Deinitialize(); | |
[DllImport("$dll", SetLastError = true)] private static extern IntPtr DirectOutput_RegisterDeviceCallback(Pfn_DirectOutput_DeviceChange pfnCb, IntPtr pCtxt); | |
[DllImport("$dll", SetLastError = true)] private static extern IntPtr DirectOutput_Enumerate(Pfn_DirectOutput_EnumerateCallback pfnCb, IntPtr pCtxt); | |
[DllImport("$dll", SetLastError = true)] private static extern IntPtr DirectOutput_RegisterPageCallback(IntPtr hDevice, Pfn_DirectOutput_PageChange pfnCb, IntPtr pCtxt); | |
[DllImport("$dll", SetLastError = true)] private static extern IntPtr DirectOutput_RegisterSoftButtonCallback(IntPtr hDevice, Pfn_DirectOutput_SoftButtonChange pfnCb, IntPtr pCtxt); | |
//[DllImport("$dll", SetLastError = true)] private static extern IntPtr DirectOutput_GetDeviceType(IntPtr hDevice, LPGUID pGuid); | |
//[DllImport("$dll", SetLastError = true)] private static extern IntPtr DirectOutput_GetDeviceInstance(IntPtr hDevice, LPGUID pGuid); | |
[DllImport("$dll", SetLastError = true, CharSet = CharSet.Ansi)] private static extern IntPtr DirectOutput_SetProfile(IntPtr hDevice, uint cchProfile, [MarshalAs(UnmanagedType.LPWStr)]System.Text.StringBuilder wszProfile); | |
[DllImport("$dll", SetLastError = true)] private static extern IntPtr DirectOutput_AddPage(IntPtr hDevice, uint dwPage, uint dwFlags); | |
[DllImport("$dll", SetLastError = true)] private static extern IntPtr DirectOutput_RemovePage(IntPtr hDevice, uint dwPage); | |
[DllImport("$dll", SetLastError = true)] private static extern IntPtr DirectOutput_SetLed(IntPtr hDevice, uint dwPage, uint dwIndex, uint dwValue); | |
[DllImport("$dll", SetLastError = true, CharSet = CharSet.Ansi)] private static extern IntPtr DirectOutput_SetString(IntPtr hDevice, uint dwPage, uint dwIndex, uint cchValue, [MarshalAs(UnmanagedType.LPWStr)]System.Text.StringBuilder wszValue); | |
[DllImport("$dll", SetLastError = true)] private static extern IntPtr DirectOutput_SetImage(IntPtr hDevice, uint dwPage, uint dwIndex, uint cbValue, IntPtr pvValue); | |
[DllImport("$dll", SetLastError = true, CharSet = CharSet.Ansi)] private static extern IntPtr DirectOutput_SetImageFromFile(IntPtr hDevice, uint dwPage, uint dwIndex, uint cchFilename, [MarshalAs(UnmanagedType.LPWStr)]System.Text.StringBuilder wszFilename); | |
private static bool _test(IntPtr a) { | |
if (a == IntPtr.Zero) | |
return true; | |
System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(a.ToInt32()); | |
return false; | |
} | |
public class Device { | |
public class Page { | |
public Device Owner; | |
public uint Id; | |
private string _Line0; | |
private string _Line1; | |
private string _Line2; | |
public string Line0 { | |
get { return _Line0; } | |
set { if (_set_string(0, value)) _Line0 = value; } | |
} | |
public string Line1 { | |
get { return _Line1; } | |
set { if (_set_string(1, value)) _Line1 = value; } | |
} | |
public string Line2 { | |
get { return _Line2; } | |
set { if (_set_string(2, value)) _Line2 = value; } | |
} | |
public Page(Device owner, uint id, bool Active = false) { | |
Owner = owner; | |
Id = id; | |
_Line0 = ""; | |
_Line1 = ""; | |
_Line2 = ""; | |
_test(DirectOutput_AddPage(Owner.hDevice, Id, Convert.ToUInt32(Active ? 1 : 0))); | |
} | |
private bool _set_string(uint Line, string Value) { | |
System.Text.StringBuilder sb = new System.Text.StringBuilder(Value); | |
return _test(DirectOutput_SetString(Owner.hDevice, Id, Line, Convert.ToUInt32(Value.Length), sb)); | |
} | |
}; | |
public class PageChangeEventArgs : EventArgs { | |
public Device Device; | |
public Page Page; | |
public bool SetActive; | |
public PageChangeEventArgs(Device device, Page page, bool setActive) { | |
Device = device; | |
Page = page; | |
SetActive = setActive; | |
} | |
}; | |
public class ButtonEventArgs : EventArgs { | |
public Device Device; | |
public uint Button; | |
public long Duration; | |
public ButtonEventArgs(Device device, uint button, long duration) { | |
Device = device; | |
Button = button; | |
Duration = duration; | |
} | |
}; | |
public IntPtr hDevice; | |
public List<Page> Pages; | |
public Page ActivePage; | |
public event EventHandler<PageChangeEventArgs> PageChange; | |
public event EventHandler<ButtonEventArgs> ButtonDown; | |
public event EventHandler<ButtonEventArgs> ButtonPress; | |
public event EventHandler<ButtonEventArgs> ButtonLongPress; | |
public event EventHandler<ButtonEventArgs> ButtonUp; | |
private Pfn_DirectOutput_PageChange _PageChangeCallback; | |
private Pfn_DirectOutput_SoftButtonChange _SoftButtonChangeCallback; | |
private System.Timers.Timer ButtonUpTimer; | |
private System.Diagnostics.Stopwatch ButtonDownStopWatch; | |
private uint ActiveButton; // currently pressed button id; 0 if no key is pressed | |
public Device(IntPtr Device) { | |
hDevice = Device; | |
Pages = new List<Page>(); | |
ActivePage = new Page(this, 0, true); | |
Pages.Add(ActivePage); | |
ButtonUpTimer = new System.Timers.Timer(100); | |
ButtonUpTimer.Elapsed += (sender, e) => { | |
ButtonDownStopWatch.Stop(); | |
ButtonUpTimer.Enabled = false; | |
var button = ActiveButton; | |
ActiveButton = 0; | |
OnButtonUp(this, new ButtonEventArgs(this, button, ButtonDownStopWatch.ElapsedMilliseconds)); | |
}; | |
ButtonDownStopWatch = new System.Diagnostics.Stopwatch(); | |
_PageChangeCallback = new Pfn_DirectOutput_PageChange(_onPageChange); | |
_test(DirectOutput_RegisterPageCallback(hDevice, _PageChangeCallback, IntPtr.Zero)); | |
_SoftButtonChangeCallback = new Pfn_DirectOutput_SoftButtonChange(_onButtonDown); | |
_test(DirectOutput_RegisterSoftButtonCallback(hDevice, _SoftButtonChangeCallback, IntPtr.Zero)); | |
} | |
private void _onPageChange(IntPtr hDevice, uint dwPage, bool bSetActive, IntPtr pCtxt) { | |
var Page = Pages.Find(page => page.Id == dwPage); | |
if (bSetActive) | |
ActivePage = Page; | |
EventHandler<PageChangeEventArgs> handler = PageChange; | |
if (handler != null) | |
handler(this, new PageChangeEventArgs(this, Page, bSetActive)); | |
} | |
private void _onButtonDown(IntPtr hDevice, uint dwButton, IntPtr pCtxt) { | |
if ((dwButton & 1) == 1) // every button that is sended simultaneously with ok/select | |
dwButton = 1; // is only passed as ok/select | |
long duration = ButtonDownStopWatch.ElapsedMilliseconds; | |
if (dwButton == 0) { // holding buttons 1,2,4 and page-buttons are sending 0 | |
if (ActiveButton > 0) { | |
ButtonUpTimer.Stop(); | |
ButtonUpTimer.Start(); // reset Timer | |
} | |
} else { | |
ButtonUpTimer.Stop(); | |
ActiveButton = dwButton; | |
ButtonUpTimer.Enabled = true; | |
ButtonUpTimer.Start(); | |
ButtonDownStopWatch.Restart(); | |
duration = 0; | |
OnButtonDown(this, new ButtonEventArgs(this, dwButton, duration)); | |
} | |
if (ActiveButton > 0) | |
OnButtonPress(this, new ButtonEventArgs(this, ActiveButton, duration)); | |
if (duration > 750) {// long click ms | |
ButtonDownStopWatch.Restart(); | |
OnButtonLongPress(this, new ButtonEventArgs(this, ActiveButton, duration)); | |
} | |
} | |
protected void OnButtonDown(object sender, ButtonEventArgs args) { | |
EventHandler<ButtonEventArgs> handler = ButtonDown; | |
if (handler != null) | |
handler(this, args); | |
} | |
protected void OnButtonPress(object sender, ButtonEventArgs args) { | |
EventHandler<ButtonEventArgs> handler = ButtonPress; | |
if (handler != null) | |
handler(this, args); | |
} | |
protected void OnButtonLongPress(object sender, ButtonEventArgs args) { | |
EventHandler<ButtonEventArgs> handler = ButtonLongPress; | |
if (handler != null) | |
handler(this, args); | |
} | |
protected void OnButtonUp(object sender, ButtonEventArgs args) { | |
EventHandler<ButtonEventArgs> handler = ButtonUp; | |
if (handler != null) | |
handler(this, args); | |
} | |
}; | |
public static bool Init(String Name) { | |
System.Text.StringBuilder sb = new System.Text.StringBuilder(Name); | |
if (_test(DirectOutput_Initialize(sb))) { | |
_DeviceChangeCallback = new Pfn_DirectOutput_DeviceChange(_onDeviceChange); | |
_EnumerateCallback = new Pfn_DirectOutput_EnumerateCallback(_onEnumerate); | |
return _test(DirectOutput_RegisterDeviceCallback(_DeviceChangeCallback, IntPtr.Zero)) && _test(DirectOutput_Enumerate(_EnumerateCallback, IntPtr.Zero)); | |
} | |
return false; | |
} | |
public static bool Reset() { | |
return _test(DirectOutput_Deinitialize()); | |
} | |
public class DeviceChangeEventArgs : EventArgs { | |
public bool Added; | |
}; | |
public static event EventHandler<DeviceChangeEventArgs> DeviceChange; | |
private static Pfn_DirectOutput_DeviceChange _DeviceChangeCallback; | |
private static Pfn_DirectOutput_EnumerateCallback _EnumerateCallback; | |
public static List<Device> Devices = new List<Device>(); | |
private static void _onDeviceChange(IntPtr hDevice, bool bAdded, IntPtr pCtxt) { | |
Device dev = Devices.Find(device => device.hDevice == hDevice); | |
if (dev == null) { | |
if (bAdded) { | |
dev = new Device(hDevice); | |
Devices.Add(dev); | |
} | |
} else { | |
if (!bAdded) | |
Devices.Remove(dev); | |
} | |
EventHandler<DeviceChangeEventArgs> handler = DeviceChange; | |
if (handler != null) { | |
DeviceChangeEventArgs args = new DeviceChangeEventArgs(); | |
args.Added = bAdded; | |
handler(dev, args); | |
} | |
} | |
private static void _onEnumerate(IntPtr hDevice, IntPtr pCtxt) { | |
if (Devices.Find(device => device.hDevice == hDevice) == null) | |
Devices.Add(new Device(hDevice)); | |
} | |
"@ | |
$DirectOutput = [Saitek.DirectOutput] | |
function Initialize-DirectOutput ([string]$PluginName) | |
{ | |
$DirectOutput::Init($PluginName) | |
} | |
function Deinitialize-DirectOutput | |
{ | |
$DirectOutput::Reset() | |
} | |
function Get-DirectOutputDevices | |
{ | |
$DirectOutput::Devices | |
} | |
function Write-MFD ([string] $Line0="", [string] $Line1="", [string] $Line2="", $Device=(Get-DirectOutputDevices|select -f 1)) | |
{ | |
$Device.ActivePage.Line0 = $Line0 | |
$Device.ActivePage.Line1 = $Line1 | |
$Device.ActivePage.Line2 = $Line2 | |
} | |
# examples: | |
Deinitialize-DirectOutput | Out-Null | |
Initialize-DirectOutput "app" | Out-Null | |
Register-ObjectEvent -InputObject $DirectOutput::Devices[0] -EventName PageChange -Action { | |
Param([Saitek.DirectOutput+Device]$Device, [Saitek.DirectOutput+Device+PageChangeEventArgs]$EventArgs) | |
Write-Host "Page: $($EventArgs.Page.Id) Active: $($EventArgs.SetActive)" | |
} | Out-Null | |
Register-ObjectEvent -InputObject $DirectOutput::Devices[0] -EventName ButtonDown -Action { | |
Param([Saitek.DirectOutput+Device]$Device, [Saitek.DirectOutput+Device+ButtonEventArgs]$EventArgs) | |
Write-Host "Button $($EventArgs.Button) pressed down" | |
} | Out-Null | |
<#Register-ObjectEvent -InputObject $DirectOutput::Devices[0] -EventName ButtonPress -Action { | |
Param([Saitek.DirectOutput+Device]$Device, [Saitek.DirectOutput+Device+ButtonEventArgs]$EventArgs) | |
Write-Host "Button $($EventArgs.Button) pressed" | |
} | Out-Null#> | |
Register-ObjectEvent -InputObject $DirectOutput::Devices[0] -EventName ButtonLongPress -Action { | |
Param([Saitek.DirectOutput+Device]$Device, [Saitek.DirectOutput+Device+ButtonEventArgs]$EventArgs) | |
Write-Host "Button $($EventArgs.Button) pressed long" | |
} | Out-Null | |
Register-ObjectEvent -InputObject $DirectOutput::Devices[0] -EventName ButtonUp -Action { | |
Param([Saitek.DirectOutput+Device]$Device, [Saitek.DirectOutput+Device+ButtonEventArgs]$EventArgs) | |
Write-Host "Button $($EventArgs.Button) released" | |
} | Out-Null | |
<#Register-ObjectEvent -InputObject $DirectOutput -EventName DeviceChange -Action { | |
Param([Saitek.DirectOutput+Device]$Device, [Saitek.DirectOutput+DeviceChangeEventArgs]$EventArgs) | |
Write-Host "Device changed: $($EventArgs.Added)" | |
} | Out-Null#> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment