Merge pull request #2 from Ryochan7/jay

Another attempt at keeping an experimental branch up to date with Ryochan7's fork
This commit is contained in:
Yuki-nyan 2017-05-12 00:36:10 +01:00 committed by GitHub
commit 81b58fd90a
126 changed files with 17393 additions and 12211 deletions

2
.gitignore vendored
View File

@ -97,7 +97,7 @@ publish/
# NuGet Packages Directory
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
#packages/
packages/
# Windows Azure Build Output
csx

View File

@ -15,12 +15,12 @@ Global
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7B9354BF-AF82-4CCB-A83D-4BEB1E9D8C96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7B9354BF-AF82-4CCB-A83D-4BEB1E9D8C96}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7B9354BF-AF82-4CCB-A83D-4BEB1E9D8C96}.Debug|x64.ActiveCfg = Debug|Any CPU
{7B9354BF-AF82-4CCB-A83D-4BEB1E9D8C96}.Debug|x64.Build.0 = Debug|Any CPU
{7B9354BF-AF82-4CCB-A83D-4BEB1E9D8C96}.Debug|x64.ActiveCfg = Debug|x64
{7B9354BF-AF82-4CCB-A83D-4BEB1E9D8C96}.Debug|x64.Build.0 = Debug|x64
{7B9354BF-AF82-4CCB-A83D-4BEB1E9D8C96}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7B9354BF-AF82-4CCB-A83D-4BEB1E9D8C96}.Release|Any CPU.Build.0 = Release|Any CPU
{7B9354BF-AF82-4CCB-A83D-4BEB1E9D8C96}.Release|x64.ActiveCfg = Release|Any CPU
{7B9354BF-AF82-4CCB-A83D-4BEB1E9D8C96}.Release|x64.Build.0 = Release|Any CPU
{7B9354BF-AF82-4CCB-A83D-4BEB1E9D8C96}.Release|x64.ActiveCfg = Release|x64
{7B9354BF-AF82-4CCB-A83D-4BEB1E9D8C96}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,8 @@ using System.Text;
using System.Drawing;
using static System.Math;
using static DS4Windows.Global;
using System.Diagnostics;
namespace DS4Windows
{
public class DS4LightBar
@ -23,124 +25,210 @@ namespace DS4Windows
{ 252, 28 } // on 90% of the time at 90
};
static double[] counters = new double[4] { 0, 0, 0, 0 };
public static double[] fadetimer = new double[4] { 0, 0, 0, 0 };
public static Stopwatch[] fadewatches = { new Stopwatch(), new Stopwatch(), new Stopwatch(), new Stopwatch() };
static bool[] fadedirection = new bool[4] { false, false, false, false };
static DateTime oldnow = DateTime.UtcNow;
static DateTime[] oldnow = { DateTime.UtcNow, DateTime.UtcNow, DateTime.UtcNow, DateTime.UtcNow };
public static bool[] forcelight = new bool[4] { false, false, false, false };
public static DS4Color[] forcedColor = new DS4Color[4];
public static byte[] forcedFlash = new byte[4];
public static void updateLightBar(DS4Device device, int deviceNum, DS4State cState, DS4StateExposed eState, Mouse tp)
{
DS4Color color;
if (!defualtLight && !forcelight[deviceNum])
{
if (UseCustomLed[deviceNum])
{
if (LedAsBatteryIndicator[deviceNum])
{
DS4Color fullColor = CustomColor[deviceNum];
DS4Color lowColor = LowColor[deviceNum];
internal const int PULSE_FLASH_DURATION = 2000;
internal const int PULSE_CHARGING_DURATION = 4000;
public static void updateLightBar(DS4Device device, int deviceNum, DS4State cState,
DS4StateExposed eState, Mouse tp)
{
/*
* TODO: Remove more property usage and use explicit getter methods instead.
* Testing in proper optimized release builds shows that it is
* still necessary to reduce lag.
*/
DS4Color color;
if (!defaultLight && !forcelight[deviceNum])
{
if (getUseCustomLed(deviceNum))
{
if (getLedAsBatteryIndicator(deviceNum))
{
DS4Color fullColor = getCustomColor(deviceNum);
DS4Color lowColor = getLowColor(deviceNum);
color = getTransitionedColor(lowColor, fullColor, device.Battery);
}
else
color = CustomColor[deviceNum];
color = getCustomColor(deviceNum);
}
else
{
if (Rainbow[deviceNum] > 0)
{// Display rainbow
double rainbow = getRainbow(deviceNum);
if (rainbow > 0)
{
// Display rainbow
DateTime now = DateTime.UtcNow;
if (now >= oldnow + TimeSpan.FromMilliseconds(10)) //update by the millisecond that way it's a smooth transtion
if (now >= oldnow[deviceNum] + TimeSpan.FromMilliseconds(10)) //update by the millisecond that way it's a smooth transtion
{
oldnow = now;
if (device.Charging)
counters[deviceNum] -= 1.5 * 3 / Rainbow[deviceNum];
oldnow[deviceNum] = now;
if (device.isCharging())
counters[deviceNum] -= 1.5 * 3 / rainbow;
else
counters[deviceNum] += 1.5 * 3 / Rainbow[deviceNum];
counters[deviceNum] += 1.5 * 3 / rainbow;
}
if (counters[deviceNum] < 0)
counters[deviceNum] = 180000;
if (counters[deviceNum] > 180000)
else if (counters[deviceNum] > 180000)
counters[deviceNum] = 0;
if (LedAsBatteryIndicator[deviceNum])
color = HuetoRGB((float)counters[deviceNum] % 360, (byte)(2.55 * device.Battery));
if (getLedAsBatteryIndicator(deviceNum))
color = HuetoRGB((float)counters[deviceNum] % 360, (byte)(2.55 * device.getBattery()));
else
color = HuetoRGB((float)counters[deviceNum] % 360, 255);
}
else if (LedAsBatteryIndicator[deviceNum])
else if (getLedAsBatteryIndicator(deviceNum))
{
//if (device.Charging == false || device.Battery >= 100) // when charged, don't show the charging animation
{
DS4Color fullColor = MainColor[deviceNum];
DS4Color lowColor = LowColor[deviceNum];
DS4Color fullColor = getMainColor(deviceNum);
DS4Color lowColor = getLowColor(deviceNum);
color = getTransitionedColor(lowColor, fullColor, (uint)device.Battery);
color = getTransitionedColor(lowColor, fullColor, (uint)device.getBattery());
}
}
else
{
color = MainColor[deviceNum];
color = getMainColor(deviceNum);
}
}
}
if (device.getBattery() <= getFlashAt(deviceNum) && !defaultLight && !device.isCharging())
{
DS4Color flashColor = getFlashColor(deviceNum);
if (!(flashColor.red == 0 &&
flashColor.green == 0 &&
flashColor.blue == 0))
color = flashColor;
if (device.Battery <= FlashAt[deviceNum] && !defualtLight && !device.Charging)
if (getFlashType(deviceNum) == 1)
{
if (!(FlashColor[deviceNum].red == 0 &&
FlashColor[deviceNum].green == 0 &&
FlashColor[deviceNum].blue == 0))
color = FlashColor[deviceNum];
if (FlashType[deviceNum] == 1)
double ratio = 0.0;
if (!fadewatches[deviceNum].IsRunning)
{
if (fadetimer[deviceNum] <= 0)
fadedirection[deviceNum] = true;
else if (fadetimer[deviceNum] >= 100)
fadedirection[deviceNum] = false;
bool temp = fadedirection[deviceNum];
fadedirection[deviceNum] = !temp;
fadewatches[deviceNum].Restart();
ratio = temp ? 100.0 : 0.0;
}
else
{
long elapsed = fadewatches[deviceNum].ElapsedMilliseconds;
if (fadedirection[deviceNum])
fadetimer[deviceNum] += 1;
{
if (elapsed < PULSE_FLASH_DURATION)
{
ratio = 100.0 * (elapsed / (double)PULSE_FLASH_DURATION);
}
else
fadetimer[deviceNum] -= 1;
color = getTransitionedColor(color, new DS4Color(0, 0, 0), fadetimer[deviceNum]);
{
ratio = 100.0;
fadewatches[deviceNum].Stop();
}
}
else
{
if (elapsed < PULSE_FLASH_DURATION)
{
ratio = (0 - 100.0) * (elapsed / (double)PULSE_FLASH_DURATION) + 100.0;
}
else
{
ratio = 0.0;
fadewatches[deviceNum].Stop();
}
}
}
if (IdleDisconnectTimeout[deviceNum] > 0 && LedAsBatteryIndicator[deviceNum] && (!device.Charging || device.Battery >= 100))
{//Fade lightbar by idle time
color = getTransitionedColor(color, new DS4Color(0, 0, 0), ratio);
}
}
int idleDisconnectTimeout = getIdleDisconnectTimeout(deviceNum);
if (idleDisconnectTimeout > 0 && getLedAsBatteryIndicator(deviceNum) &&
(!device.isCharging() || device.getBattery() >= 100))
{
//Fade lightbar by idle time
TimeSpan timeratio = new TimeSpan(DateTime.UtcNow.Ticks - device.lastActive.Ticks);
double botratio = timeratio.TotalMilliseconds;
double topratio = TimeSpan.FromSeconds(IdleDisconnectTimeout[deviceNum]).TotalMilliseconds;
double ratio = ((botratio / topratio) * 100);
if (ratio >= 50 && ratio <= 100)
double topratio = TimeSpan.FromSeconds(idleDisconnectTimeout).TotalMilliseconds;
double ratio = 100.0 * (botratio / topratio);
if (ratio >= 50.0 && ratio <= 100.0)
color = getTransitionedColor(color, new DS4Color(0, 0, 0), (uint)((ratio - 50) * 2));
else if (ratio >= 100)
color = getTransitionedColor(color, new DS4Color(0, 0, 0), 100);
else if (ratio >= 100.0)
color = getTransitionedColor(color, new DS4Color(0, 0, 0), 100.0);
}
if (device.Charging && device.Battery < 100)
switch (ChargingType[deviceNum])
if (device.isCharging() && device.getBattery() < 100)
{
switch (getChargingType(deviceNum))
{
case 1:
if (fadetimer[deviceNum] <= 0)
fadedirection[deviceNum] = true;
else if (fadetimer[deviceNum] >= 105)
fadedirection[deviceNum] = false;
if (fadedirection[deviceNum])
fadetimer[deviceNum] += .1;
{
double ratio = 0.0;
if (!fadewatches[deviceNum].IsRunning)
{
bool temp = fadedirection[deviceNum];
fadedirection[deviceNum] = !temp;
fadewatches[deviceNum].Restart();
ratio = temp ? 100.0 : 0.0;
}
else
fadetimer[deviceNum] -= .1;
color = getTransitionedColor(color, new DS4Color(0, 0, 0), fadetimer[deviceNum]);
{
long elapsed = fadewatches[deviceNum].ElapsedMilliseconds;
if (fadedirection[deviceNum])
{
if (elapsed < PULSE_CHARGING_DURATION)
{
ratio = 100.0 * (elapsed / (double)PULSE_CHARGING_DURATION);
}
else
{
ratio = 100.0;
fadewatches[deviceNum].Stop();
}
}
else
{
if (elapsed < PULSE_CHARGING_DURATION)
{
ratio = (0 - 100.0) * (elapsed / (double)PULSE_CHARGING_DURATION) + 100.0;
}
else
{
ratio = 0.0;
fadewatches[deviceNum].Stop();
}
}
}
color = getTransitionedColor(color, new DS4Color(0, 0, 0), ratio);
break;
}
case 2:
counters[deviceNum] += .167;
{
counters[deviceNum] += 0.167;
color = HuetoRGB((float)counters[deviceNum] % 360, 255);
break;
}
case 3:
color = ChargingColor[deviceNum];
break;
default:
{
color = getChargingColor(deviceNum);
break;
}
default: break;
}
}
}
else if (forcelight[deviceNum])
{
@ -150,25 +238,30 @@ namespace DS4Windows
color = new DS4Color(0, 0, 0);
else
{
if (device.ConnectionType == ConnectionType.BT)
if (device.getConnectionType() == ConnectionType.BT)
color = new DS4Color(32, 64, 64);
else
color = new DS4Color(0, 0, 0);
}
bool distanceprofile = (ProfilePath[deviceNum].ToLower().Contains("distance") || tempprofilename[deviceNum].ToLower().Contains("distance"));
if (distanceprofile && !defualtLight)
{ //Thing I did for Distance
float rumble = device.LeftHeavySlowRumble / 2.55f;
bool distanceprofile = DistanceProfiles[deviceNum] || tempprofileDistance[deviceNum];
//distanceprofile = (ProfilePath[deviceNum].ToLower().Contains("distance") || tempprofilename[deviceNum].ToLower().Contains("distance"));
if (distanceprofile && !defaultLight)
{
// Thing I did for Distance
float rumble = device.getLeftHeavySlowRumble() / 2.55f;
byte max = Max(color.red, Max(color.green, color.blue));
if (device.LeftHeavySlowRumble > 100)
if (device.getLeftHeavySlowRumble() > 100)
color = getTransitionedColor(new DS4Color(max, max, 0), new DS4Color(255, 0, 0), rumble);
else
color = getTransitionedColor(color, getTransitionedColor(new DS4Color(max, max, 0), new DS4Color(255, 0, 0), 39.6078f), device.LeftHeavySlowRumble);
color = getTransitionedColor(color, getTransitionedColor(new DS4Color(max, max, 0), new DS4Color(255, 0, 0), 39.6078f), device.getLeftHeavySlowRumble());
}
DS4HapticState haptics = new DS4HapticState
{
LightBarColor = color
};
if (haptics.IsLightBarSet())
{
if (forcelight[deviceNum] && forcedFlash[deviceNum] > 0)
@ -176,17 +269,18 @@ namespace DS4Windows
haptics.LightBarFlashDurationOff = haptics.LightBarFlashDurationOn = (byte)(25 - forcedFlash[deviceNum]);
haptics.LightBarExplicitlyOff = true;
}
else if (device.Battery <= FlashAt[deviceNum] && FlashType[deviceNum] == 0 && !defualtLight && !device.Charging)
else if (device.getBattery() <= getFlashAt(deviceNum) && getFlashType(deviceNum) == 0 && !defaultLight && !device.isCharging())
{
int level = device.Battery / 10;
//if (level >= 10)
//level = 0; // all values of ~0% or >~100% are rendered the same
int level = device.getBattery() / 10;
if (level >= 10)
level = 0; // all values of ~0% or >~100% are rendered the same
haptics.LightBarFlashDurationOn = BatteryIndicatorDurations[level, 0];
haptics.LightBarFlashDurationOff = BatteryIndicatorDurations[level, 1];
}
else if (distanceprofile && device.LeftHeavySlowRumble > 155) //also part of Distance
else if (distanceprofile && device.getLeftHeavySlowRumble() > 155) //also part of Distance
{
haptics.LightBarFlashDurationOff = haptics.LightBarFlashDurationOn = (byte)((-device.LeftHeavySlowRumble + 265));
haptics.LightBarFlashDurationOff = haptics.LightBarFlashDurationOn = (byte)((-device.getLeftHeavySlowRumble() + 265));
haptics.LightBarExplicitlyOff = true;
}
else
@ -200,14 +294,19 @@ namespace DS4Windows
{
haptics.LightBarExplicitlyOff = true;
}
if (device.LightBarOnDuration != haptics.LightBarFlashDurationOn && device.LightBarOnDuration != 1 && haptics.LightBarFlashDurationOn == 0)
byte tempLightBarOnDuration = device.getLightBarOnDuration();
if (tempLightBarOnDuration != haptics.LightBarFlashDurationOn && tempLightBarOnDuration != 1 && haptics.LightBarFlashDurationOn == 0)
haptics.LightBarFlashDurationOff = haptics.LightBarFlashDurationOn = 1;
if (device.LightBarOnDuration == 1) //helps better reset the color
System.Threading.Thread.Sleep(5);
// Comment out code for now. This condition gets hit too often and bogs down the GUI
//if (device.LightBarOnDuration == 1) //helps better reset the color
// System.Threading.Thread.Sleep(5);
device.pushHapticState(haptics);
}
public static bool defualtLight = false, shuttingdown = false;
public static bool defaultLight = false, shuttingdown = false;
public static DS4Color HuetoRGB(float hue, byte sat)
{

View File

@ -0,0 +1,146 @@

namespace DS4Windows
{
public class DS4StateFieldMapping
{
public enum ControlType { Unknown = 0, Button, AxisDir, Trigger, Touch, GyroDir, SwipeDir }
public bool[] buttons = new bool[(int)DS4Controls.SwipeDown + 1];
public byte[] axisdirs = new byte[(int)DS4Controls.SwipeDown + 1];
public byte[] triggers = new byte[(int)DS4Controls.SwipeDown + 1];
public int[] gryodirs = new int[(int)DS4Controls.SwipeDown + 1];
public byte[] swipedirs = new byte[(int)DS4Controls.SwipeDown + 1];
public bool[] swipedirbools = new bool[(int)DS4Controls.SwipeDown + 1];
public static ControlType[] mappedType = { ControlType.Unknown, // DS4Controls.None
ControlType.AxisDir, // DS4Controls.LXNeg
ControlType.AxisDir, // DS4Controls.LXPos
ControlType.AxisDir, // DS4Controls.LYNeg
ControlType.AxisDir, // DS4Controls.LYPos
ControlType.AxisDir, // DS4Controls.RXNeg
ControlType.AxisDir, // DS4Controls.RXPos
ControlType.AxisDir, // DS4Controls.RYNeg
ControlType.AxisDir, // DS4Controls.RYPos
ControlType.Button, // DS4Controls.L1
ControlType.Trigger, // DS4Controls.L2
ControlType.Button, // DS4Controls.L3
ControlType.Button, // DS4Controls.R1
ControlType.Trigger, // DS4Controls.R2
ControlType.Button, // DS4Controls.R3
ControlType.Button, // DS4Controls.Square
ControlType.Button, // DS4Controls.Triangle
ControlType.Button, // DS4Controls.Circle
ControlType.Button, // DS4Controls.Cross
ControlType.Button, // DS4Controls.DpadUp
ControlType.Button, // DS4Controls.DpadRight
ControlType.Button, // DS4Controls.DpadDown
ControlType.Button, // DS4Controls.DpadLeft
ControlType.Button, // DS4Controls.PS
ControlType.Touch, // DS4Controls.TouchLeft
ControlType.Touch, // DS4Controls.TouchUpper
ControlType.Touch, // DS4Controls.TouchMulti
ControlType.Touch, // DS4Controls.TouchRight
ControlType.Button, // DS4Controls.Share
ControlType.Button, // DS4Controls.Options
ControlType.GyroDir, // DS4Controls.GyroXPos
ControlType.GyroDir, // DS4Controls.GyroXNeg
ControlType.GyroDir, // DS4Controls.GyroZPos
ControlType.GyroDir, // DS4Controls.GyroZNeg
ControlType.SwipeDir, // DS4Controls.SwipeLeft
ControlType.SwipeDir, // DS4Controls.SwipeRight
ControlType.SwipeDir, // DS4Controls.SwipeUp
ControlType.SwipeDir, // DS4Controls.SwipeDown
};
public DS4StateFieldMapping(DS4State cState, DS4StateExposed exposeState, Mouse tp)
{
axisdirs[(int)DS4Controls.LXNeg] = cState.LX;
axisdirs[(int)DS4Controls.LXPos] = cState.LX;
axisdirs[(int)DS4Controls.LYNeg] = cState.LY;
axisdirs[(int)DS4Controls.LYPos] = cState.LY;
axisdirs[(int)DS4Controls.RXNeg] = cState.RX;
axisdirs[(int)DS4Controls.RXPos] = cState.RX;
axisdirs[(int)DS4Controls.RYNeg] = cState.RY;
axisdirs[(int)DS4Controls.RYPos] = cState.RY;
triggers[(int)DS4Controls.L2] = cState.L2;
triggers[(int)DS4Controls.R2] = cState.R2;
buttons[(int)DS4Controls.L1] = cState.L1;
buttons[(int)DS4Controls.L3] = cState.L3;
buttons[(int)DS4Controls.R1] = cState.R1;
buttons[(int)DS4Controls.R3] = cState.R3;
buttons[(int)DS4Controls.Cross] = cState.Cross;
buttons[(int)DS4Controls.Triangle] = cState.Triangle;
buttons[(int)DS4Controls.Circle] = cState.Circle;
buttons[(int)DS4Controls.Square] = cState.Square;
buttons[(int)DS4Controls.PS] = cState.PS;
buttons[(int)DS4Controls.Options] = cState.Options;
buttons[(int)DS4Controls.Share] = cState.Share;
buttons[(int)DS4Controls.DpadUp] = cState.DpadUp;
buttons[(int)DS4Controls.DpadRight] = cState.DpadRight;
buttons[(int)DS4Controls.DpadDown] = cState.DpadDown;
buttons[(int)DS4Controls.DpadLeft] = cState.DpadLeft;
buttons[(int)DS4Controls.TouchLeft] = tp != null ? tp.leftDown : false;
buttons[(int)DS4Controls.TouchRight] = tp != null ? tp.rightDown : false;
buttons[(int)DS4Controls.TouchUpper] = tp != null ? tp.upperDown : false;
buttons[(int)DS4Controls.TouchMulti] = tp != null ? tp.multiDown : false;
int gyroX = exposeState.getGyroX();
gryodirs[(int)DS4Controls.GyroXPos] = gyroX > 0 ? gyroX : 0;
gryodirs[(int)DS4Controls.GyroXNeg] = gyroX < 0 ? gyroX : 0;
int gyroZ = exposeState.getGyroZ();
gryodirs[(int)DS4Controls.GyroZPos] = gyroZ > 0 ? gyroZ : 0;
gryodirs[(int)DS4Controls.GyroZNeg] = gyroZ < 0 ? gyroZ : 0;
swipedirs[(int)DS4Controls.SwipeLeft] = tp != null ? tp.swipeLeftB : (byte)0;
swipedirs[(int)DS4Controls.SwipeRight] = tp != null ? tp.swipeRightB : (byte)0;
swipedirs[(int)DS4Controls.SwipeUp] = tp != null ? tp.swipeUpB : (byte)0;
swipedirs[(int)DS4Controls.SwipeDown] = tp != null ? tp.swipeDownB : (byte)0;
swipedirbools[(int)DS4Controls.SwipeLeft] = tp != null ? tp.swipeLeft : false;
swipedirbools[(int)DS4Controls.SwipeRight] = tp != null ? tp.swipeRight : false;
swipedirbools[(int)DS4Controls.SwipeUp] = tp != null ? tp.swipeUp : false;
swipedirbools[(int)DS4Controls.SwipeDown] = tp != null ? tp.swipeDown : false;
}
public void populateState(DS4State state)
{
state.LX = axisdirs[(int)DS4Controls.LXNeg];
state.LX = axisdirs[(int)DS4Controls.LXPos];
state.LY = axisdirs[(int)DS4Controls.LYNeg];
state.LY = axisdirs[(int)DS4Controls.LYPos];
state.RX = axisdirs[(int)DS4Controls.RXNeg];
state.RX = axisdirs[(int)DS4Controls.RXPos];
state.RY = axisdirs[(int)DS4Controls.RYNeg];
state.RY = axisdirs[(int)DS4Controls.RYPos];
state.L2 = triggers[(int)DS4Controls.L2];
state.R2 = triggers[(int)DS4Controls.R2];
state.L1 = buttons[(int)DS4Controls.L1];
state.L3 = buttons[(int)DS4Controls.L3];
state.R1 = buttons[(int)DS4Controls.R1];
state.R3 = buttons[(int)DS4Controls.R3];
state.Cross = buttons[(int)DS4Controls.Cross];
state.Triangle = buttons[(int)DS4Controls.Triangle];
state.Circle = buttons[(int)DS4Controls.Circle];
state.Square = buttons[(int)DS4Controls.Square];
state.PS = buttons[(int)DS4Controls.PS];
state.Options = buttons[(int)DS4Controls.Options];
state.Share = buttons[(int)DS4Controls.Share];
state.DpadUp = buttons[(int)DS4Controls.DpadUp];
state.DpadRight = buttons[(int)DS4Controls.DpadRight];
state.DpadDown = buttons[(int)DS4Controls.DpadDown];
state.DpadLeft = buttons[(int)DS4Controls.DpadLeft];
}
}
}

View File

@ -1,14 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace DS4Windows
{
class InputMethods
{
private static INPUT[] sendInputs = new INPUT[2]; // will allow for keyboard + mouse/tablet input within one SendInput call, or two mouse events
private static object lockob = new object();
public static void MoveCursorBy(int x, int y)
{
lock (lockob)
@ -43,6 +42,7 @@ namespace DS4Windows
sendInputs[inputs].Data.Mouse.Y = 0;
inputs++;
}
if (horizontal != 0)
{
sendInputs[inputs].Type = INPUT_MOUSE;
@ -54,6 +54,7 @@ namespace DS4Windows
sendInputs[inputs].Data.Mouse.Y = 0;
inputs++;
}
SendInput(inputs, sendInputs, (int)inputs * Marshal.SizeOf(sendInputs[0]));
}
}
@ -88,69 +89,6 @@ namespace DS4Windows
}
}
public static void performLeftClick()
{
lock (lockob)
{
sendInputs[0].Type = INPUT_MOUSE;
sendInputs[0].Data.Mouse.ExtraInfo = IntPtr.Zero;
sendInputs[0].Data.Mouse.Flags = 0;
sendInputs[0].Data.Mouse.Flags |= MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP;
sendInputs[0].Data.Mouse.MouseData = 0;
sendInputs[0].Data.Mouse.Time = 0;
sendInputs[0].Data.Mouse.X = 0;
sendInputs[0].Data.Mouse.Y = 0;
uint result = SendInput(1, sendInputs, Marshal.SizeOf(sendInputs[0]));
}
}
public static void performRightClick()
{
lock (lockob)
{
sendInputs[0].Type = INPUT_MOUSE;
sendInputs[0].Data.Mouse.ExtraInfo = IntPtr.Zero;
sendInputs[0].Data.Mouse.Flags = 0;
sendInputs[0].Data.Mouse.Flags |= MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP;
sendInputs[0].Data.Mouse.MouseData = 0;
sendInputs[0].Data.Mouse.Time = 0;
sendInputs[0].Data.Mouse.X = 0;
sendInputs[0].Data.Mouse.Y = 0;
uint result = SendInput(1, sendInputs, Marshal.SizeOf(sendInputs[0]));
}
}
public static void performMiddleClick()
{
lock (lockob)
{
sendInputs[0].Type = INPUT_MOUSE;
sendInputs[0].Data.Mouse.ExtraInfo = IntPtr.Zero;
sendInputs[0].Data.Mouse.Flags = 0;
sendInputs[0].Data.Mouse.Flags |= MOUSEEVENTF_MIDDLEDOWN | MOUSEEVENTF_MIDDLEUP;
sendInputs[0].Data.Mouse.MouseData = 0;
sendInputs[0].Data.Mouse.Time = 0;
sendInputs[0].Data.Mouse.X = 0;
sendInputs[0].Data.Mouse.Y = 0;
uint result = SendInput(1, sendInputs, Marshal.SizeOf(sendInputs[0]));
}
}
public static void performFourthClick()
{
lock (lockob)
{
sendInputs[0].Type = INPUT_MOUSE;
sendInputs[0].Data.Mouse.ExtraInfo = IntPtr.Zero;
sendInputs[0].Data.Mouse.Flags = 0;
sendInputs[0].Data.Mouse.Flags |= MOUSEEVENTF_XBUTTONDOWN | MOUSEEVENTF_XBUTTONUP;
sendInputs[0].Data.Mouse.MouseData = 1;
sendInputs[0].Data.Mouse.Time = 0;
sendInputs[0].Data.Mouse.X = 0;
sendInputs[0].Data.Mouse.Y = 0;
uint result = SendInput(1, sendInputs, Marshal.SizeOf(sendInputs[0]));
}
}
public static void performSCKeyPress(ushort key)
{
lock (lockob)
@ -169,10 +107,16 @@ namespace DS4Windows
{
lock (lockob)
{
ushort scancode = scancodeFromVK(key);
bool extended = (scancode & 0x100) != 0;
uint curflags = extended ? KEYEVENTF_EXTENDEDKEY : 0;
sendInputs[0].Type = INPUT_KEYBOARD;
sendInputs[0].Data.Keyboard.ExtraInfo = IntPtr.Zero;
sendInputs[0].Data.Keyboard.Flags = 1;
sendInputs[0].Data.Keyboard.Scan = 0;
sendInputs[0].Data.Keyboard.Flags = curflags;
sendInputs[0].Data.Keyboard.Scan = scancode;
//sendInputs[0].Data.Keyboard.Flags = 1;
//sendInputs[0].Data.Keyboard.Scan = 0;
sendInputs[0].Data.Keyboard.Time = 0;
sendInputs[0].Data.Keyboard.Vk = key;
uint result = SendInput(1, sendInputs, Marshal.SizeOf(sendInputs[0]));
@ -197,16 +141,60 @@ namespace DS4Windows
{
lock (lockob)
{
ushort scancode = scancodeFromVK(key);
bool extended = (scancode & 0x100) != 0;
uint curflags = extended ? KEYEVENTF_EXTENDEDKEY : 0;
sendInputs[0].Type = INPUT_KEYBOARD;
sendInputs[0].Data.Keyboard.ExtraInfo = IntPtr.Zero;
sendInputs[0].Data.Keyboard.Flags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
sendInputs[0].Data.Keyboard.Scan = 0;
sendInputs[0].Data.Keyboard.Flags = curflags | KEYEVENTF_KEYUP;
sendInputs[0].Data.Keyboard.Scan = scancode;
//sendInputs[0].Data.Keyboard.Flags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
//sendInputs[0].Data.Keyboard.Scan = 0;
sendInputs[0].Data.Keyboard.Time = 0;
sendInputs[0].Data.Keyboard.Vk = key;
uint result = SendInput(1, sendInputs, Marshal.SizeOf(sendInputs[0]));
}
}
private static ushort scancodeFromVK(uint vkey)
{
ushort scancode = 0;
if (vkey == VK_PAUSE)
{
// MapVirtualKey does not work with VK_PAUSE
scancode = 0x45;
}
else
{
scancode = MapVirtualKey(vkey, MAPVK_VK_TO_VSC);
}
switch (vkey)
{
case VK_LEFT:
case VK_UP:
case VK_RIGHT:
case VK_DOWN:
case VK_PRIOR:
case VK_NEXT:
case VK_END:
case VK_HOME:
case VK_INSERT:
case VK_DELETE:
case VK_DIVIDE:
case VK_NUMLOCK:
case VK_RCONTROL:
case VK_RMENU:
{
scancode |= (ushort)EXTENDED_FLAG; // set extended bit
break;
}
}
return scancode;
}
/// <summary>
/// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646270(v=vs.85).aspx
/// </summary>
@ -277,7 +265,11 @@ namespace DS4Windows
MOUSEEVENTF_XBUTTONDOWN = 128, MOUSEEVENTF_XBUTTONUP = 256,
KEYEVENTF_EXTENDEDKEY = 1, KEYEVENTF_KEYUP = 2, MOUSEEVENTF_WHEEL = 0x0800, MOUSEEVENTF_HWHEEL = 0x1000,
MOUSEEVENTF_MIDDLEWDOWN = 0x0020, MOUSEEVENTF_MIDDLEWUP = 0x0040,
KEYEVENTF_SCANCODE = 0x0008, MAPVK_VK_TO_VSC = 0, KEYEVENTF_UNICODE = 0x0004;
KEYEVENTF_SCANCODE = 0x0008, MAPVK_VK_TO_VSC = 0, KEYEVENTF_UNICODE = 0x0004, EXTENDED_FLAG = 0x100;
internal const uint VK_PAUSE = 0x13, VK_LEFT = 0x25, VK_UP = 0x26, VK_RIGHT = 0x27, VK_DOWN = 0x28,
VK_PRIOR = 0x21, VK_NEXT = 0x22, VK_END = 0x23, VK_HOME = 0x24, VK_INSERT = 0x2D, VK_DELETE = 0x2E,
VK_DIVIDE = 0x6F, VK_NUMLOCK = 0x90, VK_RCONTROL = 0xAE, VK_RMENU = 0xA5;
[DllImport("user32.dll", SetLastError = true)]
private static extern uint SendInput(uint numberOfInputs, INPUT[] inputs, int sizeOfInputs);
@ -285,6 +277,7 @@ namespace DS4Windows
private static extern ushort MapVirtualKey(uint uCode, uint uMapType);
[DllImport("user32.dll", SetLastError = true)]
static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
//Not used, just here
public static void DownKeys(ushort key)
{
@ -301,5 +294,5 @@ namespace DS4Windows
keybd_event((byte)key, 0, (int)KEYEVENTF_KEYUP, 0);
}
}
}

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DS4Windows
{

File diff suppressed because it is too large Load Diff

View File

@ -73,7 +73,9 @@ namespace DS4Windows
case 16: return s.Options;
case 17: return s.Share;
case 18: return s.PS;
default: break;
}
return false;
}
@ -98,11 +100,13 @@ namespace DS4Windows
swipeLeftB = (byte)Math.Min(255, Math.Max(0, firstTouch.hwX - arg.touches[0].hwX));
swipeRightB = (byte)Math.Min(255, Math.Max(0, arg.touches[0].hwX - firstTouch.hwX));
}
if (Math.Abs(firstTouch.hwY - arg.touches[0].hwY) < 50 && arg.touches.Length == 2)
if (arg.touches[0].hwX - firstTouch.hwX > 200 && !slideleft)
slideright = true;
else if (firstTouch.hwX - arg.touches[0].hwX > 200 && !slideright)
slideleft = true;
dev.getCurrentState(s);
synthesizeMouseButtons();
}
@ -113,14 +117,17 @@ namespace DS4Windows
cursor.touchesBegan(arg);
wheel.touchesBegan(arg);
}
pastTime = arg.timeStamp;
firstTouch = arg.touches[0];
if (Global.DoubleTap[deviceNum])
{
DateTime test = arg.timeStamp;
if (test <= (firstTap + TimeSpan.FromMilliseconds((double)Global.TapSensitivity[deviceNum] * 1.5)) && !arg.touchButtonPressed)
secondtouchbegin = true;
}
dev.getCurrentState(s);
synthesizeMouseButtons();
}
@ -129,16 +136,17 @@ namespace DS4Windows
slideright = slideleft = false;
swipeUp = swipeDown = swipeLeft = swipeRight = false;
swipeUpB = swipeDownB = swipeLeftB = swipeRightB = 0;
if (Global.TapSensitivity[deviceNum] != 0 && !Global.UseTPforControls[deviceNum])
byte tapSensitivity = Global.TapSensitivity[deviceNum];
if (tapSensitivity != 0 && !Global.UseTPforControls[deviceNum])
{
if (secondtouchbegin)
{
tappedOnce = false;
secondtouchbegin = false;
}
DateTime test = arg.timeStamp;
if (test <= (pastTime + TimeSpan.FromMilliseconds((double)Global.TapSensitivity[deviceNum] * 2)) && !arg.touchButtonPressed && !tappedOnce)
if (test <= (pastTime + TimeSpan.FromMilliseconds((double)tapSensitivity * 2)) && !arg.touchButtonPressed && !tappedOnce)
if (Math.Abs(firstTouch.hwX - arg.touches[0].hwX) < 10 && Math.Abs(firstTouch.hwY - arg.touches[0].hwY) < 10)
if (Global.DoubleTap[deviceNum])
{
@ -149,6 +157,7 @@ namespace DS4Windows
else
Mapping.MapClick(deviceNum, Mapping.Click.Left); //this way no delay if disabled
}
dev.getCurrentState(s);
synthesizeMouseButtons();
}
@ -174,19 +183,23 @@ namespace DS4Windows
public bool dragging, dragging2;
private void synthesizeMouseButtons()
{
if (Global.GetDS4Action(deviceNum, DS4Controls.TouchLeft.ToString(), false) == null && leftDown)
if (Global.GetDS4Action(deviceNum, DS4Controls.TouchLeft, false) == null && leftDown)
{
Mapping.MapClick(deviceNum, Mapping.Click.Left);
dragging2 = true;
}
else
{
dragging2 = false;
if (Global.GetDS4Action(deviceNum, DS4Controls.TouchUpper.ToString(), false) == null && upperDown)
}
if (Global.GetDS4Action(deviceNum, DS4Controls.TouchUpper, false) == null && upperDown)
Mapping.MapClick(deviceNum, Mapping.Click.Middle);
if (Global.GetDS4Action(deviceNum, DS4Controls.TouchRight.ToString(), false) == null && rightDown)
if (Global.GetDS4Action(deviceNum, DS4Controls.TouchRight, false) == null && rightDown)
Mapping.MapClick(deviceNum, Mapping.Click.Left);
if (Global.GetDS4Action(deviceNum, DS4Controls.TouchMulti.ToString(), false) == null && multiDown)
if (Global.GetDS4Action(deviceNum, DS4Controls.TouchMulti, false) == null && multiDown)
Mapping.MapClick(deviceNum, Mapping.Click.Right);
if (!Global.UseTPforControls[deviceNum])
{
if (tappedOnce)
@ -205,8 +218,11 @@ namespace DS4Windows
dragging = true;
}
else
{
dragging = false;
}
}
s = remapped;
//remapped.CopyTo(s);
}
@ -231,11 +247,13 @@ namespace DS4Windows
{
if ((Global.LowerRCOn[deviceNum] && arg.touches[0].hwX > (1920 * 3) / 4 && arg.touches[0].hwY > (960 * 3) / 4))
Mapping.MapClick(deviceNum, Mapping.Click.Right);
if (isLeft(arg.touches[0]))
leftDown = true;
else if (isRight(arg.touches[0]))
rightDown = true;
}
dev.getCurrentState(s);
synthesizeMouseButtons();
}

