2014-03-28 02:50:40 +01:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using DS4Library;
|
2014-05-07 06:35:08 +02:00
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Reflection;
|
2014-03-28 02:50:40 +01:00
|
|
|
|
namespace DS4Control
|
|
|
|
|
{
|
2014-03-29 06:29:08 +01:00
|
|
|
|
public class Control
|
2014-03-28 02:50:40 +01:00
|
|
|
|
{
|
|
|
|
|
X360Device x360Bus;
|
2014-05-19 07:55:12 +02:00
|
|
|
|
public DS4Device[] DS4Controllers = new DS4Device[4];
|
2014-04-27 21:32:09 +02:00
|
|
|
|
//TPadModeSwitcher[] modeSwitcher = new TPadModeSwitcher[4];
|
|
|
|
|
Mouse[] touchPad = new Mouse[4];
|
2014-03-28 02:50:40 +01:00
|
|
|
|
private bool running = false;
|
|
|
|
|
private DS4State[] MappedState = new DS4State[4];
|
|
|
|
|
private DS4State[] CurrentState = new DS4State[4];
|
|
|
|
|
private DS4State[] PreviousState = new DS4State[4];
|
|
|
|
|
public DS4StateExposed[] ExposedState = new DS4StateExposed[4];
|
|
|
|
|
|
|
|
|
|
public event EventHandler<DebugEventArgs> Debug = null;
|
|
|
|
|
|
|
|
|
|
private class X360Data
|
|
|
|
|
{
|
|
|
|
|
public byte[] Report = new byte[28];
|
|
|
|
|
public byte[] Rumble = new byte[8];
|
|
|
|
|
}
|
|
|
|
|
private X360Data[] processingData = new X360Data[4];
|
|
|
|
|
|
|
|
|
|
public Control()
|
|
|
|
|
{
|
|
|
|
|
x360Bus = new X360Device();
|
|
|
|
|
for (int i = 0; i < DS4Controllers.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
processingData[i] = new X360Data();
|
|
|
|
|
MappedState[i] = new DS4State();
|
|
|
|
|
CurrentState[i] = new DS4State();
|
|
|
|
|
PreviousState[i] = new DS4State();
|
|
|
|
|
ExposedState[i] = new DS4StateExposed(CurrentState[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-29 06:29:08 +01:00
|
|
|
|
private void WarnExclusiveModeFailure(DS4Device device)
|
|
|
|
|
{
|
|
|
|
|
if (DS4Devices.isExclusiveMode && !device.IsExclusive)
|
|
|
|
|
{
|
|
|
|
|
String message = "Warning: Could not open DS4 " + device.MacAddress + " exclusively. " +
|
|
|
|
|
"You must quit other applications like Steam, Uplay before activating the 'Hide DS4 Controller' option.";
|
|
|
|
|
LogDebug(message);
|
|
|
|
|
Log.LogToTray(message);
|
|
|
|
|
}
|
2014-05-07 06:35:08 +02:00
|
|
|
|
}
|
2014-05-25 01:08:40 +02:00
|
|
|
|
public bool Start(bool showlog = true)
|
2014-03-28 02:50:40 +01:00
|
|
|
|
{
|
|
|
|
|
if (x360Bus.Open() && x360Bus.Start())
|
|
|
|
|
{
|
2014-05-25 01:08:40 +02:00
|
|
|
|
if (showlog)
|
2014-03-28 02:50:40 +01:00
|
|
|
|
LogDebug("Starting...");
|
|
|
|
|
DS4Devices.isExclusiveMode = Global.getUseExclusiveMode();
|
2014-05-25 01:08:40 +02:00
|
|
|
|
if (showlog)
|
|
|
|
|
{
|
|
|
|
|
LogDebug("Searching for controllers....");
|
|
|
|
|
LogDebug("Using " + (DS4Devices.isExclusiveMode ? "Exclusive Mode" : "Shared Mode"));
|
|
|
|
|
}
|
2014-03-28 02:50:40 +01:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
DS4Devices.findControllers();
|
|
|
|
|
IEnumerable<DS4Device> devices = DS4Devices.getDS4Controllers();
|
|
|
|
|
int ind = 0;
|
|
|
|
|
foreach (DS4Device device in devices)
|
|
|
|
|
{
|
2014-05-25 01:08:40 +02:00
|
|
|
|
if (showlog)
|
|
|
|
|
LogDebug("Found Controller: " + device.MacAddress + " (" + device.ConnectionType + ")");
|
2014-03-29 06:29:08 +01:00
|
|
|
|
WarnExclusiveModeFailure(device);
|
2014-03-28 02:50:40 +01:00
|
|
|
|
DS4Controllers[ind] = device;
|
2014-04-27 21:32:09 +02:00
|
|
|
|
device.Removal -= DS4Devices.On_Removal;
|
2014-03-28 02:50:40 +01:00
|
|
|
|
device.Removal += this.On_DS4Removal;
|
2014-04-27 21:32:09 +02:00
|
|
|
|
device.Removal += DS4Devices.On_Removal;
|
|
|
|
|
//TPadModeSwitcher m_switcher = new TPadModeSwitcher(device, ind);
|
|
|
|
|
//m_switcher.Debug += OnDebug;
|
|
|
|
|
//modeSwitcher[ind] = m_switcher;
|
|
|
|
|
touchPad[ind] = new Mouse(ind, device);
|
2014-03-28 02:50:40 +01:00
|
|
|
|
DS4Color color = Global.loadColor(ind);
|
|
|
|
|
device.LightBarColor = color;
|
2014-04-30 05:54:41 +02:00
|
|
|
|
x360Bus.Plugin(ind);
|
2014-03-28 02:50:40 +01:00
|
|
|
|
device.Report += this.On_Report;
|
2014-04-27 21:32:09 +02:00
|
|
|
|
//m_switcher.setMode(Global.getInitialMode(ind));
|
|
|
|
|
TouchPadOn(ind, device);
|
2014-05-21 07:36:05 +02:00
|
|
|
|
string filename = Path.GetFileName(Global.getAProfile(ind));
|
2014-03-28 02:50:40 +01:00
|
|
|
|
ind++;
|
2014-05-25 01:08:40 +02:00
|
|
|
|
if (showlog)
|
|
|
|
|
if (System.IO.File.Exists(Global.appdatapath + "\\Profiles\\" + filename))
|
|
|
|
|
{
|
|
|
|
|
LogDebug("Controller " + ind + " is using Profile \"" + filename.Substring(0, filename.Length - 4) + "\"");
|
|
|
|
|
Log.LogToTray("Controller " + ind + " is using Profile \"" + filename.Substring(0, filename.Length - 4) + "\"");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
LogDebug("Controller " + ind + " is not using a profile");
|
|
|
|
|
Log.LogToTray("Controller " + ind + " is not using a profile");
|
|
|
|
|
}
|
2014-03-29 06:29:08 +01:00
|
|
|
|
if (ind >= 4) // out of Xinput devices!
|
2014-03-28 02:50:40 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
LogDebug(e.Message);
|
2014-03-29 06:29:08 +01:00
|
|
|
|
Log.LogToTray(e.Message);
|
2014-03-28 02:50:40 +01:00
|
|
|
|
}
|
|
|
|
|
running = true;
|
2014-05-05 09:31:24 +02:00
|
|
|
|
|
2014-03-28 02:50:40 +01:00
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-25 01:08:40 +02:00
|
|
|
|
public bool Stop(bool showlog = true)
|
2014-03-28 02:50:40 +01:00
|
|
|
|
{
|
|
|
|
|
if (running)
|
|
|
|
|
{
|
|
|
|
|
running = false;
|
2014-05-25 01:08:40 +02:00
|
|
|
|
if (showlog)
|
2014-05-28 04:49:58 +02:00
|
|
|
|
LogDebug("Stopping X360 Controllers");
|
|
|
|
|
bool anyUnplugged = false;
|
2014-03-28 02:50:40 +01:00
|
|
|
|
for (int i = 0; i < DS4Controllers.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
if (DS4Controllers[i] != null)
|
|
|
|
|
{
|
2014-05-28 04:49:58 +02:00
|
|
|
|
double oldrainbow = Global.getRainbow(i);
|
|
|
|
|
bool oldbatt = Global.getLedAsBatteryIndicator(i);
|
|
|
|
|
DS4Color oldcolor = Global.loadColor(i);
|
|
|
|
|
while (Global.loadColor(i).red != 32 || Global.loadColor(i).green != 64 || Global.loadColor(i).blue != 64 || Global.getRainbow(i) != 0 || Global.getLedAsBatteryIndicator(i) != false)
|
|
|
|
|
{
|
|
|
|
|
Global.setRainbow(i, 0);
|
|
|
|
|
Global.setLedAsBatteryIndicator(i, false);
|
|
|
|
|
Global.saveColor(i, 32, 64, 64); //Make Lightbar light blue like default bluetooth color
|
|
|
|
|
System.Threading.Thread.Sleep(5);
|
|
|
|
|
}
|
2014-04-27 21:32:09 +02:00
|
|
|
|
CurrentState[i].Battery = PreviousState[i].Battery = 0; // Reset for the next connection's initial status change.
|
2014-04-30 05:54:41 +02:00
|
|
|
|
x360Bus.Unplug(i);
|
2014-04-27 21:32:09 +02:00
|
|
|
|
anyUnplugged = true;
|
2014-03-28 02:50:40 +01:00
|
|
|
|
DS4Controllers[i] = null;
|
2014-04-27 21:32:09 +02:00
|
|
|
|
touchPad[i] = null;
|
2014-05-28 04:49:58 +02:00
|
|
|
|
Global.setRainbow(i, oldrainbow); //Set back settings once ds4windows stops, so when reconnecting it shows right colors
|
|
|
|
|
Global.setLedAsBatteryIndicator(i, oldbatt);
|
|
|
|
|
Global.saveColor(i, oldcolor.red, oldcolor.green, oldcolor.blue);
|
2014-03-28 02:50:40 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2014-04-27 21:32:09 +02:00
|
|
|
|
if (anyUnplugged)
|
|
|
|
|
System.Threading.Thread.Sleep(XINPUT_UNPLUG_SETTLE_TIME);
|
2014-03-28 02:50:40 +01:00
|
|
|
|
x360Bus.Stop();
|
2014-05-25 01:08:40 +02:00
|
|
|
|
if (showlog)
|
2014-05-28 04:49:58 +02:00
|
|
|
|
LogDebug("Stopping DS4 Controllers");
|
2014-03-28 02:50:40 +01:00
|
|
|
|
DS4Devices.stopControllers();
|
2014-05-25 01:08:40 +02:00
|
|
|
|
if (showlog)
|
2014-05-28 04:49:58 +02:00
|
|
|
|
LogDebug("Stopped DS4 Tool");
|
|
|
|
|
Global.ControllerStatusChanged(this);
|
2014-03-28 02:50:40 +01:00
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool HotPlug()
|
|
|
|
|
{
|
2014-03-29 06:29:08 +01:00
|
|
|
|
if (running)
|
2014-03-28 02:50:40 +01:00
|
|
|
|
{
|
|
|
|
|
DS4Devices.findControllers();
|
|
|
|
|
IEnumerable<DS4Device> devices = DS4Devices.getDS4Controllers();
|
|
|
|
|
foreach (DS4Device device in devices)
|
|
|
|
|
{
|
2014-03-29 06:29:08 +01:00
|
|
|
|
if (device.IsDisconnecting)
|
|
|
|
|
continue;
|
2014-03-28 02:50:40 +01:00
|
|
|
|
if (((Func<bool>)delegate
|
|
|
|
|
{
|
|
|
|
|
for (Int32 Index = 0; Index < DS4Controllers.Length; Index++)
|
2014-05-25 01:08:40 +02:00
|
|
|
|
if (DS4Controllers[Index] != null && DS4Controllers[Index].MacAddress == device.MacAddress)
|
2014-03-28 02:50:40 +01:00
|
|
|
|
return true;
|
|
|
|
|
return false;
|
|
|
|
|
})())
|
|
|
|
|
continue;
|
|
|
|
|
for (Int32 Index = 0; Index < DS4Controllers.Length; Index++)
|
|
|
|
|
if (DS4Controllers[Index] == null)
|
|
|
|
|
{
|
2014-03-29 06:29:08 +01:00
|
|
|
|
LogDebug("Found Controller: " + device.MacAddress + " (" + device.ConnectionType + ")");
|
|
|
|
|
WarnExclusiveModeFailure(device);
|
2014-03-28 02:50:40 +01:00
|
|
|
|
DS4Controllers[Index] = device;
|
2014-04-27 21:32:09 +02:00
|
|
|
|
device.Removal -= DS4Devices.On_Removal;
|
2014-03-28 02:50:40 +01:00
|
|
|
|
device.Removal += this.On_DS4Removal;
|
2014-04-27 21:32:09 +02:00
|
|
|
|
device.Removal += DS4Devices.On_Removal;
|
2014-05-05 09:31:24 +02:00
|
|
|
|
touchPad[Index] = new Mouse(Index, device);
|
2014-03-28 02:50:40 +01:00
|
|
|
|
device.LightBarColor = Global.loadColor(Index);
|
|
|
|
|
device.Report += this.On_Report;
|
2014-04-30 05:54:41 +02:00
|
|
|
|
x360Bus.Plugin(Index);
|
2014-04-27 21:32:09 +02:00
|
|
|
|
TouchPadOn(Index, device);
|
2014-05-21 07:36:05 +02:00
|
|
|
|
string filename = Path.GetFileName(Global.getAProfile(Index));
|
2014-05-19 07:55:12 +02:00
|
|
|
|
if (System.IO.File.Exists(Global.appdatapath + "\\Profiles\\" + filename))
|
2014-05-07 06:35:08 +02:00
|
|
|
|
{
|
2014-05-21 07:36:05 +02:00
|
|
|
|
LogDebug("Controller " + (Index + 1) + " is using Profile \"" + filename.Substring(0, filename.Length - 4) + "\"");
|
2014-05-07 06:46:36 +02:00
|
|
|
|
Log.LogToTray("Controller " + (Index + 1) + " is using Profile \"" + filename.Substring(0, filename.Length - 4) + "\"");
|
2014-05-07 06:35:08 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2014-05-21 07:36:05 +02:00
|
|
|
|
LogDebug("Controller " + (Index + 1) + " is not using a profile");
|
|
|
|
|
Log.LogToTray("Controller " + (Index + 1) + " is not using a profile");
|
2014-05-07 06:35:08 +02:00
|
|
|
|
}
|
|
|
|
|
|
2014-03-28 02:50:40 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-27 21:32:09 +02:00
|
|
|
|
public void TouchPadOn(int ind, DS4Device device)
|
|
|
|
|
{
|
|
|
|
|
ITouchpadBehaviour tPad = touchPad[ind];
|
|
|
|
|
device.Touchpad.TouchButtonDown += tPad.touchButtonDown;
|
|
|
|
|
device.Touchpad.TouchButtonUp += tPad.touchButtonUp;
|
|
|
|
|
device.Touchpad.TouchesBegan += tPad.touchesBegan;
|
|
|
|
|
device.Touchpad.TouchesMoved += tPad.touchesMoved;
|
|
|
|
|
device.Touchpad.TouchesEnded += tPad.touchesEnded;
|
|
|
|
|
device.Touchpad.TouchUnchanged += tPad.touchUnchanged;
|
|
|
|
|
//LogDebug("Touchpad mode for " + device.MacAddress + " is now " + tmode.ToString());
|
|
|
|
|
//Log.LogToTray("Touchpad mode for " + device.MacAddress + " is now " + tmode.ToString());
|
|
|
|
|
Global.ControllerStatusChanged(this);
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-25 01:08:40 +02:00
|
|
|
|
public void TimeoutConnection(DS4Device d)
|
2014-05-24 01:44:30 +02:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
|
|
|
|
|
sw.Start();
|
|
|
|
|
while (!d.IsAlive())
|
|
|
|
|
{
|
|
|
|
|
if (sw.ElapsedMilliseconds < 1000)
|
|
|
|
|
System.Threading.Thread.SpinWait(500);
|
|
|
|
|
//If weve been waiting less than 1 second let the thread keep its processing chunk
|
|
|
|
|
else
|
|
|
|
|
System.Threading.Thread.Sleep(500);
|
|
|
|
|
//If weve been waiting more than 1 second give up some resources
|
|
|
|
|
|
|
|
|
|
if (sw.ElapsedMilliseconds > 5000) throw new TimeoutException(); //Weve waited long enough
|
|
|
|
|
}
|
|
|
|
|
sw.Reset();
|
|
|
|
|
}
|
2014-05-25 01:08:40 +02:00
|
|
|
|
catch (TimeoutException)
|
2014-05-24 01:44:30 +02:00
|
|
|
|
{
|
2014-05-25 01:08:40 +02:00
|
|
|
|
//Global.setUseExclusiveMode(!Global.getUseExclusiveMode());
|
|
|
|
|
Stop(false);
|
|
|
|
|
Start(false);
|
|
|
|
|
//Global.setUseExclusiveMode(!Global.getUseExclusiveMode());
|
|
|
|
|
//Stop(false);
|
|
|
|
|
//Start(false);
|
2014-05-24 01:44:30 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-28 02:50:40 +01:00
|
|
|
|
public string getDS4ControllerInfo(int index)
|
|
|
|
|
{
|
|
|
|
|
if (DS4Controllers[index] != null)
|
|
|
|
|
{
|
|
|
|
|
DS4Device d = DS4Controllers[index];
|
2014-03-29 06:29:08 +01:00
|
|
|
|
if (!d.IsAlive())
|
2014-05-24 01:44:30 +02:00
|
|
|
|
//return "Connecting..."; // awaiting the first battery charge indication
|
|
|
|
|
{
|
|
|
|
|
var TimeoutThread = new System.Threading.Thread(() => TimeoutConnection(d));
|
|
|
|
|
TimeoutThread.IsBackground = true;
|
|
|
|
|
TimeoutThread.Name = "TimeoutFor" + d.MacAddress.ToString();
|
|
|
|
|
TimeoutThread.Start();
|
|
|
|
|
return "Connecting...";
|
|
|
|
|
}
|
2014-03-29 06:29:08 +01:00
|
|
|
|
String battery;
|
|
|
|
|
if (d.Charging)
|
|
|
|
|
{
|
|
|
|
|
if (d.Battery >= 100)
|
2014-04-27 21:32:09 +02:00
|
|
|
|
battery = "Charged";
|
2014-03-29 06:29:08 +01:00
|
|
|
|
else
|
2014-04-27 21:32:09 +02:00
|
|
|
|
battery = "Charging:" + d.Battery + "%";
|
2014-03-29 06:29:08 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2014-04-27 21:32:09 +02:00
|
|
|
|
battery = "Battery: " + d.Battery + "%";
|
2014-03-29 06:29:08 +01:00
|
|
|
|
}
|
2014-04-27 21:32:09 +02:00
|
|
|
|
return d.MacAddress + " (" + d.ConnectionType + "), " + battery;
|
|
|
|
|
//return d.MacAddress + " (" + d.ConnectionType + "), Battery is " + battery + ", Touchpad in " + modeSwitcher[index].ToString();
|
2014-03-28 02:50:40 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
2014-04-27 21:32:09 +02:00
|
|
|
|
return String.Empty;
|
2014-03-28 02:50:40 +01:00
|
|
|
|
}
|
|
|
|
|
|
2014-05-30 22:39:39 +02:00
|
|
|
|
public string getDS4MacAddress(int index)
|
|
|
|
|
{
|
|
|
|
|
if (DS4Controllers[index] != null)
|
|
|
|
|
{
|
|
|
|
|
DS4Device d = DS4Controllers[index];
|
|
|
|
|
if (!d.IsAlive())
|
|
|
|
|
//return "Connecting..."; // awaiting the first battery charge indication
|
|
|
|
|
{
|
|
|
|
|
var TimeoutThread = new System.Threading.Thread(() => TimeoutConnection(d));
|
|
|
|
|
TimeoutThread.IsBackground = true;
|
|
|
|
|
TimeoutThread.Name = "TimeoutFor" + d.MacAddress.ToString();
|
|
|
|
|
TimeoutThread.Start();
|
|
|
|
|
return "Connecting...";
|
|
|
|
|
}
|
|
|
|
|
return d.MacAddress;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return String.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-27 21:32:09 +02:00
|
|
|
|
public string getShortDS4ControllerInfo(int index)
|
|
|
|
|
{
|
|
|
|
|
if (DS4Controllers[index] != null)
|
|
|
|
|
{
|
|
|
|
|
DS4Device d = DS4Controllers[index];
|
|
|
|
|
String battery;
|
|
|
|
|
if (!d.IsAlive())
|
|
|
|
|
battery = "...";
|
|
|
|
|
if (d.Charging)
|
|
|
|
|
{
|
|
|
|
|
if (d.Battery >= 100)
|
|
|
|
|
battery = "Full";
|
|
|
|
|
else
|
2014-04-30 21:32:44 +02:00
|
|
|
|
battery = d.Battery + "%+";
|
2014-04-27 21:32:09 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
battery = d.Battery + "%";
|
|
|
|
|
}
|
2014-05-30 22:39:39 +02:00
|
|
|
|
return d.ConnectionType + " " + battery + " (" + System.IO.Path.GetFileNameWithoutExtension(Global.getAProfile(index)) + ")";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return "None";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string getDS4Battery(int index)
|
|
|
|
|
{
|
|
|
|
|
if (DS4Controllers[index] != null)
|
|
|
|
|
{
|
|
|
|
|
DS4Device d = DS4Controllers[index];
|
|
|
|
|
String battery;
|
|
|
|
|
if (!d.IsAlive())
|
|
|
|
|
battery = "...";
|
|
|
|
|
if (d.Charging)
|
|
|
|
|
{
|
|
|
|
|
if (d.Battery >= 100)
|
|
|
|
|
battery = "Full";
|
|
|
|
|
else
|
|
|
|
|
battery = d.Battery + "%+";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
battery = d.Battery + "%";
|
|
|
|
|
}
|
|
|
|
|
return battery;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return "N/A";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string getDS4Status(int index)
|
|
|
|
|
{
|
|
|
|
|
if (DS4Controllers[index] != null)
|
|
|
|
|
{
|
|
|
|
|
DS4Device d = DS4Controllers[index];
|
|
|
|
|
return d.ConnectionType+"";
|
2014-04-27 21:32:09 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return "None";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int XINPUT_UNPLUG_SETTLE_TIME = 250; // Inhibit races that occur with the asynchronous teardown of ScpVBus -> X360 driver instance.
|
2014-03-28 02:50:40 +01:00
|
|
|
|
//Called when DS4 is disconnected or timed out
|
|
|
|
|
protected virtual void On_DS4Removal(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
DS4Device device = (DS4Device)sender;
|
|
|
|
|
int ind = -1;
|
|
|
|
|
for (int i = 0; i < DS4Controllers.Length; i++)
|
|
|
|
|
if (DS4Controllers[i] != null && device.MacAddress == DS4Controllers[i].MacAddress)
|
|
|
|
|
ind = i;
|
|
|
|
|
if (ind != -1)
|
|
|
|
|
{
|
2014-04-27 21:32:09 +02:00
|
|
|
|
CurrentState[ind].Battery = PreviousState[ind].Battery = 0; // Reset for the next connection's initial status change.
|
2014-04-30 05:54:41 +02:00
|
|
|
|
x360Bus.Unplug(ind);
|
2014-03-28 02:50:40 +01:00
|
|
|
|
LogDebug("Controller " + device.MacAddress + " was removed or lost connection");
|
|
|
|
|
Log.LogToTray("Controller " + device.MacAddress + " was removed or lost connection");
|
2014-04-27 21:32:09 +02:00
|
|
|
|
System.Threading.Thread.Sleep(XINPUT_UNPLUG_SETTLE_TIME);
|
2014-03-28 02:50:40 +01:00
|
|
|
|
DS4Controllers[ind] = null;
|
2014-04-27 21:32:09 +02:00
|
|
|
|
//modeSwitcher[ind] = null;
|
|
|
|
|
touchPad[ind] = null;
|
2014-03-29 06:29:08 +01:00
|
|
|
|
Global.ControllerStatusChanged(this);
|
2014-03-28 02:50:40 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Called every time the new input report has arrived
|
|
|
|
|
protected virtual void On_Report(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
DS4Device device = (DS4Device)sender;
|
|
|
|
|
|
2014-05-05 09:31:24 +02:00
|
|
|
|
int ind = -1;
|
|
|
|
|
for (int i = 0; i < DS4Controllers.Length; i++)
|
|
|
|
|
if (device == DS4Controllers[i])
|
2014-03-28 02:50:40 +01:00
|
|
|
|
ind = i;
|
|
|
|
|
|
2014-05-05 09:31:24 +02:00
|
|
|
|
if (ind != -1)
|
2014-03-28 02:50:40 +01:00
|
|
|
|
{
|
2014-03-29 06:29:08 +01:00
|
|
|
|
device.getExposedState(ExposedState[ind], CurrentState[ind]);
|
|
|
|
|
DS4State cState = CurrentState[ind];
|
|
|
|
|
device.getPreviousState(PreviousState[ind]);
|
|
|
|
|
DS4State pState = PreviousState[ind];
|
2014-04-27 21:32:09 +02:00
|
|
|
|
if (pState.Battery != cState.Battery)
|
|
|
|
|
Global.ControllerStatusChanged(this);
|
|
|
|
|
CheckForHotkeys(ind, cState, pState);
|
2014-05-19 07:55:12 +02:00
|
|
|
|
GetInputkeys(ind);
|
2014-05-05 09:31:24 +02:00
|
|
|
|
|
2014-03-28 02:50:40 +01:00
|
|
|
|
if (Global.getHasCustomKeysorButtons(ind))
|
|
|
|
|
{
|
2014-04-29 23:56:58 +02:00
|
|
|
|
Mapping.MapCustom(ind, cState, MappedState[ind], pState);
|
2014-03-28 02:50:40 +01:00
|
|
|
|
cState = MappedState[ind];
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-29 06:29:08 +01:00
|
|
|
|
// Update the GUI/whatever.
|
|
|
|
|
DS4LightBar.updateLightBar(device, ind);
|
|
|
|
|
|
2014-03-28 02:50:40 +01:00
|
|
|
|
x360Bus.Parse(cState, processingData[ind].Report, ind);
|
2014-03-29 06:29:08 +01:00
|
|
|
|
// We push the translated Xinput state, and simultaneously we
|
|
|
|
|
// pull back any possible rumble data coming from Xinput consumers.
|
2014-03-28 02:50:40 +01:00
|
|
|
|
if (x360Bus.Report(processingData[ind].Report, processingData[ind].Rumble))
|
|
|
|
|
{
|
|
|
|
|
Byte Big = (Byte)(processingData[ind].Rumble[3]);
|
|
|
|
|
Byte Small = (Byte)(processingData[ind].Rumble[4]);
|
|
|
|
|
|
|
|
|
|
if (processingData[ind].Rumble[1] == 0x08)
|
|
|
|
|
{
|
|
|
|
|
setRumble(Small, Big, ind);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-04-27 21:32:09 +02:00
|
|
|
|
|
|
|
|
|
// Output any synthetic events.
|
|
|
|
|
Mapping.Commit(ind);
|
|
|
|
|
// Pull settings updates.
|
|
|
|
|
device.IdleTimeout = Global.getIdleDisconnectTimeout(ind);
|
2014-03-28 02:50:40 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-19 07:55:12 +02:00
|
|
|
|
public string GetInputkeys(int ind)
|
|
|
|
|
{
|
|
|
|
|
DS4State cState = CurrentState[ind];
|
2014-05-30 22:39:39 +02:00
|
|
|
|
if (DS4Controllers[ind] != null)
|
|
|
|
|
if (Mapping.getBoolMapping(DS4Controls.Cross, cState)) return "Cross";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.Circle, cState)) return "Circle";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.Triangle, cState)) return "Triangle";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.Square, cState)) return "Square";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.L1, cState)) return "L1";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.R1, cState)) return "R1";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.L2, cState)) return "L2";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.R2, cState)) return "R2";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.L3, cState)) return "L3";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.R3, cState)) return "R3";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.DpadUp, cState)) return "Up";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.DpadDown, cState)) return "Down";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.DpadLeft, cState)) return "Left";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.DpadRight, cState)) return "Right";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.Share, cState)) return "Share";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.Options, cState)) return "Options";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.PS, cState)) return "PS";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.LXPos, cState)) return "LS Right";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.LXNeg, cState)) return "LS Left";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.LYPos, cState)) return "LS Down";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.LYNeg, cState)) return "LS Up";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.RXPos, cState)) return "RS Right";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.RXNeg, cState)) return "RS Left";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.RYPos, cState)) return "RS Down";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.RYNeg, cState)) return "RS Up";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.TouchLeft, cState)) return "Touch Left";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.TouchRight, cState)) return "Touch Right";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.TouchMulti, cState)) return "Touch Multi";
|
|
|
|
|
else if (Mapping.getBoolMapping(DS4Controls.TouchUpper, cState)) return "Touch Upper";
|
|
|
|
|
else return "nothing";
|
2014-05-19 07:55:12 +02:00
|
|
|
|
else return "nothing";
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-30 22:39:39 +02:00
|
|
|
|
bool touchreleased = true, touchslid = false;
|
2014-05-28 04:49:58 +02:00
|
|
|
|
byte[] oldtouchvalue = { 0, 0, 0, 0 };
|
2014-03-28 02:50:40 +01:00
|
|
|
|
protected virtual void CheckForHotkeys(int deviceID, DS4State cState, DS4State pState)
|
|
|
|
|
{
|
|
|
|
|
DS4Device d = DS4Controllers[deviceID];
|
|
|
|
|
if (cState.Touch1 && !pState.Share && !pState.Options)
|
|
|
|
|
{
|
2014-04-29 04:50:56 +02:00
|
|
|
|
/*if (cState.Share)
|
2014-04-27 21:32:09 +02:00
|
|
|
|
Global.setTouchSensitivity(deviceID, 0);
|
2014-03-28 02:50:40 +01:00
|
|
|
|
else if (cState.Options)
|
2014-04-29 04:50:56 +02:00
|
|
|
|
Global.setTouchSensitivity(deviceID, 100); */
|
2014-04-27 21:32:09 +02:00
|
|
|
|
}
|
2014-05-28 04:49:58 +02:00
|
|
|
|
if ((!pState.PS || !pState.Options) && cState.PS && cState.Options)
|
|
|
|
|
{
|
2014-05-28 21:47:25 +02:00
|
|
|
|
if (!d.Charging)
|
2014-05-28 04:49:58 +02:00
|
|
|
|
{
|
2014-05-28 21:47:25 +02:00
|
|
|
|
d.DisconnectBT();
|
|
|
|
|
InputMethods.performKeyRelease(Global.getCustomKey(0, DS4Controls.PS));
|
|
|
|
|
string[] skeys = Global.getCustomMacro(0, DS4Controls.PS).Split('/');
|
|
|
|
|
ushort[] keys = new ushort[skeys.Length];
|
|
|
|
|
for (int i = 0; i < keys.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
keys[i] = ushort.Parse(skeys[i]);
|
|
|
|
|
InputMethods.performKeyRelease(keys[i]);
|
|
|
|
|
}
|
2014-05-28 04:49:58 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2014-05-30 22:39:39 +02:00
|
|
|
|
if (cState.TouchButton && pState.PS)
|
2014-04-27 21:32:09 +02:00
|
|
|
|
{
|
|
|
|
|
if (Global.getTouchSensitivity(deviceID) > 0 && touchreleased)
|
|
|
|
|
{
|
2014-05-28 04:49:58 +02:00
|
|
|
|
oldtouchvalue[deviceID] = Global.getTouchSensitivity(deviceID);
|
2014-04-27 21:32:09 +02:00
|
|
|
|
Global.setTouchSensitivity(deviceID, 0);
|
2014-04-29 04:50:56 +02:00
|
|
|
|
LogDebug("Touchpad Movement is now " + (Global.getTouchSensitivity(deviceID) > 0 ? "On" : "Off"));
|
|
|
|
|
Log.LogToTray("Touchpad Movement is now " + (Global.getTouchSensitivity(deviceID) > 0 ? "On" : "Off"));
|
2014-04-27 21:32:09 +02:00
|
|
|
|
touchreleased = false;
|
|
|
|
|
}
|
|
|
|
|
else if (touchreleased)
|
|
|
|
|
{
|
2014-05-28 04:49:58 +02:00
|
|
|
|
Global.setTouchSensitivity(deviceID, oldtouchvalue[deviceID]);
|
2014-04-29 04:50:56 +02:00
|
|
|
|
LogDebug("Touchpad Movement is now " + (Global.getTouchSensitivity(deviceID) > 0 ? "On" : "Off"));
|
|
|
|
|
Log.LogToTray("Touchpad Movement is now " + (Global.getTouchSensitivity(deviceID) > 0 ? "On" : "Off"));
|
2014-04-27 21:32:09 +02:00
|
|
|
|
touchreleased = false;
|
|
|
|
|
}
|
2014-03-28 02:50:40 +01:00
|
|
|
|
}
|
2014-04-27 21:32:09 +02:00
|
|
|
|
else
|
2014-05-30 22:39:39 +02:00
|
|
|
|
touchreleased = true;
|
2014-03-28 02:50:40 +01:00
|
|
|
|
}
|
|
|
|
|
|
2014-05-30 22:39:39 +02:00
|
|
|
|
public virtual string TouchpadSlide(int ind)
|
|
|
|
|
{
|
|
|
|
|
DS4State cState = CurrentState[ind];
|
|
|
|
|
string slidedir = "none";
|
|
|
|
|
if (cState.L1 && cState.R1)
|
|
|
|
|
if (touchPad[ind].slideright && !touchslid)
|
|
|
|
|
{
|
|
|
|
|
slidedir = "right";
|
|
|
|
|
touchslid = true;
|
|
|
|
|
}
|
|
|
|
|
else if (touchPad[ind].slideleft && !touchslid)
|
|
|
|
|
{
|
|
|
|
|
slidedir = "left";
|
|
|
|
|
touchslid = true;
|
|
|
|
|
}
|
|
|
|
|
else if (!touchPad[ind].slideleft && !touchPad[ind].slideright)
|
|
|
|
|
{
|
|
|
|
|
slidedir = "";
|
|
|
|
|
touchslid = false;
|
|
|
|
|
}
|
|
|
|
|
return slidedir;
|
|
|
|
|
}
|
2014-03-28 02:50:40 +01:00
|
|
|
|
public virtual void LogDebug(String Data)
|
|
|
|
|
{
|
2014-05-21 07:36:05 +02:00
|
|
|
|
Console.WriteLine(System.DateTime.Now.ToString("G") + "> " + Data);
|
2014-03-28 02:50:40 +01:00
|
|
|
|
if (Debug != null)
|
|
|
|
|
{
|
|
|
|
|
DebugEventArgs args = new DebugEventArgs(Data);
|
|
|
|
|
OnDebug(this, args);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public virtual void OnDebug(object sender, DebugEventArgs args)
|
|
|
|
|
{
|
|
|
|
|
if (Debug != null)
|
|
|
|
|
Debug(this, args);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//sets the rumble adjusted with rumble boost
|
|
|
|
|
public virtual void setRumble(byte heavyMotor, byte lightMotor, int deviceNum)
|
|
|
|
|
{
|
|
|
|
|
byte boost = Global.loadRumbleBoost(deviceNum);
|
|
|
|
|
uint lightBoosted = ((uint)lightMotor * (uint)boost) / 100;
|
|
|
|
|
if (lightBoosted > 255)
|
|
|
|
|
lightBoosted = 255;
|
|
|
|
|
uint heavyBoosted = ((uint)heavyMotor * (uint)boost) / 100;
|
|
|
|
|
if (heavyBoosted > 255)
|
|
|
|
|
heavyBoosted = 255;
|
2014-05-30 22:39:39 +02:00
|
|
|
|
if (deviceNum < 4)
|
|
|
|
|
if (DS4Controllers[deviceNum] != null)
|
|
|
|
|
DS4Controllers[deviceNum].setRumble((byte)lightBoosted, (byte)heavyBoosted);
|
2014-03-28 02:50:40 +01:00
|
|
|
|
}
|
2014-05-28 04:49:58 +02:00
|
|
|
|
|
|
|
|
|
public DS4State getDS4State(int ind)
|
|
|
|
|
{
|
|
|
|
|
return CurrentState[ind];
|
|
|
|
|
}
|
2014-03-28 02:50:40 +01:00
|
|
|
|
}
|
|
|
|
|
}
|