#pragma once #include "RuntimeJson.h" #include "RuntimeCoordinator.h" #include "ShaderTypes.h" #include #include #include #include #include #include #include #include #include class ControlServer; class OpenGLComposite; class OscServer; class RuntimeEventDispatcher; class RuntimeStore; struct RuntimeCoordinatorServiceResult { RuntimeCoordinatorResult result; bool failed = false; }; 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& 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 ConsumeCompletedOscCommits(std::vector& completedCommits); void ConsumeRuntimeCoordinatorResults(std::vector& results); 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 QueueRuntimeCoordinatorResult(const RuntimeCoordinatorResult& result, bool failed = false); void PublishRuntimeStateBroadcastRequested(const std::string& reason); void PublishOscValueReceived(const PendingOscUpdate& update, const std::string& routeKey); void PublishOscCommitRequested(const PendingOscCommit& commit); std::unique_ptr mControlServer; std::unique_ptr mOscServer; RuntimeEventDispatcher& mRuntimeEventDispatcher; std::thread mPollThread; std::atomic mPollRunning; std::mutex mPollWakeMutex; std::condition_variable mPollWakeCondition; bool mPollWakeRequested = false; std::mutex mRuntimeCoordinatorResultMutex; std::vector mRuntimeCoordinatorResults; std::mutex mPendingOscMutex; std::map mPendingOscUpdates; std::mutex mPendingOscCommitMutex; std::map mPendingOscCommits; std::mutex mCompletedOscCommitMutex; std::vector mCompletedOscCommits; };