mirror of
https://github.com/onyx-and-iris/vban-cmd-python.git
synced 2026-03-03 08:49:09 +00:00
125 lines
4.6 KiB
Python
125 lines
4.6 KiB
Python
from dataclasses import dataclass
|
|
from enum import Enum
|
|
|
|
from .headers import VbanPingHeader
|
|
|
|
# VBAN PING bitType constants
|
|
VBANPING_TYPE_RECEPTOR = 0x00000001 # Simple receptor
|
|
VBANPING_TYPE_TRANSMITTER = 0x00000002 # Simple Transmitter
|
|
VBANPING_TYPE_RECEPTORSPOT = 0x00000004 # SPOT receptor
|
|
VBANPING_TYPE_TRANSMITTERSPOT = 0x00000008 # SPOT transmitter
|
|
VBANPING_TYPE_VIRTUALDEVICE = 0x00000010 # Virtual Device
|
|
VBANPING_TYPE_VIRTUALMIXER = 0x00000020 # Virtual Mixer
|
|
VBANPING_TYPE_MATRIX = 0x00000040 # MATRIX
|
|
VBANPING_TYPE_DAW = 0x00000080 # Workstation
|
|
VBANPING_TYPE_SERVER = 0x01000000 # VBAN SERVER
|
|
|
|
# VBAN PING bitfeature constants
|
|
VBANPING_FEATURE_AUDIO = 0x00000001
|
|
VBANPING_FEATURE_AOIP = 0x00000002
|
|
VBANPING_FEATURE_VOIP = 0x00000004
|
|
VBANPING_FEATURE_SERIAL = 0x00000100
|
|
VBANPING_FEATURE_MIDI = 0x00000300
|
|
VBANPING_FEATURE_FRAME = 0x00001000
|
|
VBANPING_FEATURE_TXT = 0x00010000
|
|
|
|
|
|
class VbanServerType(Enum):
|
|
"""VBAN server types detected from PONG responses"""
|
|
|
|
UNKNOWN = 0
|
|
VOICEMEETER = VBANPING_TYPE_VIRTUALMIXER
|
|
MATRIX = VBANPING_TYPE_MATRIX
|
|
|
|
|
|
@dataclass
|
|
class VbanPing0Payload:
|
|
"""Represents the VBAN PING0 payload structure as defined in the VBAN protocol documentation."""
|
|
|
|
def __init__(self):
|
|
self.bit_type = VBANPING_TYPE_RECEPTOR
|
|
self.bit_feature = VBANPING_FEATURE_TXT
|
|
self.bit_feature_ex = 0x00000000
|
|
self.preferred_rate = 48000
|
|
self.min_rate = 8000
|
|
self.max_rate = 192000
|
|
self.color_rgb = 0x00FF0000
|
|
self.version = b'\x01\x02\x03\x04'
|
|
self.gps_position = b'\x00' * 8
|
|
self.user_position = b'\x00' * 8
|
|
self.lang_code = b'EN\x00\x00\x00\x00\x00\x00'
|
|
self.reserved = b'\x00' * 8
|
|
self.reserved_ex = b'\x00' * 64
|
|
self.distant_ip = b'\x00' * 32
|
|
self.distant_port = 0
|
|
self.distant_reserved = 0
|
|
self.device_name = b'VBAN-CMD-Python\x00'.ljust(64, b'\x00')
|
|
self.manufacturer_name = b'Python-VBAN\x00'.ljust(64, b'\x00')
|
|
self.application_name = b'vban-cmd\x00'.ljust(64, b'\x00')
|
|
self.host_name = b'localhost\x00'.ljust(64, b'\x00')
|
|
self.user_name = b'Python User\x00'.ljust(128, b'\x00')
|
|
self.user_comment = b'VBAN CMD Python Client\x00'.ljust(128, b'\x00')
|
|
|
|
@classmethod
|
|
def to_bytes(cls) -> bytes:
|
|
"""Convert payload to bytes"""
|
|
payload = cls()
|
|
|
|
data = bytearray()
|
|
data.extend(payload.bit_type.to_bytes(4, 'little'))
|
|
data.extend(payload.bit_feature.to_bytes(4, 'little'))
|
|
data.extend(payload.bit_feature_ex.to_bytes(4, 'little'))
|
|
data.extend(payload.preferred_rate.to_bytes(4, 'little'))
|
|
data.extend(payload.min_rate.to_bytes(4, 'little'))
|
|
data.extend(payload.max_rate.to_bytes(4, 'little'))
|
|
data.extend(payload.color_rgb.to_bytes(4, 'little'))
|
|
data.extend(payload.version)
|
|
data.extend(payload.gps_position)
|
|
data.extend(payload.user_position)
|
|
data.extend(payload.lang_code)
|
|
data.extend(payload.reserved)
|
|
data.extend(payload.reserved_ex)
|
|
data.extend(payload.distant_ip)
|
|
data.extend(payload.distant_port.to_bytes(2, 'little'))
|
|
data.extend(payload.distant_reserved.to_bytes(2, 'little'))
|
|
data.extend(payload.device_name)
|
|
data.extend(payload.manufacturer_name)
|
|
data.extend(payload.application_name)
|
|
data.extend(payload.host_name)
|
|
data.extend(payload.user_name)
|
|
data.extend(payload.user_comment)
|
|
return bytes(data)
|
|
|
|
@classmethod
|
|
def create_packet(cls, framecounter: int) -> bytes:
|
|
"""Creates a complete PING packet with header and payload."""
|
|
data = bytearray()
|
|
data.extend(VbanPingHeader.to_bytes(framecounter))
|
|
data.extend(cls.to_bytes())
|
|
return bytes(data)
|
|
|
|
@staticmethod
|
|
def detect_server_type(pong_data: bytes) -> VbanServerType:
|
|
"""Detect server type from PONG response packet.
|
|
|
|
Args:
|
|
pong_data: Raw bytes from PONG response packet
|
|
|
|
Returns:
|
|
VbanServerType enum indicating the detected server type
|
|
"""
|
|
try:
|
|
if len(pong_data) >= 32:
|
|
frame_counter_bytes = pong_data[28:32]
|
|
frame_counter = int.from_bytes(frame_counter_bytes, 'little')
|
|
|
|
if frame_counter == VbanServerType.MATRIX.value:
|
|
return VbanServerType.MATRIX
|
|
elif frame_counter == VbanServerType.VOICEMEETER.value:
|
|
return VbanServerType.VOICEMEETER
|
|
|
|
return VbanServerType.UNKNOWN
|
|
|
|
except Exception:
|
|
return VbanServerType.UNKNOWN
|