View File

@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DS4Windows
{
class MouseCursor
@ -42,10 +37,14 @@ namespace DS4Windows
int yAction = (int)yMotion;
vRemainder += yMotion - yAction;
vRemainder -= (int)vRemainder;
if (Global.GyroInvert[deviceNumber] == 2 || Global.GyroInvert[deviceNumber] == 3)
int gyroInvert = Global.GyroInvert[deviceNumber];
if (gyroInvert == 2 || gyroInvert == 3)
xAction *= -1;
if (Global.GyroInvert[deviceNumber] == 1 || Global.GyroInvert[deviceNumber] == 3)
if (gyroInvert == 1 || gyroInvert == 3)
yAction *= -1;
if (yAction != 0 || xAction != 0)
InputMethods.MoveCursorBy(xAction, yAction);
@ -65,8 +64,10 @@ namespace DS4Windows
private byte lastTouchID;
public void touchesMoved(TouchpadEventArgs arg, bool dragging)
{
if ((!dragging && arg.touches.Length != 1) || (dragging && arg.touches.Length < 1))
int touchesLen = arg.touches.Length;
if ((!dragging && touchesLen != 1) || (dragging && touchesLen < 1))
return;
int deltaX, deltaY;
if (arg.touches[0].touchID != lastTouchID)
{
@ -78,8 +79,7 @@ namespace DS4Windows
else if (Global.TouchpadJitterCompensation[deviceNumber])
{
// Often the DS4's internal jitter compensation kicks in and starts hiding changes, ironically creating jitter...
if (dragging && arg.touches.Length > 1)
if (dragging && touchesLen > 1)
{
deltaX = arg.touches[1].deltaX;
deltaY = arg.touches[1].deltaY;
@ -89,6 +89,7 @@ namespace DS4Windows
deltaX = arg.touches[0].deltaX;
deltaY = arg.touches[0].deltaY;
}
// allow only very fine, slow motions, when changing direction, even from neutral
// TODO maybe just consume it completely?
if (deltaX <= -1)
@ -127,7 +128,7 @@ namespace DS4Windows
}
else
{
if (dragging && arg.touches.Length > 1)
if (dragging && touchesLen > 1)
{
deltaX = arg.touches[1].deltaX;
deltaY = arg.touches[1].deltaY;

View File

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DS4Windows
{
class MouseWheel
@ -27,6 +26,7 @@ namespace DS4Windows
{
if (arg.touches.Length != 2 || dragging)
return;
Touch lastT0 = arg.touches[0].previousTouch;
Touch lastT1 = arg.touches[1].previousTouch;
Touch T0 = arg.touches[0];

View File

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
@ -522,7 +521,7 @@ namespace DS4Windows
protected virtual Boolean GetDeviceHandle(String Path)
{
m_FileHandle = CreateFile(Path, (GENERIC_WRITE | GENERIC_READ), FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0);
m_FileHandle = CreateFile(Path, (GENERIC_WRITE | GENERIC_READ), FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | 0x20000000 | 0x80000000, 0);
return !m_FileHandle.IsInvalid;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
@ -12,6 +11,9 @@ namespace DS4Windows
{
private const String DS3_BUS_CLASS_GUID = "{F679F562-3164-42CE-A4DB-E7DDBE723909}";
private const int CONTROLLER_OFFSET = 1; // Device 0 is the virtual USB hub itself, and we leave devices 1-10 available for other software (like the Scarlet.Crush DualShock driver itself)
private const int inputResolution = 127 - (-128);
private const float reciprocalInputResolution = 1 / (float)inputResolution;
private const int outputResolution = 32767 - (-32768);
private int firstController = 1;
// Device 0 is the virtual USB hub itself, and we can leave more available for other software (like the Scarlet.Crush DualShock driver)
@ -25,10 +27,11 @@ namespace DS4Windows
{
Value -= 0x80;
if (Value == -128) Value = -127;
if (Flip) Value *= -1;
//float temp = (Value - (-128)) / (float)inputResolution;
float temp = (Value - (-128)) * reciprocalInputResolution;
if (Flip) temp = (temp - 0.5f) * -1.0f + 0.5f;
return (Int32)((float)Value * 258.00787401574803149606299212599f);
return (Int32)(temp * outputResolution + (-32768));
}
@ -105,10 +108,11 @@ namespace DS4Windows
Output[4] = (Byte)(device + firstController);
Output[9] = 0x14;
for (int i = 10; i < Output.Length; i++)
for (int i = 10, outLen = Output.Length; i < outLen; i++)
{
Output[i] = 0;
}
if (state.Share) Output[10] |= (Byte)(1 << 5); // Back
if (state.L3) Output[10] |= (Byte)(1 << 6); // Left Thumb
if (state.R3) Output[10] |= (Byte)(1 << 7); // Right Thumb
@ -133,9 +137,9 @@ namespace DS4Windows
Output[13] = state.R2; // Right Trigger
Int32 ThumbLX = Scale(state.LX, false);
Int32 ThumbLY = -Scale(state.LY, false);
Int32 ThumbLY = Scale(state.LY, true);
Int32 ThumbRX = Scale(state.RX, false);
Int32 ThumbRY = -Scale(state.RY, false);
Int32 ThumbRY = Scale(state.RY, true);
Output[14] = (Byte)((ThumbLX >> 0) & 0xFF); // LX
Output[15] = (Byte)((ThumbLX >> 8) & 0xFF);
Output[16] = (Byte)((ThumbLY >> 0) & 0xFF); // LY

View File

@ -19,26 +19,26 @@ namespace DS4Windows
internal class WindowsEnumerator
{
private delegate int EnumCallBackDelegate(IntPtr hwnd, int lParam);
[DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
[DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int EnumWindows(EnumCallBackDelegate lpEnumFunc, int lParam);
[DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
[DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int EnumChildWindows(IntPtr hWndParent, EnumCallBackDelegate lpEnumFunc, int lParam);
[DllImport("user32", EntryPoint = "GetClassNameA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int GetClassName(IntPtr hwnd, System.Text.StringBuilder lpClassName, int nMaxCount);
[DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
[DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int IsWindowVisible(IntPtr hwnd);
[DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int GetParent(IntPtr hwnd);
[DllImport("user32", EntryPoint = "SendMessageA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
[DllImport("user32", EntryPoint = "SendMessageA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
[DllImport("user32", EntryPoint = "SendMessageA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
[DllImport("user32", EntryPoint = "SendMessageA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, System.Text.StringBuilder lParam);
private List<ApiWindow> _listChildren = new List<ApiWindow>();

View File

@ -118,6 +118,11 @@
this.hideDS4CheckBox = new System.Windows.Forms.CheckBox();
this.cBSwipeProfiles = new System.Windows.Forms.CheckBox();
this.StartWindowsCheckBox = new System.Windows.Forms.CheckBox();
this.runStartupPanel = new System.Windows.Forms.Panel();
this.uacPictureBox = new System.Windows.Forms.PictureBox();
this.runStartTaskRadio = new System.Windows.Forms.RadioButton();
this.label1 = new System.Windows.Forms.Label();
this.runStartProgRadio = new System.Windows.Forms.RadioButton();
this.startMinimizedCheckBox = new System.Windows.Forms.CheckBox();
this.panel1 = new System.Windows.Forms.Panel();
this.lbNotifications = new System.Windows.Forms.Label();
@ -129,6 +134,7 @@
this.cBFlashWhenLate = new System.Windows.Forms.CheckBox();
this.cBCloseMini = new System.Windows.Forms.CheckBox();
this.cBQuickCharge = new System.Windows.Forms.CheckBox();
this.cBUseWhiteIcon = new System.Windows.Forms.CheckBox();
this.cBDownloadLangauge = new System.Windows.Forms.CheckBox();
this.cBUpdate = new System.Windows.Forms.CheckBox();
this.pNUpdate = new System.Windows.Forms.Panel();
@ -139,7 +145,6 @@
this.lbUseXIPorts = new System.Windows.Forms.Label();
this.nUDXIPorts = new System.Windows.Forms.NumericUpDown();
this.lbLastXIPort = new System.Windows.Forms.Label();
this.cBUseWhiteIcon = new System.Windows.Forms.CheckBox();
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
this.linkProfiles = new System.Windows.Forms.LinkLabel();
this.lnkControllers = new System.Windows.Forms.LinkLabel();
@ -168,6 +173,8 @@
this.toolStrip1.SuspendLayout();
this.tabSettings.SuspendLayout();
this.fLPSettings.SuspendLayout();
this.runStartupPanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.uacPictureBox)).BeginInit();
this.panel1.SuspendLayout();
this.panel2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.nUDLatency)).BeginInit();
@ -632,8 +639,8 @@
this.lBProfiles.ContextMenuStrip = this.cMProfile;
resources.ApplyResources(this.lBProfiles, "lBProfiles");
this.lBProfiles.FormattingEnabled = true;
this.lBProfiles.MultiColumn = true;
this.lBProfiles.Name = "lBProfiles";
this.lBProfiles.SelectedIndexChanged += new System.EventHandler(this.lBProfiles_SelectedIndexChanged);
this.lBProfiles.KeyDown += new System.Windows.Forms.KeyEventHandler(this.lBProfiles_KeyDown);
this.lBProfiles.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.lBProfiles_MouseDoubleClick);
this.lBProfiles.MouseDown += new System.Windows.Forms.MouseEventHandler(this.lBProfiles_MouseDown);
@ -795,36 +802,36 @@
//
// tsBEditProfile
//
this.tsBEditProfile.Image = global::DS4Windows.Properties.Resources.edit;
resources.ApplyResources(this.tsBEditProfile, "tsBEditProfile");
this.tsBEditProfile.Image = global::DS4Windows.Properties.Resources.edit;
this.tsBEditProfile.Name = "tsBEditProfile";
this.tsBEditProfile.Click += new System.EventHandler(this.tsBNEditProfile_Click);
//
// tsBDeleteProfile
//
this.tsBDeleteProfile.Image = global::DS4Windows.Properties.Resources.delete;
resources.ApplyResources(this.tsBDeleteProfile, "tsBDeleteProfile");
this.tsBDeleteProfile.Image = global::DS4Windows.Properties.Resources.delete;
this.tsBDeleteProfile.Name = "tsBDeleteProfile";
this.tsBDeleteProfile.Click += new System.EventHandler(this.tsBDeleteProfle_Click);
//
// tSBDupProfile
//
this.tSBDupProfile.Image = global::DS4Windows.Properties.Resources.copy;
resources.ApplyResources(this.tSBDupProfile, "tSBDupProfile");
this.tSBDupProfile.Image = global::DS4Windows.Properties.Resources.copy;
this.tSBDupProfile.Name = "tSBDupProfile";
this.tSBDupProfile.Click += new System.EventHandler(this.tSBDupProfile_Click);
//
// tSBImportProfile
//
this.tSBImportProfile.Image = global::DS4Windows.Properties.Resources.import;
resources.ApplyResources(this.tSBImportProfile, "tSBImportProfile");
this.tSBImportProfile.Image = global::DS4Windows.Properties.Resources.import;
this.tSBImportProfile.Name = "tSBImportProfile";
this.tSBImportProfile.Click += new System.EventHandler(this.tSBImportProfile_Click);
//
// tSBExportProfile
//
this.tSBExportProfile.Image = global::DS4Windows.Properties.Resources.export;
resources.ApplyResources(this.tSBExportProfile, "tSBExportProfile");
this.tSBExportProfile.Image = global::DS4Windows.Properties.Resources.export;
this.tSBExportProfile.Name = "tSBExportProfile";
this.tSBExportProfile.Click += new System.EventHandler(this.tSBExportProfile_Click);
//
@ -847,6 +854,7 @@
this.fLPSettings.Controls.Add(this.hideDS4CheckBox);
this.fLPSettings.Controls.Add(this.cBSwipeProfiles);
this.fLPSettings.Controls.Add(this.StartWindowsCheckBox);
this.fLPSettings.Controls.Add(this.runStartupPanel);
this.fLPSettings.Controls.Add(this.startMinimizedCheckBox);
this.fLPSettings.Controls.Add(this.panel1);
this.fLPSettings.Controls.Add(this.cBDisconnectBT);
@ -884,6 +892,44 @@
this.StartWindowsCheckBox.UseVisualStyleBackColor = true;
this.StartWindowsCheckBox.CheckedChanged += new System.EventHandler(this.StartWindowsCheckBox_CheckedChanged);
//
// runStartupPanel
//
this.runStartupPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.runStartupPanel.Controls.Add(this.uacPictureBox);
this.runStartupPanel.Controls.Add(this.runStartTaskRadio);
this.runStartupPanel.Controls.Add(this.label1);
this.runStartupPanel.Controls.Add(this.runStartProgRadio);
resources.ApplyResources(this.runStartupPanel, "runStartupPanel");
this.runStartupPanel.Name = "runStartupPanel";
//
// uacPictureBox
//
resources.ApplyResources(this.uacPictureBox, "uacPictureBox");
this.uacPictureBox.Name = "uacPictureBox";
this.uacPictureBox.TabStop = false;
//
// runStartTaskRadio
//
resources.ApplyResources(this.runStartTaskRadio, "runStartTaskRadio");
this.runStartTaskRadio.Name = "runStartTaskRadio";
this.runStartTaskRadio.TabStop = true;
this.runStartTaskRadio.UseVisualStyleBackColor = true;
this.runStartTaskRadio.Click += new System.EventHandler(this.runStartTaskRadio_Click);
//
// label1
//
resources.ApplyResources(this.label1, "label1");
this.label1.Name = "label1";
//
// runStartProgRadio
//
resources.ApplyResources(this.runStartProgRadio, "runStartProgRadio");
this.runStartProgRadio.Checked = true;
this.runStartProgRadio.Name = "runStartProgRadio";
this.runStartProgRadio.TabStop = true;
this.runStartProgRadio.UseVisualStyleBackColor = true;
this.runStartProgRadio.Click += new System.EventHandler(this.runStartProgRadio_Click);
//
// startMinimizedCheckBox
//
resources.ApplyResources(this.startMinimizedCheckBox, "startMinimizedCheckBox");
@ -940,7 +986,7 @@
0});
this.nUDLatency.Name = "nUDLatency";
this.nUDLatency.Value = new decimal(new int[] {
10,
20,
0,
0,
0});
@ -974,6 +1020,13 @@
this.cBQuickCharge.UseVisualStyleBackColor = true;
this.cBQuickCharge.CheckedChanged += new System.EventHandler(this.cBQuickCharge_CheckedChanged);
//
// cBUseWhiteIcon
//
resources.ApplyResources(this.cBUseWhiteIcon, "cBUseWhiteIcon");
this.cBUseWhiteIcon.Name = "cBUseWhiteIcon";
this.cBUseWhiteIcon.UseVisualStyleBackColor = true;
this.cBUseWhiteIcon.CheckedChanged += new System.EventHandler(this.cBUseWhiteIcon_CheckedChanged);
//
// cBDownloadLangauge
//
resources.ApplyResources(this.cBDownloadLangauge, "cBDownloadLangauge");
@ -1068,13 +1121,6 @@
resources.ApplyResources(this.lbLastXIPort, "lbLastXIPort");
this.lbLastXIPort.Name = "lbLastXIPort";
//
// cBUseWhiteIcon
//
resources.ApplyResources(this.cBUseWhiteIcon, "cBUseWhiteIcon");
this.cBUseWhiteIcon.Name = "cBUseWhiteIcon";
this.cBUseWhiteIcon.UseVisualStyleBackColor = true;
this.cBUseWhiteIcon.CheckedChanged += new System.EventHandler(this.cBUseWhiteIcon_CheckedChanged);
//
// flowLayoutPanel1
//
resources.ApplyResources(this.flowLayoutPanel1, "flowLayoutPanel1");
@ -1157,10 +1203,6 @@
resources.ApplyResources(this.useCustomColorToolStripMenuItem, "useCustomColorToolStripMenuItem");
this.useCustomColorToolStripMenuItem.Click += new System.EventHandler(this.useCustomColorToolStripMenuItem_Click);
//
// advColorDialog
//
this.advColorDialog.OnUpdateColor += new DS4Windows.AdvancedColorDialog.ColorUpdateHandler(this.advColorDialog_OnUpdateColor);
//
// DS4Form
//
this.AllowDrop = true;
@ -1196,6 +1238,9 @@
this.tabSettings.ResumeLayout(false);
this.fLPSettings.ResumeLayout(false);
this.fLPSettings.PerformLayout();
this.runStartupPanel.ResumeLayout(false);
this.runStartupPanel.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.uacPictureBox)).EndInit();
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
this.panel2.ResumeLayout(false);
@ -1340,6 +1385,11 @@
private System.Windows.Forms.ToolStripMenuItem useCustomColorToolStripMenuItem;
private AdvancedColorDialog advColorDialog;
private System.Windows.Forms.CheckBox cBUseWhiteIcon;
private System.Windows.Forms.Panel runStartupPanel;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.RadioButton runStartProgRadio;
private System.Windows.Forms.RadioButton runStartTaskRadio;
private System.Windows.Forms.PictureBox uacPictureBox;
//private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem2;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -40,6 +40,7 @@
this.tPHotkeys = new System.Windows.Forms.TabPage();
this.lbHotkeys = new System.Windows.Forms.Label();
this.tPCredits = new System.Windows.Forms.TabPage();
this.linkTeokp = new System.Windows.Forms.LinkLabel();
this.linkKiliansch = new System.Windows.Forms.LinkLabel();
this.linkChamilsaan = new System.Windows.Forms.LinkLabel();
this.linkBoganhobo = new System.Windows.Forms.LinkLabel();
@ -85,7 +86,6 @@
this.lbTranslators = new System.Windows.Forms.Label();
this.linkSourceCode = new System.Windows.Forms.LinkLabel();
this.lbLinkText = new System.Windows.Forms.Label();
this.linkTeokp = new System.Windows.Forms.LinkLabel();
this.tCAbout.SuspendLayout();
this.tPHotkeys.SuspendLayout();
this.tPCredits.SuspendLayout();
@ -177,6 +177,13 @@
this.tPCredits.Name = "tPCredits";
this.tPCredits.UseVisualStyleBackColor = true;
//
// linkTeokp
//
resources.ApplyResources(this.linkTeokp, "linkTeokp");
this.linkTeokp.Name = "linkTeokp";
this.linkTeokp.TabStop = true;
this.linkTeokp.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkTeokp_LinkClicked);
//
// linkKiliansch
//
resources.ApplyResources(this.linkKiliansch, "linkKiliansch");
@ -448,13 +455,6 @@
resources.ApplyResources(this.lbLinkText, "lbLinkText");
this.lbLinkText.Name = "lbLinkText";
//
// linkTeokp
//
resources.ApplyResources(this.linkTeokp, "linkTeokp");
this.linkTeokp.Name = "linkTeokp";
this.linkTeokp.TabStop = true;
this.linkTeokp.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkTeokp_LinkClicked);
//
// Hotkeys
//
resources.ApplyResources(this, "$this");

View File

@ -77,7 +77,7 @@ namespace DS4Windows
private void lLChangelog_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
Process.Start("https://docs.google.com/document/d/1l4xcgVQkGUskc5CQ0p069yW22Cd5WAH_yE3Fz2hXo0E/edit?usp=sharing");
Process.Start("https://docs.google.com/document/d/1CovpH08fbPSXrC6TmEprzgPwCe0tTjQ_HTFfDotpmxk/edit?usp=sharing");
}
private void linkDonate_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)

File diff suppressed because it is too large Load Diff

View File

@ -34,8 +34,9 @@ namespace DS4Windows
device = deviceNum;
ops = ooo;
button = buton;
cBToggle.Checked = button.Font.Italic;
cBScanCode.Checked = button.Font.Bold;
DS4ControlSettings dcs = Global.getDS4CSetting(device, button.Name);
cBToggle.Checked = dcs.keyType.HasFlag(DS4KeyType.Toggle);
cBScanCode.Checked = dcs.keyType.HasFlag(DS4KeyType.ScanCode);
oldSC = cBScanCode.Location;
defaultText = btnDefault.Text;
if (button.Name.StartsWith("bnShift"))
@ -140,7 +141,17 @@ namespace DS4Windows
object keytag;
//ushort val;
if (((Button)sender).Tag != null && ((Button)sender).Tag.ToString().Contains("X360"))
keytag = ((Button)sender).Tag.ToString().Substring(4);
{
//keytag = ((Button)sender).Tag.ToString().Substring(4);
keytag = Global.getX360ControlsByName(((Button)sender).Tag.ToString().Substring(4));
DS4Controls psButton = Global.getDS4ControlsByName(button.Name);
if ((X360Controls)keytag == Global.getDefaultX360ControlBinding(psButton) &&
!cBScanCode.Checked && !cBToggle.Checked && !rBShiftModifer.Checked)
{
// Reset action
keytag = null;
}
}
else if (((Button)sender).Tag != null && ushort.TryParse(((Button)sender).Tag.ToString(), out val))
keytag = val;
else
@ -454,7 +465,7 @@ namespace DS4Windows
lBMacroOn.Visible = true;
foreach (int i in tag)
macrostag.Add(i);
if (Global.GetDS4KeyType(device, button.Name, rBShiftModifer.Checked).HasFlag(DS4KeyType.RepeatMacro))
if (Global.GetDS4KeyType(device, button.Name, rBShiftModifer.Checked).HasFlag(DS4KeyType.HoldMacro))
macrorepeat = true;
}
else if (tagO is string || tagO is X360Controls)
@ -509,7 +520,15 @@ namespace DS4Windows
}
}
}
string[] extras = Global.GetDS4Extra(device, button.Name, rBShiftModifer.Checked).Split(',');
string dcExtras = Global.GetDS4Extra(device, button.Name, rBShiftModifer.Checked);
string[] extras = null;
if (!string.IsNullOrEmpty(dcExtras))
{
extras = dcExtras.Split(',');
}
if (extras != null)
{
int b;
try
{
@ -558,6 +577,8 @@ namespace DS4Windows
nUDMouse.Value = 25;
cBMouse.Checked = false;
}
}
extraChanged = false;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -86,7 +86,6 @@ namespace DS4Windows
void AddtoDS4List()
{
dcs.Add(DS4Controls.Cross);
dcs.Add(DS4Controls.Cross);
dcs.Add(DS4Controls.Circle);
dcs.Add(DS4Controls.Square);
@ -121,7 +120,9 @@ namespace DS4Windows
else
macros.Add(value);
}
bool[] pTP = new bool[4];
void ds4_Tick(object sender, EventArgs e)
{
if (Program.rootHub.DS4Controllers[0] != null)
@ -147,17 +148,25 @@ namespace DS4Windows
pTP[0] = tP.leftDown;
pTP[1] = tP.rightDown;
}
foreach (DS4Controls dc in dcs)
//foreach (DS4Controls dc in dcs)
for (int controlIndex = 0, dcsLen = dcs.Count; controlIndex < dcsLen; controlIndex++)
{
DS4Controls dc = dcs[controlIndex];
if (Mapping.getBoolMapping(0, dc, cState, null, null))
{
int value = DS4ControltoInt(dc);
int count = 0;
foreach (int i in macros)
int macroLen = macros.Count;
//foreach (int i in macros)
for (int macroIndex = 0; macroIndex < macroLen; macroIndex++)
{
int i = macros[macroIndex];
if (i == value)
count++;
}
if (macros.Count == 0)
if (macroLen == 0)
{
AddMacroValue(value);
lVMacros.Items.Add(DS4ControltoX360(dc), 0);
@ -179,22 +188,28 @@ namespace DS4Windows
AddMacroValue(value);
lVMacros.Items.Add(DS4ControltoX360(dc), 0);
}
lVMacros.Items[lVMacros.Items.Count - 1].EnsureVisible();
}
else if (!Mapping.getBoolMapping(0, dc, cState, null, null))
{
if (macros.Count != 0)
int macroLen = macros.Count;
if (macroLen != 0)
{
int value = DS4ControltoInt(dc);
int count = 0;
foreach (int i in macros)
//foreach (int i in macros)
for (int macroIndex = 0; macroIndex < macroLen; macroIndex++)
{
int i = macros[macroIndex];
if (i == value)
count++;
}
/*for (int i = macros.Count - 1; i >= 0; i--)
if (macros.Count == 261)
count++;*/
if (count % 2 == 1)
{
if (cBRecordDelays.Checked)
@ -204,6 +219,7 @@ namespace DS4Windows
sw.Reset();
sw.Start();
}
AddMacroValue(value);
lVMacros.Items.Add(DS4ControltoX360(dc), 1);
lVMacros.Items[lVMacros.Items.Count - 1].EnsureVisible();
@ -213,6 +229,7 @@ namespace DS4Windows
}
}
}
}
public static int DS4ControltoInt(DS4Controls ctrl)
{
@ -279,8 +296,10 @@ namespace DS4Windows
}
return "None";
}
bool recordAfter = false;
int recordAfterInt = 0;
private void btnRecord_Click(object sender, EventArgs e)
{
if (btnRecord.Text != Properties.Resources.StopText)
@ -784,8 +803,7 @@ namespace DS4Windows
kbm.macrostag = macros;
kbm.macros = macronames;
kbm.lBMacroOn.Visible = true;
if (cBStyle.SelectedIndex == 1)
kbm.macrorepeat = true;
kbm.macrorepeat = cBStyle.SelectedIndex == 1;
saved = true;
if (sender != kbm)
kbm.Close();
@ -796,8 +814,7 @@ namespace DS4Windows
sA.macros = macronames;
sA.lbMacroRecorded.Text = string.Join(", ", macronames);
//kbm.lBMacroOn.Visible = true;
if (cBStyle.SelectedIndex == 1)
sA.macrorepeat = true;
sA.macrorepeat = cBStyle.SelectedIndex == 1;
saved = true;
//if (sender != sA)
// sA.Close();

View File

@ -42,7 +42,7 @@ namespace DS4Windows
WebClient wb = new WebClient();
if (!driverinstalling)
{
wb.DownloadFileAsync(new Uri("http://ds4windows.com/Files/Virtual Bus Driver.zip"), exepath + "\\VBus.zip");
wb.DownloadFileAsync(new Uri("http://23.239.26.40/ds4windows/files/Virtual Bus Driver.zip"), exepath + "\\VBus.zip");
wb.DownloadProgressChanged += wb_DownloadProgressChanged;
wb.DownloadFileCompleted += wb_DownloadFileCompleted;
driverinstalling = true;
@ -131,7 +131,7 @@ namespace DS4Windows
private void button2_Click(object sender, EventArgs e)
{
Process.Start("http://www.microsoft.com/hardware/en-us/d/xbox-360-controller-for-windows");
Process.Start("http://www.microsoft.com/accessories/en-gb/d/xbox-360-controller-for-windows");
}
}
}

View File

@ -0,0 +1,251 @@
using System;
using System.Runtime.InteropServices;
using DS4Windows.DS4Library.CoreAudio;
namespace DS4Windows.DS4Library
{
public class DS4Audio
{
private IAudioEndpointVolume endpointVolume;
private static Guid IID_IAudioEndpointVolume = new Guid("5CDF2C82-841E-4546-9722-0CF74078229A");
private static readonly PropertyKey PKEY_Device_FriendlyName =
new PropertyKey(new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), 14);
public uint Volume
{
get
{
float pfLevel = 0;
if (endpointVolume != null)
endpointVolume.GetMasterVolumeLevelScalar(out pfLevel);
return Convert.ToUInt32(pfLevel * 100);
}
}
public uint getVolume()
{
float pfLevel = 0;
if (endpointVolume != null)
endpointVolume.GetMasterVolumeLevelScalar(out pfLevel);
return Convert.ToUInt32(pfLevel * 100);
}
public DS4Audio(DataFlow audioFlags = DataFlow.Render)
{
var audioEnumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
IMMDeviceCollection audioDevices;
audioEnumerator.EnumAudioEndpoints(audioFlags, DeviceState.Active, out audioDevices);
int numAudioDevices;
Marshal.ThrowExceptionForHR(audioDevices.GetCount(out numAudioDevices));
for (int deviceNumber = 0; deviceNumber < numAudioDevices; ++deviceNumber)
{
IMMDevice audioDevice;
Marshal.ThrowExceptionForHR(audioDevices.Item(deviceNumber, out audioDevice));
string deviceName = GetAudioDeviceName(ref audioDevice);
if (deviceName.Contains("DUALSHOCK®4 USB Wireless Adaptor"))
{
object interfacePointer;
Marshal.ThrowExceptionForHR(audioDevice.Activate(ref IID_IAudioEndpointVolume, ClsCtx.ALL, IntPtr.Zero, out interfacePointer));
endpointVolume = interfacePointer as IAudioEndpointVolume;
}
Marshal.ReleaseComObject(audioDevice);
}
Marshal.ReleaseComObject(audioDevices);
Marshal.ReleaseComObject(audioEnumerator);
}
~DS4Audio()
{
if (endpointVolume != null)
{
Marshal.ReleaseComObject(endpointVolume);
endpointVolume = null;
}
}
private string GetAudioDeviceName(ref IMMDevice audioDevice)
{
IPropertyStore propertyStore;
Marshal.ThrowExceptionForHR(audioDevice.OpenPropertyStore(StorageAccessMode.Read, out propertyStore));
int numProperties;
Marshal.ThrowExceptionForHR(propertyStore.GetCount(out numProperties));
string deviceName = String.Empty;
for (int propertyNum = 0; propertyNum < numProperties; ++propertyNum)
{
PropertyKey propertyKey;
Marshal.ThrowExceptionForHR(propertyStore.GetAt(propertyNum, out propertyKey));
if ((propertyKey.formatId == PKEY_Device_FriendlyName.formatId) && (propertyKey.propertyId == PKEY_Device_FriendlyName.propertyId))
{
PropVariant propertyValue;
Marshal.ThrowExceptionForHR(propertyStore.GetValue(ref propertyKey, out propertyValue));
deviceName = Marshal.PtrToStringUni(propertyValue.pointerValue);
break;
}
}
Marshal.ReleaseComObject(propertyStore);
return deviceName;
}
}
}
namespace DS4Windows.DS4Library.CoreAudio
{
public enum DataFlow
{
Render,
Capture,
All
};
[Flags]
public enum DeviceState
{
Active = 0x00000001,
Disabled = 0x00000002,
NotPresent = 0x00000004,
Unplugged = 0x00000008,
All = 0x0000000F
}
enum StorageAccessMode
{
Read,
Write,
ReadWrite
}
[Flags]
public enum ClsCtx
{
INPROC_SERVER = 0x1,
INPROC_HANDLER = 0x2,
LOCAL_SERVER = 0x4,
INPROC_SERVER16 = 0x8,
REMOTE_SERVER = 0x10,
INPROC_HANDLER16 = 0x20,
NO_CODE_DOWNLOAD = 0x400,
NO_CUSTOM_MARSHAL = 0x1000,
ENABLE_CODE_DOWNLOAD = 0x2000,
NO_FAILURE_LOG = 0x4000,
DISABLE_AAA = 0x8000,
ENABLE_AAA = 0x10000,
FROM_DEFAULT_CONTEXT = 0x20000,
ACTIVATE_32_BIT_SERVER = 0x40000,
ACTIVATE_64_BIT_SERVER = 0x80000,
ENABLE_CLOAKING = 0x100000,
PS_DLL = unchecked((int)0x80000000),
INPROC = INPROC_SERVER | INPROC_HANDLER,
SERVER = INPROC_SERVER | LOCAL_SERVER | REMOTE_SERVER,
ALL = SERVER | INPROC_HANDLER
}
public struct PropertyKey
{
public Guid formatId;
public int propertyId;
public PropertyKey(Guid formatId, int propertyId)
{
this.formatId = formatId;
this.propertyId = propertyId;
}
}
[StructLayout(LayoutKind.Explicit)]
public struct PropVariant
{
[FieldOffset(0)] private short vt;
[FieldOffset(2)] private short wReserved1;
[FieldOffset(4)] private short wReserved2;
[FieldOffset(6)] private short wReserved3;
[FieldOffset(8)] public IntPtr pointerValue;
}
[Guid("886d8eeb-8cf2-4446-8d02-cdba1dbdcf99"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IPropertyStore
{
int GetCount(out int propCount);
int GetAt(int property, out PropertyKey key);
int GetValue(ref PropertyKey key, out PropVariant value);
int SetValue(ref PropertyKey key, ref PropVariant value);
int Commit();
}
[Guid("D666063F-1587-4E43-81F1-B948E807363F"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDevice
{
int Activate(ref Guid id, ClsCtx clsCtx, IntPtr activationParams,
[MarshalAs(UnmanagedType.IUnknown)] out object interfacePointer);
int OpenPropertyStore(StorageAccessMode stgmAccess, out IPropertyStore properties);
int GetId([MarshalAs(UnmanagedType.LPWStr)] out string id);
}
[Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDeviceCollection
{
int GetCount(out int numDevices);
int Item(int deviceNumber, out IMMDevice device);
}
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDeviceEnumerator
{
int EnumAudioEndpoints(DataFlow dataFlow, DeviceState stateMask, out IMMDeviceCollection devices);
}
[ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
class MMDeviceEnumeratorComObject
{
}
[Guid("657804FA-D6AD-4496-8A60-352752AF4F89"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IAudioEndpointVolumeCallback
{
void OnNotify(IntPtr notifyData);
};
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IAudioEndpointVolume
{
int RegisterControlChangeNotify(IAudioEndpointVolumeCallback pNotify);
int UnregisterControlChangeNotify(IAudioEndpointVolumeCallback pNotify);
int GetChannelCount(out int pnChannelCount);
int SetMasterVolumeLevel(float fLevelDB, ref Guid pguidEventContext);
int SetMasterVolumeLevelScalar(float fLevel, ref Guid pguidEventContext);
int GetMasterVolumeLevel(out float pfLevelDB);
int GetMasterVolumeLevelScalar(out float pfLevel);
int SetChannelVolumeLevel(uint nChannel, float fLevelDB, ref Guid pguidEventContext);
int SetChannelVolumeLevelScalar(uint nChannel, float fLevel, ref Guid pguidEventContext);
int GetChannelVolumeLevel(uint nChannel, out float pfLevelDB);
int GetChannelVolumeLevelScalar(uint nChannel, out float pfLevel);
int SetMute([MarshalAs(UnmanagedType.Bool)] Boolean bMute, ref Guid pguidEventContext);
int GetMute(out bool pbMute);
int GetVolumeStepInfo(out uint pnStep, out uint pnStepCount);
int VolumeStepUp(ref Guid pguidEventContext);
int VolumeStepDown(ref Guid pguidEventContext);
int QueryHardwareSupport(out uint pdwHardwareSupportMask);
int GetVolumeRange(out float pflVolumeMindB, out float pflVolumeMaxdB, out float pflVolumeIncrementdB);
}
}

View File

@ -14,6 +14,7 @@ using System.Text;
using System.IO;
using System.Collections;
using System.Drawing;
using DS4Windows.DS4Library;
namespace DS4Windows
{
@ -28,12 +29,14 @@ namespace DS4Windows
green = c.G;
blue = c.B;
}
public DS4Color(byte r, byte g, byte b)
{
red = r;
green = g;
blue = b;
}
public override bool Equals(object obj)
{
if (obj is DS4Color)
@ -44,6 +47,7 @@ namespace DS4Windows
else
return false;
}
public Color ToColor => Color.FromArgb(red, green, blue);
public Color ToColorA
{
@ -83,10 +87,11 @@ namespace DS4Windows
}
catch { return false; }
}
public override string ToString() => $"Red: {red} Green: {green} Blue: {blue}";
}
public enum ConnectionType : byte { BT, USB }; // Prioritize Bluetooth when both are connected.
public enum ConnectionType : byte { BT, SONYWA, USB }; // Prioritize Bluetooth when both BT and USB are connected.
/**
* The haptics engine uses a stack of these states representing the light bar and rumble motor settings.
@ -99,10 +104,12 @@ namespace DS4Windows
public byte LightBarFlashDurationOn, LightBarFlashDurationOff;
public byte RumbleMotorStrengthLeftHeavySlow, RumbleMotorStrengthRightLightFast;
public bool RumbleMotorsExplicitlyOff;
public bool IsLightBarSet()
{
return LightBarExplicitlyOff || LightBarColor.red != 0 || LightBarColor.green != 0 || LightBarColor.blue != 0;
}
public bool IsRumbleSet()
{
return RumbleMotorsExplicitlyOff || RumbleMotorStrengthLeftHeavySlow != 0 || RumbleMotorStrengthRightLightFast != 0;
@ -113,6 +120,16 @@ namespace DS4Windows
{
private const int BT_OUTPUT_REPORT_LENGTH = 78;
private const int BT_INPUT_REPORT_LENGTH = 547;
// Use large value for worst case scenario
private const int READ_STREAM_TIMEOUT = 100;
// Isolated BT report can have latency as high as 15 ms
// due to hardware.
private const int WARN_INTERVAL_BT = 20;
private const int WARN_INTERVAL_USB = 10;
// Maximum values for battery level when no USB cable is connected
// and when a USB cable is connected
private const int BATTERY_MAX = 8;
private const int BATTERY_MAX_USB = 11;
private HidDevice hDevice;
private string Mac;
private DS4State cState = new DS4State();
@ -121,6 +138,7 @@ namespace DS4Windows
private byte[] accel = new byte[6];
private byte[] gyro = new byte[6];
private byte[] inputReport;
private byte[] inputReport2;
private byte[] btInputReport = null;
private byte[] outputReportBuffer, outputReport;
private readonly DS4Touchpad touchpad = null;
@ -131,30 +149,128 @@ namespace DS4Windows
private byte ledFlashOn, ledFlashOff;
private Thread ds4Input, ds4Output;
private int battery;
private DS4Audio audio = null;
private DS4Audio micAudio = null;
public DateTime lastActive = DateTime.UtcNow;
public DateTime firstActive = DateTime.UtcNow;
private bool charging;
private bool outputRumble = false;
private int warnInterval = WARN_INTERVAL_USB;
public int getWarnInterval()
{
return warnInterval;
}
private bool exitOutputThread = false;
private bool exitInputThread = false;
private object exitLocker = new object();
public event EventHandler<EventArgs> Report = null;
public event EventHandler<EventArgs> Removal = null;
public HidDevice HidDevice => hDevice;
public bool IsExclusive => HidDevice.IsExclusive;
public bool IsDisconnecting { get; private set; }
public bool isExclusive()
{
return HidDevice.IsExclusive;
}
private bool isDisconnecting = false;
public bool IsDisconnecting
{
get { return isDisconnecting; }
private set
{
this.isDisconnecting = value;
}
}
public bool isDisconnectingStatus()
{
return this.isDisconnecting;
}
private bool isRemoving = false;
public bool IsRemoving
{
get { return isRemoving; }
set
{
this.isRemoving = value;
}
}
private bool isRemoved = false;
public bool IsRemoved
{
get { return isRemoved; }
set
{
this.isRemoved = value;
}
}
public object removeLocker = new object();
public string MacAddress => Mac;
public string getMacAddress()
{
return this.Mac;
}
public ConnectionType ConnectionType => conType;
public int IdleTimeout { get; set; } // behavior only active when > 0
public ConnectionType getConnectionType()
{
return this.conType;
}
// behavior only active when > 0
private int idleTimeout = 0;
public int IdleTimeout
{
get { return idleTimeout; }
set
{
idleTimeout = value;
}
}
public int getIdleTimeout()
{
return idleTimeout;
}
public void setIdleTimeout(int value)
{
if (idleTimeout != value)
{
idleTimeout = value;
}
}
public int Battery => battery;
public int getBattery()
{
return battery;
}
public bool Charging => charging;
public bool isCharging()
{
return charging;
}
private long lastTimeElapsed = 0;
public long getLastTimeElapsed()
{
return lastTimeElapsed;
}
public byte RightLightFastRumble
{
get { return rightLightFastRumble; }
set
{
if (value == rightLightFastRumble) return;
if (rightLightFastRumble != value)
rightLightFastRumble = value;
}
}
@ -164,11 +280,16 @@ namespace DS4Windows
get { return leftHeavySlowRumble; }
set
{
if (value == leftHeavySlowRumble) return;
if (leftHeavySlowRumble != value)
leftHeavySlowRumble = value;
}
}
public byte getLeftHeavySlowRumble()
{
return leftHeavySlowRumble;
}
public DS4Color LightBarColor
{
get { return ligtBarColor; }
@ -193,6 +314,11 @@ namespace DS4Windows
}
}
public byte getLightBarOnDuration()
{
return ledFlashOn;
}
public byte LightBarOffDuration
{
get { return ledFlashOff; }
@ -205,24 +331,55 @@ namespace DS4Windows
}
}
public byte getLightBarOffDuration()
{
return ledFlashOff;
}
public DS4Touchpad Touchpad { get { return touchpad; } }
public DS4SixAxis SixAxis { get { return sixAxis; } }
public static ConnectionType HidConnectionType(HidDevice hidDevice)
{
return hidDevice.Capabilities.InputReportByteLength == 64 ? ConnectionType.USB : ConnectionType.BT;
ConnectionType result = ConnectionType.USB;
if (hidDevice.Capabilities.InputReportByteLength == 64)
{
if (hidDevice.Capabilities.NumberFeatureDataIndices == 22)
{
result = ConnectionType.SONYWA;
}
}
else
{
result = ConnectionType.BT;
}
return result;
}
private SynchronizationContext uiContext = null;
public DS4Device(HidDevice hidDevice)
{
hDevice = hidDevice;
conType = HidConnectionType(hDevice);
Mac = hDevice.readSerial();
if (conType == ConnectionType.USB)
if (conType == ConnectionType.USB || conType == ConnectionType.SONYWA)
{
inputReport = new byte[64];
inputReport2 = new byte[64];
outputReport = new byte[hDevice.Capabilities.OutputReportByteLength];
outputReportBuffer = new byte[hDevice.Capabilities.OutputReportByteLength];
if (conType == ConnectionType.USB)
{
warnInterval = WARN_INTERVAL_USB;
}
else
{
warnInterval = WARN_INTERVAL_BT;
audio = new DS4Audio();
micAudio = new DS4Audio(DS4Library.CoreAudio.DataFlow.Render);
}
}
else
{
@ -230,22 +387,41 @@ namespace DS4Windows
inputReport = new byte[btInputReport.Length - 2];
outputReport = new byte[BT_OUTPUT_REPORT_LENGTH];
outputReportBuffer = new byte[BT_OUTPUT_REPORT_LENGTH];
warnInterval = WARN_INTERVAL_BT;
}
touchpad = new DS4Touchpad();
sixAxis = new DS4SixAxis();
uiContext = SynchronizationContext.Current;
}
public void StartUpdate()
{
if (ds4Input == null)
{
Console.WriteLine(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + "> start");
if (!hDevice.IsFileStreamOpen())
{
hDevice.OpenFileStream(inputReport.Length);
}
//Console.WriteLine(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + "> start");
sendOutputReport(true); // initialize the output report
if (conType == ConnectionType.BT)
{
// Only use the output thread for Bluetooth connections.
// USB will utilize overlapped IO instead.
ds4Output = new Thread(performDs4Output);
ds4Output.Priority = ThreadPriority.AboveNormal;
ds4Output.Name = "DS4 Output thread: " + Mac;
ds4Output.IsBackground = true;
ds4Output.Start();
}
ds4Input = new Thread(performDs4Input);
ds4Input.Priority = ThreadPriority.AboveNormal;
ds4Input.Name = "DS4 Input thread: " + Mac;
ds4Input.IsBackground = true;
ds4Input.Start();
}
else
@ -254,11 +430,14 @@ namespace DS4Windows
public void StopUpdate()
{
if (ds4Input.ThreadState != System.Threading.ThreadState.Stopped || ds4Input.ThreadState != System.Threading.ThreadState.Aborted)
if (ds4Input != null &&
ds4Input.IsAlive && !ds4Input.ThreadState.HasFlag(System.Threading.ThreadState.Stopped) &&
!ds4Input.ThreadState.HasFlag(System.Threading.ThreadState.AbortRequested))
{
try
{
ds4Input.Abort();
exitInputThread = true;
//ds4Input.Abort();
ds4Input.Join();
}
catch (Exception e)
@ -266,16 +445,28 @@ namespace DS4Windows
Console.WriteLine(e.Message);
}
}
StopOutputUpdate();
}
private void StopOutputUpdate()
{
if (ds4Output.ThreadState != System.Threading.ThreadState.Stopped || ds4Output.ThreadState != System.Threading.ThreadState.Aborted)
lock (exitLocker)
{
if (ds4Output != null &&
ds4Output.IsAlive && !ds4Output.ThreadState.HasFlag(System.Threading.ThreadState.Stopped) &&
!ds4Output.ThreadState.HasFlag(System.Threading.ThreadState.AbortRequested))
{
try
{
ds4Output.Abort();
exitOutputThread = true;
/*lock (outputReport)
{
Monitor.PulseAll(outputReport);
}
*/
ds4Output.Interrupt();
ds4Output.Join();
}
catch (Exception e)
@ -284,6 +475,7 @@ namespace DS4Windows
}
}
}
}
private bool writeOutput()
{
@ -293,26 +485,25 @@ namespace DS4Windows
}
else
{
return hDevice.WriteOutputReportViaInterrupt(outputReport, 8);
return hDevice.WriteAsyncOutputReportViaInterrupt(outputReport);
}
}
private void performDs4Output()
{
lock (outputReport)
{
try
{
int lastError = 0;
while (true)
while (!exitOutputThread)
{
if (writeOutput())
bool result = false;
if (outputRumble)
{
lastError = 0;
if (testRumble.IsRumbleSet()) // repeat test rumbles periodically; rumble has auto-shut-off in the DS4 firmware
Monitor.Wait(outputReport, 10000); // DS4 firmware stops it after 5 seconds, so let the motors rest for that long, too.
else
Monitor.Wait(outputReport);
}
else
result = writeOutput();
if (!result)
{
int thisError = Marshal.GetLastWin32Error();
if (lastError != thisError)
@ -321,6 +512,27 @@ namespace DS4Windows
lastError = thisError;
}
}
else
{
outputRumble = false;
}
}
if (!outputRumble)
{
lastError = 0;
Monitor.Wait(outputReport);
/*if (testRumble.IsRumbleSet()) // repeat test rumbles periodically; rumble has auto-shut-off in the DS4 firmware
Monitor.Wait(outputReport, 10000); // DS4 firmware stops it after 5 seconds, so let the motors rest for that long, too.
else
Monitor.Wait(outputReport);
*/
}
}
}
catch (ThreadInterruptedException)
{
}
}
}
@ -330,49 +542,37 @@ namespace DS4Windows
{
return priorInputReport30 != 0xff;
}
private byte priorInputReport30 = 0xff;
public double Latency = 0;
bool warn;
public string error;
public bool firstReport = false;
private void performDs4Input()
{
firstActive = DateTime.UtcNow;
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<long> Latency = new List<long>();
NativeMethods.HidD_SetNumInputBuffers(hDevice.safeReadHandle.DangerousGetHandle(), 2);
List<long> Latency = new List<long>(100);
long oldtime = 0;
Stopwatch sw = new Stopwatch();
sw.Start();
while (true)
while (!exitInputThread)
{
string currerror = string.Empty;
Latency.Add(sw.ElapsedMilliseconds - oldtime);
oldtime = sw.ElapsedMilliseconds;
long curtime = sw.ElapsedMilliseconds;
this.lastTimeElapsed = curtime - oldtime;
Latency.Add(this.lastTimeElapsed);
oldtime = curtime;
if (Latency.Count > 100)
Latency.RemoveAt(0);
this.Latency = Latency.Average();
if (this.Latency > 10 && !warn && sw.ElapsedMilliseconds > 4000)
if (conType == ConnectionType.BT)
{
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;
//HidDevice.ReadStatus res = hDevice.ReadFile(btInputReport);
HidDevice.ReadStatus res = hDevice.ReadAsyncWithFileStream(btInputReport, READ_STREAM_TIMEOUT);
if (res == HidDevice.ReadStatus.Success)
{
Array.Copy(btInputReport, 2, inputReport, 0, inputReport.Length);
@ -382,32 +582,51 @@ namespace DS4Windows
Console.WriteLine(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + "> disconnect due to read failure: " + Marshal.GetLastWin32Error());
sendOutputReport(true); // Kick Windows into noticing the disconnection.
StopOutputUpdate();
IsDisconnecting = true;
isDisconnecting = true;
uiContext.Send(new SendOrPostCallback(delegate (object state4)
{
Removal?.Invoke(this, EventArgs.Empty);
}), null);
/*
if (Removal != null)
Removal(this, EventArgs.Empty);
*/
return;
}
}
else
{
HidDevice.ReadStatus res = hDevice.ReadFile(inputReport);
readTimeout.Enabled = false;
//HidDevice.ReadStatus res = hDevice.ReadFile(inputReport);
//Array.Clear(inputReport, 0, inputReport.Length);
HidDevice.ReadStatus res = hDevice.ReadAsyncWithFileStream(inputReport, READ_STREAM_TIMEOUT);
if (res != HidDevice.ReadStatus.Success)
{
Console.WriteLine(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + "> disconnect due to read failure: " + Marshal.GetLastWin32Error());
StopOutputUpdate();
IsDisconnecting = true;
if (Removal != null)
Removal(this, EventArgs.Empty);
isDisconnecting = true;
uiContext.Send(new SendOrPostCallback(delegate (object state4)
{
Removal?.Invoke(this, EventArgs.Empty);
}), null);
//if (Removal != null)
// Removal(this, EventArgs.Empty);
return;
}
else
{
//Array.Copy(inputReport2, 0, inputReport, 0, inputReport.Length);
}
if (ConnectionType == ConnectionType.BT && btInputReport[0] != 0x11)
}
if (conType == 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;
@ -418,23 +637,14 @@ namespace DS4Windows
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;
cState.Triangle = (inputReport[5] & (1 << 7)) != 0;
cState.Circle = (inputReport[5] & (1 << 6)) != 0;
cState.Cross = (inputReport[5] & (1 << 5)) != 0;
cState.Square = (inputReport[5] & (1 << 4)) != 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));
// First 4 bits denote dpad state. Clock representation
// with 8 meaning centered and 0 meaning DpadUp.
byte dpad_state = (byte)(inputReport[5] & 0x0F);
switch (dpad_state)
{
@ -446,17 +656,18 @@ namespace DS4Windows
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;
case 8:
default: 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.R3 = (inputReport[6] & (1 << 7)) != 0;
cState.L3 = (inputReport[6] & (1 << 6)) != 0;
cState.Options = (inputReport[6] & (1 << 5)) != 0;
cState.Share = (inputReport[6] & (1 << 4)) != 0;
cState.R1 = (inputReport[6] & (1 << 1)) != 0;
cState.L1 = (inputReport[6] & (1 << 0)) != 0;
cState.PS = ((byte)inputReport[7] & (1 << 0)) != 0;
cState.PS = (inputReport[7] & (1 << 0)) != 0;
cState.TouchButton = (inputReport[7] & (1 << 2 - 1)) != 0;
cState.FrameCounter = (byte)(inputReport[7] >> 2);
@ -468,19 +679,25 @@ namespace DS4Windows
try
{
charging = (inputReport[30] & 0x10) != 0;
battery = (inputReport[30] & 0x0f) * 10;
int maxBatteryValue = charging ? BATTERY_MAX_USB : BATTERY_MAX;
int tempBattery = (inputReport[30] & 0x0f) * 100 / maxBatteryValue;
battery = Math.Min((byte)tempBattery, (byte)100);
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"));
//Console.WriteLine(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + "> power subsystem octet: 0x" + inputReport[30].ToString("x02"));
}
}
catch { currerror = "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)
// Only care if one touch packet is detected. Other touch packets
// don't seem to contain relevant data. ds4drv does not use them either.
for (int touches = Math.Max((int)(inputReport[-1 + DS4Touchpad.TOUCHPAD_DATA_OFFSET - 1]), 1), touchOffset = 0; touches > 0; touches--, touchOffset += 9)
//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
@ -503,31 +720,70 @@ namespace DS4Windows
Console.Write(" " + inputReport[i].ToString("x2"));
Console.WriteLine();
} */
if (!isDS4Idle())
bool ds4Idle = cState.FrameCounter == pState.FrameCounter;
if (!ds4Idle)
{
isRemoved = false;
}
if (conType == ConnectionType.USB)
{
lastActive = utcNow;
if (conType == ConnectionType.BT)
}
else
{
bool shouldDisconnect = false;
if (IdleTimeout > 0)
int idleTime = idleTimeout;
if (!isRemoved && idleTime > 0)
{
if (isDS4Idle())
bool idleInput = isDS4Idle();
if (idleInput)
{
DateTime timeout = lastActive + TimeSpan.FromSeconds(IdleTimeout);
if (!Charging)
DateTime timeout = lastActive + TimeSpan.FromSeconds(idleTime);
if (!charging)
shouldDisconnect = utcNow >= timeout;
}
else
{
lastActive = utcNow;
}
if (shouldDisconnect && DisconnectBT())
}
else
{
lastActive = utcNow;
}
if (shouldDisconnect)
{
if (conType == ConnectionType.BT)
{
if (DisconnectBT(true))
return; // all done
}
// XXX fix initialization ordering so the null checks all go away
else if (conType == ConnectionType.SONYWA)
{
DisconnectDongle();
}
}
}
if (Report != null)
Report(this, EventArgs.Empty);
sendOutputReport(false);
bool syncWriteReport = true;
if (conType == ConnectionType.BT)
{
syncWriteReport = false;
}
sendOutputReport(syncWriteReport);
if (!string.IsNullOrEmpty(error))
error = string.Empty;
if (!string.IsNullOrEmpty(currerror))
error = currerror;
cState.CopyTo(pState);
}
}
@ -536,10 +792,12 @@ namespace DS4Windows
{
hDevice.flush_Queue();
}
private void sendOutputReport(bool synchronous)
{
setTestRumble();
setHapticState();
if (conType == ConnectionType.BT)
{
outputReportBuffer[0] = 0x11;
@ -564,19 +822,29 @@ namespace DS4Windows
outputReportBuffer[8] = LightBarColor.blue; //blue
outputReportBuffer[9] = ledFlashOn; //flash on duration
outputReportBuffer[10] = ledFlashOff; //flash off duration
if (conType == ConnectionType.SONYWA)
{
// Headphone volume levels
outputReportBuffer[19] = outputReportBuffer[20] = Convert.ToByte(audio.getVolume());
// Microphone volume level
outputReportBuffer[21] = Convert.ToByte(micAudio.getVolume());
}
}
bool quitOutputThread = false;
lock (outputReport)
{
if (synchronous)
{
outputRumble = false;
outputReportBuffer.CopyTo(outputReport, 0);
try
{
if (!writeOutput())
{
Console.WriteLine(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + "> encountered synchronous write failure: " + Marshal.GetLastWin32Error());
ds4Output.Abort();
ds4Output.Join();
quitOutputThread = true;
}
}
catch
@ -587,18 +855,25 @@ namespace DS4Windows
else
{
bool output = false;
for (int i = 0; !output && i < outputReport.Length; i++)
for (int i = 0, arlen = outputReport.Length; !output && i < arlen; i++)
output = outputReport[i] != outputReportBuffer[i];
if (output)
{
outputRumble = true;
outputReportBuffer.CopyTo(outputReport, 0);
Monitor.Pulse(outputReport);
}
}
}
if (quitOutputThread)
{
StopOutputUpdate();
}
}
public bool DisconnectBT()
public bool DisconnectBT(bool callRemoval = false)
{
if (Mac != null)
{
@ -613,38 +888,94 @@ namespace DS4Windows
// parse hex byte in reverse order
btAddr[5 - i] = Convert.ToByte(sbytes[i], 16);
}
long lbtAddr = BitConverter.ToInt64(btAddr, 0);
bool success = false;
// Wait for output report to be written
lock (outputReport)
{
NativeMethods.BLUETOOTH_FIND_RADIO_PARAMS p = new NativeMethods.BLUETOOTH_FIND_RADIO_PARAMS();
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)
{
IsDisconnecting = true;
StopOutputUpdate();
if (Removal != null)
Removal(this, EventArgs.Empty);
if (callRemoval)
{
uiContext.Send(new SendOrPostCallback(delegate (object state)
{
Removal?.Invoke(this, EventArgs.Empty);
}), null);
//Removal?.Invoke(this, EventArgs.Empty);
}
}
return success;
}
return false;
}
public bool DisconnectDongle(bool remove = false)
{
bool result = false;
byte[] disconnectReport = new byte[65];
disconnectReport[0] = 0xe2;
disconnectReport[1] = 0x02;
Array.Clear(disconnectReport, 2, 63);
lock (outputReport)
{
result = hDevice.WriteFeatureReport(disconnectReport);
}
if (result && remove)
{
isDisconnecting = true;
StopOutputUpdate();
uiContext.Send(new SendOrPostCallback(delegate (object state4)
{
Removal?.Invoke(this, EventArgs.Empty);
}), null);
/*
if (Removal != null)
Removal(this, EventArgs.Empty);
*/
}
else if (result && !remove)
{
isRemoved = true;
}
return result;
}
private DS4HapticState testRumble = new DS4HapticState();
public void setRumble(byte rightLightFastMotor, byte leftHeavySlowMotor)
{
testRumble.RumbleMotorStrengthRightLightFast = rightLightFastMotor;
@ -675,8 +1006,8 @@ namespace DS4Windows
public void getExposedState(DS4StateExposed expState, DS4State state)
{
cState.CopyTo(state);
expState.Accel = accel;
expState.Gyro = gyro;
expState.setAccel(accel);
expState.setGyro(gyro);
}
public void getCurrentState(DS4State state)
@ -720,26 +1051,30 @@ namespace DS4Windows
// Use the "most recently set" haptic state for each of light bar/motor.
private void setHapticState()
{
int i = 0;
DS4Color lightBarColor = LightBarColor;
byte lightBarFlashDurationOn = LightBarOnDuration, lightBarFlashDurationOff = LightBarOffDuration;
byte rumbleMotorStrengthLeftHeavySlow = LeftHeavySlowRumble, rumbleMotorStrengthRightLightFast = rightLightFastRumble;
foreach (DS4HapticState haptic in hapticState)
int hapticLen = hapticState.Length;
for (int i=0; i < hapticLen; i++)
{
if (i++ == hapticStackIndex)
DS4HapticState haptic = hapticState[i];
if (i == hapticStackIndex)
break; // rest haven't been used this time
if (haptic.IsLightBarSet())
{
lightBarColor = haptic.LightBarColor;
lightBarFlashDurationOn = haptic.LightBarFlashDurationOn;
lightBarFlashDurationOff = haptic.LightBarFlashDurationOff;
}
if (haptic.IsRumbleSet())
{
rumbleMotorStrengthLeftHeavySlow = haptic.RumbleMotorStrengthLeftHeavySlow;
rumbleMotorStrengthRightLightFast = haptic.RumbleMotorStrengthRightLightFast;
}
}
LightBarColor = lightBarColor;
LightBarOnDuration = lightBarFlashDurationOn;
LightBarOffDuration = lightBarFlashDurationOff;
@ -749,12 +1084,14 @@ namespace DS4Windows
public void pushHapticState(DS4HapticState hs)
{
if (hapticStackIndex == hapticState.Length)
int hapsLen = hapticState.Length;
if (hapticStackIndex == hapsLen)
{
DS4HapticState[] newHaptics = new DS4HapticState[hapticState.Length + 1];
Array.Copy(hapticState, newHaptics, hapticState.Length);
DS4HapticState[] newHaptics = new DS4HapticState[hapsLen + 1];
Array.Copy(hapticState, newHaptics, hapsLen);
hapticState = newHaptics;
}
hapticState[hapticStackIndex++] = hs;
}
@ -763,5 +1100,15 @@ namespace DS4Windows
{
return Mac;
}
public void runRemoval()
{
Removal?.Invoke(this, EventArgs.Empty);
}
public void removeReportHandlers()
{
this.Report = null;
}
}
}

View File

@ -23,6 +23,7 @@ namespace DS4Windows
{
deviceInstanceId = deviceInstanceId.Remove(deviceInstanceId.Length - 1);
}
return deviceInstanceId;
}
@ -36,10 +37,18 @@ namespace DS4Windows
// Sort Bluetooth first in case USB is also connected on the same controller.
hDevices = hDevices.OrderBy<HidDevice, ConnectionType>((HidDevice d) => { return DS4Device.HidConnectionType(d); });
foreach (HidDevice hDevice in hDevices)
List<HidDevice> tempList = hDevices.ToList();
int devCount = tempList.Count();
string devicePlural = "device" + (devCount == 0 || devCount > 1 ? "s" : "");
//Log.LogToGui("Found " + devCount + " possible " + devicePlural + ". Examining " + devicePlural + ".", false);
for (int i = 0; i < devCount; i++)
//foreach (HidDevice hDevice in hDevices)
{
HidDevice hDevice = tempList[i];
if (DevicePaths.Contains(hDevice.DevicePath))
continue; // BT/USB endpoint already open once
if (!hDevice.IsOpen)
{
hDevice.OpenDevice(isExclusiveMode);
@ -59,6 +68,7 @@ namespace DS4Windows
startInfo.Verb = "runas";
startInfo.Arguments = "re-enabledevice " + devicePathToInstanceId(hDevice.DevicePath);
Process child = Process.Start(startInfo);
if (!child.WaitForExit(5000))
{
child.Kill();
@ -81,21 +91,22 @@ namespace DS4Windows
if (isExclusiveMode && !hDevice.IsOpen)
hDevice.OpenDevice(false);
}
if (hDevice.IsOpen)
{
if (Devices.ContainsKey(hDevice.readSerial()))
string serial = hDevice.readSerial();
bool validSerial = !serial.Equals("00:00:00:00:00:00");
if (Devices.ContainsKey(serial))
continue; // happens when the BT endpoint already is open and the USB is plugged into the same host
else
{
DS4Device ds4Device = new DS4Device(hDevice);
ds4Device.Removal += On_Removal;
//ds4Device.Removal += On_Removal;
Devices.Add(ds4Device.MacAddress, ds4Device);
DevicePaths.Add(hDevice.DevicePath);
ds4Device.StartUpdate();
}
}
}
}
}
@ -131,11 +142,15 @@ namespace DS4Windows
lock (Devices)
{
IEnumerable<DS4Device> devices = getDS4Controllers();
foreach (DS4Device device in devices)
//foreach (DS4Device device in devices)
for (int i = 0, devCount = devices.Count(); i < devCount; i++)
{
DS4Device device = devices.ElementAt(i);
device.StopUpdate();
//device.runRemoval();
device.HidDevice.CloseDevice();
}
Devices.Clear();
DevicePaths.Clear();
}
@ -188,6 +203,9 @@ namespace DS4Windows
{
throw new Exception("Error disabling device, error code = " + Marshal.GetLastWin32Error());
}
System.Threading.Thread.Sleep(50);
propChangeParams.stateChange = NativeMethods.DICS_ENABLE;
success = NativeMethods.SetupDiSetClassInstallParams(deviceInfoSet, ref deviceInfoData, ref propChangeParams, Marshal.SizeOf(propChangeParams));
if (!success)

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DS4Windows
{

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DS4Windows
{
@ -17,6 +14,9 @@ namespace DS4Windows
public byte FrameCounter; // 0, 1, 2...62, 63, 0....
public byte TouchPacketCounter; // we break these out automatically
public byte Battery; // 0 for charging, 10/20/30/40/50/60/70/80/90/100 for percentage of full
public double LSAngle; // Calculated bearing of the LS X,Y coordinates
public double RSAngle; // Calculated bearing of the RS X,Y coordinates
public static readonly int DEFAULT_AXISDIR_VALUE = 127;
public DS4State()
{
@ -29,6 +29,8 @@ namespace DS4Windows
FrameCounter = 255; // only actually has 6 bits, so this is a null indicator
TouchPacketCounter = 255; // 8 bits, no great junk value
Battery = 0;
LSAngle = 0.0;
RSAngle = 0.0;
}
public DS4State(DS4State state)
@ -65,6 +67,8 @@ namespace DS4Windows
RY = state.RY;
FrameCounter = state.FrameCounter;
Battery = state.Battery;
LSAngle = state.LSAngle;
RSAngle = state.RSAngle;
}
public DS4State Clone()
@ -106,7 +110,19 @@ namespace DS4Windows
state.RY = RY;
state.FrameCounter = FrameCounter;
state.Battery = Battery;
state.LSAngle = LSAngle;
state.RSAngle = RSAngle;
}
public void calculateStickAngles()
{
double lsangle = Math.Atan2((LX - 127), -(LY - 127));
lsangle = (lsangle >= 0 ? lsangle : (2 * Math.PI + lsangle)) * 180 / Math.PI;
LSAngle = lsangle;
double rsangle = Math.Atan2((RX - 127), -(RY - 127));
rsangle = (rsangle >= 0 ? rsangle : (2 * Math.PI + rsangle)) * 180 / Math.PI;
RSAngle = rsangle;
}
}
}

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DS4Windows
{
public class DS4StateExposed
@ -48,8 +44,17 @@ namespace DS4Windows
/// <summary> Holds raw DS4 input data from 14 to 19 </summary>
public byte[] Accel { set { accel = value; } }
public void setAccel(byte[] value)
{
accel = value;
}
/// <summary> Holds raw DS4 input data from 20 to 25 </summary>
public byte[] Gyro { set { gyro = value; } }
public void setGyro(byte[] value)
{
gyro = value;
}
/// <summary> Yaw leftward/counter-clockwise/turn to port or larboard side </summary>
/// <remarks> Add double the previous result to this delta and divide by three.</remarks>
@ -63,11 +68,28 @@ namespace DS4Windows
/// <summary> R side of controller upward </summary>
/// <remarks> Add double the previous result to this delta and divide by three.</remarks>
public int GyroX { get { return (short)((ushort)(gyro[0] << 8) | gyro[1]) / 64; } }
public int getGyroX()
{
return (short)((ushort)(gyro[0] << 8) | gyro[1]) / 64;
}
/// <summary> touchpad and button face side of controller upward </summary>
/// <remarks> Add double the previous result to this delta and divide by three.</remarks>
public int GyroY { get { return (short)((ushort)(gyro[2] << 8) | gyro[3]) / 64; } }
public int getGyroY()
{
return (short)((ushort)(gyro[2] << 8) | gyro[3]) / 64;
}
/// <summary> Audio/expansion ports upward and light bar/shoulders/bumpers/USB port downward </summary>
/// <remarks> Add double the previous result to this delta and divide by three.</remarks>
public int GyroZ { get { return (short)((ushort)(gyro[4] << 8) | gyro[5]) / 64; } }
public int getGyroZ()
{
return (short)((ushort)(gyro[4] << 8) | gyro[5]) / 64;
}
}
}

