OSC bind address
All checks were successful
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 2m41s
CI / Windows Release Package (push) Successful in 2m30s

This commit is contained in:
Aiden
2026-05-10 17:23:28 +10:00
parent a3635b5d31
commit f11d531e0c
11 changed files with 81 additions and 9 deletions

View File

@@ -55,7 +55,7 @@ OscServer::~OscServer()
Stop();
}
bool OscServer::Start(unsigned short port, const Callbacks& callbacks, std::string& error)
bool OscServer::Start(const std::string& bindAddress, unsigned short port, const Callbacks& callbacks, std::string& error)
{
if (port == 0)
return true;
@@ -78,11 +78,15 @@ bool OscServer::Start(unsigned short port, const Callbacks& callbacks, std::stri
sockaddr_in address = {};
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (!TryParseBindAddress(bindAddress, address.sin_addr, error))
{
mSocket.reset();
return false;
}
address.sin_port = htons(static_cast<u_short>(port));
if (bind(mSocket.get(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) != 0)
{
error = "Could not bind OSC listener to UDP port " + std::to_string(port) + ".";
error = "Could not bind OSC listener to " + bindAddress + ":" + std::to_string(port) + ".";
mSocket.reset();
return false;
}
@@ -92,6 +96,24 @@ bool OscServer::Start(unsigned short port, const Callbacks& callbacks, std::stri
return true;
}
bool OscServer::TryParseBindAddress(const std::string& bindAddress, in_addr& address, std::string& error)
{
if (bindAddress.empty())
{
error = "OSC bind address must not be empty.";
return false;
}
address = {};
if (InetPtonA(AF_INET, bindAddress.c_str(), &address) != 1)
{
error = "Invalid OSC bind address '" + bindAddress + "'. Use an IPv4 address such as 127.0.0.1 or 0.0.0.0.";
return false;
}
return true;
}
void OscServer::Stop()
{
mRunning = false;

View File

@@ -20,7 +20,7 @@ public:
OscServer();
~OscServer();
bool Start(unsigned short port, const Callbacks& callbacks, std::string& error);
bool Start(const std::string& bindAddress, unsigned short port, const Callbacks& callbacks, std::string& error);
void Stop();
unsigned short GetPort() const { return mPort; }
@@ -37,6 +37,7 @@ private:
void ServerLoop();
bool DecodeMessage(const char* data, int byteCount, OscMessage& message, std::string& error) const;
bool DispatchMessage(const OscMessage& message, std::string& error) const;
static bool TryParseBindAddress(const std::string& bindAddress, in_addr& address, std::string& error);
static bool DecodeArgument(const char* data, int byteCount, int& offset, char valueType, std::string& valueJson);
static bool ReadPaddedString(const char* data, int byteCount, int& offset, std::string& value);
static bool ReadInt32(const char* data, int byteCount, int& offset, int& value);

View File

@@ -44,7 +44,7 @@ bool StartRuntimeControlServices(
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);
};
if (runtimeHost.GetOscPort() > 0 && !oscServer.Start(runtimeHost.GetOscPort(), oscCallbacks, error))
if (runtimeHost.GetOscPort() > 0 && !oscServer.Start(runtimeHost.GetOscBindAddress(), runtimeHost.GetOscPort(), oscCallbacks, error))
return false;
return true;

View File

@@ -60,6 +60,7 @@ public:
bool RequestScreenshot(std::string& error);
unsigned short GetControlServerPort() const;
unsigned short GetOscPort() const;
std::string GetOscBindAddress() const;
std::string GetControlUrl() const;
std::string GetDocsUrl() const;
std::string GetOscAddress() const;

View File

@@ -15,6 +15,11 @@ unsigned short OpenGLComposite::GetOscPort() const
return mRuntimeHost ? mRuntimeHost->GetOscPort() : 0;
}
std::string OpenGLComposite::GetOscBindAddress() const
{
return mRuntimeHost ? mRuntimeHost->GetOscBindAddress() : "127.0.0.1";
}
std::string OpenGLComposite::GetControlUrl() const
{
return "http://127.0.0.1:" + std::to_string(GetControlServerPort()) + "/";
@@ -27,7 +32,7 @@ std::string OpenGLComposite::GetDocsUrl() const
std::string OpenGLComposite::GetOscAddress() const
{
return "udp://127.0.0.1:" + std::to_string(GetOscPort()) + " /VideoShaderToys/{Layer}/{Parameter}";
return "udp://" + GetOscBindAddress() + ":" + std::to_string(GetOscPort()) + " /VideoShaderToys/{Layer}/{Parameter}";
}
bool OpenGLComposite::AddLayer(const std::string& shaderId, std::string& error)

View File

@@ -1474,6 +1474,8 @@ bool RuntimeHost::LoadConfig(std::string& error)
mConfig.serverPort = static_cast<unsigned short>(serverPortValue->asNumber(mConfig.serverPort));
if (const JsonValue* oscPortValue = configJson.find("oscPort"))
mConfig.oscPort = static_cast<unsigned short>(oscPortValue->asNumber(mConfig.oscPort));
if (const JsonValue* oscBindAddressValue = configJson.find("oscBindAddress"))
mConfig.oscBindAddress = oscBindAddressValue->asString();
if (const JsonValue* autoReloadValue = configJson.find("autoReload"))
mConfig.autoReload = autoReloadValue->asBoolean(mConfig.autoReload);
if (const JsonValue* maxTemporalHistoryFramesValue = configJson.find("maxTemporalHistoryFrames"))
@@ -1870,6 +1872,7 @@ JsonValue RuntimeHost::BuildStateValue() const
JsonValue app = JsonValue::MakeObject();
app.set("serverPort", JsonValue(static_cast<double>(mServerPort)));
app.set("oscPort", JsonValue(static_cast<double>(mConfig.oscPort)));
app.set("oscBindAddress", JsonValue(mConfig.oscBindAddress));
app.set("autoReload", JsonValue(mAutoReloadEnabled));
app.set("maxTemporalHistoryFrames", JsonValue(static_cast<double>(mConfig.maxTemporalHistoryFrames)));
app.set("previewFps", JsonValue(static_cast<double>(mConfig.previewFps)));

View File

@@ -64,6 +64,7 @@ public:
const std::filesystem::path& GetRuntimeRoot() const { return mRuntimeRoot; }
unsigned short GetServerPort() const { return mServerPort; }
unsigned short GetOscPort() const { return mConfig.oscPort; }
const std::string& GetOscBindAddress() const { return mConfig.oscBindAddress; }
unsigned GetMaxTemporalHistoryFrames() const { return mConfig.maxTemporalHistoryFrames; }
unsigned GetPreviewFps() const { return mConfig.previewFps; }
bool ExternalKeyingEnabled() const { return mConfig.enableExternalKeying; }
@@ -80,6 +81,7 @@ private:
std::string shaderLibrary = "shaders";
unsigned short serverPort = 8080;
unsigned short oscPort = 9000;
std::string oscBindAddress = "127.0.0.1";
bool autoReload = true;
unsigned maxTemporalHistoryFrames = 4;
unsigned previewFps = 30;