mirror of
https://github.com/cemu-project/DS4Windows.git
synced 2025-02-16 16:09:13 +01:00
Added output slot manager. Added plug and unplug delay of 100 ms for output devices.
Related to issue #879
This commit is contained in:
parent
424b456175
commit
21518134fc
@ -50,6 +50,7 @@ namespace DS4Windows
|
||||
public bool suspending;
|
||||
//SoundPlayer sp = new SoundPlayer();
|
||||
private UdpServer _udpServer;
|
||||
private OutputSlotManager outputslotMan;
|
||||
|
||||
private class X360Data
|
||||
{
|
||||
@ -193,6 +194,8 @@ namespace DS4Windows
|
||||
PreviousState[i] = new DS4State();
|
||||
ExposedState[i] = new DS4StateExposed(CurrentState[i]);
|
||||
}
|
||||
|
||||
outputslotMan = new OutputSlotManager();
|
||||
}
|
||||
|
||||
private void TestQueueBus(Action temp)
|
||||
@ -366,58 +369,53 @@ namespace DS4Windows
|
||||
{
|
||||
if (contType == OutContType.X360)
|
||||
{
|
||||
//LogDebug("Plugging in X360 Controller for input #" + (index + 1));
|
||||
LogDebug("Plugging in X360 Controller for input #" + (index + 1));
|
||||
activeOutDevType[index] = OutContType.X360;
|
||||
|
||||
Xbox360OutDevice tempXbox = new Xbox360OutDevice(vigemTestClient);
|
||||
//Xbox360OutDevice tempXbox = outputslotMan.AllocateController(OutContType.X360, vigemTestClient)
|
||||
// as Xbox360OutDevice;
|
||||
outputDevices[index] = tempXbox;
|
||||
//Xbox360OutDevice tempXbox = new Xbox360OutDevice(vigemTestClient);
|
||||
Xbox360OutDevice tempXbox = outputslotMan.AllocateController(OutContType.X360, vigemTestClient)
|
||||
as Xbox360OutDevice;
|
||||
//outputDevices[index] = tempXbox;
|
||||
int devIndex = index;
|
||||
tempXbox.cont.FeedbackReceived += (sender, args) =>
|
||||
{
|
||||
SetDevRumble(device, args.LargeMotor, args.SmallMotor, devIndex);
|
||||
};
|
||||
|
||||
//outputslotMan.DeferredPlugin(tempXbox, index, outputDevices);
|
||||
tempXbox.Connect();
|
||||
LogDebug("X360 Controller #" + (index + 1) + " connected");
|
||||
outputslotMan.DeferredPlugin(tempXbox, index, outputDevices);
|
||||
}
|
||||
else if (contType == OutContType.DS4)
|
||||
{
|
||||
//LogDebug("Plugging in DS4 Controller for input #" + (index + 1));
|
||||
LogDebug("Plugging in DS4 Controller for input #" + (index + 1));
|
||||
activeOutDevType[index] = OutContType.DS4;
|
||||
DS4OutDevice tempDS4 = new DS4OutDevice(vigemTestClient);
|
||||
//DS4OutDevice tempDS4 = outputslotMan.AllocateController(OutContType.DS4, vigemTestClient)
|
||||
// as DS4OutDevice;
|
||||
outputDevices[index] = tempDS4;
|
||||
//DS4OutDevice tempDS4 = new DS4OutDevice(vigemTestClient);
|
||||
DS4OutDevice tempDS4 = outputslotMan.AllocateController(OutContType.DS4, vigemTestClient)
|
||||
as DS4OutDevice;
|
||||
//outputDevices[index] = tempDS4;
|
||||
int devIndex = index;
|
||||
tempDS4.cont.FeedbackReceived += (sender, args) =>
|
||||
{
|
||||
SetDevRumble(device, args.LargeMotor, args.SmallMotor, devIndex);
|
||||
};
|
||||
|
||||
//outputslotMan.DeferredPlugin(tempDS4, index, outputDevices);
|
||||
tempDS4.Connect();
|
||||
LogDebug("DS4 Controller #" + (index + 1) + " connected");
|
||||
outputslotMan.DeferredPlugin(tempDS4, index, outputDevices);
|
||||
}
|
||||
}
|
||||
|
||||
useDInputOnly[index] = false;
|
||||
}
|
||||
|
||||
public void UnplugOutDev(int index, DS4Device device)
|
||||
public void UnplugOutDev(int index, DS4Device device, bool immediate = false)
|
||||
{
|
||||
if (!useDInputOnly[index])
|
||||
{
|
||||
//OutContType contType = Global.OutContType[index];
|
||||
string tempType = outputDevices[index].GetDeviceType();
|
||||
LogDebug("Unplugging " + tempType + " Controller for input #" + (index + 1), false);
|
||||
OutputDevice dev = outputDevices[index];
|
||||
outputDevices[index] = null;
|
||||
activeOutDevType[index] = OutContType.None;
|
||||
//outputslotMan.DeferredRemoval(dev);
|
||||
dev.Disconnect();
|
||||
LogDebug(tempType + " Controller # " + (index + 1) + " unplugged");
|
||||
outputslotMan.DeferredRemoval(dev, index, outputDevices, immediate);
|
||||
useDInputOnly[index] = true;
|
||||
}
|
||||
}
|
||||
@ -646,10 +644,15 @@ namespace DS4Windows
|
||||
}
|
||||
|
||||
CurrentState[i].Battery = PreviousState[i].Battery = 0; // Reset for the next connection's initial status change.
|
||||
outputDevices[i]?.Disconnect();
|
||||
outputDevices[i] = null;
|
||||
useDInputOnly[i] = true;
|
||||
Global.activeOutDevType[i] = OutContType.None;
|
||||
OutputDevice tempout = outputDevices[i];
|
||||
if (tempout != null)
|
||||
{
|
||||
UnplugOutDev(i, tempDevice, true);
|
||||
}
|
||||
|
||||
//outputDevices[i] = null;
|
||||
//useDInputOnly[i] = true;
|
||||
//Global.activeOutDevType[i] = OutContType.None;
|
||||
DS4Controllers[i] = null;
|
||||
touchPad[i] = null;
|
||||
lag[i] = false;
|
||||
@ -669,6 +672,11 @@ namespace DS4Windows
|
||||
if (showlog)
|
||||
LogDebug(Properties.Resources.StoppedDS4Windows);
|
||||
|
||||
while (outputslotMan.RunningQueue)
|
||||
{
|
||||
Thread.SpinWait(500);
|
||||
}
|
||||
|
||||
stopViGEm();
|
||||
}
|
||||
|
||||
|
146
DS4Windows/DS4Control/OutputSlotManager.cs
Normal file
146
DS4Windows/DS4Control/OutputSlotManager.cs
Normal file
@ -0,0 +1,146 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Nefarius.ViGEm.Client;
|
||||
|
||||
namespace DS4Windows
|
||||
{
|
||||
public class OutputSlotManager
|
||||
{
|
||||
private const int DELAY_TIME = 100; // measured in ms
|
||||
|
||||
private Dictionary<int, OutputDevice> devictDict = new Dictionary<int, OutputDevice>();
|
||||
private Dictionary<OutputDevice, int> revDevictDict = new Dictionary<OutputDevice, int>();
|
||||
private OutputDevice[] outputDevices = new OutputDevice[4];
|
||||
private Queue<Action> actions = new Queue<Action>();
|
||||
private object actionLock = new object();
|
||||
private bool runningQueue;
|
||||
|
||||
public bool RunningQueue { get => runningQueue; }
|
||||
|
||||
public OutputDevice AllocateController(OutContType contType, ViGEmClient client)
|
||||
{
|
||||
OutputDevice outputDevice = null;
|
||||
switch(contType)
|
||||
{
|
||||
case OutContType.X360:
|
||||
outputDevice = new Xbox360OutDevice(client);
|
||||
break;
|
||||
case OutContType.DS4:
|
||||
outputDevice = new DS4OutDevice(client);
|
||||
break;
|
||||
case OutContType.None:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return outputDevice;
|
||||
}
|
||||
|
||||
private int FindSlot()
|
||||
{
|
||||
int result = -1;
|
||||
for (int i = 0; i < outputDevices.Length && result == -1; i++)
|
||||
{
|
||||
OutputDevice tempdev = outputDevices[i];
|
||||
if (tempdev == null)
|
||||
{
|
||||
result = i;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void LaunchEvents()
|
||||
{
|
||||
bool hasItems = false;
|
||||
Action act = null;
|
||||
lock (actionLock)
|
||||
{
|
||||
hasItems = actions.Count > 0;
|
||||
}
|
||||
|
||||
while (hasItems)
|
||||
{
|
||||
lock (actionLock)
|
||||
{
|
||||
act = actions.Dequeue();
|
||||
}
|
||||
|
||||
act.Invoke();
|
||||
|
||||
lock (actionLock)
|
||||
{
|
||||
hasItems = actions.Count > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void PrepareEventTask()
|
||||
{
|
||||
if (!runningQueue)
|
||||
{
|
||||
runningQueue = true;
|
||||
Task.Run(() =>
|
||||
{
|
||||
LaunchEvents();
|
||||
runningQueue = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void DeferredPlugin(OutputDevice outputDevice, int inIdx, OutputDevice[] outdevs)
|
||||
{
|
||||
Action tempAction = new Action(() =>
|
||||
{
|
||||
int slot = FindSlot();
|
||||
if (slot != -1)
|
||||
{
|
||||
outputDevice.Connect();
|
||||
outputDevices[slot] = outputDevice;
|
||||
devictDict.Add(slot, outputDevice);
|
||||
revDevictDict.Add(outputDevice, slot);
|
||||
Task.Delay(DELAY_TIME).Wait();
|
||||
outdevs[inIdx] = outputDevice;
|
||||
}
|
||||
});
|
||||
|
||||
lock (actionLock)
|
||||
{
|
||||
actions.Enqueue(tempAction);
|
||||
}
|
||||
|
||||
PrepareEventTask();
|
||||
}
|
||||
|
||||
public void DeferredRemoval(OutputDevice outputDevice, int inIdx, OutputDevice[] outdevs, bool immediate = false)
|
||||
{
|
||||
Action tempAction = new Action(() =>
|
||||
{
|
||||
if (revDevictDict.ContainsKey(outputDevice))
|
||||
{
|
||||
int slot = revDevictDict[outputDevice];
|
||||
outputDevices[slot] = null;
|
||||
devictDict.Remove(slot);
|
||||
revDevictDict.Remove(outputDevice);
|
||||
outputDevice.Disconnect();
|
||||
outdevs[inIdx] = null;
|
||||
if (!immediate)
|
||||
{
|
||||
Task.Delay(DELAY_TIME).Wait();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
lock (actionLock)
|
||||
{
|
||||
actions.Enqueue(tempAction);
|
||||
}
|
||||
|
||||
PrepareEventTask();
|
||||
}
|
||||
}
|
||||
}
|
@ -152,6 +152,7 @@
|
||||
<Compile Include="DS4Control\MouseCursor.cs" />
|
||||
<Compile Include="DS4Control\MouseWheel.cs" />
|
||||
<Compile Include="DS4Control\OutputDevice.cs" />
|
||||
<Compile Include="DS4Control\OutputSlotManager.cs" />
|
||||
<Compile Include="DS4Control\ProfilePropGroups.cs" />
|
||||
<Compile Include="DS4Control\ScpUtil.cs" />
|
||||
<Compile Include="DS4Control\UdpServer.cs" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user