Make the platform lights slider update directly when dragged, so we can delay config updates.
This is just a safeguard to prevent hammering the EEPROM erase cycles. It also makes the platform slider update more smoothly (previously it would only update at a few FPS since it was using config changes).
This commit is contained in:
parent
48fe72af4a
commit
102fe2f9f9
@ -96,6 +96,23 @@ SMX_API void SMX_SetLights2(const char *lightData, int lightDataSize)
|
|||||||
|
|
||||||
SMXManager::g_pSMX->SetLights(lights);
|
SMXManager::g_pSMX->SetLights(lights);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is internal for SMXConfig. These lights aren't meant to be animated.
|
||||||
|
SMX_API void SMX_SetPlatformLights(const char lightData[88*3], int lightDataSize)
|
||||||
|
{
|
||||||
|
if(lightDataSize != 88*3)
|
||||||
|
{
|
||||||
|
Log(ssprintf("SMX_SetPlatformLights: lightDataSize is invalid (must be %i)\n",
|
||||||
|
88*3));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string lights[2];
|
||||||
|
lights[0] = string(lightData, 44*3);
|
||||||
|
lights[1] = string(lightData + 44*3, 44*3);
|
||||||
|
SMXManager::g_pSMX->SetPlatformLights(lights);
|
||||||
|
}
|
||||||
|
|
||||||
SMX_API void SMX_ReenableAutoLights() { SMXManager::g_pSMX->ReenableAutoLights(); }
|
SMX_API void SMX_ReenableAutoLights() { SMXManager::g_pSMX->ReenableAutoLights(); }
|
||||||
SMX_API const char *SMX_Version() { return SMX_BUILD_VERSION; }
|
SMX_API const char *SMX_Version() { return SMX_BUILD_VERSION; }
|
||||||
|
|
||||||
|
@ -334,6 +334,17 @@ void SMX::SMXDevice::SendConfig()
|
|||||||
if(m_bWaitingForConfigResponse)
|
if(m_bWaitingForConfigResponse)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Rate limit updating the configuration, to prevent excess EEPROM wear. This is just
|
||||||
|
// a safeguard in case applications try to change the configuration in realtime. If we've
|
||||||
|
// written the configuration recently, stop. We'll write the most recent configuration
|
||||||
|
// once enough time has passed. This is hidden to the application, since GetConfig returns
|
||||||
|
// wanted_config if it's set.
|
||||||
|
const float fTimeBetweenConfigUpdates = 1.0f;
|
||||||
|
double fNow = SMX::GetMonotonicTime();
|
||||||
|
if(m_fDelayConfigUpdatesUntil > fNow)
|
||||||
|
return;
|
||||||
|
m_fDelayConfigUpdatesUntil = fNow + 1.0f;
|
||||||
|
|
||||||
SMXDeviceInfo deviceInfo = m_pConnection->GetDeviceInfo();
|
SMXDeviceInfo deviceInfo = m_pConnection->GetDeviceInfo();
|
||||||
|
|
||||||
// Write configuration command. This is "w" in versions 1-4, and "W" in versions 5
|
// Write configuration command. This is "w" in versions 1-4, and "W" in versions 5
|
||||||
|
@ -105,6 +105,7 @@ private:
|
|||||||
SMXConfig config;
|
SMXConfig config;
|
||||||
vector<uint8_t> rawConfig;
|
vector<uint8_t> rawConfig;
|
||||||
bool m_bHaveConfig = false;
|
bool m_bHaveConfig = false;
|
||||||
|
double m_fDelayConfigUpdatesUntil = 0;
|
||||||
|
|
||||||
// This is the configuration the user has set, if he's changed anything. We send this to
|
// This is the configuration the user has set, if he's changed anything. We send this to
|
||||||
// the device if m_bSendConfig is true. Once we send it once, m_bSendConfig is cleared, and
|
// the device if m_bSendConfig is true. Once we send it once, m_bSendConfig is cleared, and
|
||||||
|
@ -485,6 +485,47 @@ void SMX::SMXManager::SetLights(const string sPanelLights[2])
|
|||||||
SetEvent(m_hEvent->value());
|
SetEvent(m_hEvent->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SMX::SMXManager::SetPlatformLights(const string sPanelLights[2])
|
||||||
|
{
|
||||||
|
g_Lock.AssertNotLockedByCurrentThread();
|
||||||
|
LockMutex L(g_Lock);
|
||||||
|
|
||||||
|
// Read the linearly arranged color data we've been given and split it into top and
|
||||||
|
// bottom commands for each pad.
|
||||||
|
for(int iPad = 0; iPad < 2; ++iPad)
|
||||||
|
{
|
||||||
|
// If there's no data for this pad, skip it.
|
||||||
|
string sLightsDataForPad = sPanelLights[iPad];
|
||||||
|
if(sLightsDataForPad.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(sLightsDataForPad.size() != 44*3)
|
||||||
|
{
|
||||||
|
Log(ssprintf("SetPlatformLights: Platform lights data should be %i bytes, received %i",
|
||||||
|
44*3, sLightsDataForPad.size()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this master doesn't support this, skip it.
|
||||||
|
SMXConfig config;
|
||||||
|
if(!m_pDevices[iPad]->GetConfigLocked(config))
|
||||||
|
continue;
|
||||||
|
if(config.masterVersion < 4)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string sLightCommand;
|
||||||
|
sLightCommand.push_back('L');
|
||||||
|
sLightCommand.push_back(0); // LED strip index (always 0)
|
||||||
|
sLightCommand.push_back(44); // number of LEDs to set
|
||||||
|
sLightCommand += sLightsDataForPad;
|
||||||
|
|
||||||
|
m_pDevices[iPad]->SendCommandLocked(sLightCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wake up the I/O thread if it's blocking on WaitForMultipleObjectsEx.
|
||||||
|
SetEvent(m_hEvent->value());
|
||||||
|
}
|
||||||
|
|
||||||
void SMX::SMXManager::ReenableAutoLights()
|
void SMX::SMXManager::ReenableAutoLights()
|
||||||
{
|
{
|
||||||
g_Lock.AssertNotLockedByCurrentThread();
|
g_Lock.AssertNotLockedByCurrentThread();
|
||||||
|
@ -44,6 +44,7 @@ public:
|
|||||||
void Shutdown();
|
void Shutdown();
|
||||||
shared_ptr<SMXDevice> GetDevice(int pad);
|
shared_ptr<SMXDevice> GetDevice(int pad);
|
||||||
void SetLights(const string sLights[2]);
|
void SetLights(const string sLights[2]);
|
||||||
|
void SetPlatformLights(const string sLights[2]);
|
||||||
void ReenableAutoLights();
|
void ReenableAutoLights();
|
||||||
void SetPanelTestMode(PanelTestMode mode);
|
void SetPanelTestMode(PanelTestMode mode);
|
||||||
void SetSerialNumbers();
|
void SetSerialNumbers();
|
||||||
|
@ -380,6 +380,8 @@ namespace SMX
|
|||||||
[DllImport("SMX.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("SMX.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
private static extern bool SMX_SetLights2(byte[] buf, int lightDataSize);
|
private static extern bool SMX_SetLights2(byte[] buf, int lightDataSize);
|
||||||
[DllImport("SMX.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("SMX.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern bool SMX_SetPlatformLights(byte[] buf, int lightDataSize);
|
||||||
|
[DllImport("SMX.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
private static extern bool SMX_ReenableAutoLights();
|
private static extern bool SMX_ReenableAutoLights();
|
||||||
[DllImport("SMX.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
[DllImport("SMX.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||||
private static extern IntPtr SMX_Version();
|
private static extern IntPtr SMX_Version();
|
||||||
@ -565,6 +567,13 @@ namespace SMX
|
|||||||
SMX_SetLights2(buf, buf.Length);
|
SMX_SetLights2(buf, buf.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SMX_SetPlatformLights(byte[] buf)
|
||||||
|
{
|
||||||
|
if(!DLLAvailable()) return;
|
||||||
|
|
||||||
|
SMX_SetPlatformLights(buf, buf.Length);
|
||||||
|
}
|
||||||
|
|
||||||
public static void ReenableAutoLights()
|
public static void ReenableAutoLights()
|
||||||
{
|
{
|
||||||
if(!DLLAvailable()) return;
|
if(!DLLAvailable()) return;
|
||||||
|
@ -7,6 +7,7 @@ using System.Windows.Input;
|
|||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Threading;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
@ -633,14 +634,14 @@ namespace smx_config
|
|||||||
SMX.SMXConfig config = args.controller[pad].config;
|
SMX.SMXConfig config = args.controller[pad].config;
|
||||||
return config.masterVersion >= 4;
|
return config.masterVersion >= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void setColor(Color color)
|
public override void setColor(Color color)
|
||||||
{
|
{
|
||||||
// Apply the change and save it to the device.
|
// Apply the change and save it to the device.
|
||||||
int pad = getPadNo();
|
int pad = getPadNo();
|
||||||
SMX.SMXConfig config;
|
SMX.SMXConfig config;
|
||||||
if(!SMX.SMX.GetConfig(pad, out config))
|
if(!SMX.SMX.GetConfig(pad, out config))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
config.platformStripColor[0] = color.R;
|
config.platformStripColor[0] = color.R;
|
||||||
config.platformStripColor[1] = color.G;
|
config.platformStripColor[1] = color.G;
|
||||||
@ -648,6 +649,50 @@ namespace smx_config
|
|||||||
|
|
||||||
SMX.SMX.SetConfig(pad, config);
|
SMX.SMX.SetConfig(pad, config);
|
||||||
CurrentSMXDevice.singleton.FireConfigurationChanged(this);
|
CurrentSMXDevice.singleton.FireConfigurationChanged(this);
|
||||||
|
|
||||||
|
QueueSetPlatformLights();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Queue SetPlatformLights to happen after a brief delay. This rate limits setting
|
||||||
|
// the color, so we don't spam the device when dragging the color slider.
|
||||||
|
DispatcherTimer PlatformLightsTimer;
|
||||||
|
void QueueSetPlatformLights()
|
||||||
|
{
|
||||||
|
// Stop if SetPlatformLights is already queued.
|
||||||
|
if(PlatformLightsTimer!= null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PlatformLightsTimer = new DispatcherTimer();
|
||||||
|
PlatformLightsTimer.Interval = new TimeSpan(0,0,0,0,33);
|
||||||
|
PlatformLightsTimer.Start();
|
||||||
|
|
||||||
|
PlatformLightsTimer.Tick += delegate(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
PlatformLightsTimer.Stop();
|
||||||
|
PlatformLightsTimer = null;
|
||||||
|
SetPlatformLights();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// The config update doesn't happen in realtime, so set the platform LED colors directly.
|
||||||
|
void SetPlatformLights()
|
||||||
|
{
|
||||||
|
CommandBuffer cmd = new CommandBuffer();
|
||||||
|
|
||||||
|
for(int pad = 0; pad < 2; ++pad)
|
||||||
|
{
|
||||||
|
// Use this panel's color. If a panel isn't connected, we still need to run the
|
||||||
|
// loop below to insert data for the panel.
|
||||||
|
byte[] color = new byte[3];
|
||||||
|
SMX.SMXConfig config;
|
||||||
|
if(SMX.SMX.GetConfig(pad, out config))
|
||||||
|
color = config.platformStripColor;
|
||||||
|
for(int i = 0; i < 44; ++i)
|
||||||
|
cmd.Write(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
SMX.SMX.SMX_SetPlatformLights(cmd.Get());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the color set for this panel in config.
|
// Return the color set for this panel in config.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user