diff --git a/DS4Control/Control.cs b/DS4Control/Control.cs index 74a34e530c..e83af4d132 100644 --- a/DS4Control/Control.cs +++ b/DS4Control/Control.cs @@ -6,6 +6,7 @@ using System.IO; using System.Reflection; using System.Media; +using DS4Control.Enums; namespace DS4Control { public class Control @@ -444,23 +445,40 @@ protected virtual void On_Report(object sender, EventArgs e) { if (Global.getFlushHIDQueue(ind)) device.FlushHID(); - if (!string.IsNullOrEmpty(device.error)) + + //This shouldn't be altering the collection from outside. + //something to fix + while (device.currentErrors.Count() > 0) { - LogDebug(device.error); + LogDebug(device.currentErrors[0]); + device.currentErrors.RemoveAt(0); } + device.getExposedState(ExposedState[ind], CurrentState[ind]); DS4State cState = CurrentState[ind]; device.getPreviousState(PreviousState[ind]); DS4State pState = PreviousState[ind]; + if (pState.Battery != cState.Battery) + { Global.ControllerStatusChanged(this); + } + CheckForHotkeys(ind, cState, pState); if (eastertime) + { EasterTime(ind); + } + GetInputkeys(ind); + if (Global.getLSCurve(ind) + Global.getRSCurve(ind) + Global.getLSDeadzone(ind) + Global.getRSDeadzone(ind) + - Global.getL2Deadzone(ind) + Global.getR2Deadzone(ind) > 0) //if a curve or deadzone is in place + Global.getL2Deadzone(ind) + Global.getR2Deadzone(ind) > 0) + { + //if a curve or deadzone is in place cState = Mapping.SetCurveAndDeadzone(ind, cState); + } + if (!recordingMacro && (!string.IsNullOrEmpty(Global.tempprofilename[ind]) || Global.getHasCustomKeysorButtons(ind) || Global.getHasShiftCustomKeysorButtons(ind) || Global.GetProfileActions(ind).Count > 0)) { @@ -733,7 +751,9 @@ protected virtual void CheckForHotkeys(int deviceID, DS4State cState, DS4State p } } else - touchreleased[deviceID] = true; + { + touchreleased[deviceID] = true; + } } public virtual void StartTPOff(int deviceID) @@ -746,8 +766,8 @@ public virtual void StartTPOff(int deviceID) Global.setScrollSensitivity(deviceID, 0); } } - - public virtual string TouchpadSlide(int ind) + + public virtual string TouchpadSlideString(int ind) { DS4State cState = CurrentState[ind]; string slidedir = "none"; @@ -771,6 +791,32 @@ public virtual string TouchpadSlide(int ind) } return slidedir; } + + public virtual TouchpadSlideDirections TouchpadSlideEnum(int ind) + { + DS4State cState = CurrentState[ind]; + TouchpadSlideDirections slidedir = TouchpadSlideDirections.none; + if (DS4Controllers[ind] != null) + if (cState.Touch2) + if (DS4Controllers[ind] != null) + if (touchPad[ind].slideright && !touchslid[ind]) + { + slidedir = TouchpadSlideDirections.right; + touchslid[ind] = true; + } + else if (touchPad[ind].slideleft && !touchslid[ind]) + { + slidedir = TouchpadSlideDirections.left; + touchslid[ind] = true; + } + else if (!touchPad[ind].slideleft && !touchPad[ind].slideright) + { + slidedir = TouchpadSlideDirections.none; + touchslid[ind] = false; + } + return slidedir; + } + public virtual void LogDebug(String Data, bool warning = false) { Console.WriteLine(System.DateTime.Now.ToString("G") + "> " + Data); diff --git a/DS4Control/DS4Control.csproj b/DS4Control/DS4Control.csproj index a8120f6ec5..07a9d2b37d 100644 --- a/DS4Control/DS4Control.csproj +++ b/DS4Control/DS4Control.csproj @@ -45,6 +45,7 @@ + @@ -57,6 +58,7 @@ True Resources.resx + Component @@ -79,6 +81,9 @@ ScpHub.cs + + + diff --git a/DS4Control/Enums/TouchpadSlideDirections.cs b/DS4Control/Enums/TouchpadSlideDirections.cs new file mode 100644 index 0000000000..4a5c979419 --- /dev/null +++ b/DS4Control/Enums/TouchpadSlideDirections.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DS4Control.Enums +{ + public enum TouchpadSlideDirections + { + none = 0, + right, + left + } +} diff --git a/DS4Control/Mapping.cs b/DS4Control/Mapping.cs index 030a9b37ed..72a29c337f 100644 --- a/DS4Control/Mapping.cs +++ b/DS4Control/Mapping.cs @@ -55,6 +55,7 @@ public void SavePrevious(bool performClear) public static DateTime oldnow = DateTime.UtcNow; private static bool pressagain = false; private static int wheel = 0, keyshelddown = 0; + public static void Commit(int device) { SyntheticState state = deviceState[device]; @@ -329,20 +330,59 @@ static double TValue(double value1, double value2, double percent) return value1 * percent + value2 * (1 - percent); } + private static void ProccessCurveState(int curve, DS4State cState, DS4State dState) + { + int x = cState.LX; + int y = cState.LY; + + float max = x + y; + double curvex; + double curvey; + //curve = Global.getLSCurve(device); + double multimax = TValue(382.5, max, curve); + double multimin = TValue(127.5, max, curve); + if ((x > 127.5f && y > 127.5f) || (x < 127.5f && y < 127.5f)) + { + curvex = (x > 127.5f ? Math.Min(x, (x / max) * multimax) : Math.Max(x, (x / max) * multimin)); + curvey = (y > 127.5f ? Math.Min(y, (y / max) * multimax) : Math.Max(y, (y / max) * multimin)); + //btnLSTrack.Location = new Point((int)(dpix * curvex / 2.09 + lbLSTrack.Location.X), (int)(dpiy * curvey / 2.09 + lbLSTrack.Location.Y)); + } + else + { + if (x < 127.5f) + { + curvex = Math.Min(x, (x / max) * multimax); + curvey = Math.Min(y, (-(y / max) * multimax + 510)); + } + else + { + curvex = Math.Min(x, (-(x / max) * multimax + 510)); + curvey = Math.Min(y, (y / max) * multimax); + } + } + + dState.LX = (byte)Math.Round(curvex, 0); + dState.LY = (byte)Math.Round(curvey, 0); + } + public static DS4State SetCurveAndDeadzone(int device, DS4State cState) { + //Copy constructor... DS4State dState = new DS4State(cState); - int x; - int y; + + //int x; + //int y; int curve; - if (Global.getLSCurve(device) > 0) + if ((curve = Global.getLSCurve(device)) > 0) { + + /* x = cState.LX; y = cState.LY; float max = x + y; double curvex; double curvey; - curve = Global.getLSCurve(device); + //curve = Global.getLSCurve(device); double multimax = TValue(382.5, max, curve); double multimin = TValue(127.5, max, curve); if ((x > 127.5f && y > 127.5f) || (x < 127.5f && y < 127.5f)) @@ -365,10 +405,15 @@ public static DS4State SetCurveAndDeadzone(int device, DS4State cState) } } dState.LX = (byte)Math.Round(curvex, 0); - dState.LY = (byte)Math.Round(curvey, 0); + dState.LY = (byte)Math.Round(curvey, 0);*/ + + ProccessCurveState(curve, cState, dState); } - if (Global.getRSCurve(device) > 0) + + if ((curve = Global.getRSCurve(device)) > 0) { + + /* x = cState.RX; y = cState.RY; float max = x + y; @@ -377,6 +422,7 @@ public static DS4State SetCurveAndDeadzone(int device, DS4State cState) curve = Global.getRSCurve(device); double multimax = TValue(382.5, max, curve); double multimin = TValue(127.5, max, curve); + if ((x > 127.5f && y > 127.5f) || (x < 127.5f && y < 127.5f)) { curvex = (x > 127.5f ? Math.Min(x, (x / max) * multimax) : Math.Max(x, (x / max) * multimin)); @@ -396,30 +442,37 @@ public static DS4State SetCurveAndDeadzone(int device, DS4State cState) } } dState.RX = (byte)Math.Round(curvex, 0); - dState.RY = (byte)Math.Round(curvey, 0); + dState.RY = (byte)Math.Round(curvey, 0);*/ + + ProccessCurveState(curve, cState, dState); } + if (Global.getLSDeadzone(device) > 0 && Math.Sqrt(Math.Pow(cState.LX - 127.5f, 2) + Math.Pow(cState.LY - 127.5f, 2)) < Global.getLSDeadzone(device)) { dState.LX = 127; dState.LY = 127; } + if (Global.getRSDeadzone(device) > 0 && Math.Sqrt(Math.Pow(cState.RX - 127.5f, 2) + Math.Pow(cState.RY - 127.5f, 2)) < Global.getLSDeadzone(device)) { dState.RX = 127; dState.RY = 127; } + if (Global.getL2Deadzone(device) > 0 && cState.L2 < Global.getL2Deadzone(device)) dState.L2 = 0; if (Global.getR2Deadzone(device) > 0 && cState.R2 < Global.getR2Deadzone(device)) dState.R2 = 0; + return dState; } public static bool[] pressedonce = new bool[261], macrodone = new bool[34]; public static int test = 0; static bool[] macroControl = new bool[25]; + /// /// Map DS4 Buttons/Axes to other DS4 Buttons/Axes (largely the same as Xinput ones) and to keyboard and mouse buttons. /// @@ -463,7 +516,10 @@ public static async void MapCustom(int device, DS4State cState, DS4State MappedS } cState.CopyTo(MappedState); if (shift) - MapShiftCustom(device, cState, MappedState, eState, tp); + { + MapShiftCustom(device, cState, MappedState, eState, tp); + } + foreach (KeyValuePair customKey in Global.getCustomMacros(device)) { if (shift == false || @@ -497,27 +553,34 @@ public static async void MapCustom(int device, DS4State cState, DS4State MappedS if (!macrodone[DS4ControltoInt(customKey.Key)]) { macrodone[DS4ControltoInt(customKey.Key)] = true; + for (int i = 0; i < keys.Length; i++) { if (keys[i] >= 300) //ints over 300 used to delay + { await Task.Delay(keys[i] - 300); + } else if (!keydown[keys[i]]) { - if (keys[i] == 256) InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTDOWN); //anything above 255 is not a keyvalue + if (keys[i] == 256) + { + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTDOWN); //anything above 255 is not a keyvalue + } + else if (keys[i] == 257) InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTDOWN); else if (keys[i] == 258) InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEDOWN); else if (keys[i] == 259) InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 1); else if (keys[i] == 260) InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 2); - else if (keys[i] == 261) macroControl[0] = true; - else if (keys[i] == 262) macroControl[1] = true; - else if (keys[i] == 263) macroControl[2] = true; - else if (keys[i] == 264) macroControl[3] = true; - else if (keys[i] == 265) macroControl[4] = true; - else if (keys[i] == 266) macroControl[5] = true; - else if (keys[i] == 267) macroControl[6] = true; - else if (keys[i] == 268) macroControl[7] = true; - else if (keys[i] == 269) macroControl[8] = true; - else if (keys[i] == 270) macroControl[9] = true; + else if (keys[i] == 261) macroControl[0] = true; + else if (keys[i] == 262) macroControl[1] = true; + else if (keys[i] == 263) macroControl[2] = true; + else if (keys[i] == 264) macroControl[3] = true; + else if (keys[i] == 265) macroControl[4] = true; + else if (keys[i] == 266) macroControl[5] = true; + else if (keys[i] == 267) macroControl[6] = true; + else if (keys[i] == 268) macroControl[7] = true; + else if (keys[i] == 269) macroControl[8] = true; + else if (keys[i] == 270) macroControl[9] = true; else if (keys[i] == 271) macroControl[10] = true; else if (keys[i] == 272) macroControl[11] = true; else if (keys[i] == 273) macroControl[12] = true; @@ -541,21 +604,25 @@ public static async void MapCustom(int device, DS4State cState, DS4State MappedS } else { - if (keys[i] == 256) InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTUP); //anything above 255 is not a keyvalue + if (keys[i] == 256) + { + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTUP); //anything above 255 is not a keyvalue + } + else if (keys[i] == 257) InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTUP); else if (keys[i] == 258) InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEUP); else if (keys[i] == 259) InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 1); else if (keys[i] == 260) InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 2); - else if (keys[i] == 261) macroControl[0] = false; - else if (keys[i] == 262) macroControl[1] = false; - else if (keys[i] == 263) macroControl[2] = false; - else if (keys[i] == 264) macroControl[3] = false; - else if (keys[i] == 265) macroControl[4] = false; - else if (keys[i] == 266) macroControl[5] = false; - else if (keys[i] == 267) macroControl[6] = false; - else if (keys[i] == 268) macroControl[7] = false; - else if (keys[i] == 269) macroControl[8] = false; - else if (keys[i] == 270) macroControl[9] = false; + else if (keys[i] == 261) macroControl[0] = false; + else if (keys[i] == 262) macroControl[1] = false; + else if (keys[i] == 263) macroControl[2] = false; + else if (keys[i] == 264) macroControl[3] = false; + else if (keys[i] == 265) macroControl[4] = false; + else if (keys[i] == 266) macroControl[5] = false; + else if (keys[i] == 267) macroControl[6] = false; + else if (keys[i] == 268) macroControl[7] = false; + else if (keys[i] == 269) macroControl[8] = false; + else if (keys[i] == 270) macroControl[9] = false; else if (keys[i] == 271) macroControl[10] = false; else if (keys[i] == 272) macroControl[11] = false; else if (keys[i] == 273) macroControl[12] = false; @@ -695,6 +762,7 @@ public static async void MapCustom(int device, DS4State cState, DS4State MappedS List RXP = new List(); List RYN = new List(); List RYP = new List(); + foreach (KeyValuePair customButton in Global.getCustomButtons(device)) { if (shift == false || diff --git a/DS4Control/MouseWheel.cs b/DS4Control/MouseWheel.cs index d4b80bbd9d..9c682dce30 100644 --- a/DS4Control/MouseWheel.cs +++ b/DS4Control/MouseWheel.cs @@ -35,6 +35,7 @@ public void touchesMoved(TouchpadEventArgs arg) //mouse wheel 120 == 1 wheel click according to Windows API double lastMidX = (lastT0.hwX + lastT1.hwX) / 2d, lastMidY = (lastT0.hwY + lastT1.hwY) / 2d, currentMidX = (T0.hwX + T1.hwX) / 2d, currentMidY = (T0.hwY + T1.hwY) / 2d; + double coefficient = Global.getScrollSensitivity(deviceNumber); // Adjust for touch distance: "standard" distance is 960 pixels, i.e. half the width. Scroll farther if fingers are farther apart, and vice versa, in linear proportion. double touchXDistance = T1.hwX - T0.hwX, touchYDistance = T1.hwY - T0.hwY, touchDistance = Math.Sqrt(touchXDistance * touchXDistance + touchYDistance * touchYDistance); diff --git a/DS4Control/ScpUtil.cs b/DS4Control/ScpUtil.cs index 9e6354121e..a46f0f6681 100644 --- a/DS4Control/ScpUtil.cs +++ b/DS4Control/ScpUtil.cs @@ -8,6 +8,9 @@ using System.Drawing; using DS4Library; using System.Security.Principal; +using DS4Windows.XML_Files; +using System.Xml.Serialization; +using DS4Control.XML_FIles; namespace DS4Control { [Flags] @@ -1026,10 +1029,91 @@ public DS4KeyType GetShiftCustomKeyType(int device, DS4Controls controlName) catch { return 0; } } + private void CreateXMLNode(XmlNode parentNode, XmlDocument document, string name, string textData) + { + XmlNode newNode = m_Xdoc.CreateNode(XmlNodeType.Element, name, null); + newNode.InnerText = textData; + parentNode.AppendChild(newNode); + } + public Boolean SaveProfile(int device, String propath, System.Windows.Forms.Control[] buttons, System.Windows.Forms.Control[] shiftbuttons) { Boolean Saved = true; String path = Global.appdatapath + @"\Profiles\" + Path.GetFileNameWithoutExtension(propath) + ".xml"; + + //New System to replace save. Right now this is on hold while I clean up the existing implementation + //ProfileXML file = new ProfileXML + //{ + // flushHIDQueue = flushHIDQueue[device], + // idleDisconnectTimeout = idleDisconnectTimeout[device], + // color = new DS4Color + // { + // red = m_Leds[device][0], + // green = m_Leds[device][1], + // blue = m_Leds[device][2] + // }, + // RumbleBoost = rumble[device], + // ledAsBatteryIndicator = ledAsBattery[device], + // lowBatteryFlash = flashLedLowBattery[device], + // flashBatteryAt = flashAt[device], + // touchSensitivity = touchSensitivity[device], + // LowColor = new DS4Color + // { + // red = m_LowLeds[device][0], + // green = m_LowLeds[device][1], + // blue = m_LowLeds[device][2] + // }, + // ChargingColor = new DS4Color + // { + // red = m_ChargingLeds[device][0], + // green = m_ChargingLeds[device][1], + // blue = m_ChargingLeds[device][2] + // }, + // ShiftColor = new DS4Color + // { + // red = m_ShiftLeds[device][0], + // green = m_ShiftLeds[device][1], + // blue = m_ShiftLeds[device][2] + // }, + // ShiftColorOn = shiftColorOn[device], + // FlashColor = new DS4Color + // { + // red = m_FlashLeds[device][0], + // green = m_FlashLeds[device][1], + // blue = m_FlashLeds[device][2] + // }, + // touchpadJitterCompensation = touchpadJitterCompensation[device], + // lowerRCOn = lowerRCOn[device], + // tapSensitivity = tapSensitivity[device], + // doubleTap = doubleTap[device], + // scrollSensitivity = scrollSensitivity[device], + // LeftTriggerMiddle = l2Deadzone[device], + // RightTriggerMiddle = r2Deadzone[device], + // ButtonMouseSensitivity = buttonMouseSensitivity[device], + // Rainbow = rainbow[device], + // LSDeadZone = LSDeadzone[device], + // RSDeadZone = RSDeadzone[device], + // SXDeadZone = SXDeadzone[device], + // SZDeadZone = SZDeadzone[device], + // ChargingType = chargingType[device], + // MouseAcceleration = mouseAccel[device], + // ShiftModifier = shiftModifier[device], + // LaunchProgram = launchProgram[device], + // DinputOnly = dinputOnly[device], + // StartTouchpadOff = startTouchpadOff[device], + // UseTPforControls = useTPforControls[device], + // LSCurve = lsCurve[device], + // RSCurve = rsCurve[device], + // ProfileActions = profileActions[device], + // Controls = new List() + //}; + + //using (FileStream stream = new FileStream("testXML.xml", FileMode.Create)) + //{ + // XmlSerializer serializer = new XmlSerializer(typeof(ProfileXML)); + // serializer.Serialize(stream, file); + //} + try { XmlNode Node; @@ -1048,52 +1132,43 @@ public Boolean SaveProfile(int device, String propath, System.Windows.Forms.Cont Node = m_Xdoc.CreateNode(XmlNodeType.Element, "DS4Windows", null); - XmlNode xmlFlushHIDQueue = m_Xdoc.CreateNode(XmlNodeType.Element, "flushHIDQueue", null); xmlFlushHIDQueue.InnerText = flushHIDQueue[device].ToString(); Node.AppendChild(xmlFlushHIDQueue); - XmlNode xmlIdleDisconnectTimeout = m_Xdoc.CreateNode(XmlNodeType.Element, "idleDisconnectTimeout", null); xmlIdleDisconnectTimeout.InnerText = idleDisconnectTimeout[device].ToString(); Node.AppendChild(xmlIdleDisconnectTimeout); - XmlNode xmlColor = m_Xdoc.CreateNode(XmlNodeType.Element, "Color", null); - xmlColor.InnerText = m_Leds[device][0].ToString() + "," + m_Leds[device][1].ToString() + "," + m_Leds[device][2].ToString(); - Node.AppendChild(xmlColor); - XmlNode xmlRumbleBoost = m_Xdoc.CreateNode(XmlNodeType.Element, "RumbleBoost", null); xmlRumbleBoost.InnerText = rumble[device].ToString(); Node.AppendChild(xmlRumbleBoost); - XmlNode xmlLedAsBatteryIndicator = m_Xdoc.CreateNode(XmlNodeType.Element, "ledAsBatteryIndicator", null); xmlLedAsBatteryIndicator.InnerText = ledAsBattery[device].ToString(); Node.AppendChild(xmlLedAsBatteryIndicator); - XmlNode xmlLowBatteryFlash = m_Xdoc.CreateNode(XmlNodeType.Element, "lowBatteryFlash", null); xmlLowBatteryFlash.InnerText = flashLedLowBattery[device].ToString(); Node.AppendChild(xmlLowBatteryFlash); - XmlNode xmlFlashBatterAt = m_Xdoc.CreateNode(XmlNodeType.Element, "flashBatteryAt", null); xmlFlashBatterAt.InnerText = flashAt[device].ToString(); Node.AppendChild(xmlFlashBatterAt); - XmlNode xmlTouchSensitivity = m_Xdoc.CreateNode(XmlNodeType.Element, "touchSensitivity", null); xmlTouchSensitivity.InnerText = touchSensitivity[device].ToString(); Node.AppendChild(xmlTouchSensitivity); - XmlNode xmlLowColor = m_Xdoc.CreateNode(XmlNodeType.Element, "LowColor", null); - xmlLowColor.InnerText = m_LowLeds[device][0].ToString() + "," + m_LowLeds[device][1].ToString() + "," + m_LowLeds[device][2].ToString(); - Node.AppendChild(xmlLowColor); - XmlNode xmlChargingColor = m_Xdoc.CreateNode(XmlNodeType.Element, "ChargingColor", null); - xmlChargingColor.InnerText = m_ChargingLeds[device][0].ToString() + "," + m_ChargingLeds[device][1].ToString() + "," + m_ChargingLeds[device][2].ToString(); - Node.AppendChild(xmlChargingColor); - XmlNode xmlShiftColor = m_Xdoc.CreateNode(XmlNodeType.Element, "ShiftColor", null); - xmlShiftColor.InnerText = m_ShiftLeds[device][0].ToString() + "," + m_ShiftLeds[device][1].ToString() + "," + m_ShiftLeds[device][2].ToString(); - Node.AppendChild(xmlShiftColor); - XmlNode xmlShiftColorOn = m_Xdoc.CreateNode(XmlNodeType.Element, "ShiftColorOn", null); xmlShiftColorOn.InnerText = shiftColorOn[device].ToString(); Node.AppendChild(xmlShiftColorOn); - XmlNode xmlFlashColor = m_Xdoc.CreateNode(XmlNodeType.Element, "FlashColor", null); - xmlFlashColor.InnerText = m_FlashLeds[device][0].ToString() + "," + m_FlashLeds[device][1].ToString() + "," + m_FlashLeds[device][2].ToString(); - Node.AppendChild(xmlFlashColor); - XmlNode xmlTouchpadJitterCompensation = m_Xdoc.CreateNode(XmlNodeType.Element, "touchpadJitterCompensation", null); xmlTouchpadJitterCompensation.InnerText = touchpadJitterCompensation[device].ToString(); Node.AppendChild(xmlTouchpadJitterCompensation); - XmlNode xmlLowerRCOn = m_Xdoc.CreateNode(XmlNodeType.Element, "lowerRCOn", null); xmlLowerRCOn.InnerText = lowerRCOn[device].ToString(); Node.AppendChild(xmlLowerRCOn); - XmlNode xmlTapSensitivity = m_Xdoc.CreateNode(XmlNodeType.Element, "tapSensitivity", null); xmlTapSensitivity.InnerText = tapSensitivity[device].ToString(); Node.AppendChild(xmlTapSensitivity); - XmlNode xmlDouble = m_Xdoc.CreateNode(XmlNodeType.Element, "doubleTap", null); xmlDouble.InnerText = doubleTap[device].ToString(); Node.AppendChild(xmlDouble); - XmlNode xmlScrollSensitivity = m_Xdoc.CreateNode(XmlNodeType.Element, "scrollSensitivity", null); xmlScrollSensitivity.InnerText = scrollSensitivity[device].ToString(); Node.AppendChild(xmlScrollSensitivity); - XmlNode xmlLeftTriggerMiddle = m_Xdoc.CreateNode(XmlNodeType.Element, "LeftTriggerMiddle", null); xmlLeftTriggerMiddle.InnerText = l2Deadzone[device].ToString(); Node.AppendChild(xmlLeftTriggerMiddle); - XmlNode xmlRightTriggerMiddle = m_Xdoc.CreateNode(XmlNodeType.Element, "RightTriggerMiddle", null); xmlRightTriggerMiddle.InnerText = r2Deadzone[device].ToString(); Node.AppendChild(xmlRightTriggerMiddle); - XmlNode xmlButtonMouseSensitivity = m_Xdoc.CreateNode(XmlNodeType.Element, "ButtonMouseSensitivity", null); xmlButtonMouseSensitivity.InnerText = buttonMouseSensitivity[device].ToString(); Node.AppendChild(xmlButtonMouseSensitivity); - XmlNode xmlRainbow = m_Xdoc.CreateNode(XmlNodeType.Element, "Rainbow", null); xmlRainbow.InnerText = rainbow[device].ToString(); Node.AppendChild(xmlRainbow); - XmlNode xmlLSD = m_Xdoc.CreateNode(XmlNodeType.Element, "LSDeadZone", null); xmlLSD.InnerText = LSDeadzone[device].ToString(); Node.AppendChild(xmlLSD); - XmlNode xmlRSD = m_Xdoc.CreateNode(XmlNodeType.Element, "RSDeadZone", null); xmlRSD.InnerText = RSDeadzone[device].ToString(); Node.AppendChild(xmlRSD); - XmlNode xmlSXD = m_Xdoc.CreateNode(XmlNodeType.Element, "SXDeadZone", null); xmlSXD.InnerText = SXDeadzone[device].ToString(); Node.AppendChild(xmlSXD); - XmlNode xmlSZD = m_Xdoc.CreateNode(XmlNodeType.Element, "SZDeadZone", null); xmlSZD.InnerText = SZDeadzone[device].ToString(); Node.AppendChild(xmlSZD); - XmlNode xmlChargingType = m_Xdoc.CreateNode(XmlNodeType.Element, "ChargingType", null); xmlChargingType.InnerText = chargingType[device].ToString(); Node.AppendChild(xmlChargingType); - XmlNode xmlMouseAccel = m_Xdoc.CreateNode(XmlNodeType.Element, "MouseAcceleration", null); xmlMouseAccel.InnerText = mouseAccel[device].ToString(); Node.AppendChild(xmlMouseAccel); - XmlNode xmlShiftMod = m_Xdoc.CreateNode(XmlNodeType.Element, "ShiftModifier", null); xmlShiftMod.InnerText = shiftModifier[device].ToString(); Node.AppendChild(xmlShiftMod); - XmlNode xmlLaunchProgram = m_Xdoc.CreateNode(XmlNodeType.Element, "LaunchProgram", null); xmlLaunchProgram.InnerText = launchProgram[device].ToString(); Node.AppendChild(xmlLaunchProgram); - XmlNode xmlDinput = m_Xdoc.CreateNode(XmlNodeType.Element, "DinputOnly", null); xmlDinput.InnerText = dinputOnly[device].ToString(); Node.AppendChild(xmlDinput); - XmlNode xmlStartTouchpadOff = m_Xdoc.CreateNode(XmlNodeType.Element, "StartTouchpadOff", null); xmlStartTouchpadOff.InnerText = startTouchpadOff[device].ToString(); Node.AppendChild(xmlStartTouchpadOff); - XmlNode xmlUseTPforControls = m_Xdoc.CreateNode(XmlNodeType.Element, "UseTPforControls", null); xmlUseTPforControls.InnerText = useTPforControls[device].ToString(); Node.AppendChild(xmlUseTPforControls); - XmlNode xmlLSC = m_Xdoc.CreateNode(XmlNodeType.Element, "LSCurve", null); xmlLSC.InnerText = lsCurve[device].ToString(); Node.AppendChild(xmlLSC); - XmlNode xmlRSC = m_Xdoc.CreateNode(XmlNodeType.Element, "RSCurve", null); xmlRSC.InnerText = rsCurve[device].ToString(); Node.AppendChild(xmlRSC); - XmlNode xmlProfileActions = m_Xdoc.CreateNode(XmlNodeType.Element, "ProfileActions", null); xmlProfileActions.InnerText = string.Join("/", profileActions[device]); Node.AppendChild(xmlProfileActions); + this.CreateXMLNode(Node, m_Xdoc, "flushHIDQueue", flushHIDQueue[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "idleDisconnectTimeout", idleDisconnectTimeout[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "Color", m_Leds[device][0].ToString() + "," + m_Leds[device][1].ToString() + "," + m_Leds[device][2].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "RumbleBoost", rumble[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "ledAsBatteryIndicator", ledAsBattery[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "lowBatteryFlash", flashLedLowBattery[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "flashBatteryAt", flashAt[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "touchSensitivity", touchSensitivity[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "LowColor", m_LowLeds[device][0].ToString() + "," + m_LowLeds[device][1].ToString() + "," + m_LowLeds[device][2].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "ChargingColor", m_ChargingLeds[device][0].ToString() + "," + m_ChargingLeds[device][1].ToString() + "," + m_ChargingLeds[device][2].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "ShiftColor", m_ShiftLeds[device][0].ToString() + "," + m_ShiftLeds[device][1].ToString() + "," + m_ShiftLeds[device][2].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "ShiftColorOn", shiftColorOn[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "FlashColor", m_FlashLeds[device][0].ToString() + "," + m_FlashLeds[device][1].ToString() + "," + m_FlashLeds[device][2].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "touchpadJitterCompensation", touchpadJitterCompensation[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "lowerRCOn", lowerRCOn[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "tapSensitivity", tapSensitivity[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "doubleTap", doubleTap[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "scrollSensitivity", scrollSensitivity[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "LeftTriggerMiddle", l2Deadzone[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "RightTriggerMiddle", r2Deadzone[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "ButtonMouseSensitivity", buttonMouseSensitivity[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "Rainbow", rainbow[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "LSDeadZone", LSDeadzone[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "RSDeadZone", RSDeadzone[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "SXDeadZone", SXDeadzone[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "SZDeadZone", SZDeadzone[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "ChargingType", chargingType[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "MouseAcceleration", mouseAccel[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "ShiftModifier", shiftModifier[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "LaunchProgram", launchProgram[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "DinputOnly", dinputOnly[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "StartTouchpadOff", startTouchpadOff[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "UseTPforControls", useTPforControls[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "LSCurve", lsCurve[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "RSCurve", rsCurve[device].ToString()); + this.CreateXMLNode(Node, m_Xdoc, "ProfileActions", string.Join("/", profileActions[device])); + XmlNode NodeControl = m_Xdoc.CreateNode(XmlNodeType.Element, "Control", null); XmlNode Key = m_Xdoc.CreateNode(XmlNodeType.Element, "Key", null); @@ -1101,93 +1176,16 @@ public Boolean SaveProfile(int device, String propath, System.Windows.Forms.Cont XmlNode KeyType = m_Xdoc.CreateNode(XmlNodeType.Element, "KeyType", null); XmlNode Button = m_Xdoc.CreateNode(XmlNodeType.Element, "Button", null); XmlNode Extras = m_Xdoc.CreateNode(XmlNodeType.Element, "Extras", null); + if (buttons != null) { - foreach (var button in buttons) - { - // Save even if string (for xbox controller buttons) - if (button.Tag != null) - { - XmlNode buttonNode; - string keyType = String.Empty; - - if (button.Tag is KeyValuePair) - if (((KeyValuePair)button.Tag).Key == "Unbound") - keyType += DS4KeyType.Unbound; - - if (button.Font.Strikeout) - keyType += DS4KeyType.HoldMacro; - if (button.Font.Underline) - keyType += DS4KeyType.Macro; - if (button.Font.Italic) - keyType += DS4KeyType.Toggle; - if (button.Font.Bold) - keyType += DS4KeyType.ScanCode; - if (keyType != String.Empty) - { - buttonNode = m_Xdoc.CreateNode(XmlNodeType.Element, button.Name, null); - buttonNode.InnerText = keyType; - KeyType.AppendChild(buttonNode); - } - - string[] extras; - buttonNode = m_Xdoc.CreateNode(XmlNodeType.Element, button.Name, null); - if (button.Tag is KeyValuePair, string> || button.Tag is KeyValuePair || button.Tag is KeyValuePair) - { - KeyValuePair tag = (KeyValuePair)button.Tag; - int[] ii = tag.Key; - buttonNode.InnerText = string.Join("/", ii); - Macro.AppendChild(buttonNode); - extras = tag.Value.Split(','); - } - else if (button.Tag is KeyValuePair || button.Tag is KeyValuePair || button.Tag is KeyValuePair) - { - KeyValuePair tag = (KeyValuePair)button.Tag; - buttonNode.InnerText = tag.Key.ToString(); - Key.AppendChild(buttonNode); - extras = tag.Value.Split(','); - } - else if (button.Tag is KeyValuePair) - { - KeyValuePair tag = (KeyValuePair)button.Tag; - buttonNode.InnerText = tag.Key; - Button.AppendChild(buttonNode); - extras = tag.Value.Split(','); - } - else - { - KeyValuePair tag = (KeyValuePair)button.Tag; - extras = tag.Value.Split(','); - } - bool hasvalue = false; - foreach (string s in extras) - if (s != "0") - { - hasvalue = true; - break; - } - if (hasvalue) - { - XmlNode extraNode = m_Xdoc.CreateNode(XmlNodeType.Element, button.Name, null); - extraNode.InnerText = String.Join(",", extras); - Extras.AppendChild(extraNode); - } - } - } - Node.AppendChild(NodeControl); - if (Button.HasChildNodes) - NodeControl.AppendChild(Button); - if (Macro.HasChildNodes) - NodeControl.AppendChild(Macro); - if (Key.HasChildNodes) - NodeControl.AppendChild(Key); - if (Extras.HasChildNodes) - NodeControl.AppendChild(Extras); - if (KeyType.HasChildNodes) - NodeControl.AppendChild(KeyType); + SaveButtons(shiftbuttons, Node, NodeControl, Key, Macro, KeyType, Button, Extras); } else if (xmlControls != null) + { Node.AppendChild(xmlControls); + } + if (shiftModifier[device] > 0) { XmlNode NodeShiftControl = m_Xdoc.CreateNode(XmlNodeType.Element, "ShiftControl", null); @@ -1199,85 +1197,7 @@ public Boolean SaveProfile(int device, String propath, System.Windows.Forms.Cont XmlNode ShiftExtras = m_Xdoc.CreateNode(XmlNodeType.Element, "Extras", null); if (shiftbuttons != null) { - foreach (var button in shiftbuttons) - { - // Save even if string (for xbox controller buttons) - if (button.Tag != null) - { - XmlNode buttonNode; - string keyType = String.Empty; - if (button.Tag is KeyValuePair) - if (((KeyValuePair)button.Tag).Key == "Unbound") - keyType += DS4KeyType.Unbound; - - if (button.Font.Strikeout) - keyType += DS4KeyType.HoldMacro; - if (button.Font.Underline) - keyType += DS4KeyType.Macro; - if (button.Font.Italic) - keyType += DS4KeyType.Toggle; - if (button.Font.Bold) - keyType += DS4KeyType.ScanCode; - if (keyType != String.Empty) - { - buttonNode = m_Xdoc.CreateNode(XmlNodeType.Element, button.Name, null); - buttonNode.InnerText = keyType; - ShiftKeyType.AppendChild(buttonNode); - } - - string[] extras; - buttonNode = m_Xdoc.CreateNode(XmlNodeType.Element, button.Name, null); - if (button.Tag is KeyValuePair, string> || button.Tag is KeyValuePair || button.Tag is KeyValuePair) - { - KeyValuePair tag = (KeyValuePair)button.Tag; - int[] ii = tag.Key; - buttonNode.InnerText = string.Join("/", ii); - ShiftMacro.AppendChild(buttonNode); - extras = tag.Value.Split(','); - } - else if (button.Tag is KeyValuePair || button.Tag is KeyValuePair || button.Tag is KeyValuePair) - { - KeyValuePair tag = (KeyValuePair)button.Tag; - buttonNode.InnerText = tag.Key.ToString(); - ShiftKey.AppendChild(buttonNode); - extras = tag.Value.Split(','); - } - else if (button.Tag is KeyValuePair) - { - KeyValuePair tag = (KeyValuePair)button.Tag; - buttonNode.InnerText = tag.Key; - ShiftButton.AppendChild(buttonNode); - extras = tag.Value.Split(','); - } - else - { - KeyValuePair tag = (KeyValuePair)button.Tag; - extras = tag.Value.Split(','); - } - bool hasvalue = false; - foreach (string s in extras) - if (s != "0") - { - hasvalue = true; - break; - } - if (hasvalue && !string.IsNullOrEmpty(String.Join(",", extras))) - { - XmlNode extraNode = m_Xdoc.CreateNode(XmlNodeType.Element, button.Name, null); - extraNode.InnerText = String.Join(",", extras); - ShiftExtras.AppendChild(extraNode); - } - } - } - Node.AppendChild(NodeShiftControl); - if (ShiftButton.HasChildNodes) - NodeShiftControl.AppendChild(ShiftButton); - if (ShiftMacro.HasChildNodes) - NodeShiftControl.AppendChild(ShiftMacro); - if (ShiftKey.HasChildNodes) - NodeShiftControl.AppendChild(ShiftKey); - if (ShiftKeyType.HasChildNodes) - NodeShiftControl.AppendChild(ShiftKeyType); + SaveButtons(shiftbuttons, Node, NodeShiftControl, ShiftKey, ShiftMacro, ShiftKeyType, ShiftButton, ShiftExtras); } else if (xmlShiftControls != null) Node.AppendChild(xmlShiftControls); @@ -1290,6 +1210,90 @@ public Boolean SaveProfile(int device, String propath, System.Windows.Forms.Cont catch { Saved = false; } return Saved; } + + private void SaveButtons(System.Windows.Forms.Control[] buttons, XmlNode node, XmlNode control, XmlNode Key, XmlNode Macro, XmlNode KeyType, XmlNode Button, XmlNode Extras) + { + foreach (var button in buttons) + { + if (button.Tag != null) + { + XmlNode buttonNode; + string keyType = String.Empty; + if (button.Tag is KeyValuePair) + if (((KeyValuePair)button.Tag).Key == "Unbound") + keyType += DS4KeyType.Unbound; + + if (button.Font.Strikeout) + keyType += DS4KeyType.HoldMacro; + if (button.Font.Underline) + keyType += DS4KeyType.Macro; + if (button.Font.Italic) + keyType += DS4KeyType.Toggle; + if (button.Font.Bold) + keyType += DS4KeyType.ScanCode; + if (keyType != String.Empty) + { + buttonNode = m_Xdoc.CreateNode(XmlNodeType.Element, button.Name, null); + buttonNode.InnerText = keyType; + KeyType.AppendChild(buttonNode); + } + + string[] extras; + buttonNode = m_Xdoc.CreateNode(XmlNodeType.Element, button.Name, null); + if (button.Tag is KeyValuePair, string> || button.Tag is KeyValuePair || button.Tag is KeyValuePair) + { + KeyValuePair tag = (KeyValuePair)button.Tag; + int[] ii = tag.Key; + buttonNode.InnerText = string.Join("/", ii); + Macro.AppendChild(buttonNode); + extras = tag.Value.Split(','); + } + else if (button.Tag is KeyValuePair || button.Tag is KeyValuePair || button.Tag is KeyValuePair) + { + KeyValuePair tag = (KeyValuePair)button.Tag; + buttonNode.InnerText = tag.Key.ToString(); + Key.AppendChild(buttonNode); + extras = tag.Value.Split(','); + } + else if (button.Tag is KeyValuePair) + { + KeyValuePair tag = (KeyValuePair)button.Tag; + buttonNode.InnerText = tag.Key; + Button.AppendChild(buttonNode); + extras = tag.Value.Split(','); + } + else + { + KeyValuePair tag = (KeyValuePair)button.Tag; + extras = tag.Value.Split(','); + } + bool hasvalue = false; + foreach (string s in extras) + if (s != "0") + { + hasvalue = true; + break; + } + if (hasvalue && !string.IsNullOrEmpty(String.Join(",", extras))) + { + XmlNode extraNode = m_Xdoc.CreateNode(XmlNodeType.Element, button.Name, null); + extraNode.InnerText = String.Join(",", extras); + Extras.AppendChild(extraNode); + } + } + } + + node.AppendChild(control); + if (Button.HasChildNodes) + control.AppendChild(Button); + if (Macro.HasChildNodes) + control.AppendChild(Macro); + if (Key.HasChildNodes) + control.AppendChild(Key); + if (KeyType.HasChildNodes) + control.AppendChild(KeyType); + } + private DS4Controls getDS4ControlsByName(string key) { switch (key) @@ -1486,6 +1490,7 @@ public Boolean LoadProfile(int device, System.Windows.Forms.Control[] buttons, S Dictionary shiftCustomMapButtons = new Dictionary(); Dictionary shiftCustomMapMacros = new Dictionary(); Dictionary shiftCustomMapExtras = new Dictionary(); + string rootname = "DS4Windows"; Boolean missingSetting = false; string profilepath; diff --git a/DS4Control/Tools/XMLFile.cs b/DS4Control/Tools/XMLFile.cs new file mode 100644 index 0000000000..0735b277fa --- /dev/null +++ b/DS4Control/Tools/XMLFile.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DS4Control.Tools +{ + class XMLFile + { + + } +} diff --git a/DS4Control/XML FIles/ControlXML.cs b/DS4Control/XML FIles/ControlXML.cs new file mode 100644 index 0000000000..f3d5531aee --- /dev/null +++ b/DS4Control/XML FIles/ControlXML.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DS4Control.XML_FIles +{ + struct Key + { + public string name { get; set; } + public int type { get; set; } + } + + public class ControlXML + { + public string Name { get; set; } + + public int Key { get; set; } + public int KeyType { get; set; } + public List Macro { get; set; } + public string Button { get; set; } + public string Extras { get; set; } + } +} diff --git a/DS4Control/XML FIles/KeyXML.cs b/DS4Control/XML FIles/KeyXML.cs new file mode 100644 index 0000000000..86e8e62a90 --- /dev/null +++ b/DS4Control/XML FIles/KeyXML.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DS4Control.XML_FIles +{ + class KeyXML + { + } +} diff --git a/DS4Control/XML FIles/ProfileXML.cs b/DS4Control/XML FIles/ProfileXML.cs new file mode 100644 index 0000000000..cf2c848022 --- /dev/null +++ b/DS4Control/XML FIles/ProfileXML.cs @@ -0,0 +1,56 @@ +using DS4Control.XML_FIles; +using DS4Library; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace DS4Windows.XML_Files +{ + [Serializable] + public class ProfileXML + { + public bool flushHIDQueue { get; set; } + public int idleDisconnectTimeout { get; set; } + public DS4Color color { get; set; } + public int RumbleBoost { get; set; } + public bool ledAsBatteryIndicator { get; set; } + public bool lowBatteryFlash { get; set; } + public int flashBatteryAt { get; set; } + public int touchSensitivity { get; set; } + public DS4Color LowColor { get; set; } + public DS4Color ChargingColor { get; set; } + public DS4Color ShiftColor { get; set; } + public bool ShiftColorOn { get; set; } + public DS4Color FlashColor { get; set; } + public bool touchpadJitterCompensation { get; set; } + public bool lowerRCOn { get; set; } + public int tapSensitivity { get; set; } + public bool doubleTap { get; set; } + public int scrollSensitivity { get; set; } + public int LeftTriggerMiddle { get; set; } + public int RightTriggerMiddle { get; set; } + public int ButtonMouseSensitivity { get; set; } + public double Rainbow { get; set; } + public double LSDeadZone { get; set; } + public double RSDeadZone { get; set; } + public double SXDeadZone { get; set; } + public double SZDeadZone { get; set; } + public double ChargingType { get; set; } + public bool MouseAcceleration { get; set; } + public double ShiftModifier { get; set; } + public bool DinputOnly { get; set; } + public bool StartTouchpadOff { get; set; } + public bool UseTPforControls { get; set; } + public double LSCurve { get; set; } + public double RSCurve { get; set; } + public List ProfileActions { get; set; } + + public string LaunchProgram { get; set; } + + public List Controls; + } +} diff --git a/DS4Library/DS4Device.cs b/DS4Library/DS4Device.cs index 373f217a13..888f56825f 100644 --- a/DS4Library/DS4Device.cs +++ b/DS4Library/DS4Device.cs @@ -62,6 +62,8 @@ public bool IsRumbleSet() public class DS4Device { + private enum InputLoopStatus { OK, DISCONNECTED }; + private const int BT_OUTPUT_REPORT_LENGTH = 78; private const int BT_INPUT_REPORT_LENGTH = 547; private HidDevice hDevice; @@ -166,6 +168,7 @@ public DS4Device(HidDevice hidDevice) hDevice = hidDevice; conType = HidConnectionType(hDevice); Mac = hDevice.readSerial(); + if (conType == ConnectionType.USB) { inputReport = new byte[64]; @@ -196,7 +199,9 @@ public void StartUpdate() ds4Input.Start(); } else + { Console.WriteLine("Thread already running for DS4: " + Mac); + } } public void StopUpdate() @@ -277,62 +282,163 @@ public bool IsAlive() { return priorInputReport30 != 0xff; } + private byte priorInputReport30 = 0xff; - public double Latency = 0; + public double Latency = 0.0d; bool warn; - public string error; + public List currentErrors = new List(); + const double LATENCY_THRESHOLD = 10.0d; + + public void BuildCurrentState(byte[] inputReport) + { + DateTime utcNow = System.DateTime.UtcNow; + + cState.ReportTimeStamp = utcNow; + cState.LX = inputReport[1]; + cState.LY = inputReport[2]; + cState.RX = inputReport[3]; + cState.RY = inputReport[4]; + cState.L2 = inputReport[8]; + cState.R2 = inputReport[9]; + + cState.Triangle = ((byte)inputReport[5] & (1 << 7)) != 0; + cState.Circle = ((byte)inputReport[5] & (1 << 6)) != 0; + cState.Cross = ((byte)inputReport[5] & (1 << 5)) != 0; + cState.Square = ((byte)inputReport[5] & (1 << 4)) != 0; + cState.DpadUp = ((byte)inputReport[5] & (1 << 3)) != 0; + cState.DpadDown = ((byte)inputReport[5] & (1 << 2)) != 0; + cState.DpadLeft = ((byte)inputReport[5] & (1 << 1)) != 0; + cState.DpadRight = ((byte)inputReport[5] & (1 << 0)) != 0; + + //Convert dpad into individual On/Off bits instead of a clock representation + byte dpad_state = 0; + + dpad_state = (byte)( + ((cState.DpadRight ? 1 : 0) << 0) | + ((cState.DpadLeft ? 1 : 0) << 1) | + ((cState.DpadDown ? 1 : 0) << 2) | + ((cState.DpadUp ? 1 : 0) << 3)); + + switch (dpad_state) + { + case 0: cState.DpadUp = true; cState.DpadDown = false; cState.DpadLeft = false; cState.DpadRight = false; break; + case 1: cState.DpadUp = true; cState.DpadDown = false; cState.DpadLeft = false; cState.DpadRight = true; break; + case 2: cState.DpadUp = false; cState.DpadDown = false; cState.DpadLeft = false; cState.DpadRight = true; break; + case 3: cState.DpadUp = false; cState.DpadDown = true; cState.DpadLeft = false; cState.DpadRight = true; break; + case 4: cState.DpadUp = false; cState.DpadDown = true; cState.DpadLeft = false; cState.DpadRight = false; break; + case 5: cState.DpadUp = false; cState.DpadDown = true; cState.DpadLeft = true; cState.DpadRight = false; break; + case 6: cState.DpadUp = false; cState.DpadDown = false; cState.DpadLeft = true; cState.DpadRight = false; break; + case 7: cState.DpadUp = true; cState.DpadDown = false; cState.DpadLeft = true; cState.DpadRight = false; break; + case 8: cState.DpadUp = false; cState.DpadDown = false; cState.DpadLeft = false; cState.DpadRight = false; break; + } + + cState.R3 = ((byte)inputReport[6] & (1 << 7)) != 0; + cState.L3 = ((byte)inputReport[6] & (1 << 6)) != 0; + cState.Options = ((byte)inputReport[6] & (1 << 5)) != 0; + cState.Share = ((byte)inputReport[6] & (1 << 4)) != 0; + cState.R1 = ((byte)inputReport[6] & (1 << 1)) != 0; + cState.L1 = ((byte)inputReport[6] & (1 << 0)) != 0; + + cState.PS = ((byte)inputReport[7] & (1 << 0)) != 0; + cState.TouchButton = (inputReport[7] & (1 << 2 - 1)) != 0; + cState.FrameCounter = (byte)(inputReport[7] >> 2); + + // Store Gyro and Accel values + Array.Copy(inputReport, 14, accel, 0, 6); + Array.Copy(inputReport, 20, gyro, 0, 6); + + try + { + charging = (inputReport[30] & 0x10) != 0; + battery = (inputReport[30] & 0x0f) * 10; + cState.Battery = (byte)battery; + if (inputReport[30] != priorInputReport30) + { + priorInputReport30 = inputReport[30]; + Console.WriteLine(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + "> power subsystem octet: 0x" + inputReport[30].ToString("x02")); + } + } + catch + { + currentErrors.Add("Index out of bounds: battery"); + } + + // XXX DS4State mapping needs fixup, turn touches into an array[4] of structs. And include the touchpad details there instead. + try + { + + for (int touches = inputReport[-1 + DS4Touchpad.TOUCHPAD_DATA_OFFSET - 1], touchOffset = 0; touches > 0; touches--, touchOffset += 9) + { + cState.TouchPacketCounter = inputReport[-1 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset]; + cState.Touch1 = (inputReport[0 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] >> 7) != 0 ? false : true; // >= 1 touch detected + cState.Touch1Identifier = (byte)(inputReport[0 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] & 0x7f); + cState.Touch2 = (inputReport[4 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] >> 7) != 0 ? false : true; // 2 touches detected + cState.Touch2Identifier = (byte)(inputReport[4 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] & 0x7f); + cState.TouchLeft = (inputReport[1 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] + ((inputReport[2 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] & 0xF) * 255) >= 1920 * 2 / 5) ? false : true; + cState.TouchRight = (inputReport[1 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] + ((inputReport[2 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] & 0xF) * 255) < 1920 * 2 / 5) ? false : true; + // Even when idling there is still a touch packet indicating no touch 1 or 2 + touchpad.handleTouchpad(inputReport, cState, touchOffset); + } + } + catch + { + currentErrors.Add("Index out of bounds: touchpad"); + } + } + private void performDs4Input() { System.Timers.Timer readTimeout = new System.Timers.Timer(); // Await 30 seconds for the initial packet, then 3 seconds thereafter. readTimeout.Elapsed += delegate { HidDevice.CancelIO(); }; - List Latency = new List(); + readTimeout.Interval = 3000.0d; + long oldtime = 0; Stopwatch sw = new Stopwatch(); sw.Start(); - while (true) + + LatencyCounter latencyCounter = new LatencyCounter(200); + + InputLoopStatus status = InputLoopStatus.OK; + + //OK you should never have a while(true) statement. A condition should still allow it to exit + while (status == InputLoopStatus.OK) { string currerror = string.Empty; - Latency.Add(sw.ElapsedMilliseconds - oldtime); + latencyCounter.PushLatencyReading(sw.ElapsedMilliseconds - oldtime); + this.Latency = latencyCounter.Latency; oldtime = sw.ElapsedMilliseconds; - if (Latency.Count > 100) - Latency.RemoveAt(0); - - this.Latency = Latency.Average(); - - if (this.Latency > 10 && !warn && sw.ElapsedMilliseconds > 4000) + warn = false; + if (this.Latency > LATENCY_THRESHOLD) { warn = true; - //System.Diagnostics.Trace.WriteLine(System.DateTime.UtcNow.ToString("o") + "> " + "Controller " + /*this.DeviceNum*/ + 1 + " (" + this.MacAddress + ") is experiencing latency issues. Currently at " + Math.Round(this.Latency, 2).ToString() + "ms of recomended maximum 10ms"); } - else if (this.Latency <= 10 && warn) warn = false; - if (readTimeout.Interval != 3000.0) - { - if (readTimeout.Interval != 30000.0) - readTimeout.Interval = 30000.0; - else - readTimeout.Interval = 3000.0; - } readTimeout.Enabled = true; if (conType != ConnectionType.USB) { HidDevice.ReadStatus res = hDevice.ReadFile(btInputReport); readTimeout.Enabled = false; + if (res == HidDevice.ReadStatus.Success) { Array.Copy(btInputReport, 2, inputReport, 0, inputReport.Length); } else { - Console.WriteLine(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + "> disconnect due to read failure: " + Marshal.GetLastWin32Error()); - sendOutputReport(true); // Kick Windows into noticing the disconnection. + this.currentErrors.Add(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + "> disconnect due to read failure: " + Marshal.GetLastWin32Error()); + + sendOutputReport(synchronous:true); // Kick Windows into noticing the disconnection. StopOutputUpdate(); IsDisconnecting = true; + if (Removal != null) + { Removal(this, EventArgs.Empty); - return; + } + status = InputLoopStatus.DISCONNECTED; + continue; } } else @@ -341,116 +447,35 @@ private void performDs4Input() readTimeout.Enabled = false; if (res != HidDevice.ReadStatus.Success) { - Console.WriteLine(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + "> disconnect due to read failure: " + Marshal.GetLastWin32Error()); + //Console.WriteLine(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + "> disconnect due to read failure: " + Marshal.GetLastWin32Error()); + this.currentErrors.Add(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + "> disconnect due to read failure: " + Marshal.GetLastWin32Error()); + StopOutputUpdate(); IsDisconnecting = true; if (Removal != null) + { Removal(this, EventArgs.Empty); - return; + } + + status = InputLoopStatus.DISCONNECTED; + continue; } } + if (ConnectionType == ConnectionType.BT && btInputReport[0] != 0x11) { //Received incorrect report, skip it continue; } - DateTime utcNow = System.DateTime.UtcNow; // timestamp with UTC in case system time zone changes - resetHapticState(); - cState.ReportTimeStamp = utcNow; - cState.LX = inputReport[1]; - cState.LY = inputReport[2]; - cState.RX = inputReport[3]; - cState.RY = inputReport[4]; - cState.L2 = inputReport[8]; - cState.R2 = inputReport[9]; - - cState.Triangle = ((byte)inputReport[5] & (1 << 7)) != 0; - cState.Circle = ((byte)inputReport[5] & (1 << 6)) != 0; - cState.Cross = ((byte)inputReport[5] & (1 << 5)) != 0; - cState.Square = ((byte)inputReport[5] & (1 << 4)) != 0; - cState.DpadUp = ((byte)inputReport[5] & (1 << 3)) != 0; - cState.DpadDown = ((byte)inputReport[5] & (1 << 2)) != 0; - cState.DpadLeft = ((byte)inputReport[5] & (1 << 1)) != 0; - cState.DpadRight = ((byte)inputReport[5] & (1 << 0)) != 0; - - //Convert dpad into individual On/Off bits instead of a clock representation - byte dpad_state = 0; - - dpad_state = (byte)( - ((cState.DpadRight ? 1 : 0) << 0) | - ((cState.DpadLeft ? 1 : 0) << 1) | - ((cState.DpadDown ? 1 : 0) << 2) | - ((cState.DpadUp ? 1 : 0) << 3)); - - switch (dpad_state) - { - case 0: cState.DpadUp = true; cState.DpadDown = false; cState.DpadLeft = false; cState.DpadRight = false; break; - case 1: cState.DpadUp = true; cState.DpadDown = false; cState.DpadLeft = false; cState.DpadRight = true; break; - case 2: cState.DpadUp = false; cState.DpadDown = false; cState.DpadLeft = false; cState.DpadRight = true; break; - case 3: cState.DpadUp = false; cState.DpadDown = true; cState.DpadLeft = false; cState.DpadRight = true; break; - case 4: cState.DpadUp = false; cState.DpadDown = true; cState.DpadLeft = false; cState.DpadRight = false; break; - case 5: cState.DpadUp = false; cState.DpadDown = true; cState.DpadLeft = true; cState.DpadRight = false; break; - case 6: cState.DpadUp = false; cState.DpadDown = false; cState.DpadLeft = true; cState.DpadRight = false; break; - case 7: cState.DpadUp = true; cState.DpadDown = false; cState.DpadLeft = true; cState.DpadRight = false; break; - case 8: cState.DpadUp = false; cState.DpadDown = false; cState.DpadLeft = false; cState.DpadRight = false; break; - } - - cState.R3 = ((byte)inputReport[6] & (1 << 7)) != 0; - cState.L3 = ((byte)inputReport[6] & (1 << 6)) != 0; - cState.Options = ((byte)inputReport[6] & (1 << 5)) != 0; - cState.Share = ((byte)inputReport[6] & (1 << 4)) != 0; - cState.R1 = ((byte)inputReport[6] & (1 << 1)) != 0; - cState.L1 = ((byte)inputReport[6] & (1 << 0)) != 0; - - cState.PS = ((byte)inputReport[7] & (1 << 0)) != 0; - cState.TouchButton = (inputReport[7] & (1 << 2 - 1)) != 0; - cState.FrameCounter = (byte)(inputReport[7] >> 2); - - // Store Gyro and Accel values - Array.Copy(inputReport, 14, accel, 0, 6); - Array.Copy(inputReport, 20, gyro, 0, 6); + this.resetHapticState(); + this.BuildCurrentState(inputReport); - try - { - charging = (inputReport[30] & 0x10) != 0; - battery = (inputReport[30] & 0x0f) * 10; - cState.Battery = (byte)battery; - if (inputReport[30] != priorInputReport30) - { - priorInputReport30 = inputReport[30]; - Console.WriteLine(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + "> power subsystem octet: 0x" + inputReport[30].ToString("x02")); - } - } - catch { currerror = "Index out ofr bounds: battery"; } - // XXX DS4State mapping needs fixup, turn touches into an array[4] of structs. And include the touchpad details there instead. - try - { - for (int touches = inputReport[-1 + DS4Touchpad.TOUCHPAD_DATA_OFFSET - 1], touchOffset = 0; touches > 0; touches--, touchOffset += 9) - { - cState.TouchPacketCounter = inputReport[-1 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset]; - cState.Touch1 = (inputReport[0 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] >> 7) != 0 ? false : true; // >= 1 touch detected - cState.Touch1Identifier = (byte)(inputReport[0 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] & 0x7f); - cState.Touch2 = (inputReport[4 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] >> 7) != 0 ? false : true; // 2 touches detected - cState.Touch2Identifier = (byte)(inputReport[4 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] & 0x7f); - cState.TouchLeft = (inputReport[1 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] + ((inputReport[2 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] & 0xF) * 255) >= 1920 * 2 / 5) ? false : true; - cState.TouchRight = (inputReport[1 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] + ((inputReport[2 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] & 0xF) * 255) < 1920 * 2 / 5) ? false : true; - // Even when idling there is still a touch packet indicating no touch 1 or 2 - touchpad.handleTouchpad(inputReport, cState, touchOffset); - } - } - catch { currerror = "Index out ofr bounds: touchpad"; } - - /* Debug output of incoming HID data: - if (cState.L2 == 0xff && cState.R2 == 0xff) - { - Console.Write(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + ">"); - for (int i = 0; i < inputReport.Length; i++) - Console.Write(" " + inputReport[i].ToString("x2")); - Console.WriteLine(); - } */ + DateTime utcNow = System.DateTime.UtcNow; if (!isNonSixaxisIdle()) + { lastActive = utcNow; + } if (conType == ConnectionType.BT) { bool shouldDisconnect = false; @@ -460,20 +485,25 @@ private void performDs4Input() { DateTime timeout = lastActive + TimeSpan.FromSeconds(IdleTimeout); if (!Charging) + { shouldDisconnect = utcNow >= timeout; + } } } if (shouldDisconnect && DisconnectBT()) + { + status = InputLoopStatus.DISCONNECTED; return; // all done + } } // XXX fix initialization ordering so the null checks all go away if (Report != null) + { Report(this, EventArgs.Empty); + } + sendOutputReport(false); - if (!string.IsNullOrEmpty(error)) - error = string.Empty; - if (!string.IsNullOrEmpty(currerror)) - error = currerror; + cState.CopyTo(pState); } } @@ -511,6 +541,7 @@ private void sendOutputReport(bool synchronous) outputReportBuffer[9] = ledFlashOn; //flash on duration outputReportBuffer[10] = ledFlashOff; //flash off duration } + lock (outputReport) { if (synchronous) @@ -565,20 +596,27 @@ public bool DisconnectBT() p.dwSize = Marshal.SizeOf(typeof(NativeMethods.BLUETOOTH_FIND_RADIO_PARAMS)); IntPtr searchHandle = NativeMethods.BluetoothFindFirstRadio(ref p, ref btHandle); int bytesReturned = 0; + bool success = false; while (!success && btHandle != IntPtr.Zero) { success = NativeMethods.DeviceIoControl(btHandle, IOCTL_BTH_DISCONNECT_DEVICE, ref lbtAddr, 8, IntPtr.Zero, 0, ref bytesReturned, IntPtr.Zero); NativeMethods.CloseHandle(btHandle); if (!success) + { if (!NativeMethods.BluetoothFindNextRadio(searchHandle, ref btHandle)) + { btHandle = IntPtr.Zero; + } + } } + NativeMethods.BluetoothFindRadioClose(searchHandle); Console.WriteLine("Disconnect successful: " + success); + success = true; // XXX return value indicates failure, but it still works? - if(success) + if (success) { IsDisconnecting = true; StopOutputUpdate(); diff --git a/DS4Library/DS4Library.csproj b/DS4Library/DS4Library.csproj index 157489cb47..326e559be3 100644 --- a/DS4Library/DS4Library.csproj +++ b/DS4Library/DS4Library.csproj @@ -47,6 +47,7 @@ + diff --git a/DS4Library/LatencyCounter.cs b/DS4Library/LatencyCounter.cs new file mode 100644 index 0000000000..a2e19ad2c9 --- /dev/null +++ b/DS4Library/LatencyCounter.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DS4Library +{ + public class LatencyCounter + { + long[] _LatencyReadings; + int _bufferPointer = 0; + int _bufferEndPointer = 0; + + public LatencyCounter(int bufferSize) + { + _LatencyReadings = new long[bufferSize]; + } + + + public double Latency + { + get + { + if (_bufferEndPointer == 0) + { + return 0; + } + + long result = 0L; + + for (int pos = 0; pos < _bufferEndPointer; ++pos) + { + result += _LatencyReadings[pos]; + } + + return (double)result / (_bufferEndPointer + 1); + } + } + + public void PushLatencyReading(long reading) + { + if (_bufferPointer > _LatencyReadings.Length - 1) + { + _bufferPointer = 0; + } + + _LatencyReadings[_bufferPointer] = reading; + + if (_bufferEndPointer < _LatencyReadings.Length - 1) + { + _bufferEndPointer = _bufferPointer; + } + + _bufferPointer++; + } + + } +} diff --git a/DS4Tool/DS4Form.cs b/DS4Tool/DS4Form.cs index 5b965a749a..ee9ed8ef25 100644 --- a/DS4Tool/DS4Form.cs +++ b/DS4Tool/DS4Form.cs @@ -16,6 +16,9 @@ using System.Globalization; using System.Threading.Tasks; using System.ServiceProcess; +using DS4Control.Enums; +using DS4Windows.Tools; +using DS4Windows.XML_Files; namespace DS4Windows { public partial class DS4Form : Form @@ -33,7 +36,7 @@ public partial class DS4Form : Form string exepath = Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName; string appdatapath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\DS4Windows"; string oldappdatapath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\DS4Tool"; - string tempProfileProgram = "null"; + string tempProfileProgram = null; float dpix, dpiy; List profilenames= new List(); List programpaths = new List(); @@ -74,8 +77,10 @@ public partial class DS4Form : Form public DS4Form(string[] args) { InitializeComponent(); + arguements = args; ThemeUtil.SetTheme(lvDebug); + Pads = new Label[4] { lbPad1, lbPad2, lbPad3, lbPad4 }; Batteries = new Label[4] { lBBatt1, lBBatt2, lBBatt3, lBBatt4 }; cbs = new ComboBox[4] { cBController1, cBController2, cBController3, cBController4 }; @@ -85,44 +90,43 @@ public DS4Form(string[] args) (ToolStripMenuItem)notifyIcon1.ContextMenuStrip.Items[1], (ToolStripMenuItem)notifyIcon1.ContextMenuStrip.Items[2], (ToolStripMenuItem)notifyIcon1.ContextMenuStrip.Items[3] }; + SystemEvents.PowerModeChanged += OnPowerChange; tSOptions.Visible = false; bool firstrun = false; - if (File.Exists(exepath + "\\Auto Profiles.xml") - && File.Exists(appdatapath + "\\Auto Profiles.xml")) - { - firstrun = true; - new SaveWhere(true).ShowDialog(); - } - else if (File.Exists(exepath + "\\Auto Profiles.xml")) - Global.SaveWhere(exepath); - else if (File.Exists(appdatapath + "\\Auto Profiles.xml")) - Global.SaveWhere(appdatapath); - else if (File.Exists(oldappdatapath + "\\Auto Profiles.xml")) + + string profileFileName = "\\Auto Profiles.xml"; + + string executionPathAutoProfile = exepath + profileFileName; + string appDataPathAutoProfile = appdatapath + profileFileName; + + ProfileFileSystem profileLocations = new ProfileFileSystem(exepath, appdatapath, oldappdatapath); + + ProfileDirectories existingProfileLocations = profileLocations.CheckForFileInProfileDirectories(profileFileName); + ProfileDirectories saveLocation = profileLocations.GetCurrentSaveLocation(profileFileName); + + if (saveLocation == ProfileDirectories.None) { - try + if (profileLocations.GetProfileExistsInOldLocation(profileFileName)) { - if (Directory.Exists(appdatapath)) - Directory.Move(appdatapath, Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\DS4Windows Old"); - Directory.Move(oldappdatapath, appdatapath); - Global.SaveWhere(appdatapath); + profileLocations.MigrateToNewFileLocation(profileFileName, ProfileDirectories.OldFilePath, ProfileDirectories.AppDataPath); + Global.SaveWhere(profileLocations.GetDirectoryString(ProfileDirectories.AppDataPath)); } - catch + else { - MessageBox.Show(Properties.Resources.CannotMoveFiles, "DS4Windows"); - Process.Start("explorer.exe", @"/select, " + appdatapath); - Close(); - return; + firstrun = true; + new SaveWhere(true).ShowDialog(); } } - else if (!File.Exists(exepath + "\\Auto Profiles.xml") - && !File.Exists(appdatapath + "\\Auto Profiles.xml")) + else { - firstrun = true; - new SaveWhere(false).ShowDialog(); + Global.SaveWhere(profileLocations.GetCurrentSaveLocationDirectory(profileFileName)); } + if (firstrun) + { CheckDrivers(); + } else { var AppCollectionThread = new System.Threading.Thread(() => CheckDrivers()); @@ -135,6 +139,7 @@ public DS4Form(string[] args) Close(); return; } + Graphics g = this.CreateGraphics(); try { @@ -145,6 +150,7 @@ public DS4Form(string[] args) { g.Dispose(); } + Icon = Properties.Resources.DS4W; notifyIcon1.Icon = Properties.Resources.DS4W; Program.rootHub.Debug += On_Debug; @@ -187,6 +193,7 @@ public DS4Form(string[] args) } foreach (ToolStripMenuItem t in shortcuts) t.DropDownItemClicked += Profile_Changed_Menu; + hideDS4CheckBox.CheckedChanged -= hideDS4CheckBox_CheckedChanged; hideDS4CheckBox.Checked = Global.getUseExclusiveMode(); hideDS4CheckBox.CheckedChanged += hideDS4CheckBox_CheckedChanged; @@ -208,6 +215,7 @@ public DS4Form(string[] args) { string[] profiles = Directory.GetFiles(Global.appdatapath + @"\Profiles\"); foreach (String s in profiles) + { if (Path.GetExtension(s) == ".xml") { xDoc.Load(s); @@ -227,9 +235,11 @@ public DS4Form(string[] args) xDoc.Save(s); Global.LoadActions(); } + } } catch { } - } + } + bool start = true; bool mini = false; for (int i = 0; i < arguements.Length; i++) @@ -280,7 +290,6 @@ public DS4Form(string[] args) } Uri url = new Uri("http://ds4windows.com/Files/Builds/newest.txt"); //Sorry other devs, gonna have to find your own server - if (checkwhen > 0 && DateTime.Now >= Global.getLastChecked() + TimeSpan.FromHours(checkwhen)) { wc.DownloadFileAsync(url, Global.appdatapath + "\\version.txt"); @@ -420,26 +429,33 @@ private void test_Tick(object sender, EventArgs e) } void Hotkeys(object sender, EventArgs e) { + if (Global.getSwipeProfiles()) + { for (int i = 0; i < 4; i++) { - string slide = Program.rootHub.TouchpadSlide(i); - if (slide == "left") + //string slide = Program.rootHub.TouchpadSlideString(i); + + TouchpadSlideDirections slide = Program.rootHub.TouchpadSlideEnum(i); + + if (slide == TouchpadSlideDirections.left) if (cbs[i].SelectedIndex <= 0) cbs[i].SelectedIndex = cbs[i].Items.Count - 2; else cbs[i].SelectedIndex--; - else if (slide == "right") + else if (slide == TouchpadSlideDirections.right) if (cbs[i].SelectedIndex == cbs[i].Items.Count - 2) cbs[i].SelectedIndex = 0; else cbs[i].SelectedIndex++; - if (slide.Contains("t")) + if (slide != TouchpadSlideDirections.none) ShowNotification(this, Properties.Resources.UsingProfile.Replace("*number*", (i + 1).ToString()).Replace("*Profile name*", cbs[i].Text)); } + } //Check for process for auto profiles - if (tempProfileProgram == "null") + if (tempProfileProgram == null) + { for (int i = 0; i < programpaths.Count; i++) { string name = programpaths[i].ToLower().Replace('/', '\\'); @@ -454,11 +470,12 @@ void Hotkeys(object sender, EventArgs e) tempProfileProgram = name; } } + } else { if (tempProfileProgram != GetTopWindowName().ToLower().Replace('/', '\\')) { - tempProfileProgram = "null"; + tempProfileProgram = null; for (int j = 0; j < 4; j++) Global.LoadProfile(j, false, Program.rootHub); } @@ -468,30 +485,24 @@ void Hotkeys(object sender, EventArgs e) public void LoadP() { - XmlDocument doc = new XmlDocument(); - proprofiles = new List[4] { new List(), new List(), - new List(), new List() }; programpaths.Clear(); - if (!File.Exists(Global.appdatapath + "\\Auto Profiles.xml")) - return; - doc.Load(Global.appdatapath + "\\Auto Profiles.xml"); - XmlNodeList programslist = doc.SelectNodes("Programs/Program"); - foreach (XmlNode x in programslist) - programpaths.Add(x.Attributes["path"].Value); - foreach (string s in programpaths) - for (int i = 0; i < 4; i++) - { - proprofiles[i].Add(doc.SelectSingleNode("/Programs/Program[@path=\"" + s + "\"]" - + "/Controller" + (i + 1)).InnerText); - } + + if (File.Exists(Global.appdatapath + "\\Auto Profiles.xml")) + { + AutoProfileXML profiles = new AutoProfileXML(Global.appdatapath + "\\Auto Profiles.xml"); + proprofiles = profiles.Profiles; + + //Does this need to be... closed? XMLDocument has no close function + } } + string originalsettingstext; private void CheckDrivers() { bool deriverinstalled = false; try { - ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PnPSignedDriver"); + ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PnPSignedDriver"); foreach (ManagementObject obj in searcher.Get()) { @@ -503,7 +514,10 @@ private void CheckDrivers() break; } } - catch { } + catch + { + deriverinstalled = false; + } } if (!deriverinstalled) @@ -569,19 +583,20 @@ public void RefreshProfiles() try { profilenames.Clear(); - string[] profiles = Directory.GetFiles(Global.appdatapath + @"\Profiles\"); - foreach (String s in profiles) - if (s.EndsWith(".xml")) - profilenames.Add(Path.GetFileNameWithoutExtension(s)); - lBProfiles.Items.Clear(); - lBProfiles.Items.AddRange(profilenames.ToArray()); - if (lBProfiles.Items.Count == 0) + + profilenames = new ProfilesDirectory(Global.appdatapath + @"\Profiles\"); + + if (profilenames.Count == 0) { Global.SaveProfile(0, "Default", null, null); Global.setAProfile(0, "Default"); RefreshProfiles(); return; } + + lBProfiles.Items.Clear(); + lBProfiles.Items.AddRange(profilenames.ToArray()); + for (int i = 0; i < 4; i++) { cbs[i].Items.Clear(); @@ -590,6 +605,7 @@ public void RefreshProfiles() foreach (string s in profilenames) shortcuts[i].DropDownItems.Add(s); for (int j = 0; j < cbs[i].Items.Count; j++) + { if (cbs[i].Items[j].ToString() == Path.GetFileNameWithoutExtension(Global.getAProfile(i))) { cbs[i].SelectedIndex = j; @@ -605,6 +621,7 @@ public void RefreshProfiles() shortcuts[i].Text = Properties.Resources.ContextNew.Replace("*number*", (i + 1).ToString()); ebns[i].Text = Properties.Resources.New; } + } } } catch (DirectoryNotFoundException) diff --git a/DS4Tool/DS4Windows.csproj b/DS4Tool/DS4Windows.csproj index adcd04eefe..b449b5eede 100644 --- a/DS4Tool/DS4Windows.csproj +++ b/DS4Tool/DS4Windows.csproj @@ -62,10 +62,10 @@ DS4Windows.Program - 5F2A5A97E42A73158D79996F7F3BE738271F5047 + 3C326011412379D2F068BFB13E9D8AE555D8C274 - DS4Tool_TemporaryKey.pfx + DS4Windows_TemporaryKey.pfx true @@ -167,6 +167,8 @@ SpecActions.cs + + Form @@ -179,6 +181,8 @@ WinProgs.cs + + Alreadyrunning.cs @@ -410,7 +414,6 @@ WinProgs.cs - SettingsSingleFileGenerator Settings.Designer.cs @@ -535,7 +538,8 @@ - ilmerge /targetplatform:"v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319" /out:Build\DS4Windows.exe DS4Windows.exe HidLibrary.dll DS4Control.dll DS4Library.dll + + + \ No newline at end of file diff --git a/DS4WCF/MainWindow.xaml b/DS4WCF/MainWindow.xaml new file mode 100644 index 0000000000..3cc096312e --- /dev/null +++ b/DS4WCF/MainWindow.xaml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + diff --git a/DS4WCF/MainWindow.xaml.cs b/DS4WCF/MainWindow.xaml.cs new file mode 100644 index 0000000000..b31f86c7db --- /dev/null +++ b/DS4WCF/MainWindow.xaml.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace DS4WCF +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + //Window does not own control + private DS4Control.Control _control; + List _controllerGrids = new List(); + + public MainWindow( DS4Control.Control control ) + { + _control = control; + + InitializeComponent(); + GetAllControllerPanels(); + GetAllControllers(); + } + + private void GetAllControllerPanels() + { + _controllerGrids.Add(FindName("ControllerPanel0") as ControllerInputGrid); + _controllerGrids.Add(FindName("ControllerPanel1") as ControllerInputGrid); + _controllerGrids.Add(FindName("ControllerPanel2") as ControllerInputGrid); + _controllerGrids.Add(FindName("ControllerPanel3") as ControllerInputGrid); + } + + private void GetAllControllers() + { + DS4Library.DS4Device[] devices = this._control.DS4Controllers; + for (int deviceIndex = 0; deviceIndex < devices.Count(); deviceIndex++) + { + if (devices[deviceIndex] != null) + { + _controllerGrids[deviceIndex].InitializeWithDS4Device(devices[deviceIndex]); + } + } + } + + } +} diff --git a/DS4WCF/Properties/AssemblyInfo.cs b/DS4WCF/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..4d2642b535 --- /dev/null +++ b/DS4WCF/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("DS4WCF")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DS4WCF")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/DS4WCF/Properties/Resources.Designer.cs b/DS4WCF/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..d3f77d23ab --- /dev/null +++ b/DS4WCF/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34014 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace DS4WCF.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DS4WCF.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/DS4WCF/Properties/Resources.resx b/DS4WCF/Properties/Resources.resx new file mode 100644 index 0000000000..af7dbebbac --- /dev/null +++ b/DS4WCF/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/DS4WCF/Properties/Settings.Designer.cs b/DS4WCF/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..9be19726f2 --- /dev/null +++ b/DS4WCF/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34014 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace DS4WCF.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/DS4WCF/Properties/Settings.settings b/DS4WCF/Properties/Settings.settings new file mode 100644 index 0000000000..033d7a5e9e --- /dev/null +++ b/DS4WCF/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/DS4WCF/UI Components/ControllerInputGrid.xaml b/DS4WCF/UI Components/ControllerInputGrid.xaml new file mode 100644 index 0000000000..c135ca849e --- /dev/null +++ b/DS4WCF/UI Components/ControllerInputGrid.xaml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + diff --git a/DS4WCF/UI Components/ControllerInputGrid.xaml.cs b/DS4WCF/UI Components/ControllerInputGrid.xaml.cs new file mode 100644 index 0000000000..0c0850d842 --- /dev/null +++ b/DS4WCF/UI Components/ControllerInputGrid.xaml.cs @@ -0,0 +1,77 @@ +using DS4Library; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace DS4WCF +{ + /// + /// Interaction logic for ControllerInputGrid.xaml + /// + public partial class ControllerInputGrid : UserControl, INotifyPropertyChanged + { + private void OnPropertyChanged(string name) + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs(name)); + } + } + + string _batteryLevel; + public string BatteryLevel + { + get + { + return _batteryLevel; + } + set + { + + _batteryLevel = value; + OnPropertyChanged("BatteryLevel"); + } + } + + Brush _barColor; + public Brush BarColor + { + get + { + return _barColor; + } + set + { + _barColor = value; + OnPropertyChanged("barColor"); + } + } + + public ControllerInputGrid() + { + InitializeComponent(); + this.DataContext = this; + } + + public void InitializeWithDS4Device(DS4Device device) + { + this.BatteryLevel = device.Battery.ToString() + "%"; + this.BarColor = new SolidColorBrush(Color.FromRgb(device.LightBarColor.red, device.LightBarColor.green, device.LightBarColor.blue)); + } + + + public event PropertyChangedEventHandler PropertyChanged; + } +} diff --git a/Performance1.psess b/Performance1.psess new file mode 100644 index 0000000000..7dc9d392dd --- /dev/null +++ b/Performance1.psess @@ -0,0 +1,21 @@ + + + Sampling + None + true + Timestamp + Cycles + 10000000 + 10 + 10 + + false + + + + false + + + false + +