View File

@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace DS4Windows
{
public class TouchpadEventArgs : EventArgs

View File

@ -30,9 +30,12 @@
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<DefineConstants>
</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup>
<StartupObject>DS4Windows.Program</StartupObject>
@ -52,7 +55,33 @@
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="JetBrains.Annotations, Version=10.2.1.0, Culture=neutral, PublicKeyToken=1010a0d8d6380325, processorArchitecture=MSIL">
<HintPath>..\packages\TaskScheduler.2.5.23\lib\net40\JetBrains.Annotations.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Win32.TaskScheduler, Version=2.5.23.0, Culture=neutral, PublicKeyToken=0d013ddd5178a2ae, processorArchitecture=MSIL">
<HintPath>..\packages\TaskScheduler.2.5.23\lib\net40\Microsoft.Win32.TaskScheduler.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
@ -72,6 +101,7 @@
<ItemGroup>
<Compile Include="DS4Control\ControlSerivce.cs" />
<Compile Include="DS4Control\DS4LightBar.cs" />
<Compile Include="DS4Control\DS4StateFieldMapping.cs" />
<Compile Include="DS4Control\InputMethods.cs" />
<Compile Include="DS4Control\ITouchpadBehaviour.cs" />
<Compile Include="DS4Control\Log.cs" />
@ -98,6 +128,7 @@
<Compile Include="DS4Control\X360Device.designer.cs">
<DependentUpon>X360Device.cs</DependentUpon>
</Compile>
<Compile Include="DS4Library\DS4Audio.cs" />
<Compile Include="DS4Library\DS4Device.cs" />
<Compile Include="DS4Library\DS4Devices.cs" />
<Compile Include="DS4Library\DS4Sixaxis.cs" />
@ -1004,6 +1035,7 @@
<EmbeddedResource Include="Properties\Resources.zh-hans.resx" />
<EmbeddedResource Include="Properties\Resources.zh-Hant.resx" />
<None Include="app.manifest" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
@ -1034,7 +1066,7 @@
</COMReference>
</ItemGroup>
<ItemGroup>
<Content Include="HidLibrary\LICENSE.htm" />
<Content Include="HidLibrary\LICENSE" />
<Content Include="Resources\360 fades.png" />
<None Include="Resources\360 map.png" />
<None Include="Resources\360 highlight.png" />
@ -1117,6 +1149,7 @@
<Content Include="Resources\xbox_360_controller.png" />
<Content Include="Resources\Y.png" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -83,6 +83,25 @@ namespace DS4Windows
IsExclusive = isExclusive;
}
public void OpenFileStream(int reportSize)
{
if (fileStream == null && !safeReadHandle.IsInvalid)
{
fileStream = new FileStream(safeReadHandle, FileAccess.ReadWrite, reportSize, true);
}
}
public bool IsFileStreamOpen()
{
bool result = false;
if (fileStream != null)
{
result = !fileStream.SafeFileHandle.IsInvalid && !fileStream.SafeFileHandle.IsClosed;
}
return result;
}
public void CloseDevice()
{
if (!IsOpen) return;
@ -110,6 +129,17 @@ namespace DS4Windows
return NativeMethods.HidD_GetInputReport(safeReadHandle, data, data.Length);
}
public bool WriteFeatureReport(byte[] data)
{
bool result = false;
if (IsOpen && safeReadHandle != null)
{
result = NativeMethods.HidD_SetFeature(safeReadHandle, data, data.Length);
}
return result;
}
private static HidDeviceAttributes GetDeviceAttributes(SafeFileHandle hidHandle)
{
@ -129,21 +159,37 @@ namespace DS4Windows
NativeMethods.HidP_GetCaps(preparsedDataPointer, ref capabilities);
NativeMethods.HidD_FreePreparsedData(preparsedDataPointer);
}
return new HidDeviceCapabilities(capabilities);
}
private void closeFileStreamIO()
{
if (fileStream != null)
{
try
{
fileStream.Close();
}
catch (IOException) { }
catch (OperationCanceledException) { }
}
fileStream = null;
Console.WriteLine("Close fs");
if (safeReadHandle != null && !safeReadHandle.IsInvalid)
{
try
{
if (!safeReadHandle.IsClosed)
{
safeReadHandle.Close();
Console.WriteLine("Close sh");
}
}
catch (IOException) { }
}
safeReadHandle = null;
}
@ -173,6 +219,7 @@ namespace DS4Windows
return ReadStatus.ReadError;
}
}
public ReadStatus ReadFile(byte[] inputBuffer)
{
if (safeReadHandle == null)
@ -202,10 +249,10 @@ namespace DS4Windows
if (safeReadHandle == null)
safeReadHandle = OpenHandle(_devicePath, true);
if (fileStream == null && !safeReadHandle.IsInvalid)
fileStream = new FileStream(safeReadHandle, FileAccess.ReadWrite, inputBuffer.Length, false);
fileStream = new FileStream(safeReadHandle, FileAccess.ReadWrite, inputBuffer.Length, true);
if (!safeReadHandle.IsInvalid && fileStream.CanRead)
{
Task<ReadStatus> readFileTask = new Task<ReadStatus>(() => ReadWithFileStreamTask(inputBuffer));
readFileTask.Start();
bool success = readFileTask.Wait(timeout);
@ -242,8 +289,45 @@ namespace DS4Windows
}
}
return ReadStatus.ReadError;
}
public ReadStatus ReadAsyncWithFileStream(byte[] inputBuffer, int timeout)
{
try
{
if (safeReadHandle == null)
safeReadHandle = OpenHandle(_devicePath, true);
if (fileStream == null && !safeReadHandle.IsInvalid)
fileStream = new FileStream(safeReadHandle, FileAccess.ReadWrite, inputBuffer.Length, true);
if (!safeReadHandle.IsInvalid && fileStream.CanRead)
{
Task<int> readTask = fileStream.ReadAsync(inputBuffer, 0, inputBuffer.Length);
readTask.Wait(timeout);
if (readTask.Result > 0)
{
return ReadStatus.Success;
}
else
{
return ReadStatus.NoDataRead;
}
}
}
catch (Exception e)
{
if (e is AggregateException)
{
Console.WriteLine(e.Message);
return ReadStatus.WaitFail;
}
else
{
return ReadStatus.ReadError;
}
}
return ReadStatus.ReadError;
}
@ -285,7 +369,7 @@ namespace DS4Windows
}
if (fileStream == null && !safeReadHandle.IsInvalid)
{
fileStream = new FileStream(safeReadHandle, FileAccess.ReadWrite, outputBuffer.Length, false);
fileStream = new FileStream(safeReadHandle, FileAccess.ReadWrite, outputBuffer.Length, true);
}
if (fileStream != null && fileStream.CanWrite && !safeReadHandle.IsInvalid)
{
@ -304,6 +388,36 @@ namespace DS4Windows
}
public bool WriteAsyncOutputReportViaInterrupt(byte[] outputBuffer)
{
try
{
if (safeReadHandle == null)
{
safeReadHandle = OpenHandle(_devicePath, true);
}
if (fileStream == null && !safeReadHandle.IsInvalid)
{
fileStream = new FileStream(safeReadHandle, FileAccess.ReadWrite, outputBuffer.Length, true);
}
if (fileStream != null && fileStream.CanWrite && !safeReadHandle.IsInvalid)
{
Task writeTask = fileStream.WriteAsync(outputBuffer, 0, outputBuffer.Length);
//fileStream.Write(outputBuffer, 0, outputBuffer.Length);
return true;
}
else
{
return false;
}
}
catch (Exception)
{
return false;
}
}
private SafeFileHandle OpenHandle(String devicePathName, Boolean isExclusive)
{
SafeFileHandle hidHandle;
@ -312,11 +426,11 @@ namespace DS4Windows
{
if (isExclusive)
{
hidHandle = NativeMethods.CreateFile(devicePathName, NativeMethods.GENERIC_READ | NativeMethods.GENERIC_WRITE, 0, IntPtr.Zero, NativeMethods.OpenExisting, 0, 0);
hidHandle = NativeMethods.CreateFile(devicePathName, NativeMethods.GENERIC_READ | NativeMethods.GENERIC_WRITE, 0, IntPtr.Zero, NativeMethods.OpenExisting, 0x20000000 | 0x80000000 | NativeMethods.FILE_FLAG_OVERLAPPED, 0);
}
else
{
hidHandle = NativeMethods.CreateFile(devicePathName, NativeMethods.GENERIC_READ | NativeMethods.GENERIC_WRITE, NativeMethods.FILE_SHARE_READ | NativeMethods.FILE_SHARE_WRITE, IntPtr.Zero, NativeMethods.OpenExisting, 0, 0);
hidHandle = NativeMethods.CreateFile(devicePathName, NativeMethods.GENERIC_READ | NativeMethods.GENERIC_WRITE, NativeMethods.FILE_SHARE_READ | NativeMethods.FILE_SHARE_WRITE, IntPtr.Zero, NativeMethods.OpenExisting, 0x20000000 | 0x80000000 | NativeMethods.FILE_FLAG_OVERLAPPED, 0);
}
}
catch (Exception)

View File

@ -0,0 +1,18 @@
Copyright (c) 2010 Ultraviolet Catastrophe
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,739 +0,0 @@
<!DOCTYPE html>
<html>
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# githubog: http://ogp.me/ns/fb/githubog#">
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>HidLibrary/LICENSE at master · mikeobrien/HidLibrary · GitHub</title>
<link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub" />
<link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub" />
<link rel="apple-touch-icon" sizes="57x57" href="/apple-touch-icon-114.png" />
<link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon-114.png" />
<link rel="apple-touch-icon" sizes="72x72" href="/apple-touch-icon-144.png" />
<link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-144.png" />
<link rel="logo" type="image/svg" href="https://github-media-downloads.s3.amazonaws.com/github-logo.svg" />
<meta property="og:image" content="https://github.global.ssl.fastly.net/images/modules/logos_page/Octocat.png">
<meta name="hostname" content="github-fe124-cp1-prd.iad.github.net">
<meta name="ruby" content="ruby 2.1.0p0-github-tcmalloc (60139581e1) [x86_64-linux]">
<link rel="assets" href="https://github.global.ssl.fastly.net/">
<link rel="conduit-xhr" href="https://ghconduit.com:25035/">
<link rel="xhr-socket" href="/_sockets" />
<meta name="msapplication-TileImage" content="/windows-tile.png" />
<meta name="msapplication-TileColor" content="#ffffff" />
<meta name="selected-link" value="repo_source" data-pjax-transient />
<meta content="collector.githubapp.com" name="octolytics-host" /><meta content="collector-cdn.github.com" name="octolytics-script-host" /><meta content="github" name="octolytics-app-id" /><meta content="87178203:4B92:28E6A2:52D598B8" name="octolytics-dimension-request_id" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<meta content="authenticity_token" name="csrf-param" />
<meta content="AAeSffXRAam6Bf/AzN/4KUjR6SAPkbVO9N7hC8xppV4=" name="csrf-token" />
<link href="https://github.global.ssl.fastly.net/assets/github-4b925c759ed9bc7974bc328563cd4a70197d6ac9.css" media="all" rel="stylesheet" type="text/css" />
<link href="https://github.global.ssl.fastly.net/assets/github2-0598952211c73091a719781ed3c02cad780eac93.css" media="all" rel="stylesheet" type="text/css" />
<script src="https://github.global.ssl.fastly.net/assets/frameworks-e075736093c12b6b7444888c0c54d072c23c2a9a.js" type="text/javascript"></script>
<script src="https://github.global.ssl.fastly.net/assets/github-bf24f7542f2bfe4c53cfbd818e3480f9e3c9b969.js" type="text/javascript"></script>
<meta http-equiv="x-pjax-version" content="a69fa8c704f4aa3b75677a6903ec30ee">
<link data-pjax-transient rel='permalink' href='/mikeobrien/HidLibrary/blob/ea06e067816f81d4a27847f97d6da5cb89b9ae81/LICENSE'>
<meta property="og:title" content="HidLibrary"/>
<meta property="og:type" content="githubog:gitrepository"/>
<meta property="og:url" content="https://github.com/mikeobrien/HidLibrary"/>
<meta property="og:image" content="https://github.global.ssl.fastly.net/images/gravatars/gravatar-user-420.png"/>
<meta property="og:site_name" content="GitHub"/>
<meta property="og:description" content="HidLibrary - This library enables you to enumerate and communicate with Hid compatible USB devices in .NET."/>
<meta name="description" content="HidLibrary - This library enables you to enumerate and communicate with Hid compatible USB devices in .NET." />
<meta content="187817" name="octolytics-dimension-user_id" /><meta content="mikeobrien" name="octolytics-dimension-user_login" /><meta content="830324" name="octolytics-dimension-repository_id" /><meta content="mikeobrien/HidLibrary" name="octolytics-dimension-repository_nwo" /><meta content="true" name="octolytics-dimension-repository_public" /><meta content="false" name="octolytics-dimension-repository_is_fork" /><meta content="830324" name="octolytics-dimension-repository_network_root_id" /><meta content="mikeobrien/HidLibrary" name="octolytics-dimension-repository_network_root_nwo" />
<link href="https://github.com/mikeobrien/HidLibrary/commits/master.atom" rel="alternate" title="Recent Commits to HidLibrary:master" type="application/atom+xml" />
</head>
<body class="logged_out env-production windows vis-public page-blob">
<div class="wrapper">
<div class="header header-logged-out">
<div class="container clearfix">
<a class="header-logo-wordmark" href="https://github.com/">
<span class="mega-octicon octicon-logo-github"></span>
</a>
<div class="header-actions">
<a class="button primary" href="/join">Sign up</a>
<a class="button signin" href="/login?return_to=%2Fmikeobrien%2FHidLibrary%2Fblob%2Fmaster%2FLICENSE">Sign in</a>
</div>
<div class="command-bar js-command-bar in-repository">
<ul class="top-nav">
<li class="explore"><a href="/explore">Explore</a></li>
<li class="features"><a href="/features">Features</a></li>
<li class="enterprise"><a href="https://enterprise.github.com/">Enterprise</a></li>
<li class="blog"><a href="/blog">Blog</a></li>
</ul>
<form accept-charset="UTF-8" action="/search" class="command-bar-form" id="top_search_form" method="get">
<input type="text" data-hotkey="/ s" name="q" id="js-command-bar-field" placeholder="Search or type a command" tabindex="1" autocapitalize="off"
data-repo="mikeobrien/HidLibrary"
data-branch="master"
data-sha="59d7991355c6403ce0fd98f568483f054e942d8f"
>
<input type="hidden" name="nwo" value="mikeobrien/HidLibrary" />
<div class="select-menu js-menu-container js-select-menu search-context-select-menu">
<span class="minibutton select-menu-button js-menu-target">
<span class="js-select-button">This repository</span>
</span>
<div class="select-menu-modal-holder js-menu-content js-navigation-container">
<div class="select-menu-modal">
<div class="select-menu-item js-navigation-item js-this-repository-navigation-item selected">
<span class="select-menu-item-icon octicon octicon-check"></span>
<input type="radio" class="js-search-this-repository" name="search_target" value="repository" checked="checked" />
<div class="select-menu-item-text js-select-button-text">This repository</div>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item js-all-repositories-navigation-item">
<span class="select-menu-item-icon octicon octicon-check"></span>
<input type="radio" name="search_target" value="global" />
<div class="select-menu-item-text js-select-button-text">All repositories</div>
</div> <!-- /.select-menu-item -->
</div>
</div>
</div>
<span class="octicon help tooltipped downwards" title="Show command bar help">
<span class="octicon octicon-question"></span>
</span>
<input type="hidden" name="ref" value="cmdform">
</form>
</div>
</div>
</div>
<div class="site" itemscope itemtype="http://schema.org/WebPage">
<div class="pagehead repohead instapaper_ignore readability-menu">
<div class="container">
<ul class="pagehead-actions">
<li>
<a href="/login?return_to=%2Fmikeobrien%2FHidLibrary"
class="minibutton with-count js-toggler-target star-button tooltipped upwards"
title="You must be signed in to use this feature" rel="nofollow">
<span class="octicon octicon-star"></span>Star
</a>
<a class="social-count js-social-count" href="/mikeobrien/HidLibrary/stargazers">
58
</a>
</li>
<li>
<a href="/login?return_to=%2Fmikeobrien%2FHidLibrary"
class="minibutton with-count js-toggler-target fork-button tooltipped upwards"
title="You must be signed in to fork a repository" rel="nofollow">
<span class="octicon octicon-git-branch"></span>Fork
</a>
<a href="/mikeobrien/HidLibrary/network" class="social-count">
25
</a>
</li>
</ul>
<h1 itemscope itemtype="http://data-vocabulary.org/Breadcrumb" class="entry-title public">
<span class="repo-label"><span>public</span></span>
<span class="mega-octicon octicon-repo"></span>
<span class="author">
<a href="/mikeobrien" class="url fn" itemprop="url" rel="author"><span itemprop="title">mikeobrien</span></a>
</span>
<span class="repohead-name-divider">/</span>
<strong><a href="/mikeobrien/HidLibrary" class="js-current-repository js-repo-home-link">HidLibrary</a></strong>
<span class="page-context-loader">
<img alt="Octocat-spinner-32" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32.gif" width="16" />
</span>
</h1>
</div><!-- /.container -->
</div><!-- /.repohead -->
<div class="container">
<div class="repository-with-sidebar repo-container ">
<div class="repository-sidebar">
<div class="sunken-menu vertical-right repo-nav js-repo-nav js-repository-container-pjax js-octicon-loaders">
<div class="sunken-menu-contents">
<ul class="sunken-menu-group">
<li class="tooltipped leftwards" title="Code">
<a href="/mikeobrien/HidLibrary" aria-label="Code" class="selected js-selected-navigation-item sunken-menu-item" data-gotokey="c" data-pjax="true" data-selected-links="repo_source repo_downloads repo_commits repo_tags repo_branches /mikeobrien/HidLibrary">
<span class="octicon octicon-code"></span> <span class="full-word">Code</span>
<img alt="Octocat-spinner-32" class="mini-loader" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
<li class="tooltipped leftwards" title="Issues">
<a href="/mikeobrien/HidLibrary/issues" aria-label="Issues" class="js-selected-navigation-item sunken-menu-item js-disable-pjax" data-gotokey="i" data-selected-links="repo_issues /mikeobrien/HidLibrary/issues">
<span class="octicon octicon-issue-opened"></span> <span class="full-word">Issues</span>
<span class='counter'>20</span>
<img alt="Octocat-spinner-32" class="mini-loader" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
<li class="tooltipped leftwards" title="Pull Requests">
<a href="/mikeobrien/HidLibrary/pulls" aria-label="Pull Requests" class="js-selected-navigation-item sunken-menu-item js-disable-pjax" data-gotokey="p" data-selected-links="repo_pulls /mikeobrien/HidLibrary/pulls">
<span class="octicon octicon-git-pull-request"></span> <span class="full-word">Pull Requests</span>
<span class='counter'>1</span>
<img alt="Octocat-spinner-32" class="mini-loader" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
<li class="tooltipped leftwards" title="Wiki">
<a href="/mikeobrien/HidLibrary/wiki" aria-label="Wiki" class="js-selected-navigation-item sunken-menu-item" data-pjax="true" data-selected-links="repo_wiki /mikeobrien/HidLibrary/wiki">
<span class="octicon octicon-book"></span> <span class="full-word">Wiki</span>
<img alt="Octocat-spinner-32" class="mini-loader" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
</ul>
<div class="sunken-menu-separator"></div>
<ul class="sunken-menu-group">
<li class="tooltipped leftwards" title="Pulse">
<a href="/mikeobrien/HidLibrary/pulse" aria-label="Pulse" class="js-selected-navigation-item sunken-menu-item" data-pjax="true" data-selected-links="pulse /mikeobrien/HidLibrary/pulse">
<span class="octicon octicon-pulse"></span> <span class="full-word">Pulse</span>
<img alt="Octocat-spinner-32" class="mini-loader" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
<li class="tooltipped leftwards" title="Graphs">
<a href="/mikeobrien/HidLibrary/graphs" aria-label="Graphs" class="js-selected-navigation-item sunken-menu-item" data-pjax="true" data-selected-links="repo_graphs repo_contributors /mikeobrien/HidLibrary/graphs">
<span class="octicon octicon-graph"></span> <span class="full-word">Graphs</span>
<img alt="Octocat-spinner-32" class="mini-loader" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
<li class="tooltipped leftwards" title="Network">
<a href="/mikeobrien/HidLibrary/network" aria-label="Network" class="js-selected-navigation-item sunken-menu-item js-disable-pjax" data-selected-links="repo_network /mikeobrien/HidLibrary/network">
<span class="octicon octicon-git-branch"></span> <span class="full-word">Network</span>
<img alt="Octocat-spinner-32" class="mini-loader" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
</ul>
</div>
</div>
<div class="only-with-full-nav">
<div class="clone-url open"
data-protocol-type="http"
data-url="/users/set_protocol?protocol_selector=http&amp;protocol_type=clone">
<h3><strong>HTTPS</strong> clone URL</h3>
<div class="clone-url-box">
<input type="text" class="clone js-url-field"
value="https://github.com/mikeobrien/HidLibrary.git" readonly="readonly">
<span class="js-zeroclipboard url-box-clippy minibutton zeroclipboard-button" data-clipboard-text="https://github.com/mikeobrien/HidLibrary.git" data-copied-hint="copied!" title="copy to clipboard"><span class="octicon octicon-clippy"></span></span>
</div>
</div>
<div class="clone-url "
data-protocol-type="subversion"
data-url="/users/set_protocol?protocol_selector=subversion&amp;protocol_type=clone">
<h3><strong>Subversion</strong> checkout URL</h3>
<div class="clone-url-box">
<input type="text" class="clone js-url-field"
value="https://github.com/mikeobrien/HidLibrary" readonly="readonly">
<span class="js-zeroclipboard url-box-clippy minibutton zeroclipboard-button" data-clipboard-text="https://github.com/mikeobrien/HidLibrary" data-copied-hint="copied!" title="copy to clipboard"><span class="octicon octicon-clippy"></span></span>
</div>
</div>
<p class="clone-options">You can clone with
<a href="#" class="js-clone-selector" data-protocol="http">HTTPS</a>,
or <a href="#" class="js-clone-selector" data-protocol="subversion">Subversion</a>.
<span class="octicon help tooltipped upwards" title="Get help on which URL is right for you.">
<a href="https://help.github.com/articles/which-remote-url-should-i-use">
<span class="octicon octicon-question"></span>
</a>
</span>
</p>
<a href="http://windows.github.com" class="minibutton sidebar-button">
<span class="octicon octicon-device-desktop"></span>
Clone in Desktop
</a>
<a href="/mikeobrien/HidLibrary/archive/master.zip"
class="minibutton sidebar-button"
title="Download this repository as a zip file"
rel="nofollow">
<span class="octicon octicon-cloud-download"></span>
Download ZIP
</a>
</div>
</div><!-- /.repository-sidebar -->
<div id="js-repo-pjax-container" class="repository-content context-loader-container" data-pjax-container>
<!-- blob contrib key: blob_contributors:v21:cd71f166ab60e838fa56ed6b9690fbfd -->
<p title="This is a placeholder element" class="js-history-link-replace hidden"></p>
<a href="/mikeobrien/HidLibrary/find/master" data-pjax data-hotkey="t" class="js-show-file-finder" style="display:none">Show File Finder</a>
<div class="file-navigation">
<div class="select-menu js-menu-container js-select-menu" >
<span class="minibutton select-menu-button js-menu-target" data-hotkey="w"
data-master-branch="master"
data-ref="master"
role="button" aria-label="Switch branches or tags" tabindex="0">
<span class="octicon octicon-git-branch"></span>
<i>branch:</i>
<span class="js-select-button">master</span>
</span>
<div class="select-menu-modal-holder js-menu-content js-navigation-container" data-pjax>
<div class="select-menu-modal">
<div class="select-menu-header">
<span class="select-menu-title">Switch branches/tags</span>
<span class="octicon octicon-remove-close js-menu-close"></span>
</div> <!-- /.select-menu-header -->
<div class="select-menu-filters">
<div class="select-menu-text-filter">
<input type="text" aria-label="Filter branches/tags" id="context-commitish-filter-field" class="js-filterable-field js-navigation-enable" placeholder="Filter branches/tags">
</div>
<div class="select-menu-tabs">
<ul>
<li class="select-menu-tab">
<a href="#" data-tab-filter="branches" class="js-select-menu-tab">Branches</a>
</li>
<li class="select-menu-tab">
<a href="#" data-tab-filter="tags" class="js-select-menu-tab">Tags</a>
</li>
</ul>
</div><!-- /.select-menu-tabs -->
</div><!-- /.select-menu-filters -->
<div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="branches">
<div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring">
<div class="select-menu-item js-navigation-item selected">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/blob/master/LICENSE"
data-name="master"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="master">master</a>
</div> <!-- /.select-menu-item -->
</div>
<div class="select-menu-no-results">Nothing to show</div>
</div> <!-- /.select-menu-list -->
<div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="tags">
<div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring">
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.2.23.0/LICENSE"
data-name="v3.2.23.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.2.23.0">v3.2.23.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.2.22.0/LICENSE"
data-name="v3.2.22.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.2.22.0">v3.2.22.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.2.20.0/LICENSE"
data-name="v3.2.20.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.2.20.0">v3.2.20.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.2.19.0/LICENSE"
data-name="v3.2.19.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.2.19.0">v3.2.19.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.2.18.0/LICENSE"
data-name="v3.2.18.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.2.18.0">v3.2.18.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.2.17.0/LICENSE"
data-name="v3.2.17.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.2.17.0">v3.2.17.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.2.16.0/LICENSE"
data-name="v3.2.16.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.2.16.0">v3.2.16.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.2.12.0/LICENSE"
data-name="v3.2.12.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.2.12.0">v3.2.12.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.2.11.0/LICENSE"
data-name="v3.2.11.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.2.11.0">v3.2.11.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.2.10.0/LICENSE"
data-name="v3.2.10.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.2.10.0">v3.2.10.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.2.9.0/LICENSE"
data-name="v3.2.9.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.2.9.0">v3.2.9.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.2.8.0/LICENSE"
data-name="v3.2.8.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.2.8.0">v3.2.8.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.2.7.0/LICENSE"
data-name="v3.2.7.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.2.7.0">v3.2.7.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.2.6.0/LICENSE"
data-name="v3.2.6.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.2.6.0">v3.2.6.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.2.5.0/LICENSE"
data-name="v3.2.5.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.2.5.0">v3.2.5.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.2.4.0/LICENSE"
data-name="v3.2.4.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.2.4.0">v3.2.4.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.2.3.0/LICENSE"
data-name="v3.2.3.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.2.3.0">v3.2.3.0</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/v3.0.5/LICENSE"
data-name="v3.0.5"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="v3.0.5">v3.0.5</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/mikeobrien/HidLibrary/tree/hidlibrary-v3.2.2.0/LICENSE"
data-name="hidlibrary-v3.2.2.0"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="hidlibrary-v3.2.2.0">hidlibrary-v3.2.2.0</a>
</div> <!-- /.select-menu-item -->
</div>
<div class="select-menu-no-results">Nothing to show</div>
</div> <!-- /.select-menu-list -->
</div> <!-- /.select-menu-modal -->
</div> <!-- /.select-menu-modal-holder -->
</div> <!-- /.select-menu -->
<div class="breadcrumb">
<span class='repo-root js-repo-root'><span itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb"><a href="/mikeobrien/HidLibrary" data-branch="master" data-direction="back" data-pjax="true" itemscope="url"><span itemprop="title">HidLibrary</span></a></span></span><span class="separator"> / </span><strong class="final-path">LICENSE</strong> <span class="js-zeroclipboard minibutton zeroclipboard-button" data-clipboard-text="LICENSE" data-copied-hint="copied!" title="copy to clipboard"><span class="octicon octicon-clippy"></span></span>
</div>
</div>
<div class="commit file-history-tease">
<img class="main-avatar" height="24" src="https://2.gravatar.com/avatar/15505f4513a7f05d16b71bde610827c5?d=https%3A%2F%2Fidenticons.github.com%2F3469cadaa0686184b49895d4249a3480.png&amp;r=x&amp;s=140" width="24" />
<span class="author"><a href="/mikeobrien" rel="author">mikeobrien</a></span>
<time class="js-relative-date" datetime="2010-08-11T07:50:59-07:00" title="2010-08-11 07:50:59">August 11, 2010</time>
<div class="commit-title">
<a href="/mikeobrien/HidLibrary/commit/57632b64175c0a06b3214027cb325704d3210ec9" class="message" data-pjax="true" title="Initial commit">Initial commit</a>
</div>
<div class="participation">
<p class="quickstat"><a href="#blob_contributors_box" rel="facebox"><strong>1</strong> contributor</a></p>
</div>
<div id="blob_contributors_box" style="display:none">
<h2 class="facebox-header">Users who have contributed to this file</h2>
<ul class="facebox-user-list">
<li class="facebox-user-list-item">
<img height="24" src="https://2.gravatar.com/avatar/15505f4513a7f05d16b71bde610827c5?d=https%3A%2F%2Fidenticons.github.com%2F3469cadaa0686184b49895d4249a3480.png&amp;r=x&amp;s=140" width="24" />
<a href="/mikeobrien">mikeobrien</a>
</li>
</ul>
</div>
</div>
<div id="files" class="bubble">
<div class="file">
<div class="meta">
<div class="info">
<span class="icon"><b class="octicon octicon-file-text"></b></span>
<span class="mode" title="File Mode">file</span>
<span>18 lines (15 sloc)</span>
<span>1.094 kb</span>
</div>
<div class="actions">
<div class="button-group">
<a class="minibutton tooltipped leftwards"
href="http://windows.github.com" title="Open this file in GitHub for Windows">
<span class="octicon octicon-device-desktop"></span> Open
</a>
<a class="minibutton disabled tooltipped leftwards" href="#"
title="You must be signed in to make or propose changes">Edit</a>
<a href="/mikeobrien/HidLibrary/raw/master/LICENSE" class="button minibutton " id="raw-url">Raw</a>
<a href="/mikeobrien/HidLibrary/blame/master/LICENSE" class="button minibutton ">Blame</a>
<a href="/mikeobrien/HidLibrary/commits/master/LICENSE" class="button minibutton " rel="nofollow">History</a>
</div><!-- /.button-group -->
<a class="minibutton danger disabled empty-icon tooltipped leftwards" href="#"
title="You must be signed in to make or propose changes">
Delete
</a>
</div><!-- /.actions -->
</div>
<div class="blob-wrapper data type-text js-blob-data">
<table class="file-code file-diff">
<tr class="file-code-line">
<td class="blob-line-nums">
<span id="L1" rel="#L1">1</span>
<span id="L2" rel="#L2">2</span>
<span id="L3" rel="#L3">3</span>
<span id="L4" rel="#L4">4</span>
<span id="L5" rel="#L5">5</span>
<span id="L6" rel="#L6">6</span>
<span id="L7" rel="#L7">7</span>
<span id="L8" rel="#L8">8</span>
<span id="L9" rel="#L9">9</span>
<span id="L10" rel="#L10">10</span>
<span id="L11" rel="#L11">11</span>
<span id="L12" rel="#L12">12</span>
<span id="L13" rel="#L13">13</span>
<span id="L14" rel="#L14">14</span>
<span id="L15" rel="#L15">15</span>
<span id="L16" rel="#L16">16</span>
<span id="L17" rel="#L17">17</span>
<span id="L18" rel="#L18">18</span>
</td>
<td class="blob-line-code">
<div class="code-body highlight"><pre><div class='line' id='LC1'>Copyright (c) 2010 Ultraviolet Catastrophe</div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'>Permission is hereby granted, free of charge, to any person obtaining a copy </div><div class='line' id='LC4'>of this software and associated documentation files (the &quot;Software&quot;), to deal </div><div class='line' id='LC5'>in the Software without restriction, including without limitation the rights </div><div class='line' id='LC6'>to use, copy, modify, merge, publish, distribute, sublicense, and/or sell </div><div class='line' id='LC7'>copies of the Software, and to permit persons to whom the Software is furnished </div><div class='line' id='LC8'>to do so, subject to the following conditions:</div><div class='line' id='LC9'><br/></div><div class='line' id='LC10'>The above copyright notice and this permission notice shall be included in all </div><div class='line' id='LC11'>copies or substantial portions of the Software.</div><div class='line' id='LC12'><br/></div><div class='line' id='LC13'>THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, </div><div class='line' id='LC14'>INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A </div><div class='line' id='LC15'>PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT </div><div class='line' id='LC16'>HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION </div><div class='line' id='LC17'>OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE </div><div class='line' id='LC18'>SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</div></pre></div>
</td>
</tr>
</table>
</div>
</div>
</div>
<a href="#jump-to-line" rel="facebox[.linejump]" data-hotkey="l" class="js-jump-to-line" style="display:none">Jump to Line</a>
<div id="jump-to-line" style="display:none">
<form accept-charset="UTF-8" class="js-jump-to-line-form">
<input class="linejump-input js-jump-to-line-field" type="text" placeholder="Jump to line&hellip;" autofocus>
<button type="submit" class="button">Go</button>
</form>
</div>
</div>
</div><!-- /.repo-container -->
<div class="modal-backdrop"></div>
</div><!-- /.container -->
</div><!-- /.site -->
</div><!-- /.wrapper -->
<div class="container">
<div class="site-footer">
<ul class="site-footer-links right">
<li><a href="https://status.github.com/">Status</a></li>
<li><a href="http://developer.github.com">API</a></li>
<li><a href="http://training.github.com">Training</a></li>
<li><a href="http://shop.github.com">Shop</a></li>
<li><a href="/blog">Blog</a></li>
<li><a href="/about">About</a></li>
</ul>
<a href="/">
<span class="mega-octicon octicon-mark-github" title="GitHub"></span>
</a>
<ul class="site-footer-links">
<li>&copy; 2014 <span title="0.02103s from github-fe124-cp1-prd.iad.github.net">GitHub</span>, Inc.</li>
<li><a href="/site/terms">Terms</a></li>
<li><a href="/site/privacy">Privacy</a></li>
<li><a href="/security">Security</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</div><!-- /.site-footer -->
</div><!-- /.container -->
<div class="fullscreen-overlay js-fullscreen-overlay" id="fullscreen_overlay">
<div class="fullscreen-container js-fullscreen-container">
<div class="textarea-wrap">
<textarea name="fullscreen-contents" id="fullscreen-contents" class="js-fullscreen-contents" placeholder="" data-suggester="fullscreen_suggester"></textarea>
<div class="suggester-container">
<div class="suggester fullscreen-suggester js-navigation-container" id="fullscreen_suggester"
data-url="/mikeobrien/HidLibrary/suggestions/commit">
</div>
</div>
</div>
</div>
<div class="fullscreen-sidebar">
<a href="#" class="exit-fullscreen js-exit-fullscreen tooltipped leftwards" title="Exit Zen Mode">
<span class="mega-octicon octicon-screen-normal"></span>
</a>
<a href="#" class="theme-switcher js-theme-switcher tooltipped leftwards"
title="Switch themes">
<span class="octicon octicon-color-mode"></span>
</a>
</div>
</div>
<div id="ajax-error-message" class="flash flash-error">
<span class="octicon octicon-alert"></span>
<a href="#" class="octicon octicon-remove-close close ajax-error-dismiss"></a>
Something went wrong with that request. Please try again.
</div>
</body>
</html>

View File

@ -74,10 +74,10 @@ namespace DS4Windows
static internal extern IntPtr CreateEvent(ref SECURITY_ATTRIBUTES securityAttributes, int bManualReset, int bInitialState, string lpName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static internal extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, ref SECURITY_ATTRIBUTES lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile);
static internal extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, ref SECURITY_ATTRIBUTES lpSecurityAttributes, int dwCreationDisposition, uint dwFlagsAndAttributes, int hTemplateFile);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern SafeFileHandle CreateFile(String lpFileName, UInt32 dwDesiredAccess, Int32 dwShareMode, IntPtr lpSecurityAttributes, Int32 dwCreationDisposition, Int32 dwFlagsAndAttributes, Int32 hTemplateFile);
internal static extern SafeFileHandle CreateFile(String lpFileName, UInt32 dwDesiredAccess, Int32 dwShareMode, IntPtr lpSecurityAttributes, Int32 dwCreationDisposition, UInt32 dwFlagsAndAttributes, Int32 hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
static internal extern bool ReadFile(IntPtr hFile, [Out] byte[] lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);

View File

@ -5,6 +5,7 @@ using System.Runtime.InteropServices;
using System.Diagnostics;
using System.ComponentModel;
using System.Globalization;
using Microsoft.Win32.TaskScheduler;
namespace DS4Windows
{
@ -32,7 +33,7 @@ namespace DS4Windows
static void Main(string[] args)
{
//Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("he");
for (int i = 0; i < args.Length; i++)
for (int i = 0, argsLen = args.Length; i < argsLen; i++)
{
string s = args[i];
if (s == "driverinstall" || s == "-driverinstall")
@ -58,8 +59,21 @@ namespace DS4Windows
return;
}
}
else if (s == "runtask" || s == "-runtask")
{
TaskService ts = new TaskService();
Task tasker = ts.FindTask("RunDS4Windows");
if (tasker != null)
{
tasker.Run("");
}
Environment.ExitCode = 0;
return;
}
}
System.Runtime.GCSettings.LatencyMode = System.Runtime.GCLatencyMode.LowLatency;
try
{
Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.High;
@ -68,6 +82,7 @@ namespace DS4Windows
{
// Ignore problems raising the priority.
}
try
{
// another instance is already running if OpenExsting succeeds.
@ -77,6 +92,7 @@ namespace DS4Windows
return; // return immediatly.
}
catch { /* don't care about errors */ }
// Create the Event handle
threadComEvent = new EventWaitHandle(false, EventResetMode.AutoReset, SingleAppComEventName);
CreateInterAppComThread();

View File

@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DS4Windows")]
[assembly: AssemblyCopyright("Copyright © Scarlet.Crush Productions 2012, 2013; InhexSTER, HecticSeptic, electrobrains 2013, 2014; Jays2Kings 2013, 2014, 2015")]
[assembly: AssemblyCopyright("Copyright © Scarlet.Crush Productions 2012, 2013; InhexSTER, HecticSeptic, electrobrains 2013, 2014; Jays2Kings 2013, 2014, 2015, 2016; Ryochan7 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// 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.4.52")]
[assembly: AssemblyFileVersion("1.4.52")]
[assembly: AssemblyVersion("1.4.69")]
[assembly: AssemblyFileVersion("1.4.69")]

View File

@ -293,7 +293,7 @@ namespace DS4Windows.Properties {
}
/// <summary>
/// Looks up a localized string similar to Color by Battey %.
/// Looks up a localized string similar to Color by Battery %.
/// </summary>
internal static string ColorByBattery {
get {
@ -412,7 +412,7 @@ namespace DS4Windows.Properties {
}
/// <summary>
/// Looks up a localized string similar to Dim by Battey %.
/// Looks up a localized string similar to Dim by Battery %.
/// </summary>
internal static string DimByBattery {
get {
@ -1573,6 +1573,15 @@ namespace DS4Windows.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Tells Windows to start DS4Windows after login.
/// </summary>
internal static string RunAtStartup {
get {
return ResourceManager.GetString("RunAtStartup", resourceCulture);
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@ -1945,6 +1954,15 @@ namespace DS4Windows.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to You need to run DS4Windows as the Administrator in order to activate this mode..
/// </summary>
internal static string UACTask {
get {
return ResourceManager.GetString("UACTask", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Unassigned.
/// </summary>

View File

@ -263,7 +263,7 @@
<value>Charging: *number*%</value>
</data>
<data name="ColorByBattery" xml:space="preserve">
<value>Color by Battey %</value>
<value>Color by Battery %</value>
</data>
<data name="Connecting" xml:space="preserve">
<value>Connecting...</value>
@ -296,7 +296,7 @@
<value>Delete Profile?</value>
</data>
<data name="DimByBattery" xml:space="preserve">
<value>Dim by Battey %</value>
<value>Dim by Battery %</value>
</data>
<data name="Disconnected" xml:space="preserve">
<value>Disconnected</value>
@ -775,4 +775,10 @@
<data name="SelectMacro" xml:space="preserve">
<value>Select a macro</value>
</data>
<data name="RunAtStartup" xml:space="preserve">
<value>Tells Windows to start DS4Windows after login</value>
</data>
<data name="UACTask" xml:space="preserve">
<value>You need to run DS4Windows as the Administrator in order to activate this mode.</value>
</data>
</root>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 573 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 928 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 534 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 350 KiB

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 394 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 361 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 791 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 859 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 825 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 KiB

After

Width:  |  Height:  |  Size: 370 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 780 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 527 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 575 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 519 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 506 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 496 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 1010 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 550 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 361 KiB

After

Width:  |  Height:  |  Size: 125 KiB

Some files were not shown because too many files have changed in this diff Show More