diff --git a/.idea/.idea.SwitchSlidePresenter/.idea/.gitignore b/.idea/.idea.ControllerSlidePresenter/.idea/.gitignore
similarity index 100%
rename from .idea/.idea.SwitchSlidePresenter/.idea/.gitignore
rename to .idea/.idea.ControllerSlidePresenter/.idea/.gitignore
diff --git a/.idea/.idea.ControllerSlidePresenter/.idea/.name b/.idea/.idea.ControllerSlidePresenter/.idea/.name
new file mode 100644
index 0000000..ef9baeb
--- /dev/null
+++ b/.idea/.idea.ControllerSlidePresenter/.idea/.name
@@ -0,0 +1 @@
+ControllerSlidePresenter
\ No newline at end of file
diff --git a/.idea/.idea.SwitchSlidePresenter/.idea/encodings.xml b/.idea/.idea.ControllerSlidePresenter/.idea/encodings.xml
similarity index 100%
rename from .idea/.idea.SwitchSlidePresenter/.idea/encodings.xml
rename to .idea/.idea.ControllerSlidePresenter/.idea/encodings.xml
diff --git a/.idea/.idea.SwitchSlidePresenter/.idea/git_toolbox_prj.xml b/.idea/.idea.ControllerSlidePresenter/.idea/git_toolbox_prj.xml
similarity index 100%
rename from .idea/.idea.SwitchSlidePresenter/.idea/git_toolbox_prj.xml
rename to .idea/.idea.ControllerSlidePresenter/.idea/git_toolbox_prj.xml
diff --git a/.idea/.idea.SwitchSlidePresenter/.idea/indexLayout.xml b/.idea/.idea.ControllerSlidePresenter/.idea/indexLayout.xml
similarity index 100%
rename from .idea/.idea.SwitchSlidePresenter/.idea/indexLayout.xml
rename to .idea/.idea.ControllerSlidePresenter/.idea/indexLayout.xml
diff --git a/.idea/.idea.SwitchSlidePresenter/.idea/vcs.xml b/.idea/.idea.ControllerSlidePresenter/.idea/vcs.xml
similarity index 100%
rename from .idea/.idea.SwitchSlidePresenter/.idea/vcs.xml
rename to .idea/.idea.ControllerSlidePresenter/.idea/vcs.xml
diff --git a/ControllerSlidePresenter.sln b/ControllerSlidePresenter.sln
new file mode 100644
index 0000000..eb48f5c
--- /dev/null
+++ b/ControllerSlidePresenter.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwitchSlidePresenter", "SlidePresenter\SwitchSlidePresenter.csproj", "{F9832F2F-C7CA-4725-8F70-0FF3F76C0A5D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Win32Api", "Win32Api\Win32Api.csproj", "{16DC83C8-381A-4CA7-9E45-2A9CBC7BF48A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F9832F2F-C7CA-4725-8F70-0FF3F76C0A5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F9832F2F-C7CA-4725-8F70-0FF3F76C0A5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F9832F2F-C7CA-4725-8F70-0FF3F76C0A5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F9832F2F-C7CA-4725-8F70-0FF3F76C0A5D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {16DC83C8-381A-4CA7-9E45-2A9CBC7BF48A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {16DC83C8-381A-4CA7-9E45-2A9CBC7BF48A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {16DC83C8-381A-4CA7-9E45-2A9CBC7BF48A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {16DC83C8-381A-4CA7-9E45-2A9CBC7BF48A}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/Program.cs b/Program.cs
deleted file mode 100644
index 99e227d..0000000
--- a/Program.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace SwitchSlidePresenter {
- class Program {
- private static async Task Main() {
- IGamepadReader reader = new JoyConRead();
- SlideSwitcher switcher = new(reader);
- await reader.Read();
- switcher.Dispose();
- }
- }
-}
\ No newline at end of file
diff --git a/SlidePresenter/ControllerSelector.cs b/SlidePresenter/ControllerSelector.cs
new file mode 100644
index 0000000..8efff0f
--- /dev/null
+++ b/SlidePresenter/ControllerSelector.cs
@@ -0,0 +1,27 @@
+namespace SwitchSlidePresenter;
+
+public static class ControllerSelector {
+ public static IGamepadReader? GetReader() {
+ Console.WriteLine("Write a number to select controller type:");
+ Console.WriteLine("[1] - JoyCon");
+ Console.WriteLine("[2] - Wiimote");
+
+ string? line = Console.ReadLine();
+ if (line == null) {
+ Console.WriteLine("Invalid input.");
+ return null;
+ }
+ if (!int.TryParse(line, out int id)) {
+ Console.WriteLine("Invalid number.");
+ return null;
+ }
+
+ return GetReader(id);
+ }
+
+ private static IGamepadReader? GetReader(int id) => id switch {
+ 1 => new JoyConRead(),
+ 2 => new WiimoteRead(),
+ _ => null
+ };
+}
\ No newline at end of file
diff --git a/GamepadReader.cs b/SlidePresenter/IGamepadReader.cs
similarity index 100%
rename from GamepadReader.cs
rename to SlidePresenter/IGamepadReader.cs
diff --git a/JoyConRead.cs b/SlidePresenter/JoyConRead.cs
similarity index 97%
rename from JoyConRead.cs
rename to SlidePresenter/JoyConRead.cs
index 5496085..3eb2a94 100644
--- a/JoyConRead.cs
+++ b/SlidePresenter/JoyConRead.cs
@@ -1,12 +1,9 @@
using System.Text;
using HidSharp;
using wtf.cluster.JoyCon;
-using wtf.cluster.JoyCon.Calibration;
using wtf.cluster.JoyCon.ExtraData;
-using wtf.cluster.JoyCon.HomeLed;
using wtf.cluster.JoyCon.InputData;
using wtf.cluster.JoyCon.InputReports;
-using wtf.cluster.JoyCon.Rumble;
namespace SwitchSlidePresenter;
diff --git a/SlidePresenter/Program.cs b/SlidePresenter/Program.cs
new file mode 100644
index 0000000..9a8e12c
--- /dev/null
+++ b/SlidePresenter/Program.cs
@@ -0,0 +1,14 @@
+namespace SwitchSlidePresenter {
+ internal abstract class Program {
+ private static async Task Main() {
+ IGamepadReader? reader = ControllerSelector.GetReader();
+ if (reader == null) {
+ Console.WriteLine("Invalid Controller Selected.");
+ return;
+ }
+ SlideSwitcher switcher = new(reader);
+ await reader.Read();
+ switcher.Dispose();
+ }
+ }
+}
\ No newline at end of file
diff --git a/SlidePresenter/SlideSwitcher.cs b/SlidePresenter/SlideSwitcher.cs
new file mode 100644
index 0000000..d81adae
--- /dev/null
+++ b/SlidePresenter/SlideSwitcher.cs
@@ -0,0 +1,65 @@
+using System.Runtime.InteropServices;
+using Win32Api;
+
+namespace SwitchSlidePresenter;
+
+public class SlideSwitcher : IDisposable {
+ private readonly IGamepadReader? _reader;
+
+ private const uint INPUT_KEYBOARD = 1;
+ private const ushort VK_NEXT = 0x22;
+ private const ushort VK_PRIOR = 0x21;
+ private const uint KEYEVENTF_KEYDOWN = 0x0000;
+ private const uint KEYEVENTF_KEYUP = 0x0002;
+
+ public SlideSwitcher(IGamepadReader? reader) {
+ _reader = reader;
+ _reader.NextSlide += NextSlide;
+ _reader.PrevSlide += PreviousSlide;
+ }
+
+ public void Dispose() {
+ _reader.NextSlide -= NextSlide;
+ _reader.PrevSlide -= PreviousSlide;
+ }
+
+ private static void NextSlide() {
+ SimulateKeyPress(VK_NEXT);
+ }
+
+ private static void PreviousSlide() {
+ SimulateKeyPress(VK_PRIOR);
+ }
+
+ private static void SimulateKeyPress(ushort keyCode) {
+ Input[] inputs = new Input[2];
+
+ inputs[0] = new Input {
+ type = INPUT_KEYBOARD,
+ u = new InputUnion {
+ ki = new KeyboardInput {
+ wVk = keyCode,
+ wScan = 0,
+ dwFlags = KEYEVENTF_KEYDOWN,
+ time = 0,
+ dwExtraInfo = IntPtr.Zero
+ }
+ }
+ };
+
+ inputs[1] = new Input {
+ type = INPUT_KEYBOARD,
+ u = new InputUnion {
+ ki = new KeyboardInput {
+ wVk = keyCode,
+ wScan = 0,
+ dwFlags = KEYEVENTF_KEYUP,
+ time = 0,
+ dwExtraInfo = IntPtr.Zero
+ }
+ }
+ };
+
+ Win32Api.Win32Api.SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(Input)));
+ }
+}
\ No newline at end of file
diff --git a/SwitchSlidePresenter.csproj b/SlidePresenter/SwitchSlidePresenter.csproj
similarity index 67%
rename from SwitchSlidePresenter.csproj
rename to SlidePresenter/SwitchSlidePresenter.csproj
index 21b392a..3e00c50 100644
--- a/SwitchSlidePresenter.csproj
+++ b/SlidePresenter/SwitchSlidePresenter.csproj
@@ -9,6 +9,11 @@
+
+
+
+
+
diff --git a/SlidePresenter/WiimoteRead.cs b/SlidePresenter/WiimoteRead.cs
new file mode 100644
index 0000000..7ab8dca
--- /dev/null
+++ b/SlidePresenter/WiimoteRead.cs
@@ -0,0 +1,58 @@
+using WiimoteLib.NetCore;
+
+namespace SwitchSlidePresenter;
+
+public class WiimoteRead : IGamepadReader {
+ public event Action NextSlide;
+ public event Action PrevSlide;
+
+ private const int RetryDelay = 1000;
+
+ public async Task Read() {
+ Wiimote wiimote = new();
+ while (string.IsNullOrEmpty(wiimote.HIDDevicePath)) {
+ wiimote.Connect();
+ if (string.IsNullOrEmpty(wiimote.HIDDevicePath)) {
+ Console.WriteLine("Wiimote connection failed, trying again...");
+ await Task.Delay(RetryDelay);
+ } else {
+ Console.WriteLine("Wiimote ready for presenting!");
+ }
+ }
+
+ ButtonState previousState = wiimote.WiimoteState.ButtonState;
+ while (true) {
+ if (PreviousPressed(wiimote.WiimoteState.ButtonState, previousState)) {
+ PrevSlide?.Invoke();
+ }
+ if (NextPressed(wiimote.WiimoteState.ButtonState, previousState)) {
+ NextSlide?.Invoke();
+ }
+ previousState = wiimote.WiimoteState.ButtonState;
+
+ await Task.Yield();
+
+ if (!Console.KeyAvailable || Console.ReadKey().Key != ConsoleKey.Enter)
+ continue;
+ wiimote.Disconnect();
+
+ Console.WriteLine();
+ Console.WriteLine("Stopped.");
+ break;
+ }
+ }
+
+ private static bool PreviousPressed(ButtonState input) {
+ return input.B || input.Left;
+ }
+ private static bool NextPressed(ButtonState input) {
+ return input.A || input.Right;
+ }
+
+ private static bool PreviousPressed(ButtonState input, ButtonState previousState) {
+ return PreviousPressed(input) && !PreviousPressed(previousState);
+ }
+ private static bool NextPressed(ButtonState input, ButtonState previousState) {
+ return NextPressed(input) && !NextPressed(previousState);
+ }
+}
\ No newline at end of file
diff --git a/SlideSwitcher.cs b/SlideSwitcher.cs
deleted file mode 100644
index 645d039..0000000
--- a/SlideSwitcher.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-namespace SwitchSlidePresenter;
-
-public class SlideSwitcher : IDisposable {
- private readonly IGamepadReader _reader;
-
- public SlideSwitcher(IGamepadReader reader) {
- _reader = reader;
- _reader.NextSlide += NextSlide;
- _reader.PrevSlide += PreviousSlide;
- }
-
- public void Dispose() {
- _reader.NextSlide -= NextSlide;
- _reader.PrevSlide -= PreviousSlide;
- }
-
- private void NextSlide() {
- IntPtr handle = Win32Api.GetForegroundWindow();
- Win32Api.PostMessage(handle, Win32Api.WM_KEYDOWN, Win32Api.VK_NEXT, 0);
- }
-
- private void PreviousSlide() {
- IntPtr handle = Win32Api.GetForegroundWindow();
- Win32Api.PostMessage(handle, Win32Api.WM_KEYDOWN, Win32Api.VK_PRIOR, 0);
- }
-}
\ No newline at end of file
diff --git a/SwitchSlidePresenter.sln b/SwitchSlidePresenter.sln
deleted file mode 100644
index d5f8c1e..0000000
--- a/SwitchSlidePresenter.sln
+++ /dev/null
@@ -1,16 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwitchSlidePresenter", "SwitchSlidePresenter.csproj", "{50CECFA5-3AC2-4F08-82F2-ED8C82993360}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {50CECFA5-3AC2-4F08-82F2-ED8C82993360}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {50CECFA5-3AC2-4F08-82F2-ED8C82993360}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {50CECFA5-3AC2-4F08-82F2-ED8C82993360}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {50CECFA5-3AC2-4F08-82F2-ED8C82993360}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
-EndGlobal
diff --git a/Win32Api.cs b/Win32Api.cs
deleted file mode 100644
index e5f503c..0000000
--- a/Win32Api.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace SwitchSlidePresenter;
-
-public static class Win32Api {
- public const UInt32 WM_KEYDOWN = 0x0100;
- public const int VK_NEXT = 0x22;
- public const int VK_PRIOR = 0x21;
-
- [DllImport("user32.dll")]
- public static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
- [DllImport("user32.dll")]
- public static extern IntPtr GetForegroundWindow();
-}
\ No newline at end of file
diff --git a/Win32Api/HardwareInput.cs b/Win32Api/HardwareInput.cs
new file mode 100644
index 0000000..6df4733
--- /dev/null
+++ b/Win32Api/HardwareInput.cs
@@ -0,0 +1,10 @@
+using System.Runtime.InteropServices;
+
+namespace Win32Api;
+
+[StructLayout(LayoutKind.Sequential)]
+public struct HardwareInput {
+ public uint uMsg;
+ public ushort wParamL;
+ public ushort wParamH;
+}
\ No newline at end of file
diff --git a/Win32Api/Input.cs b/Win32Api/Input.cs
new file mode 100644
index 0000000..991c3da
--- /dev/null
+++ b/Win32Api/Input.cs
@@ -0,0 +1,9 @@
+using System.Runtime.InteropServices;
+
+namespace Win32Api;
+
+[StructLayout(LayoutKind.Sequential)]
+public struct Input {
+ public uint type;
+ public InputUnion u;
+}
\ No newline at end of file
diff --git a/Win32Api/InputUnion.cs b/Win32Api/InputUnion.cs
new file mode 100644
index 0000000..93bf663
--- /dev/null
+++ b/Win32Api/InputUnion.cs
@@ -0,0 +1,10 @@
+using System.Runtime.InteropServices;
+
+namespace Win32Api;
+
+[StructLayout(LayoutKind.Explicit)]
+public struct InputUnion {
+ [FieldOffset(0)] public MouseInput mi;
+ [FieldOffset(0)] public KeyboardInput ki;
+ [FieldOffset(0)] public HardwareInput hi;
+}
\ No newline at end of file
diff --git a/Win32Api/KeyboardInput.cs b/Win32Api/KeyboardInput.cs
new file mode 100644
index 0000000..0a28b48
--- /dev/null
+++ b/Win32Api/KeyboardInput.cs
@@ -0,0 +1,12 @@
+using System.Runtime.InteropServices;
+
+namespace Win32Api;
+
+[StructLayout(LayoutKind.Sequential)]
+public struct KeyboardInput {
+ public ushort wVk;
+ public ushort wScan;
+ public uint dwFlags;
+ public uint time;
+ public IntPtr dwExtraInfo;
+}
\ No newline at end of file
diff --git a/Win32Api/MouseInput.cs b/Win32Api/MouseInput.cs
new file mode 100644
index 0000000..47eaa35
--- /dev/null
+++ b/Win32Api/MouseInput.cs
@@ -0,0 +1,13 @@
+using System.Runtime.InteropServices;
+
+namespace Win32Api;
+
+[StructLayout(LayoutKind.Sequential)]
+public struct MouseInput {
+ public int dx;
+ public int dy;
+ public uint mouseData;
+ public uint dwFlags;
+ public uint time;
+ public IntPtr dwExtraInfo;
+}
\ No newline at end of file
diff --git a/Win32Api/Win32Api.cs b/Win32Api/Win32Api.cs
new file mode 100644
index 0000000..62e51fd
--- /dev/null
+++ b/Win32Api/Win32Api.cs
@@ -0,0 +1,8 @@
+using System.Runtime.InteropServices;
+
+namespace Win32Api;
+
+public static class Win32Api {
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern uint SendInput(uint nInputs, Input[] pInputs, int cbSize);
+}
\ No newline at end of file
diff --git a/Win32Api/Win32Api.csproj b/Win32Api/Win32Api.csproj
new file mode 100644
index 0000000..3a63532
--- /dev/null
+++ b/Win32Api/Win32Api.csproj
@@ -0,0 +1,9 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+