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).
master
Glenn Maynard 5 years ago
parent 48fe72af4a
commit 102fe2f9f9
  1. 17
      sdk/Windows/SMX.cpp
  2. 11
      sdk/Windows/SMXDevice.cpp
  3. 1
      sdk/Windows/SMXDevice.h
  4. 41
      sdk/Windows/SMXManager.cpp
  5. 1
      sdk/Windows/SMXManager.h
  6. 9
      smx-config/SMX.cs
  7. 49
      smx-config/Widgets.cs

@ -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;
@ -633,14 +634,14 @@ namespace smx_config
SMX.SMXConfig config = args.controller[pad].config;
return config.masterVersion >= 4;
}
public override void setColor(Color color)
{
// Apply the change and save it to the device.
int pad = getPadNo();
SMX.SMXConfig config;
if(!SMX.SMX.GetConfig(pad, out config))
return;
return;
config.platformStripColor[0] = color.R;
config.platformStripColor[1] = color.G;
@ -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…
Cancel
Save