OSC fixes
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
namespace
|
||||
{
|
||||
constexpr DWORD kStateBroadcastIntervalMs = 250;
|
||||
constexpr DWORD kStateBroadcastThrottleMs = 50;
|
||||
|
||||
bool InitializeWinsock(std::string& error)
|
||||
{
|
||||
@@ -75,7 +76,7 @@ std::string GuessContentType(const std::filesystem::path& assetPath)
|
||||
}
|
||||
|
||||
ControlServer::ControlServer()
|
||||
: mPort(0), mRunning(false)
|
||||
: mPort(0), mRunning(false), mBroadcastPending(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -161,10 +162,16 @@ void ControlServer::Stop()
|
||||
|
||||
void ControlServer::BroadcastState()
|
||||
{
|
||||
mBroadcastPending = false;
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
BroadcastStateLocked();
|
||||
}
|
||||
|
||||
void ControlServer::RequestBroadcastState()
|
||||
{
|
||||
mBroadcastPending = true;
|
||||
}
|
||||
|
||||
void ControlServer::ServerLoop()
|
||||
{
|
||||
DWORD lastStateBroadcastMs = GetTickCount();
|
||||
@@ -173,7 +180,12 @@ void ControlServer::ServerLoop()
|
||||
TryAcceptClient();
|
||||
|
||||
const DWORD nowMs = GetTickCount();
|
||||
if (nowMs - lastStateBroadcastMs >= kStateBroadcastIntervalMs)
|
||||
if (mBroadcastPending && nowMs - lastStateBroadcastMs >= kStateBroadcastThrottleMs)
|
||||
{
|
||||
BroadcastState();
|
||||
lastStateBroadcastMs = nowMs;
|
||||
}
|
||||
else if (nowMs - lastStateBroadcastMs >= kStateBroadcastIntervalMs)
|
||||
{
|
||||
BroadcastState();
|
||||
lastStateBroadcastMs = nowMs;
|
||||
@@ -469,6 +481,7 @@ bool ControlServer::HandleWebSocketUpgrade(UniqueSocket clientSocket, const Http
|
||||
client.socket.reset(clientSocket.release());
|
||||
client.websocket = true;
|
||||
mClients.push_back(std::move(client));
|
||||
mBroadcastPending = false;
|
||||
BroadcastStateLocked();
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -41,6 +41,7 @@ public:
|
||||
bool Start(const std::filesystem::path& uiRoot, const std::filesystem::path& docsRoot, unsigned short preferredPort, const Callbacks& callbacks, std::string& error);
|
||||
void Stop();
|
||||
void BroadcastState();
|
||||
void RequestBroadcastState();
|
||||
|
||||
unsigned short GetPort() const { return mPort; }
|
||||
|
||||
@@ -100,6 +101,7 @@ private:
|
||||
unsigned short mPort;
|
||||
std::thread mThread;
|
||||
std::atomic<bool> mRunning;
|
||||
std::atomic<bool> mBroadcastPending;
|
||||
mutable std::mutex mMutex;
|
||||
std::vector<ClientConnection> mClients;
|
||||
};
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
#include "OpenGLComposite.h"
|
||||
#include "OscServer.h"
|
||||
#include "RuntimeHost.h"
|
||||
#include "RuntimeServices.h"
|
||||
|
||||
bool StartRuntimeControlServices(
|
||||
OpenGLComposite& composite,
|
||||
RuntimeHost& runtimeHost,
|
||||
RuntimeServices& runtimeServices,
|
||||
ControlServer& controlServer,
|
||||
OscServer& oscServer,
|
||||
std::string& error)
|
||||
@@ -41,8 +43,8 @@ bool StartRuntimeControlServices(
|
||||
runtimeHost.SetServerPort(controlServer.GetPort());
|
||||
|
||||
OscServer::Callbacks oscCallbacks;
|
||||
oscCallbacks.updateParameter = [&composite](const std::string& layerKey, const std::string& parameterKey, const std::string& valueJson, std::string& actionError) {
|
||||
return composite.UpdateLayerParameterByControlKeyJson(layerKey, parameterKey, valueJson, actionError);
|
||||
oscCallbacks.updateParameter = [&runtimeServices](const std::string& layerKey, const std::string& parameterKey, const std::string& valueJson, std::string& actionError) {
|
||||
return runtimeServices.QueueOscUpdate(layerKey, parameterKey, valueJson, actionError);
|
||||
};
|
||||
if (runtimeHost.GetOscPort() > 0 && !oscServer.Start(runtimeHost.GetOscBindAddress(), runtimeHost.GetOscPort(), oscCallbacks, error))
|
||||
return false;
|
||||
|
||||
@@ -6,10 +6,12 @@ class ControlServer;
|
||||
class OpenGLComposite;
|
||||
class OscServer;
|
||||
class RuntimeHost;
|
||||
class RuntimeServices;
|
||||
|
||||
bool StartRuntimeControlServices(
|
||||
OpenGLComposite& composite,
|
||||
RuntimeHost& runtimeHost,
|
||||
RuntimeServices& runtimeServices,
|
||||
ControlServer& controlServer,
|
||||
OscServer& oscServer,
|
||||
std::string& error);
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "OscServer.h"
|
||||
#include "RuntimeControlBridge.h"
|
||||
#include "RuntimeHost.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
RuntimeServices::RuntimeServices() :
|
||||
@@ -26,7 +25,7 @@ bool RuntimeServices::Start(OpenGLComposite& composite, RuntimeHost& runtimeHost
|
||||
{
|
||||
Stop();
|
||||
|
||||
if (!StartRuntimeControlServices(composite, runtimeHost, *mControlServer, *mOscServer, error))
|
||||
if (!StartRuntimeControlServices(composite, runtimeHost, *this, *mControlServer, *mOscServer, error))
|
||||
{
|
||||
Stop();
|
||||
return false;
|
||||
@@ -57,6 +56,62 @@ void RuntimeServices::BroadcastState()
|
||||
mControlServer->BroadcastState();
|
||||
}
|
||||
|
||||
void RuntimeServices::RequestBroadcastState()
|
||||
{
|
||||
if (mControlServer)
|
||||
mControlServer->RequestBroadcastState();
|
||||
}
|
||||
|
||||
bool RuntimeServices::QueueOscUpdate(const std::string& layerKey, const std::string& parameterKey, const std::string& valueJson, std::string& error)
|
||||
{
|
||||
(void)error;
|
||||
|
||||
PendingOscUpdate update;
|
||||
update.layerKey = layerKey;
|
||||
update.parameterKey = parameterKey;
|
||||
update.valueJson = valueJson;
|
||||
|
||||
const std::string routeKey = layerKey + "\n" + parameterKey;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mPendingOscMutex);
|
||||
mPendingOscUpdates[routeKey] = std::move(update);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RuntimeServices::ApplyPendingOscUpdates(std::vector<AppliedOscUpdate>& appliedUpdates, std::string& error)
|
||||
{
|
||||
appliedUpdates.clear();
|
||||
|
||||
std::map<std::string, PendingOscUpdate> pending;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mPendingOscMutex);
|
||||
if (mPendingOscUpdates.empty())
|
||||
return true;
|
||||
pending.swap(mPendingOscUpdates);
|
||||
}
|
||||
|
||||
for (const auto& entry : pending)
|
||||
{
|
||||
JsonValue targetValue;
|
||||
std::string parseError;
|
||||
if (!ParseJson(entry.second.valueJson, targetValue, parseError))
|
||||
{
|
||||
OutputDebugStringA(("OSC queued value parse failed: " + parseError + "\n").c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
AppliedOscUpdate appliedUpdate;
|
||||
appliedUpdate.layerKey = entry.second.layerKey;
|
||||
appliedUpdate.parameterKey = entry.second.parameterKey;
|
||||
appliedUpdate.targetValue = targetValue;
|
||||
appliedUpdates.push_back(std::move(appliedUpdate));
|
||||
}
|
||||
|
||||
(void)error;
|
||||
return true;
|
||||
}
|
||||
|
||||
RuntimePollEvents RuntimeServices::ConsumePollEvents()
|
||||
{
|
||||
RuntimePollEvents events;
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "RuntimeJson.h"
|
||||
#include "ShaderTypes.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
@@ -22,6 +26,13 @@ struct RuntimePollEvents
|
||||
class RuntimeServices
|
||||
{
|
||||
public:
|
||||
struct AppliedOscUpdate
|
||||
{
|
||||
std::string layerKey;
|
||||
std::string parameterKey;
|
||||
JsonValue targetValue;
|
||||
};
|
||||
|
||||
RuntimeServices();
|
||||
~RuntimeServices();
|
||||
|
||||
@@ -29,9 +40,19 @@ public:
|
||||
void BeginPolling(RuntimeHost& runtimeHost);
|
||||
void Stop();
|
||||
void BroadcastState();
|
||||
void RequestBroadcastState();
|
||||
bool QueueOscUpdate(const std::string& layerKey, const std::string& parameterKey, const std::string& valueJson, std::string& error);
|
||||
bool ApplyPendingOscUpdates(std::vector<AppliedOscUpdate>& appliedUpdates, std::string& error);
|
||||
RuntimePollEvents ConsumePollEvents();
|
||||
|
||||
private:
|
||||
struct PendingOscUpdate
|
||||
{
|
||||
std::string layerKey;
|
||||
std::string parameterKey;
|
||||
std::string valueJson;
|
||||
};
|
||||
|
||||
void StartPolling(RuntimeHost& runtimeHost);
|
||||
void StopPolling();
|
||||
void PollLoop(RuntimeHost& runtimeHost);
|
||||
@@ -45,4 +66,6 @@ private:
|
||||
std::atomic<bool> mPollFailed;
|
||||
std::mutex mPollErrorMutex;
|
||||
std::string mPollError;
|
||||
std::mutex mPendingOscMutex;
|
||||
std::map<std::string, PendingOscUpdate> mPendingOscUpdates;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user