Start up procedures
Some checks failed
CI / React UI Build (push) Successful in 10s
CI / Native Windows Build And Tests (push) Failing after 19s
CI / Windows Release Package (push) Has been skipped

This commit is contained in:
2026-05-06 11:56:02 +10:00
parent 515f58b848
commit a58f8aaf43
7 changed files with 196 additions and 179 deletions

View File

@@ -207,6 +207,7 @@
</ClCompile>
<ClCompile Include="gl\VideoFrameTransfer.cpp" />
<ClCompile Include="DeckLinkAPI_i.c" />
<ClCompile Include="control\RuntimeServices.cpp" />
<ClCompile Include="decklink\DeckLinkSession.cpp" />
</ItemGroup>
<ItemGroup>
@@ -221,6 +222,7 @@
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="gl\VideoFrameTransfer.h" />
<ClInclude Include="control\RuntimeServices.h" />
<ClInclude Include="decklink\DeckLinkSession.h" />
</ItemGroup>
<ItemGroup>

View File

@@ -48,6 +48,9 @@
<ClCompile Include="DeckLinkAPI_i.c">
<Filter>DeckLink API</Filter>
</ClCompile>
<ClCompile Include="control\RuntimeServices.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="decklink\DeckLinkSession.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -86,6 +89,9 @@
<ClInclude Include="gl\VideoFrameTransfer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="control\RuntimeServices.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="decklink\DeckLinkSession.h">
<Filter>Header Files</Filter>
</ClInclude>

View File

@@ -0,0 +1,119 @@
#include "RuntimeServices.h"
#include "ControlServer.h"
#include "OscServer.h"
#include "RuntimeControlBridge.h"
#include "RuntimeHost.h"
#include <windows.h>
RuntimeServices::RuntimeServices() :
mControlServer(std::make_unique<ControlServer>()),
mOscServer(std::make_unique<OscServer>()),
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<std::mutex> 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<std::mutex> 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);
}
}

View File

@@ -0,0 +1,48 @@
#pragma once
#include <atomic>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
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<ControlServer> mControlServer;
std::unique_ptr<OscServer> mOscServer;
std::thread mPollThread;
std::atomic<bool> mPollRunning;
std::atomic<bool> mRegistryChanged;
std::atomic<bool> mReloadRequested;
std::atomic<bool> mPollFailed;
std::mutex mPollErrorMutex;
std::string mPollError;
};

View File

@@ -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 <memory>
#include <string>
#include <thread>
#include <vector>
OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
hGLWnd(hWnd), hGLDC(hDC), hGLRC(hRC),
mDeckLink(std::make_unique<DeckLinkSession>()),
mRenderer(std::make_unique<OpenGLRenderer>()),
mRuntimePollRunning(false),
mRuntimeRegistryChanged(false),
mRuntimeReloadRequested(false),
mRuntimePollFailed(false)
mRenderer(std::make_unique<OpenGLRenderer>())
{
InitializeCriticalSection(&pMutex);
mRuntimeHost = std::make_unique<RuntimeHost>();
@@ -78,19 +31,15 @@ OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
[this]() { paintGL(); });
mRenderPass = std::make_unique<OpenGLRenderPass>(*mRenderer);
mShaderPrograms = std::make_unique<OpenGLShaderPrograms>(*mRenderer, *mRuntimeHost);
mControlServer = std::make_unique<ControlServer>();
mOscServer = std::make_unique<OscServer>();
mRuntimeServices = std::make_unique<RuntimeServices>();
}
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<std::mutex> 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<std::mutex> 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()

View File

@@ -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 <atomic>
#include <functional>
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include <vector>
#include <deque>
class ControlServer;
class DeckLinkSession;
class OscServer;
class OpenGLDeckLinkBridge;
class OpenGLRenderPass;
class OpenGLShaderPrograms;
class RuntimeServices;
class OpenGLComposite
@@ -120,22 +76,11 @@ private:
std::unique_ptr<OpenGLDeckLinkBridge> mDeckLinkBridge;
std::unique_ptr<OpenGLRenderPass> mRenderPass;
std::unique_ptr<OpenGLShaderPrograms> mShaderPrograms;
std::unique_ptr<ControlServer> mControlServer;
std::unique_ptr<OscServer> mOscServer;
std::thread mRuntimePollThread;
std::atomic<bool> mRuntimePollRunning;
std::atomic<bool> mRuntimeRegistryChanged;
std::atomic<bool> mRuntimeReloadRequested;
std::atomic<bool> mRuntimePollFailed;
std::mutex mRuntimePollErrorMutex;
std::string mRuntimePollError;
std::unique_ptr<RuntimeServices> mRuntimeServices;
std::vector<RuntimeRenderState> mCachedLayerRenderStates;
bool InitOpenGLState();
void renderEffect();
void StartRuntimePolling();
void StopRuntimePolling();
void RuntimePollLoop();
bool ProcessRuntimePollResults();
void broadcastRuntimeState();
void resetTemporalHistoryState();