Umsci
Upmix Spatial Control Interface — OCA/OCP.1 spatial audio utility
Loading...
Searching...
No Matches
DeviceController Class Reference

Singleton that owns the OCP.1 (AES70) TCP connection to a d&b audiotechnik DS100 device and exposes a high-level Remote-Object API to the rest of Umsci. More...

#include <DeviceController.h>

+ Inheritance diagram for DeviceController:
+ Collaboration diagram for DeviceController:

Classes

struct  RemObjAddr
 Two-dimensional address of a remote object on the DS100. More...
 
struct  RemoteObject
 A fully-qualified remote parameter including its type, address, and current value. More...
 
class  RemoteObjectReceivedMessage
 Carries a decoded RemoteObject across the thread boundary via JUCE's message queue. More...
 
class  StateChangeMessage
 Carries a State value across the thread boundary via JUCE's message queue. More...
 

Public Types

enum  State {
  Disconnected ,
  Connecting ,
  Subscribing ,
  Subscribed ,
  GetValues ,
  Connected
}
 Represents the logical phase of the OCP.1 connection. More...
 
enum  DbDeviceModel {
  InvalidDev = 0 ,
  DS100 ,
  DS100D ,
  DS100M ,
  InvalidDev_max
}
 Identifies which DS100 hardware variant is connected. More...
 
enum  MappingAreaId {
  InvalidMapId = -1 ,
  First = 1 ,
  Second ,
  Third ,
  Fourth ,
  InvaliMapId_max
}
 Identifies a DS100 coordinate-mapping area (1–4). More...
 

Public Member Functions

 DeviceController ()
 
virtual ~DeviceController ()
 
void timerCallback () override
 juce::Timer callback — retries connectToSocket() while in Connecting state.
 
void handleMessage (const juce::Message &message) override
 juce::MessageListener callback — dispatches messages posted from the socket thread.
 
bool connect ()
 Initiates the TCP connection. No-op if not in Disconnected state.
 
void disconnect ()
 Closes the TCP connection and resets state to Disconnected. Safe to call from any state, including already-Disconnected.
 
void setConnectionParameters (juce::IPAddress ip, int port, int timeoutMs=150)
 Updates connection parameters and reconnects if currently connected.
 
const std::tuple< juce::IPAddress, int, int > getConnectionParameters ()
 Returns the current connection parameters as {ip, port, timeoutMs}.
 
const State getState () const
 Returns the current connection/subscription state.
 
bool SetActiveRemoteObjects (const std::vector< RemoteObject > &remObjs)
 Sets the list of remote objects to subscribe to on the next connection.
 
const std::vector< RemoteObject > & GetActiveRemoteObjects ()
 Returns the active subscription list last set by SetActiveRemoteObjects().
 
bool SetObjectValue (const RemoteObject &remObj)
 Sends a SetValue command to the device for the given remote object.
 

Public Attributes

std::function< bool(const RemoteObject &)> onRemoteObjectReceived
 Called on the JUCE message thread when a notification or get-value response is decoded for a subscribed remote object.
 
std::function< void(const State state)> onStateChanged
 Called on the JUCE message thread whenever the connection state changes.
 

Static Public Attributes

static constexpr std::uint16_t sc_MAX_INPUTS_CHANNELS = 128
 
static constexpr std::uint16_t sc_MAX_OUTPUT_CHANNELS = 64
 
static constexpr std::uint16_t sc_MAX_FUNCTION_GROUPS = 32
 
static constexpr std::uint16_t sc_MAX_REVERB_ZONES = 4
 

Detailed Description

Singleton that owns the OCP.1 (AES70) TCP connection to a d&b audiotechnik DS100 device and exposes a high-level Remote-Object API to the rest of Umsci.

Overview

OCP.1 is a binary protocol defined in the AES70 standard. Every controllable parameter on the device lives at a fixed 32-bit Object Number (ONo) and can be subscribed to, queried, or set. This class hides all that complexity behind the RemoteObject/RemObjIdent/RemObjAddr vocabulary that the rest of the application uses.

Connection lifecycle

