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);
|
||||
}
|
||||
|
||||
// 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 const char *SMX_Version() { return SMX_BUILD_VERSION; }
|
||||
|
||||
|
@ -334,6 +334,17 @@ void SMX::SMXDevice::SendConfig()
|
||||
if(m_bWaitingForConfigResponse)
|
||||
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();
|
||||
|
||||
// Write configuration command. This is "w" in versions 1-4, and "W" in versions 5
|
||||
|
@ -105,6 +105,7 @@ private:
|
||||
SMXConfig config;
|
||||
vector<uint8_t> rawConfig;
|
||||
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
|
||||
// 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());
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
g_Lock.AssertNotLockedByCurrentThread();
|
||||
|
@ -44,6 +44,7 @@ public:
|
||||
void Shutdown();
|
||||
shared_ptr<SMXDevice> GetDevice(int pad);
|
||||
void SetLights(const string sLights[2]);
|
||||
void SetPlatformLights(const string sLights[2]);
|
||||
void ReenableAutoLights();
|
||||
void SetPanelTestMode(PanelTestMode mode);
|
||||
void SetSerialNumbers();
|
||||
|
@ -380,6 +380,8 @@ namespace SMX
|
||||
[DllImport("SMX.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern bool SMX_SetLights2(byte[] buf, int lightDataSize);
|
||||
[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();
|
||||
[DllImport("SMX.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
private static extern IntPtr SMX_Version();
|
||||
@ -565,6 +567,13 @@ namespace SMX
|
||||
SMX_SetLights2(buf, buf.Length);
|
||||
}
|
||||
|
||||
public static void SMX_SetPlatformLights(byte[] buf)
|
||||
{
|
||||
if(!DLLAvailable()) return;
|
||||
|
||||
SMX_SetPlatformLights(buf, buf.Length);
|
||||
}
|
||||
|
||||
public static void ReenableAutoLights()
|
||||
{
|
||||
if(!DLLAvailable()) return;
|
||||
|
@ -7,6 +7,7 @@ using System.Windows.Input;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Shapes;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Threading;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@ -648,6 +649,50 @@ namespace smx_config
|
||||
|
||||
SMX.SMX.SetConfig(pad, config);
|
||||
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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user