From a58f8aaf43fde52a0572c367931e7445ada24a56 Mon Sep 17 00:00:00 2001 From: Aiden Date: Wed, 6 May 2026 11:56:02 +1000 Subject: [PATCH] Start up procedures --- CMakeLists.txt | 2 + .../LoopThroughWithOpenGLCompositing.vcxproj | 2 + ...roughWithOpenGLCompositing.vcxproj.filters | 6 + .../control/RuntimeServices.cpp | 119 +++++++++++++++ .../control/RuntimeServices.h | 48 ++++++ .../gl/OpenGLComposite.cpp | 139 +++--------------- .../gl/OpenGLComposite.h | 59 +------- 7 files changed, 196 insertions(+), 179 deletions(-) create mode 100644 apps/LoopThroughWithOpenGLCompositing/control/RuntimeServices.cpp create mode 100644 apps/LoopThroughWithOpenGLCompositing/control/RuntimeServices.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 535d39e..75118ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,8 @@ set(APP_SOURCES "${APP_DIR}/control/OscServer.h" "${APP_DIR}/control/RuntimeControlBridge.cpp" "${APP_DIR}/control/RuntimeControlBridge.h" + "${APP_DIR}/control/RuntimeServices.cpp" + "${APP_DIR}/control/RuntimeServices.h" "${APP_DIR}/decklink/DeckLinkDisplayMode.cpp" "${APP_DIR}/decklink/DeckLinkDisplayMode.h" "${APP_DIR}/decklink/DeckLinkFrameTransfer.cpp" diff --git a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj index 205008f..ab541a0 100644 --- a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj +++ b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj @@ -207,6 +207,7 @@ + @@ -221,6 +222,7 @@ + diff --git a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters index c6841d4..7d368eb 100644 --- a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters +++ b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters @@ -48,6 +48,9 @@ DeckLink API + + Source Files + Source Files @@ -86,6 +89,9 @@ Header Files + + Header Files + Header Files diff --git a/apps/LoopThroughWithOpenGLCompositing/control/RuntimeServices.cpp b/apps/LoopThroughWithOpenGLCompositing/control/RuntimeServices.cpp new file mode 100644 index 0000000..ff398a3 --- /dev/null +++ b/apps/LoopThroughWithOpenGLCompositing/control/RuntimeServices.cpp @@ -0,0 +1,119 @@ +#include "RuntimeServices.h" + +#include "ControlServer.h" +#include "OscServer.h" +#include "RuntimeControlBridge.h" +#include "RuntimeHost.h" + +#include + +RuntimeServices::RuntimeServices() : + mControlServer(std::make_unique()), + mOscServer(std::make_unique()), + mPollRunning(false), + mRegistryChanged(false), + mReloadRequested(false), + mPollFailed(false) +{ +} + +RuntimeServices::~RuntimeServices() +{ + Stop(); +} + +bool RuntimeServices::Start(OpenGLComposite& composite, RuntimeHost& runtimeHost, std::string& error) +{ + Stop(); + + if (!StartRuntimeControlServices(composite, runtimeHost, *mControlServer, *mOscServer, error)) + { + Stop(); + return false; + } + + return true; +} + +void RuntimeServices::BeginPolling(RuntimeHost& runtimeHost) +{ + StartPolling(runtimeHost); +} + +void RuntimeServices::Stop() +{ + StopPolling(); + + if (mOscServer) + mOscServer->Stop(); + + if (mControlServer) + mControlServer->Stop(); +} + +void RuntimeServices::BroadcastState() +{ + if (mControlServer) + mControlServer->BroadcastState(); +} + +RuntimePollEvents RuntimeServices::ConsumePollEvents() +{ + RuntimePollEvents events; + events.registryChanged = mRegistryChanged.exchange(false); + events.reloadRequested = mReloadRequested.exchange(false); + events.failed = mPollFailed.exchange(false); + + if (events.failed) + { + std::lock_guard lock(mPollErrorMutex); + events.error = mPollError; + } + + return events; +} + +void RuntimeServices::StartPolling(RuntimeHost& runtimeHost) +{ + if (mPollRunning.exchange(true)) + return; + + mPollThread = std::thread([this, &runtimeHost]() { PollLoop(runtimeHost); }); +} + +void RuntimeServices::StopPolling() +{ + if (!mPollRunning.exchange(false)) + return; + + if (mPollThread.joinable()) + mPollThread.join(); +} + +void RuntimeServices::PollLoop(RuntimeHost& runtimeHost) +{ + while (mPollRunning) + { + bool registryChanged = false; + bool reloadRequested = false; + std::string runtimeError; + if (!runtimeHost.PollFileChanges(registryChanged, reloadRequested, runtimeError)) + { + { + std::lock_guard lock(mPollErrorMutex); + mPollError = runtimeError; + } + mPollFailed = true; + } + else + { + if (registryChanged) + mRegistryChanged = true; + if (reloadRequested) + mReloadRequested = true; + } + + for (int i = 0; i < 25 && mPollRunning; ++i) + Sleep(10); + } +} diff --git a/apps/LoopThroughWithOpenGLCompositing/control/RuntimeServices.h b/apps/LoopThroughWithOpenGLCompositing/control/RuntimeServices.h new file mode 100644 index 0000000..29ba710 --- /dev/null +++ b/apps/LoopThroughWithOpenGLCompositing/control/RuntimeServices.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include +#include +#include + +class ControlServer; +class OpenGLComposite; +class OscServer; +class RuntimeHost; + +struct RuntimePollEvents +{ + bool registryChanged = false; + bool reloadRequested = false; + bool failed = false; + std::string error; +}; + +class RuntimeServices +{ +public: + RuntimeServices(); + ~RuntimeServices(); + + bool Start(OpenGLComposite& composite, RuntimeHost& runtimeHost, std::string& error); + void BeginPolling(RuntimeHost& runtimeHost); + void Stop(); + void BroadcastState(); + RuntimePollEvents ConsumePollEvents(); + +private: + void StartPolling(RuntimeHost& runtimeHost); + void StopPolling(); + void PollLoop(RuntimeHost& runtimeHost); + + std::unique_ptr mControlServer; + std::unique_ptr mOscServer; + std::thread mPollThread; + std::atomic mPollRunning; + std::atomic mRegistryChanged; + std::atomic mReloadRequested; + std::atomic mPollFailed; + std::mutex mPollErrorMutex; + std::string mPollError; +}; diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/OpenGLComposite.cpp b/apps/LoopThroughWithOpenGLCompositing/gl/OpenGLComposite.cpp index bc6b05c..2d10b12 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/OpenGLComposite.cpp +++ b/apps/LoopThroughWithOpenGLCompositing/gl/OpenGLComposite.cpp @@ -1,44 +1,3 @@ -/* -LICENSE-START- - ** Copyright (c) 2012 Blackmagic Design - ** - ** Permission is hereby granted, free of charge, to any person or organization - ** obtaining a copy of the software and accompanying documentation (the - ** "Software") to use, reproduce, display, distribute, sub-license, execute, - ** and transmit the Software, and to prepare derivative works of the Software, - ** and to permit third-parties to whom the Software is furnished to do so, in - ** accordance with: - ** - ** (1) if the Software is obtained from Blackmagic Design, the End User License - ** Agreement for the Software Development Kit ("EULA") available at - ** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or - ** - ** (2) if the Software is obtained from any third party, such licensing terms - ** as notified by that third party, - ** - ** and all subject to the following: - ** - ** (3) the copyright notices in the Software and this entire statement, - ** including the above license grant, this restriction and the following - ** disclaimer, must be included in all copies of the Software, in whole or in - ** part, and all derivative works of the Software, unless such copies or - ** derivative works are solely in the form of machine-executable object code - ** generated by a source language processor. - ** - ** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT - ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE - ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, - ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - ** DEALINGS IN THE SOFTWARE. - ** - ** A copy of the Software is available free of charge at - ** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. - ** - ** -LICENSE-END- - */ - -#include "ControlServer.h" #include "DeckLinkDisplayMode.h" #include "DeckLinkFrameTransfer.h" #include "DeckLinkSession.h" @@ -48,22 +7,16 @@ #include "OpenGLDeckLinkBridge.h" #include "OpenGLRenderPass.h" #include "OpenGLShaderPrograms.h" -#include "OscServer.h" -#include "RuntimeControlBridge.h" +#include "RuntimeServices.h" #include #include -#include #include OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) : hGLWnd(hWnd), hGLDC(hDC), hGLRC(hRC), mDeckLink(std::make_unique()), - mRenderer(std::make_unique()), - mRuntimePollRunning(false), - mRuntimeRegistryChanged(false), - mRuntimeReloadRequested(false), - mRuntimePollFailed(false) + mRenderer(std::make_unique()) { InitializeCriticalSection(&pMutex); mRuntimeHost = std::make_unique(); @@ -78,19 +31,15 @@ OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) : [this]() { paintGL(); }); mRenderPass = std::make_unique(*mRenderer); mShaderPrograms = std::make_unique(*mRenderer, *mRuntimeHost); - mControlServer = std::make_unique(); - mOscServer = std::make_unique(); + mRuntimeServices = std::make_unique(); } OpenGLComposite::~OpenGLComposite() { - StopRuntimePolling(); + if (mRuntimeServices) + mRuntimeServices->Stop(); mDeckLink->ReleaseResources(); mRenderer->DestroyResources(); - if (mOscServer) - mOscServer->Stop(); - if (mControlServer) - mControlServer->Stop(); DeleteCriticalSection(&pMutex); } @@ -255,7 +204,7 @@ bool OpenGLComposite::InitOpenGLState() return false; } - if (!StartRuntimeControlServices(*this, *mRuntimeHost, *mControlServer, *mOscServer, runtimeError)) + if (!mRuntimeServices->Start(*this, *mRuntimeHost, runtimeError)) { MessageBoxA(NULL, runtimeError.c_str(), "Runtime control services failed to start", MB_OK); return false; @@ -284,7 +233,7 @@ bool OpenGLComposite::InitOpenGLState() } broadcastRuntimeState(); - StartRuntimePolling(); + mRuntimeServices->BeginPolling(*mRuntimeHost); return true; } @@ -306,13 +255,8 @@ bool OpenGLComposite::Start() bool OpenGLComposite::Stop() { - StopRuntimePolling(); - - if (mOscServer) - mOscServer->Stop(); - - if (mControlServer) - mControlServer->Stop(); + if (mRuntimeServices) + mRuntimeServices->Stop(); const bool wasExternalKeyingActive = mDeckLink->ExternalKeyingActive(); mDeckLink->Stop(); @@ -380,72 +324,23 @@ void OpenGLComposite::renderEffect() }); } -void OpenGLComposite::StartRuntimePolling() -{ - if (!mRuntimeHost || mRuntimePollRunning.exchange(true)) - return; - - mRuntimePollThread = std::thread([this]() { RuntimePollLoop(); }); -} - -void OpenGLComposite::StopRuntimePolling() -{ - if (!mRuntimePollRunning.exchange(false)) - return; - - if (mRuntimePollThread.joinable()) - mRuntimePollThread.join(); -} - -void OpenGLComposite::RuntimePollLoop() -{ - while (mRuntimePollRunning) - { - bool registryChanged = false; - bool reloadRequested = false; - std::string runtimeError; - if (!mRuntimeHost->PollFileChanges(registryChanged, reloadRequested, runtimeError)) - { - { - std::lock_guard lock(mRuntimePollErrorMutex); - mRuntimePollError = runtimeError; - } - mRuntimePollFailed = true; - } - else - { - if (registryChanged) - mRuntimeRegistryChanged = true; - if (reloadRequested) - mRuntimeReloadRequested = true; - } - - for (int i = 0; i < 25 && mRuntimePollRunning; ++i) - Sleep(10); - } -} - bool OpenGLComposite::ProcessRuntimePollResults() { - if (!mRuntimeHost) + if (!mRuntimeHost || !mRuntimeServices) return true; - if (mRuntimePollFailed.exchange(false)) + const RuntimePollEvents events = mRuntimeServices->ConsumePollEvents(); + if (events.failed) { - std::string runtimeError; - { - std::lock_guard lock(mRuntimePollErrorMutex); - runtimeError = mRuntimePollError; - } - mRuntimeHost->SetCompileStatus(false, runtimeError); + mRuntimeHost->SetCompileStatus(false, events.error); broadcastRuntimeState(); return false; } - if (mRuntimeRegistryChanged.exchange(false)) + if (events.registryChanged) broadcastRuntimeState(); - if (!mRuntimeReloadRequested.exchange(false)) + if (!events.reloadRequested) return true; char compilerErrorMessage[1024] = {}; @@ -464,8 +359,8 @@ bool OpenGLComposite::ProcessRuntimePollResults() void OpenGLComposite::broadcastRuntimeState() { - if (mControlServer) - mControlServer->BroadcastState(); + if (mRuntimeServices) + mRuntimeServices->BroadcastState(); } void OpenGLComposite::resetTemporalHistoryState() diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/OpenGLComposite.h b/apps/LoopThroughWithOpenGLCompositing/gl/OpenGLComposite.h index 5586758..1fc5005 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/OpenGLComposite.h +++ b/apps/LoopThroughWithOpenGLCompositing/gl/OpenGLComposite.h @@ -1,43 +1,3 @@ -/* -LICENSE-START- - ** Copyright (c) 2012 Blackmagic Design - ** - ** Permission is hereby granted, free of charge, to any person or organization - ** obtaining a copy of the software and accompanying documentation (the - ** "Software") to use, reproduce, display, distribute, sub-license, execute, - ** and transmit the Software, and to prepare derivative works of the Software, - ** and to permit third-parties to whom the Software is furnished to do so, in - ** accordance with: - ** - ** (1) if the Software is obtained from Blackmagic Design, the End User License - ** Agreement for the Software Development Kit ("EULA") available at - ** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or - ** - ** (2) if the Software is obtained from any third party, such licensing terms - ** as notified by that third party, - ** - ** and all subject to the following: - ** - ** (3) the copyright notices in the Software and this entire statement, - ** including the above license grant, this restriction and the following - ** disclaimer, must be included in all copies of the Software, in whole or in - ** part, and all derivative works of the Software, unless such copies or - ** derivative works are solely in the form of machine-executable object code - ** generated by a source language processor. - ** - ** (4) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT - ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE - ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, - ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - ** DEALINGS IN THE SOFTWARE. - ** - ** A copy of the Software is available free of charge at - ** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA. - ** - ** -LICENSE-END- - */ - #ifndef __OPENGL_COMPOSITE_H__ #define __OPENGL_COMPOSITE_H__ @@ -56,22 +16,18 @@ #include "OpenGLRenderer.h" #include "RuntimeHost.h" -#include #include #include #include -#include #include -#include #include #include -class ControlServer; class DeckLinkSession; -class OscServer; class OpenGLDeckLinkBridge; class OpenGLRenderPass; class OpenGLShaderPrograms; +class RuntimeServices; class OpenGLComposite @@ -120,22 +76,11 @@ private: std::unique_ptr mDeckLinkBridge; std::unique_ptr mRenderPass; std::unique_ptr mShaderPrograms; - std::unique_ptr mControlServer; - std::unique_ptr mOscServer; - std::thread mRuntimePollThread; - std::atomic mRuntimePollRunning; - std::atomic mRuntimeRegistryChanged; - std::atomic mRuntimeReloadRequested; - std::atomic mRuntimePollFailed; - std::mutex mRuntimePollErrorMutex; - std::string mRuntimePollError; + std::unique_ptr mRuntimeServices; std::vector mCachedLayerRenderStates; bool InitOpenGLState(); void renderEffect(); - void StartRuntimePolling(); - void StopRuntimePolling(); - void RuntimePollLoop(); bool ProcessRuntimePollResults(); void broadcastRuntimeState(); void resetTemporalHistoryState();