Disconnected ─connect()──► Connecting ──TCP established──► (queries GUID)
▲ │
└──disconnect()──────────────────── Connected ◄──── Subscribed ◄── Subscribing
GetValues ──all responses──┘
@ Connected
All subscriptions confirmed and all initial values received.
@ Connecting
TCP connect in progress; timer retries until success.
@ GetValues
GetValue responses being collected.
@ Subscribing
AddSubscription commands sent, awaiting acknowledgements.
@ Disconnected
No TCP connection exists; no resources are allocated.
@ Subscribed
All subscriptions confirmed; GetValue queries still pending.

State transitions are posted as StateChangeMessage objects to the JUCE message thread so that onStateChanged is always called on the message thread.

Addressing

Most DS100 objects are indexed by a primary channel (1-based) and sometimes a secondary record (mapping area 1-4, output channel, function group, etc.). These two dimensions are captured in RemObjAddr::pri and RemObjAddr::sec. Objects with no channel addressing use RemObjAddr() (both fields == sc_INV == 0).

Threading

NanoOcp1::NanoOcp1Client fires onDataReceived on the JUCE IPC/socket thread. ocp1MessageReceived() runs there. State changes and decoded RemoteObjects are dispatched to the message thread via juce::MessageListener::postMessage().

How to add a new subscribed object

  1. Add an entry to RemObjIdent.
  2. Handle it in GetObjectDescription().
  3. Add it to CreateKnownONosMap() with the right dbOcaObjectDef_* factory.
  4. Add it to GetObjectDefinition() to allow on-demand definition creation.
  5. Add it to the datatype switch in UpdateObjectValue().

DS100 hardware background

The DS100 is a signal engine by d&b audiotechnik: it combines an audio matrix, a convolution reverb engine (En-Space), and a spatialization algorithm (En-Scene) to drive a distributed d&b loudspeaker system.

  • Matrix inputs/outputs — audio channels accepted from (inputs) or sent to (outputs) the audio network (Dante or Milan). Internal routing and processing are fully configurable via AES70/OCA/OCP.1. The available I/O count depends on the active software license (M / L / XL).
  • Sound objects — when En-Scene (the spatialization algorithm) is activated for a matrix input, it controls the matrix nodes to create a spatially specific routing of that input to the connected loudspeaker outputs. This turns the matrix input into a positionable "sound object" with X/Y/Z coordinates, spread, and delay mode.
  • Function groups — logical groups of matrix outputs, each corresponding to a distinct subset of loudspeakers in the system (e.g. main PA, subwoofers, ceiling, surround). Grouping allows users to manage per-group delay and spread without addressing individual outputs.
  • En-Space zones — the four processing zones for the convolution reverb engine's early-reflection algorithm. Three zones (Left, Center, Right) cover the stage area; one zone (Audience) covers the rest of the venue. The zone assignment tells the algorithm which set of impulse responses to apply for each position.
  • Coordinate mapping — En-Scene can optionally transform sound-object positions through a virtual-to-real coordinate mapping (up to four independent areas, each defined by corner-point pairs) before driving the routing.

Definition at line 94 of file DeviceController.h.

Member Enumeration Documentation

◆ DbDeviceModel

Identifies which DS100 hardware variant is connected.

Detected automatically from the 8-character device GUID returned by the Fixed_GUID OCA object immediately after TCP connection. The model affects which OCA object definitions are used for speaker positions (see SetOcaRevisionAndDeviceModel() and ProcessGuidAndSubscribe()).

Hardware variants:

  • DS100 — the original Dante-based machine (legacy audio network).
  • DS100D — updated Dante machine (newer OCA revision; all known firmware releases include scalability, so stack ident is always 1).
  • DS100M — Milan audio-network enabled machine (newer protocol standard, scalability added from firmware version "02" onward).
Enumerator
InvalidDev 

Not yet determined or unsupported device.

DS100 

Standard DS100.

DS100D 

DS100D (Dante network audio variant).

DS100M 

DS100M (Milan network audio variant).

InvalidDev_max 

Definition at line 129 of file DeviceController.h.

◆ MappingAreaId

Identifies a DS100 coordinate-mapping area (1–4).

