Files
LookingGlass/idd/LGCommon/LGAudioBroker.h
Geoffrey McRae efc9952e74 [idd] audio: support 32-bit and common channel layouts
Advertise signed and floating-point 32-bit formats across mono,
stereo, quad, surround, 5.1, and 7.1 at every supported rate.

Carry sample encoding through the broker and LGMP protocol so integer
and floating-point streams remain distinct.

Expand packet, shared-memory, and ring capacity for eight-channel
32-bit audio.
2026-11-06 14:34:25 +11:00

262 lines
7.2 KiB
C

/**
* Looking Glass
* Copyright © 2017-2026 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#pragma once
#if defined(_KERNEL_MODE) || defined(_NTDDK_) || defined(_WDMDDK_)
extern "C"
{
#include <ntddk.h>
}
#else
#include <Windows.h>
#include <winioctl.h>
#endif
static constexpr wchar_t LGAUDIO_BROKER_NT_DEVICE_NAME[] =
L"\\Device\\LookingGlassAudioBroker";
static constexpr wchar_t LGAUDIO_BROKER_DOS_DEVICE_NAME[] =
L"\\DosDevices\\LookingGlassAudioBroker";
static constexpr wchar_t LGAUDIO_BROKER_USER_DEVICE_PATH[] =
L"\\\\.\\LookingGlassAudioBroker";
// This GUID identifies the security policy for the named control device. It
// is not a PnP device-interface class.
static const GUID LGAUDIO_BROKER_DEVICE_CLASS_GUID =
{ 0x98f877f1, 0x73d6, 0x4429,
{ 0xb4, 0x90, 0x28, 0xc5, 0x30, 0xd2, 0x38, 0xcd } };
static constexpr UINT32 LGAUDIO_BROKER_ABI_VERSION = 2U;
// The transfer limits in LGAudioBrokerCaps exclude the packet header.
static constexpr UINT32 LGAUDIO_BROKER_MAX_PAYLOAD_BYTES = 64U * 1024U;
enum LGAudioBrokerCapability : UINT32
{
LGAUDIO_BROKER_CAP_CONTROL = 1U << 0,
LGAUDIO_BROKER_CAP_RENDER_READ = 1U << 1,
LGAUDIO_BROKER_CAP_CAPTURE_WRITE = 1U << 2,
LGAUDIO_BROKER_CAP_CLOCK_CONTROL = 1U << 3
};
enum LGAudioBrokerStateFlag : UINT32
{
LGAUDIO_BROKER_STATE_ADAPTER_PRESENT = 1U << 0,
LGAUDIO_BROKER_STATE_BOUND = 1U << 1,
LGAUDIO_BROKER_STATE_DATA_PLANE_ACTIVE = 1U << 2
};
enum LGAudioBrokerStreamStateValue : UINT32
{
LGAUDIO_BROKER_STREAM_UNAVAILABLE = 0,
LGAUDIO_BROKER_STREAM_STOPPED = 1,
LGAUDIO_BROKER_STREAM_ACQUIRED = 2,
LGAUDIO_BROKER_STREAM_PAUSED = 3,
LGAUDIO_BROKER_STREAM_RUNNING = 4
};
enum LGAudioBrokerStreamFlag : UINT32
{
LGAUDIO_BROKER_STREAM_FORMAT_VALID = 1U << 0
};
enum LGAudioBrokerPacketDirection : UINT32
{
LGAUDIO_BROKER_PACKET_RENDER = 1,
LGAUDIO_BROKER_PACKET_CAPTURE = 2
};
enum LGAudioBrokerPacketFlag : UINT32
{
LGAUDIO_BROKER_PACKET_DISCONTINUITY = 1U << 0
};
enum LGAudioBrokerSampleFormat : UINT32
{
LGAUDIO_BROKER_SAMPLE_S16_LE = 1,
LGAUDIO_BROKER_SAMPLE_S24_LE = 2,
LGAUDIO_BROKER_SAMPLE_S32_LE = 3,
LGAUDIO_BROKER_SAMPLE_F32_LE = 4
};
static constexpr UINT32 IOCTL_LGAUDIO_BROKER_QUERY_CAPS =
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_BUFFERED,
FILE_READ_ACCESS | FILE_WRITE_ACCESS);
static constexpr UINT32 IOCTL_LGAUDIO_BROKER_QUERY_STATE =
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x901, METHOD_BUFFERED,
FILE_READ_ACCESS | FILE_WRITE_ACCESS);
static constexpr UINT32 IOCTL_LGAUDIO_BROKER_BIND =
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x902, METHOD_BUFFERED,
FILE_READ_ACCESS | FILE_WRITE_ACCESS);
static constexpr UINT32 IOCTL_LGAUDIO_BROKER_UNBIND =
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x903, METHOD_BUFFERED,
FILE_READ_ACCESS | FILE_WRITE_ACCESS);
static constexpr UINT32 IOCTL_LGAUDIO_BROKER_QUERY_STATS =
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x904, METHOD_BUFFERED,
FILE_READ_ACCESS | FILE_WRITE_ACCESS);
static constexpr UINT32 IOCTL_LGAUDIO_BROKER_SET_CLOCK_CONTROL =
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x905, METHOD_BUFFERED,
FILE_READ_ACCESS | FILE_WRITE_ACCESS);
#pragma pack(push, 8)
struct LGAudioBrokerHeader
{
UINT32 size;
UINT32 version;
};
struct LGAudioBrokerFormat
{
UINT32 sampleFormat;
UINT32 sampleRate;
UINT32 channelMask;
UINT16 channels;
UINT16 containerBits;
UINT16 validBits;
UINT16 blockAlign;
UINT32 reserved;
};
struct LGAudioBrokerStreamState
{
// Changes on format configuration and each transition to STOP.
UINT64 generation;
UINT32 state;
UINT32 flags;
LGAudioBrokerFormat format;
};
struct LGAudioBrokerPacketHeader
{
// READ returns this header followed by render payload. WRITE accepts this
// header followed by capture payload. size is always the header size.
UINT32 size;
UINT32 version;
UINT32 flags;
UINT32 direction;
UINT64 adapterGeneration;
UINT64 bindingGeneration;
UINT64 streamGeneration;
// Render sequence is monotonic for the driver lifetime. Capture starts at
// zero for each binding/stream-generation pair and must be contiguous.
UINT64 sequence;
LGAudioBrokerFormat format;
UINT32 frameCount;
UINT32 payloadBytes;
UINT32 reserved[2];
};
struct LGAudioBrokerCaps
{
UINT32 size;
UINT32 version;
UINT32 minimumVersion;
UINT32 maximumVersion;
UINT32 capabilities;
UINT32 maximumRenderTransfer;
UINT32 maximumCaptureTransfer;
UINT32 reserved0;
UINT64 reserved[4];
};
struct LGAudioBrokerState
{
UINT32 size;
UINT32 version;
UINT32 flags;
UINT32 reserved0;
UINT64 adapterGeneration;
UINT64 eventSequence;
UINT64 bindingGeneration;
LGAudioBrokerStreamState render;
LGAudioBrokerStreamState capture;
};
struct LGAudioBrokerBind
{
UINT32 size;
UINT32 version;
UINT32 flags;
UINT32 reserved0;
UINT64 adapterGeneration;
UINT64 bindingGeneration;
UINT64 reserved[2];
};
struct LGAudioBrokerStats
{
UINT32 size;
UINT32 version;
UINT64 adapterGeneration;
UINT64 eventSequence;
UINT64 bindingGeneration;
UINT64 bindCount;
UINT64 unbindCount;
UINT64 cleanupCount;
UINT64 rejectedRequestCount;
UINT64 renderPacketCount;
UINT64 renderByteCount;
UINT64 renderDropBytes;
UINT64 capturePacketCount;
UINT64 captureByteCount;
UINT64 captureDropBytes;
UINT64 captureUnderrunBytes;
UINT64 cancelledReadCount;
UINT64 reserved[4];
};
struct LGAudioBrokerClockControl
{
UINT32 size;
UINT32 version;
UINT32 flags;
UINT32 reserved0;
UINT64 adapterGeneration;
UINT64 bindingGeneration;
UINT64 streamGeneration;
// Absolute render frames per second in unsigned Q32.32 format.
UINT64 targetRateQ32;
UINT64 reserved[2];
};
#pragma pack(pop)
static_assert(sizeof(LGAudioBrokerHeader) == 8,
"LGAudio broker header layout changed");
static_assert(sizeof(LGAudioBrokerFormat) == 24,
"LGAudio broker format layout changed");
static_assert(sizeof(LGAudioBrokerStreamState) == 40,
"LGAudio broker stream-state layout changed");
static_assert(sizeof(LGAudioBrokerPacketHeader) == 88,
"LGAudio broker packet layout changed");
static_assert(sizeof(LGAudioBrokerCaps) == 64,
"LGAudio broker capabilities layout changed");
static_assert(sizeof(LGAudioBrokerState) == 120,
"LGAudio broker state layout changed");
static_assert(sizeof(LGAudioBrokerBind) == 48,
"LGAudio broker binding layout changed");
static_assert(sizeof(LGAudioBrokerStats) == 160,
"LGAudio broker statistics layout changed");
static_assert(sizeof(LGAudioBrokerClockControl) == 64,
"LGAudio broker clock-control layout changed");
static_assert(LGAUDIO_BROKER_MAX_PAYLOAD_BYTES >=
(192000U / 100U) * 8U * 4U,
"LGAudio broker payload cannot hold 10 ms at the maximum format");