SuperDMX Module API Documentation
Document Version: 1.0
Applicable Version: SuperStage Plugin 2025/2026
Target Audience: Blueprint Developers / C++ Plugin Integration Developers (without source code modification permissions)
Last Updated: 2026-03
Table of Contents
- Module Overview
- Data Types
- USuperDMXSubsystem — DMX Communication Subsystem
- Sequencer Integration
- Thread Safety Model
- Network Protocol Details
- Universe Numbering and StartUniverse Mapping
- Usage Examples
- FAQ and Troubleshooting
1. Module Overview
SuperDMX is the underlying communication module of the SuperStage plugin suite, responsible for DMX over IP data transmission, reception, and caching.
| Item | Description |
|---|---|
| Module Type | Runtime |
| Export Macro | SUPERDMX_API |
| Module Entry | FSuperDMXModule (SuperDMX.h) |
| Core Subsystem | USuperDMXSubsystem (UEngineSubsystem global singleton) |
| Protocol Support | Art-Net (UDP 6454), sACN/E1.31 (UDP 5568, reserved in code) |
| Header Directory | Source/SuperDMX/Public/ |
Module Dependencies
Add to .Build.cs:
PublicDependencyModuleNames.Add("SuperDMX");
Public Header File List
| Header File | Content |
|---|---|
SuperDMX.h |
Module interface (FSuperDMXModule) |
SuperDMXTypes.h |
Data types (protocol enum, endpoint, I/O config) |
SuperDMXSubsystem.h |
DMX subsystem (send/receive/cache/query) |
Sequencer/MovieSceneSuperDMXTrack.h |
Sequencer DMX track |
Sequencer/MovieSceneSuperDMXSection.h |
Sequencer DMX section |
2. Data Types
2.1 ESuperDMXProtocol
Header File: SuperDMXTypes.h
DMX network protocol enum.
UENUM(BlueprintType)
enum class ESuperDMXProtocol : uint8
{
ArtNet UMETA(DisplayName = "Art-Net"),
};
| Value | Description | Default Port |
|---|---|---|
ArtNet |
Art-Net protocol (OpDmx 0x5000) | 6454 |
Note: sACN/E1.31 protocol is reserved in code (port 5568), current version only supports Art-Net.
2.2 FSuperDMXEndpoint
Header File: SuperDMXTypes.h
DMX network endpoint configuration struct, defines network parameters for one input or output endpoint.
USTRUCT(BlueprintType)
struct FSuperDMXEndpoint
Properties
| Property | Type | Default | Description |
|---|---|---|---|
bEnabled |
bool |
true |
Whether the endpoint is enabled. When disabled, receiver/transmitter will not be created |
LocalIp |
FString |
"" |
Local bind IP. When empty or "0.0.0.0", binds all network interfaces |
RemoteIp |
FString |
"" |
Remote target IP. For output: unicast/broadcast address; sACN uses 239.255.*.* multicast |
Port |
int32 |
6454 |
Network port. Art-Net standard port 6454, sACN standard port 5568 |
StartUniverse |
int32 |
0 |
Starting Universe offset (see Section 7 for details) |
Property Details
bEnabled
Controls whether the endpoint is active. For input (FSuperDMXIOConfig.Input):
true: Create UDP receiver, begin listening for DMX datafalse: Do not create receiver, no network resource consumption
For output (FSuperDMXIOConfig.Output):
true: Create UDP sender,SendDMXBuffer()sends data to networkfalse:SendDMXBuffer()only updates local cache, does not send to network
LocalIp
Specifies the local network interface to bind to. In multi-NIC environments, a specific IP can be specified to ensure DMX data is only sent/received through that interface.
| Value | Behavior |
|---|---|
"" or "0.0.0.0" |
Listen on all network interfaces |
"192.168.1.100" |
Listen only on specified interface |
"10.0.0.1" |
Used to isolate DMX network segment |
RemoteIp
Target address for the output endpoint.
| Scenario | Value |
|---|---|
| Broadcast (all devices) | "255.255.255.255" or "2.255.255.255" (Art-Net subnet broadcast) |
| Unicast (specific device) | "192.168.1.200" |
| sACN multicast | "239.255.0.1" (Universe 1) |
StartUniverse
Used to align different consoles’ Universe numbering conventions. See Section 7 for details.
2.3 FSuperDMXIOConfig
Header File: SuperDMXTypes.h
Complete DMX input/output configuration entity.
USTRUCT(BlueprintType)
struct FSuperDMXIOConfig
Properties
| Property | Type | Default | Description |
|---|---|---|---|
Protocol |
ESuperDMXProtocol |
ArtNet |
Network protocol |
Input |
FSuperDMXEndpoint |
See Endpoint defaults | Input configuration (receive DMX) |
Output |
FSuperDMXEndpoint |
See Endpoint defaults | Output configuration (send DMX) |
Usage Example
FSuperDMXIOConfig Config;
Config.Protocol = ESuperDMXProtocol::ArtNet;
// Input configuration: listen for Art-Net on all interfaces
Config.Input.bEnabled = true;
Config.Input.LocalIp = TEXT(""); // 0.0.0.0
Config.Input.Port = 6454;
Config.Input.StartUniverse = 0; // MA2 default alignment
// Output configuration: broadcast to entire subnet
Config.Output.bEnabled = true;
Config.Output.RemoteIp = TEXT("255.255.255.255");
Config.Output.Port = 6454;
Config.Output.StartUniverse = 0;
3. USuperDMXSubsystem — DMX Communication Subsystem
Header File: SuperDMXSubsystem.h
Base Class: UEngineSubsystem
Export Macro: SUPERDMX_API
The core singleton service for DMX communication, automatically created on engine startup, providing the following capabilities:
- Network configuration and lifecycle management
- Art-Net/sACN data reception and parsing
- Multi-Universe DMX data caching
- DMX data query (thread-safe)
- DMX data transmission (Sequencer playback / programmatic output)
- Signal activity diagnostics
3.1 Getting the Instance
USuperDMXSubsystem is a UEngineSubsystem, globally unique, no manual creation needed.
C++ access method:
#include "SuperDMXSubsystem.h"
USuperDMXSubsystem* DMX = GEngine->GetEngineSubsystem<USuperDMXSubsystem>();
Blueprint access method:
In the current version, the UFUNCTION macros have been commented out (
//UFUNCTION), therefore these functions cannot be called directly in Blueprint. They need to be bridged through custom Blueprint function libraries or C++ plugins.
3.2 Lifecycle
| Phase | Behavior |
|---|---|
| Engine Startup | Initialize() automatically called → start receiver and sender with default configuration |
| Runtime | Receive thread continuously parses DMX packets → writes to cache |
| Engine Shutdown | Deinitialize() automatically called → stop receiver → destroy sender → release network resources |
Important: On engine startup, the system automatically begins listening with default configuration (ArtNet, port 6454, bind 0.0.0.0). To change configuration, call
ApplyConfig().
3.3 Configuration Management
ApplyConfig
void ApplyConfig(const FSuperDMXIOConfig& InConfig);
Apply I/O configuration and restart receiver and sender.
Parameters:
| Parameter | Type | Description |
|---|---|---|
InConfig |
const FSuperDMXIOConfig& |
Complete I/O configuration |
Behavior:
- Save configuration to internal
Configmember - Stop current receiver → recreate receiver with new configuration
- Destroy current sender → recreate sender with new configuration
Notes:
- Takes effect immediately after calling, cached DMX data is not cleared
- If
Input.bEnabled = false, receiver will not start - If
Output.bEnabled = false, sender will not be created - Can be called multiple times at runtime to switch network configuration
Example:
USuperDMXSubsystem* DMX = GEngine->GetEngineSubsystem<USuperDMXSubsystem>();
FSuperDMXIOConfig Config;
Config.Protocol = ESuperDMXProtocol::ArtNet;
Config.Input.bEnabled = true;
Config.Input.Port = 6454;
Config.Output.bEnabled = true;
Config.Output.RemoteIp = TEXT("192.168.1.255");
Config.Output.Port = 6454;
DMX->ApplyConfig(Config);
Stop
void Stop();
Stop all network activity (receiver and sender).
Behavior:
- Stop receive thread
- Close receive socket
- Destroy send socket
- Cached DMX data is retained unchanged
Use cases:
- Temporarily pause DMX communication
- Cleanup before switching network environments
3.4 Data Reception and Query
GetDMXBuffer
bool GetDMXBuffer(int32 Universe, TArray<uint8>& OutBuffer) const;
Get the complete DMX buffer (latest frame) for a specified Universe.
Parameters:
| Parameter | Type | Direction | Description |
|---|---|---|---|
Universe |
int32 |
Input | Target Universe number (internal numbering, starting from 1) |
OutBuffer |
TArray<uint8>& |
Output | Receive buffer, length equals actual frame data size (usually 512 bytes) |
Return value:
| Value | Description |
|---|---|
true |
Successfully retrieved data |
false |
This Universe has not received any data yet |
Thread-safe: ✅ Internally protected with FCriticalSection
Notes:
- Returns a copy of the data, modifying
OutBufferafter the call does not affect the internal cache - Buffer length depends on the Length field of the received Art-Net packet (usually 512)
- Channel indexing:
OutBuffer[0]corresponds to DMX channel 1,OutBuffer[511]corresponds to channel 512
Example:
TArray<uint8> Buffer;
if (DMX->GetDMXBuffer(1, Buffer)) // Universe 1
{
// Buffer[0] = Channel 1 value (0-255)
// Buffer[1] = Channel 2 value
// ...
uint8 DimmerValue = Buffer[0]; // Assuming Dimmer is on channel 1
}
GetDMXValue
bool GetDMXValue(int32 Universe, int32 Address, uint8& OutValue) const;
Get a single DMX value for a specified Universe and channel address.
Parameters:
| Parameter | Type | Direction | Description |
|---|---|---|---|
Universe |
int32 |
Input | Target Universe number (internal numbering, starting from 1) |
Address |
int32 |
Input | DMX channel address (1-512, note: starts from 1) |
OutValue |
uint8& |
Output | Channel value (0-255) |
Return value:
| Value | Description |
|---|---|
true |
Successfully retrieved |
false |
Address out of bounds (<1 or >512), Universe has no data, or address exceeds received data range |
Thread-safe: ✅
Notes:
- Address starts from 1, consistent with DMX industry standards
- If Address < 1 or Address > 512, returns
falsedirectly - If Universe exists but Address exceeds received data length, returns
false
Example:
uint8 Value = 0;
if (DMX->GetDMXValue(1, 1, Value)) // Universe 1, Channel 1
{
float Normalized = Value / 255.0f; // Normalize to 0.0-1.0
}
GetKnownUniverses
void GetKnownUniverses(TArray<int32>& OutUniverses) const;
Get a list of all Universe numbers that currently have cached data.
Parameters:
| Parameter | Type | Direction | Description |
|---|---|---|---|
OutUniverses |
TArray<int32>& |
Output | List of Universe numbers (sorted ascending) |
Thread-safe: ✅
Use cases:
- Building a DMX Activity Monitor
- Dynamically discovering active Universes
Example:
TArray<int32> Universes;
DMX->GetKnownUniverses(Universes);
for (int32 Uni : Universes)
{
UE_LOG(LogTemp, Log, TEXT("Active Universe: %d"), Uni);
}
GetActiveUniverses
void GetActiveUniverses(TArray<int32>& OutUniverses) const;
Get a list of all active Universes (same functionality as GetKnownUniverses, but without sorting).
Parameters:
| Parameter | Type | Direction | Description |
|---|---|---|---|
OutUniverses |
TArray<int32>& |
Output | List of Universe numbers (unspecified order) |
Thread-safe: ✅
Difference from GetKnownUniverses:
GetKnownUniversesreturns results sorted ascending,GetActiveUniversesreturns unsorted results (slightly better performance).
ClearAllDMXBuffers
void ClearAllDMXBuffers();
Clear DMX buffer data for all Universes.
Behavior:
- Clears internal
UniverseToSlotsmap - Does not affect receiver/sender running state
- After clearing,
GetDMXBuffer()/GetDMXValue()will returnfalseuntil new data is received
Use cases:
- Reset DMX state
- Cleanup before switching scenes/shows
ClearDMXBufferForUniverse
void ClearDMXBufferForUniverse(int32 Universe);
Clear DMX buffer data for a specified Universe.
Parameters:
| Parameter | Type | Description |
|---|---|---|
Universe |
int32 |
The Universe number to clear |
Behavior:
- Removes data for the specified Universe from the cache
- Other Universes are unaffected
3.5 Data Transmission
SendDMXBuffer
bool SendDMXBuffer(int32 Universe, const TArray<uint8>& Buffer);
Send one frame of DMX data to a specified Universe.
Parameters:
| Parameter | Type | Direction | Description |
|---|---|---|---|
Universe |
int32 |
Input | Target Universe number (internal numbering, ≥1) |
Buffer |
const TArray<uint8>& |
Input | DMX data (length 1-512 bytes) |
Return value:
| Value | Description |
|---|---|
true |
Send successful (or output not enabled but local cache updated successfully) |
false |
Invalid parameters, engine not initialized, or network send failed |
Behavior flow:
- Parameter validation:
GEnginenot null,Universe > 0,Buffer.Num() > 0 - Universe mapping: Calculate
NetworkUniverse = Universe + StartUniverse - 1 - Update local cache: Write Buffer to
UniverseToSlots[Universe](for real-time activity monitor reflection) - Network send (only when
Output.bEnabled = true):- Build Art-Net OpDmx packet (18-byte header + DMX data)
- Send via UDP to
Output.RemoteIp:Output.Port
- If sender not yet created, automatically attempt
SetupSender()initialization
Art-Net packet structure (built internally by SendDMXBuffer):
| Offset | Bytes | Content |
|---|---|---|
| 0-7 | 8 | "Art-Net\0" magic number |
| 8-9 | 2 | OpCode 0x5000 (little-endian) |
| 10-11 | 2 | Protocol version 0x000E (14) |
| 12 | 1 | Sequence number (fixed 0) |
| 13 | 1 | Physical port (fixed 0) |
| 14-15 | 2 | Universe (little-endian) |
| 16-17 | 2 | Data length (big-endian) |
| 18+ | 1-512 | DMX data |
Notes:
- Buffer length will be clamped to 1-512 bytes
- Even if
Output.bEnabled = false, local cache will be updated - Send socket enables broadcast mode (
SetBroadcast(true))
Example:
// Build and send DMX frame
TArray<uint8> Buffer;
Buffer.SetNumZeroed(512);
Buffer[0] = 255; // Channel 1 = full
Buffer[1] = 128; // Channel 2 = 50%
Buffer[2] = 0; // Channel 3 = off
DMX->SendDMXBuffer(1, Buffer); // Send to Universe 1
3.6 Diagnostics and Monitoring
GetSecondsSinceLastInput
float GetSecondsSinceLastInput() const;
Get the number of seconds since the last DMX packet was received from any Universe.
Return value:
| Value | Description |
|---|---|
float |
Seconds since last input |
BIG_NUMBER |
No input has ever been received |
Thread-safe: ✅
Use cases:
- Signal loss detection
- Network connection status indicator
- Auto-sleep/wake mechanism
Example:
float Elapsed = DMX->GetSecondsSinceLastInput();
if (Elapsed > 5.0f)
{
// No DMX data received for over 5 seconds, possible signal loss
UE_LOG(LogTemp, Warning, TEXT("DMX signal lost for %.1f seconds"), Elapsed);
}
GetSecondsSinceLastInputForUniverse
float GetSecondsSinceLastInputForUniverse(int32 Universe) const;
Get the number of seconds since the last DMX packet was received for a specified Universe.
Parameters:
| Parameter | Type | Description |
|---|---|---|
Universe |
int32 |
Target Universe number |
Return value:
| Value | Description |
|---|---|
float |
Seconds since last input for this Universe |
BIG_NUMBER |
This Universe has never received input |
Thread-safe: ✅
GetProtocol
ESuperDMXProtocol GetProtocol() const;
Get the currently configured DMX protocol.
Return value: Current ESuperDMXProtocol value (ArtNet)
3.7 sACN Multicast Management
SetSACNMulticastUniverses
void SetSACNMulticastUniverses(const TArray<int32>& InUniverses);
Set the list of multicast Universes to join in sACN mode.
Parameters:
| Parameter | Type | Description |
|---|---|---|
InUniverses |
const TArray<int32>& |
List of Universe numbers (>0) |
Behavior (in sACN mode):
- Save the Universe list
- Stop receiver
- Restart receiver with new multicast groups (automatically computes
239.255.{Hi}.{Lo}multicast addresses)
Current status: sACN functionality is reserved but not activated in the current version (code is commented out). Calling this function has no effect.
4. Sequencer Integration
SuperDMX provides deep integration with UE5 Sequencer, allowing DMX animations to be recorded and played back on a timeline.
4.1 UMovieSceneSuperDMXTrack
Header File: Sequencer/MovieSceneSuperDMXTrack.h
Base Class: UMovieSceneNameableTrack, IMovieSceneTrackTemplateProducer
Export Macro: SUPERDMX_API
DMX track container in Sequencer that manages DMX sections for multiple Universes.
Class Structure
UMovieSceneSuperDMXTrack (DMX Track)
├── Section[0]: DMX section for Universe 1
├── Section[1]: DMX section for Universe 2
└── Section[N]: DMX section for Universe N
Public Methods
AddNewSection
UMovieSceneSuperDMXSection* AddNewSection(int32 Universe);
Add a section for the specified Universe. If a section for that Universe already exists, returns the existing one.
Parameters:
| Parameter | Type | Description |
|---|---|---|
Universe |
int32 |
Target Universe number |
Return value: Pointer to newly created or existing UMovieSceneSuperDMXSection
UMovieSceneTrack Interface
| Method | Description |
|---|---|
GetAllSections() |
Return array of all sections |
CreateNewSection() |
Create a blank section |
AddSection(Section) |
Add section to track |
RemoveSection(Section) |
Remove section |
HasSection(Section) |
Check if section exists |
IsEmpty() |
Whether track is empty |
RemoveAllAnimationData() |
Clear all sections |
SupportsType(SectionClass) |
Type support check |
CreateTemplateForSection(Section) |
Create evaluation template (FMovieSceneSuperDMXTemplate) |
4.2 UMovieSceneSuperDMXSection
Header File: Sequencer/MovieSceneSuperDMXSection.h
Base Class: UMovieSceneSection
Export Macro: SUPERDMX_API
DMX animation section for a single Universe, storing keyframe curves for 1-512 channels.
Properties
| Property | Type | Description |
|---|---|---|
Universe |
int32 |
Target Universe number |
ChannelCurves |
TMap<int32, FRichCurve> |
Channel curve mapping (channel number 1-512 → animation curve) |
bIsRecording |
bool |
Recording status flag |
Public Methods
GetOrCreateCurve
FRichCurve& GetOrCreateCurve(int32 Channel);
Get or create the animation curve for a specified channel.
Parameters:
| Parameter | Type | Description |
|---|---|---|
Channel |
int32 |
DMX channel number (1-512) |
Return value: Reference to the corresponding channel’s FRichCurve (creates empty curve if not exists)
GetCurve
const FRichCurve* GetCurve(int32 Channel) const;
Get the animation curve for a specified channel (read-only).
Return value: Pointer to curve, returns nullptr if not exists
EvaluateAndSendDMX
void EvaluateAndSendDMX(const FMovieSceneContext& Context) const;
Evaluate all channel curves based on the current time of the Sequencer context, and send via USuperDMXSubsystem::SendDMXBuffer().
Behavior:
- Check
bIsRecording, skip sending during recording (avoid echo conflicts) - Read the last state of the current Universe as base buffer
- Iterate through
ChannelCurves, evaluate the current value of each curve based on time - Only overwrite channels that have curve definitions (preserve channel values from other sources)
- Call
SendDMXBuffer()to send the merged 512-byte frame
Recording Control
bool GetIsRecording() const;
void SetIsRecording(bool bIn);
Control recording status. During recording, EvaluateAndSendDMX() will not send data, avoiding echo/conflict during recording.
Data Flow
Sequencer playback engine
│
▼
UMovieSceneSuperDMXTrack::CreateTemplateForSection()
│ Create FMovieSceneSuperDMXTemplate
▼
FMovieSceneSuperDMXTemplate::Evaluate()
│ Pass FMovieSceneContext (contains current time)
▼
UMovieSceneSuperDMXSection::EvaluateAndSendDMX()
│ Iterate ChannelCurves → evaluate curve values → build 512B buffer
▼
USuperDMXSubsystem::SendDMXBuffer()
│ Update local cache + build Art-Net packet + UDP send
▼
External DMX devices / Light Actors read
5. Thread Safety Model
USuperDMXSubsystem operates in a multi-threaded environment with the following protection mechanisms:
Thread Roles
| Thread | Responsibility |
|---|---|
Receive Thread (FUdpSocketReceiver) |
Runs continuously in background, receives UDP packets → parses → writes to cache |
| Game Thread | Calls GetDMXValue/GetDMXBuffer/SendDMXBuffer to read/write cache |
Mutex Protection
| Mutex | Protected Data | Users |
|---|---|---|
DataMutex (FCriticalSection) |
UniverseToSlots (DMX data cache) |
Read: GetDMXBuffer/Value/Active/KnownUniverses, ClearAll/ClearForUniverseWrite: HandleDatagram, SendDMXBuffer |
TimeMutex (FCriticalSection) |
LastAnyInputSeconds, UniverseToLastInputSeconds |
Read: GetSecondsSinceLastInput*Write: HandleDatagram |
Lock Usage Pattern
All locks use the FScopeLock RAII pattern, ensuring exception safety:
// Typical read pattern
bool USuperDMXSubsystem::GetDMXValue(...) const
{
FScopeLock Lock(&DataMutex);
// Read UniverseToSlots under lock protection
// FScopeLock destructor automatically releases the lock
}
Performance Considerations
- Receiver uses zero throttling (
FTimespan::FromMicroseconds(0)), maximizing throughput - Receive buffer 2 MB, send buffer 256 KB
- Lock granularity is at operation level (not channel level), simple and efficient
GetDMXBufferreturns a data copy, lock hold time is extremely short
6. Network Protocol Details
6.1 Art-Net OpDmx Packet Format
Art-Net packets sent and received by SuperDMX follow the Art-Net 4 protocol:
Offset Size Field Value / Description
─────────────────────────────────────
0 8 Magic "Art-Net\0" (ASCII + NULL)
8 2 OpCode 0x5000 (little-endian, DMX data packet)
10 2 ProtVer 0x000E (14, big-endian)
12 1 Sequence 0 (sequence number, currently fixed)
13 1 Physical 0 (physical port, currently fixed)
14 2 Universe Universe number (little-endian)
16 2 Length DMX data length (big-endian, 1-512)
18 N Data DMX channel data (N = Length)
6.2 sACN E1.31 Packet Format (Reserved)
Offset Size Field Value / Description
──────────────────────────────────────────
4 12 ACN Packet ID "ACN-E1.17\0\0\0"
113 2 Universe Universe number (big-endian)
123 2 Property Value Count DMX data length + 1 (big-endian, includes start code)
125 1 Start Code 0x00
126 N Data DMX channel data (N = Count - 1)
6.3 Parsing Key Points
| Item | Art-Net | sACN |
|---|---|---|
| Minimum packet length | 18 bytes | 126 bytes |
| Magic number verification | "Art-Net\0" 8 bytes |
ACN ID 12 bytes |
| Universe byte order | Little-endian (LE) | Big-endian (BE) |
| Data length byte order | Big-endian (BE) | Big-endian (BE) |
| OpCode verification | 0x5000 |
None (identified by ACN ID) |
7. Universe Numbering and StartUniverse Mapping
Problem Background
Different consoles have different Universe numbering conventions:
- MA2/MA3 default: Network Universe starts from 0 (Art-Net standard)
- Some consoles: Network Universe starts from 1
- SuperStage internal: Universe starts from 1
Mapping Formula
FSuperDMXEndpoint.StartUniverse is used to unify numbering:
Input direction (receive):
InternalUniverse = NetworkUniverse - StartUniverse + 1
Output direction (send):
NetworkUniverse = InternalUniverse + StartUniverse - 1
Configuration Examples
| Scenario | StartUniverse | Network Universe 0 | Network Universe 1 |
|---|---|---|---|
| MA2 default | 0 |
→ Internal 1 | → Internal 2 |
| Console starting from 1 | 1 |
→ Discard (<1) | → Internal 1 |
| Offset alignment | 10 |
→ Discard | → Discard (<1) |
Important: If the calculated
InternalUniverse < 1, the packet will be discarded.
Best Practices
| Console | Recommended StartUniverse |
|---|---|
| grandMA2 | 0 |
| grandMA3 | 0 |
| Hog4 | 0 |
| ETC Eos | 0 |
| Custom / Starting from 1 | 1 |
8. Usage Examples
8.1 Basic Reception Example
#include "SuperDMXSubsystem.h"
void AMyActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
USuperDMXSubsystem* DMX = GEngine->GetEngineSubsystem<USuperDMXSubsystem>();
if (!DMX) return;
// Read Universe 1, Channel 1 value
uint8 DimmerRaw = 0;
if (DMX->GetDMXValue(1, 1, DimmerRaw))
{
float Dimmer = DimmerRaw / 255.0f;
// Apply brightness...
}
// Read entire frame
TArray<uint8> Buffer;
if (DMX->GetDMXBuffer(1, Buffer))
{
uint8 Red = Buffer[1]; // Channel 2
uint8 Green = Buffer[2]; // Channel 3
uint8 Blue = Buffer[3]; // Channel 4
}
}
8.2 Configuration Switching Example
void AMyController::SwitchToArtNet(const FString& BindIp, int32 Port)
{
USuperDMXSubsystem* DMX = GEngine->GetEngineSubsystem<USuperDMXSubsystem>();
if (!DMX) return;
FSuperDMXIOConfig Config;
Config.Protocol = ESuperDMXProtocol::ArtNet;
// Input: bind to specific network interface
Config.Input.bEnabled = true;
Config.Input.LocalIp = BindIp;
Config.Input.Port = Port;
Config.Input.StartUniverse = 0;
// Output: broadcast
Config.Output.bEnabled = true;
Config.Output.RemoteIp = TEXT("255.255.255.255");
Config.Output.Port = Port;
Config.Output.StartUniverse = 0;
DMX->ApplyConfig(Config);
}
8.3 DMX Send Example (Programmatic Control)
void AMyController::SendDMXFrame(int32 Universe)
{
USuperDMXSubsystem* DMX = GEngine->GetEngineSubsystem<USuperDMXSubsystem>();
if (!DMX) return;
TArray<uint8> Frame;
Frame.SetNumZeroed(512);
// Set channel values
Frame[0] = 255; // Channel 1: Dimmer full
Frame[1] = 128; // Channel 2: Pan center
Frame[2] = 64; // Channel 3: Tilt 1/4
Frame[3] = 200; // Channel 4: Red
Frame[4] = 100; // Channel 5: Green
Frame[5] = 50; // Channel 6: Blue
bool bSuccess = DMX->SendDMXBuffer(Universe, Frame);
// bSuccess is true indicating successful send
}
8.4 Signal Monitoring Example
void AMyMonitor::CheckDMXHealth()
{
USuperDMXSubsystem* DMX = GEngine->GetEngineSubsystem<USuperDMXSubsystem>();
if (!DMX) return;
// Global signal check
float GlobalElapsed = DMX->GetSecondsSinceLastInput();
bool bSignalActive = (GlobalElapsed < 2.0f);
// Per-Universe check
TArray<int32> Universes;
DMX->GetKnownUniverses(Universes);
for (int32 Uni : Universes)
{
float UniElapsed = DMX->GetSecondsSinceLastInputForUniverse(Uni);
if (UniElapsed > 5.0f)
{
UE_LOG(LogTemp, Warning, TEXT("Universe %d: signal lost (%.1fs)"), Uni, UniElapsed);
}
}
}
9. FAQ and Troubleshooting
Q1: Cannot receive DMX data
| Check Item | Action |
|---|---|
| Firewall | Ensure UDP port 6454 is not blocked |
| IP Binding | Try LocalIp = "" to bind all interfaces |
| Console Output | Confirm console has Art-Net output enabled and correct subnet |
| StartUniverse | Check if offset causes InternalUniverse < 1 (data discarded) |
| Input.bEnabled | Ensure set to true |
| Diagnostics | GetSecondsSinceLastInput() returning BIG_NUMBER means no data has ever been received |
Q2: High data latency
| Check Item | Action |
|---|---|
| Network Topology | DMX devices and UE host should be on the same subnet/VLAN |
| Switch | Use gigabit switch, avoid IGMP snooping interference with broadcasts |
| Frame Rate | Ensure UE frame rate ≥ DMX refresh rate (usually 44fps) |
Q3: SendDMXBuffer returns false
| Cause | Solution |
|---|---|
Universe ≤ 0 |
Universe must be ≥ 1 |
Buffer is empty |
Must contain at least 1 byte |
Output.bEnabled = false |
In this case, only local cache is updated (returns true) |
| Sender not initialized | Check if Output.RemoteIp is valid |
Q4: Multi-Universe performance
- Each Universe independently cached, queries do not interfere
- Lock granularity at operation level, no significant contention under high concurrency
- Recommend using
GetDMXBuffer()for batch reading rather than per-channelGetDMXValue()
Q5: Sequencer recording and playback conflict
- During recording,
bIsRecording = true, playback sending is automatically skipped - After recording, call
SetIsRecording(false)to resume playback - Buffer merge strategy during playback: only overwrite channels with curves, preserve other channel values
Appendix: API Quick Reference
USuperDMXSubsystem
| Function | Category | Thread-Safe | Description |
|---|---|---|---|
ApplyConfig(Config) |
Config | — | Apply I/O config and restart transceiver |
Stop() |
Config | — | Stop all network activity |
GetDMXBuffer(Uni, Out) |
Query | ✅ | Get full DMX frame buffer |
GetDMXValue(Uni, Addr, Out) |
Query | ✅ | Get single channel value |
GetKnownUniverses(Out) |
Query | ✅ | Get known Universe list (sorted) |
GetActiveUniverses(Out) |
Query | ✅ | Get active Universe list (unsorted) |
ClearAllDMXBuffers() |
Management | ✅ | Clear all buffers |
ClearDMXBufferForUniverse(Uni) |
Management | ✅ | Clear single Universe buffer |
SendDMXBuffer(Uni, Buffer) |
Send | ✅ | Send DMX frame |
GetSecondsSinceLastInput() |
Diagnostic | ✅ | Global last input time |
GetSecondsSinceLastInputForUniverse(Uni) |
Diagnostic | ✅ | Specified Universe last input time |
GetProtocol() |
Query | — | Current protocol |
SetSACNMulticastUniverses(Universes) |
sACN | — | Set multicast Universes (reserved) |
UMovieSceneSuperDMXTrack
| Function | Description |
|---|---|
AddNewSection(Universe) |
Add Universe section |
GetAllSections() |
Get all sections |
UMovieSceneSuperDMXSection
| Function/Property | Description |
|---|---|
Universe |
Target Universe |
ChannelCurves |
Channel → Curve mapping |
GetOrCreateCurve(Channel) |
Get/create channel curve |
GetCurve(Channel) |
Get channel curve (read-only) |
EvaluateAndSendDMX(Context) |
Evaluate and send DMX |
SetIsRecording(bool) |
Set recording status |
GetIsRecording() |
Query recording status |