En-Scene supports up to four independent coordinate-mapping areas. Each area defines a virtual-to-real transform via corner-point pairs (P1/P2/P3/P4 real and P1/P3 virtual), enabling a single sound object to be positioned in different virtual coordinate spaces that are each mapped to different parts of the physical room.

Each sound object can have a position in every mapping area simultaneously. Used as the sec (secondary/record) dimension of RemObjAddr for CoordinateMapping_SourcePosition and CoordinateMappingSettings_* objects.

Enumerator
InvalidMapId 

Sentinel for "no mapping area".

First 

Mapping area 1.

Second 

Mapping area 2.

Third 

Mapping area 3.

Fourth 

Mapping area 4.

InvaliMapId_max 

Definition at line 151 of file DeviceController.h.

◆ State

Represents the logical phase of the OCP.1 connection.

Transitions always flow in order from Disconnected toward Connected; they never skip steps. The reverse direction (toward Disconnected) happens only when disconnect() is called explicitly or the TCP connection is lost.

Enumerator
Disconnected 

No TCP connection exists; no resources are allocated.

Connecting 

TCP connect in progress; timer retries until success.

Subscribing 

AddSubscription commands sent, awaiting acknowledgements.

Subscribed 

All subscriptions confirmed; GetValue queries still pending.

GetValues 

GetValue responses being collected.

Connected 

All subscriptions confirmed and all initial values received.

Definition at line 104 of file DeviceController.h.

Constructor & Destructor Documentation

◆ DeviceController()

DeviceController::DeviceController ( )

Constructs the singleton.

Initialization order:

  1. CreateKnownONosMap() — pre-builds the ROI→ONo lookup tables for the full DS100 parameter set so that subsequent GetObjectDefinition() calls are fast.
  2. A NanoOcp1Client is created with callbacksOnMessageThread = false so that onDataReceived fires on the JUCE IPC/socket thread. This avoids blocking the message thread with network I/O.
  3. Three lambdas are wired to the client:
    • onConnectionEstablished — resets device-specific state, then issues the first and only synchronous OCA query: Fixed_GUID. Subscriptions are deferred until the GUID response arrives (see ProcessGuidAndSubscribe()), because the speaker-position object definitions depend on the firmware revision encoded in the GUID.
    • onConnectionLost — clears all pending handles, resets device state, and (if the connection was live) posts a Connecting state + restarts the retry timer.
    • onDataReceived — forwards raw bytes to ocp1MessageReceived().

Default target: 127.0.0.1:50014 (DS100 OCP.1 default port).

Definition at line 47 of file DeviceController.cpp.

◆ ~DeviceController()

DeviceController::~DeviceController ( )
virtual

Definition at line 92 of file DeviceController.cpp.

References disconnect().

Member Function Documentation

◆ connect()

bool DeviceController::connect ( )

Initiates the TCP connection. No-op if not in Disconnected state.

Returns
true if the connection attempt was started.

Definition at line 138 of file DeviceController.cpp.

References Connecting, Disconnected, getState(), and timerCallback().

Referenced by setConnectionParameters().

◆ disconnect()

void DeviceController::disconnect ( )

Closes the TCP connection and resets state to Disconnected. Safe to call from any state, including already-Disconnected.

Definition at line 157 of file DeviceController.cpp.

References Disconnected.

Referenced by setConnectionParameters(), timerCallback(), and ~DeviceController().

◆ GetActiveRemoteObjects()

const std::vector< DeviceController::RemoteObject > & DeviceController::GetActiveRemoteObjects ( )

Returns the active subscription list last set by SetActiveRemoteObjects().

Definition at line 1027 of file DeviceController.cpp.

◆ getConnectionParameters()

const std::tuple< juce::IPAddress, int, int > DeviceController::getConnectionParameters ( )

Returns the current connection parameters as {ip, port, timeoutMs}.

Definition at line 184 of file DeviceController.cpp.

◆ getState()

const DeviceController::State DeviceController::getState ( ) const

Returns the current connection/subscription state.

Definition at line 133 of file DeviceController.cpp.

Referenced by connect(), SetActiveRemoteObjects(), setConnectionParameters(), SetObjectValue(), and timerCallback().

◆ handleMessage()

void DeviceController::handleMessage ( const juce::Message &  message)
override

