Files
video-shader-toys/apps/LoopThroughWithOpenGLCompositing/control/ControlServices.h
2026-05-11 19:09:01 +10:00

96 lines
2.8 KiB
C++

#pragma once
#include "RuntimeJson.h"
#include "RuntimeCoordinator.h"
#include "ShaderTypes.h"
#include <atomic>
#include <condition_variable>
#include <chrono>
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include <vector>
class ControlServer;
class OpenGLComposite;
class OscServer;
class RuntimeEventDispatcher;
class RuntimeStore;
class ControlServices
{
public:
struct AppliedOscUpdate
{
std::string routeKey;
std::string layerKey;
std::string parameterKey;
JsonValue targetValue;
};
struct CompletedOscCommit
{
std::string routeKey;
uint64_t generation = 0;
};
explicit ControlServices(RuntimeEventDispatcher& runtimeEventDispatcher);
~ControlServices();
bool Start(OpenGLComposite& composite, RuntimeStore& runtimeStore, std::string& error);
void BeginPolling(RuntimeCoordinator& runtimeCoordinator);
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);
bool QueueOscCommit(const std::string& routeKey, const std::string& layerKey, const std::string& parameterKey, const JsonValue& value, uint64_t generation, std::string& error);
void ClearOscState();
void ClearOscStateForLayerKey(const std::string& layerKey);
void ConsumeCompletedOscCommits(std::vector<CompletedOscCommit>& completedCommits);
private:
struct PendingOscUpdate
{
std::string layerKey;
std::string parameterKey;
std::string valueJson;
};
struct PendingOscCommit
{
std::string routeKey;
std::string layerKey;
std::string parameterKey;
JsonValue value;
uint64_t generation = 0;
};
void StartPolling(RuntimeCoordinator& runtimeCoordinator);
void StopPolling();
void PollLoop(RuntimeCoordinator& runtimeCoordinator);
void WakePolling();
void PublishRuntimeStateBroadcastRequested(const std::string& reason);
void PublishOscValueReceived(const PendingOscUpdate& update, const std::string& routeKey);
void PublishOscCommitRequested(const PendingOscCommit& commit);
void PublishOscOverlaySettled(const PendingOscCommit& commit);
std::unique_ptr<ControlServer> mControlServer;
std::unique_ptr<OscServer> mOscServer;
RuntimeEventDispatcher& mRuntimeEventDispatcher;
std::thread mPollThread;
std::atomic<bool> mPollRunning;
std::mutex mPollWakeMutex;
std::condition_variable mPollWakeCondition;
bool mPollWakeRequested = false;
std::mutex mPendingOscMutex;
std::map<std::string, PendingOscUpdate> mPendingOscUpdates;
std::mutex mPendingOscCommitMutex;
std::map<std::string, PendingOscCommit> mPendingOscCommits;
std::mutex mCompletedOscCommitMutex;
std::vector<CompletedOscCommit> mCompletedOscCommits;
};