juce::MessageListener callback — dispatches messages posted from the socket thread.

Handles StateChangeMessage (calls setState()) and RemoteObjectReceivedMessage (calls onRemoteObjectReceived). Always invoked on the JUCE message thread.

Definition at line 202 of file DeviceController.cpp.

References onRemoteObjectReceived.

◆ SetActiveRemoteObjects()

bool DeviceController::SetActiveRemoteObjects ( const std::vector< RemoteObject > &  remObjs)

Sets the list of remote objects to subscribe to on the next connection.

Must be called while in Disconnected state (returns false otherwise). The list is used by CreateObjectSubscriptions() and QueryObjectValues() once the GUID handshake completes. Objects with RemObjIdent::Fixed_GUID are handled specially and do not need to be included here.

Parameters
remObjsDesired subscriptions (id + addr pairs; Var field is ignored).
Returns
true on success; false if not currently Disconnected.

Definition at line 1032 of file DeviceController.cpp.

References Disconnected, and getState().

◆ setConnectionParameters()

void DeviceController::setConnectionParameters ( juce::IPAddress  ip,
int  port,
int  timeoutMs = 150 
)

Updates connection parameters and reconnects if currently connected.

Parameters
ipTarget device IP address.
portOCP.1 TCP port (DS100 default: 50014).
timeoutMsSocket connect/send timeout in milliseconds.

Definition at line 169 of file DeviceController.cpp.

References connect(), disconnect(), Disconnected, and getState().

◆ SetObjectValue()

bool DeviceController::SetObjectValue ( const RemoteObject remObj)

Sends a SetValue command to the device for the given remote object.

Builds the appropriate OCA SetValue command from remObj.Id, remObj.Addr, and remObj.Var, sends it over TCP, and records the pending handle so the response can be matched. Only valid in Connected state.

Parameters
remObjObject to set, with Var populated with the desired value.
Returns
true if the command was sent successfully.

Definition at line 737 of file DeviceController.cpp.

References DeviceController::RemoteObject::Addr, Connected, DeviceController::RemoteObject::GetObjectDescription(), getState(), DeviceController::RemoteObject::Id, DeviceController::RemObjAddr::pri, DeviceController::RemObjAddr::toNiceString(), and DeviceController::RemoteObject::Var.

◆ timerCallback()

void DeviceController::timerCallback ( )
override

juce::Timer callback — retries connectToSocket() while in Connecting state.

Definition at line 189 of file DeviceController.cpp.

References Connecting, disconnect(), and getState().

Referenced by connect().

Member Data Documentation

◆ onRemoteObjectReceived

std::function<bool(const RemoteObject&)> DeviceController::onRemoteObjectReceived

Called on the JUCE message thread when a notification or get-value response is decoded for a subscribed remote object.

Set this callback before calling connect(). The RemoteObject's Var field contains the decoded value.

Definition at line 762 of file DeviceController.h.

Referenced by handleMessage().

◆ onStateChanged

std::function<void(const State state)> DeviceController::onStateChanged

Called on the JUCE message thread whenever the connection state changes.

Useful for updating UI elements (e.g. enable/disable controls when Connected, show a progress indicator when Subscribing, etc.).

Definition at line 770 of file DeviceController.h.

◆ sc_MAX_FUNCTION_GROUPS

constexpr std::uint16_t DeviceController::sc_MAX_FUNCTION_GROUPS = 32
staticconstexpr

Definition at line 163 of file DeviceController.h.

◆ sc_MAX_INPUTS_CHANNELS

constexpr std::uint16_t DeviceController::sc_MAX_INPUTS_CHANNELS = 128
staticconstexpr

Definition at line 161 of file DeviceController.h.

◆ sc_MAX_OUTPUT_CHANNELS

constexpr std::uint16_t DeviceController::sc_MAX_OUTPUT_CHANNELS = 64
staticconstexpr

Definition at line 162 of file DeviceController.h.

◆ sc_MAX_REVERB_ZONES

constexpr std::uint16_t DeviceController::sc_MAX_REVERB_ZONES = 4
staticconstexpr

Definition at line 164 of file DeviceController.h.


The documentation for this class was generated from the following files: