Display controls (enum/get/set): - Add PROTO_DISPLAY_CTRL_SCALE/ANCHOR/NO_SIGNAL_FPS constants to protocol.h - handle_enum_controls: if device index maps to an active display slot, return the three display controls (scale, anchor, no_signal_fps) - handle_get_control: read display control values from slot under mutex - handle_set_control: write display control values to slot under mutex; scale/anchor are applied to the viewer by display_loop_tick each tick Device IDs in enum-devices output: - Proto_Display_Device_Info gains device_id field (wire format +2 bytes) - handle_enum_devices computes device_id = total_v4l2 + display_index - on_video_node/on_standalone callbacks take int* userdata to print [idx] - on_display prints [device_id] from the wire field Bug fix — protocol error on invalid device index: - proto_read_enum_controls_response: early-return APP_OK after reading status if status != OK; error responses have no count/data fields, so the CUR_CHECK on count was failing with "payload too short" Helpers added to main.c: - count_v4l2_devices(): sum of media vnodes + standalone - find_display_by_device_idx(): maps flat index to Display_Slot Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
547 lines
19 KiB
C
547 lines
19 KiB
C
#pragma once
|
|
|
|
#include <stdint.h>
|
|
#include "error.h"
|
|
#include "transport.h"
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Message type constants
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
#define PROTO_MSG_VIDEO_FRAME 0x0001u
|
|
#define PROTO_MSG_CONTROL_REQUEST 0x0002u
|
|
#define PROTO_MSG_CONTROL_RESPONSE 0x0003u
|
|
#define PROTO_MSG_STREAM_EVENT 0x0004u
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Command codes (carried in CONTROL_REQUEST payload offset 2)
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
#define PROTO_CMD_STREAM_OPEN 0x0001u
|
|
#define PROTO_CMD_STREAM_CLOSE 0x0002u
|
|
#define PROTO_CMD_ENUM_DEVICES 0x0003u
|
|
#define PROTO_CMD_ENUM_CONTROLS 0x0004u
|
|
#define PROTO_CMD_GET_CONTROL 0x0005u
|
|
#define PROTO_CMD_SET_CONTROL 0x0006u
|
|
#define PROTO_CMD_ENUM_MONITORS 0x0007u
|
|
#define PROTO_CMD_START_INGEST 0x0008u
|
|
#define PROTO_CMD_STOP_INGEST 0x0009u
|
|
#define PROTO_CMD_START_DISPLAY 0x000Au
|
|
#define PROTO_CMD_STOP_DISPLAY 0x000Bu
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Response status codes (carried in CONTROL_RESPONSE payload offset 2)
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
#define PROTO_STATUS_OK 0x0000u
|
|
#define PROTO_STATUS_ERROR 0x0001u
|
|
#define PROTO_STATUS_UNKNOWN_CMD 0x0002u
|
|
#define PROTO_STATUS_INVALID_PARAMS 0x0003u
|
|
#define PROTO_STATUS_NOT_FOUND 0x0004u
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Stream event codes (carried in STREAM_EVENT payload offset 2)
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
#define PROTO_EVENT_INTERRUPTED 0x01u
|
|
#define PROTO_EVENT_RESUMED 0x02u
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Codec format codes (STREAM_OPEN format field)
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
#define PROTO_FORMAT_MJPEG 0x0001u
|
|
#define PROTO_FORMAT_H264 0x0002u
|
|
#define PROTO_FORMAT_H265 0x0003u
|
|
#define PROTO_FORMAT_AV1 0x0004u
|
|
#define PROTO_FORMAT_FFV1 0x0005u
|
|
#define PROTO_FORMAT_PRORES 0x0006u
|
|
#define PROTO_FORMAT_QOI 0x0007u
|
|
#define PROTO_FORMAT_RAW 0x0008u
|
|
#define PROTO_FORMAT_RAW_ZSTD 0x0009u
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Pixel format codes (STREAM_OPEN pixel_format field; 0 for compressed)
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
#define PROTO_PIXEL_BGRA8888 0x0001u
|
|
#define PROTO_PIXEL_RGBA8888 0x0002u
|
|
#define PROTO_PIXEL_BGR888 0x0003u
|
|
#define PROTO_PIXEL_YUV420P 0x0004u
|
|
#define PROTO_PIXEL_YUV422 0x0005u
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Transport mode codes (START_INGEST transport_mode field)
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
#define PROTO_TRANSPORT_ENCAPSULATED 0x0001u /* framed: message_type + payload_length header */
|
|
#define PROTO_TRANSPORT_OPAQUE 0x0002u /* raw byte stream, no frame boundaries */
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Origin codes (STREAM_OPEN origin field; informational only)
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
#define PROTO_ORIGIN_DEVICE_NATIVE 0x0001u
|
|
#define PROTO_ORIGIN_LIBJPEG_TURBO 0x0002u
|
|
#define PROTO_ORIGIN_FFMPEG_LIBAV 0x0003u
|
|
#define PROTO_ORIGIN_FFMPEG_PROC 0x0004u
|
|
#define PROTO_ORIGIN_VAAPI 0x0005u
|
|
#define PROTO_ORIGIN_NVENC 0x0006u
|
|
#define PROTO_ORIGIN_SOFTWARE 0x0007u
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Structs used by write functions (variable-length response payloads)
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
struct Proto_Menu_Item {
|
|
uint32_t index;
|
|
const char *name;
|
|
int64_t int_value;
|
|
};
|
|
|
|
struct Proto_Control_Info {
|
|
uint32_t id;
|
|
uint8_t type;
|
|
uint32_t flags;
|
|
const char *name;
|
|
int32_t min, max, step, default_val, current_val;
|
|
uint8_t menu_count;
|
|
const struct Proto_Menu_Item *menu_items;
|
|
};
|
|
|
|
/*
|
|
* A video node associated with a media controller device.
|
|
* entity_type and entity_flags are MEDIA_ENT_F_* / MEDIA_ENT_FL_* values.
|
|
* pad_flags uses MEDIA_PAD_FLAG_SOURCE / MEDIA_PAD_FLAG_SINK.
|
|
* is_capture: 1 if this node is the primary video capture output.
|
|
*/
|
|
struct Proto_Video_Node_Info {
|
|
const char *path;
|
|
const char *entity_name;
|
|
uint32_t entity_type;
|
|
uint32_t entity_flags;
|
|
uint32_t device_caps; /* V4L2_CAP_* bits from VIDIOC_QUERYCAP */
|
|
uint8_t pad_flags;
|
|
uint8_t is_capture;
|
|
};
|
|
|
|
/*
|
|
* A media controller device and its associated video nodes.
|
|
* video_node_count must be <= 255.
|
|
*/
|
|
struct Proto_Media_Device_Info {
|
|
const char *path;
|
|
const char *driver;
|
|
const char *model;
|
|
const char *bus_info;
|
|
uint8_t video_node_count;
|
|
const struct Proto_Video_Node_Info *video_nodes;
|
|
};
|
|
|
|
/*
|
|
* A standalone V4L2 device with no associated media controller.
|
|
* name is the card name from VIDIOC_QUERYCAP.
|
|
*/
|
|
struct Proto_Standalone_Device_Info {
|
|
const char *path;
|
|
const char *name;
|
|
};
|
|
|
|
/*
|
|
* An active display window (video sink role).
|
|
* device_id is the flat device index (follows all V4L2 devices).
|
|
* stream_id is the stream being displayed; win_* are current geometry.
|
|
*/
|
|
struct Proto_Display_Device_Info {
|
|
uint16_t device_id;
|
|
uint16_t stream_id;
|
|
int16_t win_x, win_y;
|
|
uint16_t win_w, win_h;
|
|
uint8_t scale;
|
|
uint8_t anchor;
|
|
};
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Display device pseudo-control IDs — used in ENUM_CONTROLS / GET_CONTROL /
|
|
* SET_CONTROL for display device indices returned by ENUM_DEVICES.
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
#define PROTO_DISPLAY_CTRL_SCALE 0x00D00001u /* int 0-3: stretch/fit/fill/1:1 */
|
|
#define PROTO_DISPLAY_CTRL_ANCHOR 0x00D00002u /* int 0-1: center/topleft */
|
|
#define PROTO_DISPLAY_CTRL_NO_SIGNAL_FPS 0x00D00003u /* int 1-60: no-signal animation fps */
|
|
|
|
struct Proto_Monitor_Info {
|
|
int32_t x, y;
|
|
uint32_t width, height;
|
|
const char *name;
|
|
};
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Structs used by read functions
|
|
* Fields with pointer types point INTO the caller's payload buffer.
|
|
* The caller must keep the payload alive while using those pointers.
|
|
* Strings are NOT NUL-terminated.
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
struct Proto_Video_Frame {
|
|
uint16_t stream_id;
|
|
const uint8_t *data;
|
|
uint32_t data_len;
|
|
};
|
|
|
|
struct Proto_Stream_Event {
|
|
uint16_t stream_id;
|
|
uint8_t event_code;
|
|
};
|
|
|
|
struct Proto_Request_Header {
|
|
uint16_t request_id;
|
|
uint16_t command;
|
|
};
|
|
|
|
struct Proto_Stream_Open {
|
|
uint16_t request_id;
|
|
uint16_t stream_id;
|
|
uint16_t format;
|
|
uint16_t pixel_format;
|
|
uint16_t origin;
|
|
};
|
|
|
|
struct Proto_Stream_Close {
|
|
uint16_t request_id;
|
|
uint16_t stream_id;
|
|
};
|
|
|
|
struct Proto_Enum_Controls_Req {
|
|
uint16_t request_id;
|
|
uint16_t device_index;
|
|
};
|
|
|
|
struct Proto_Get_Control_Req {
|
|
uint16_t request_id;
|
|
uint16_t device_index;
|
|
uint32_t control_id;
|
|
};
|
|
|
|
struct Proto_Set_Control_Req {
|
|
uint16_t request_id;
|
|
uint16_t device_index;
|
|
uint32_t control_id;
|
|
int32_t value;
|
|
};
|
|
|
|
/*
|
|
* START_INGEST: controller tells a source node to open a V4L2 device and
|
|
* connect outbound to a sink at dest_host:dest_port.
|
|
* format/width/height/fps_n/fps_d of 0 mean auto-select.
|
|
* Strings point into the caller's payload buffer; not NUL-terminated.
|
|
*/
|
|
struct Proto_Start_Ingest {
|
|
uint16_t request_id;
|
|
uint16_t stream_id;
|
|
uint16_t format; /* PROTO_FORMAT_* code; 0 = auto (best MJPEG) */
|
|
uint16_t width; /* 0 = auto */
|
|
uint16_t height; /* 0 = auto */
|
|
uint16_t fps_n; /* 0 = auto */
|
|
uint16_t fps_d;
|
|
uint16_t dest_port;
|
|
uint16_t transport_mode; /* PROTO_TRANSPORT_ENCAPSULATED or PROTO_TRANSPORT_OPAQUE */
|
|
const char *device_path;
|
|
uint8_t device_path_len;
|
|
const char *dest_host;
|
|
uint8_t dest_host_len;
|
|
};
|
|
|
|
struct Proto_Stop_Ingest {
|
|
uint16_t request_id;
|
|
uint16_t stream_id;
|
|
};
|
|
|
|
/*
|
|
* START_DISPLAY: controller tells a sink node to open a viewer window and
|
|
* display incoming VIDEO_FRAME messages for the given stream_id.
|
|
* win_x/win_y are screen-space window position (signed: multi-monitor).
|
|
* win_w/win_h of 0 mean use a default size.
|
|
* scale: 0=stretch 1=fit 2=fill 3=1:1 (PROTO_DISPLAY_SCALE_*)
|
|
* anchor: 0=center 1=topleft (PROTO_DISPLAY_ANCHOR_*)
|
|
*/
|
|
struct Proto_Start_Display {
|
|
uint16_t request_id;
|
|
uint16_t stream_id;
|
|
int16_t win_x;
|
|
int16_t win_y;
|
|
uint16_t win_w;
|
|
uint16_t win_h;
|
|
uint8_t scale;
|
|
uint8_t anchor;
|
|
uint8_t no_signal_fps; /* 0 = default (15); no-signal animation frame rate */
|
|
/* 1 byte reserved */
|
|
};
|
|
|
|
struct Proto_Stop_Display {
|
|
uint16_t request_id;
|
|
uint16_t stream_id;
|
|
};
|
|
|
|
/* Scale/anchor constants for Proto_Start_Display */
|
|
#define PROTO_DISPLAY_SCALE_STRETCH 0u
|
|
#define PROTO_DISPLAY_SCALE_FIT 1u
|
|
#define PROTO_DISPLAY_SCALE_FILL 2u
|
|
#define PROTO_DISPLAY_SCALE_1_1 3u
|
|
|
|
#define PROTO_DISPLAY_ANCHOR_CENTER 0u
|
|
#define PROTO_DISPLAY_ANCHOR_TOPLEFT 1u
|
|
|
|
struct Proto_Response_Header {
|
|
uint16_t request_id;
|
|
uint16_t status;
|
|
};
|
|
|
|
struct Proto_Get_Control_Resp {
|
|
uint16_t request_id;
|
|
uint16_t status;
|
|
int32_t value;
|
|
};
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Write functions — serialize and send via transport_send_frame.
|
|
* All return APP_OK or an error from the transport layer.
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
/*
|
|
* VIDEO_FRAME: prepends stream_id (2 bytes) to data and sends.
|
|
* data/data_len is the compressed frame; the stream must already be open.
|
|
*/
|
|
struct App_Error proto_write_video_frame(struct Transport_Conn *conn,
|
|
uint16_t stream_id, const uint8_t *data, uint32_t data_len);
|
|
|
|
/* STREAM_EVENT (3 bytes) */
|
|
struct App_Error proto_write_stream_event(struct Transport_Conn *conn,
|
|
uint16_t stream_id, uint8_t event_code);
|
|
|
|
/* CONTROL_REQUEST: STREAM_OPEN (12 bytes) */
|
|
struct App_Error proto_write_stream_open(struct Transport_Conn *conn,
|
|
uint16_t request_id, uint16_t stream_id,
|
|
uint16_t format, uint16_t pixel_format, uint16_t origin);
|
|
|
|
/* CONTROL_REQUEST: STREAM_CLOSE (6 bytes) */
|
|
struct App_Error proto_write_stream_close(struct Transport_Conn *conn,
|
|
uint16_t request_id, uint16_t stream_id);
|
|
|
|
/* CONTROL_REQUEST: ENUM_DEVICES (4 bytes, no extra fields) */
|
|
struct App_Error proto_write_enum_devices(struct Transport_Conn *conn,
|
|
uint16_t request_id);
|
|
|
|
/* CONTROL_REQUEST: ENUM_CONTROLS (6 bytes) */
|
|
struct App_Error proto_write_enum_controls(struct Transport_Conn *conn,
|
|
uint16_t request_id, uint16_t device_index);
|
|
|
|
/* CONTROL_REQUEST: GET_CONTROL (10 bytes) */
|
|
struct App_Error proto_write_get_control(struct Transport_Conn *conn,
|
|
uint16_t request_id, uint16_t device_index, uint32_t control_id);
|
|
|
|
/* CONTROL_REQUEST: SET_CONTROL (14 bytes) */
|
|
struct App_Error proto_write_set_control(struct Transport_Conn *conn,
|
|
uint16_t request_id, uint16_t device_index,
|
|
uint32_t control_id, int32_t value);
|
|
|
|
/* CONTROL_REQUEST: ENUM_MONITORS (4 bytes, no extra fields) */
|
|
struct App_Error proto_write_enum_monitors(struct Transport_Conn *conn,
|
|
uint16_t request_id);
|
|
|
|
/* CONTROL_REQUEST: START_INGEST */
|
|
struct App_Error proto_write_start_ingest(struct Transport_Conn *conn,
|
|
uint16_t request_id, uint16_t stream_id,
|
|
uint16_t format, uint16_t width, uint16_t height,
|
|
uint16_t fps_n, uint16_t fps_d,
|
|
uint16_t transport_mode,
|
|
const char *device_path, const char *dest_host, uint16_t dest_port);
|
|
|
|
/* CONTROL_REQUEST: STOP_INGEST */
|
|
struct App_Error proto_write_stop_ingest(struct Transport_Conn *conn,
|
|
uint16_t request_id, uint16_t stream_id);
|
|
|
|
/* CONTROL_REQUEST: START_DISPLAY */
|
|
struct App_Error proto_write_start_display(struct Transport_Conn *conn,
|
|
uint16_t request_id, uint16_t stream_id,
|
|
int16_t win_x, int16_t win_y, uint16_t win_w, uint16_t win_h,
|
|
uint8_t scale, uint8_t anchor, uint8_t no_signal_fps);
|
|
|
|
/* CONTROL_REQUEST: STOP_DISPLAY */
|
|
struct App_Error proto_write_stop_display(struct Transport_Conn *conn,
|
|
uint16_t request_id, uint16_t stream_id);
|
|
|
|
/*
|
|
* CONTROL_RESPONSE: generic.
|
|
* payload/payload_len are the command-specific bytes after request_id+status.
|
|
* Pass payload=NULL, payload_len=0 for responses with no extra fields
|
|
* (e.g. STREAM_OPEN ok, STREAM_CLOSE, SET_CONTROL).
|
|
*/
|
|
struct App_Error proto_write_control_response(struct Transport_Conn *conn,
|
|
uint16_t request_id, uint16_t status,
|
|
const uint8_t *payload, uint32_t payload_len);
|
|
|
|
/* CONTROL_RESPONSE: ENUM_DEVICES */
|
|
struct App_Error proto_write_enum_devices_response(struct Transport_Conn *conn,
|
|
uint16_t request_id, uint16_t status,
|
|
const struct Proto_Media_Device_Info *media_devices, uint16_t media_count,
|
|
const struct Proto_Standalone_Device_Info *standalone, uint16_t standalone_count,
|
|
const struct Proto_Display_Device_Info *displays, uint16_t display_count);
|
|
|
|
/* CONTROL_RESPONSE: ENUM_CONTROLS */
|
|
struct App_Error proto_write_enum_controls_response(struct Transport_Conn *conn,
|
|
uint16_t request_id, uint16_t status,
|
|
const struct Proto_Control_Info *controls, uint16_t count);
|
|
|
|
/* CONTROL_RESPONSE: GET_CONTROL */
|
|
struct App_Error proto_write_get_control_response(struct Transport_Conn *conn,
|
|
uint16_t request_id, uint16_t status, int32_t value);
|
|
|
|
/* CONTROL_RESPONSE: ENUM_MONITORS */
|
|
struct App_Error proto_write_enum_monitors_response(struct Transport_Conn *conn,
|
|
uint16_t request_id, uint16_t status,
|
|
const struct Proto_Monitor_Info *monitors, uint16_t count);
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Read functions — parse raw payload bytes into typed structs.
|
|
* All return APP_INVALID_ERROR_MSG(0, ...) on malformed payloads.
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
struct App_Error proto_read_video_frame(
|
|
const uint8_t *payload, uint32_t length,
|
|
struct Proto_Video_Frame *out);
|
|
|
|
struct App_Error proto_read_stream_event(
|
|
const uint8_t *payload, uint32_t length,
|
|
struct Proto_Stream_Event *out);
|
|
|
|
/*
|
|
* Read the common 4-byte request header (request_id + command).
|
|
* Dispatch on header.command, then call the appropriate specific reader.
|
|
* ENUM_DEVICES and ENUM_MONITORS have no extra fields beyond the header.
|
|
*/
|
|
struct App_Error proto_read_request_header(
|
|
const uint8_t *payload, uint32_t length,
|
|
struct Proto_Request_Header *out);
|
|
|
|
struct App_Error proto_read_stream_open(
|
|
const uint8_t *payload, uint32_t length,
|
|
struct Proto_Stream_Open *out);
|
|
|
|
struct App_Error proto_read_stream_close(
|
|
const uint8_t *payload, uint32_t length,
|
|
struct Proto_Stream_Close *out);
|
|
|
|
struct App_Error proto_read_enum_controls_req(
|
|
const uint8_t *payload, uint32_t length,
|
|
struct Proto_Enum_Controls_Req *out);
|
|
|
|
struct App_Error proto_read_get_control_req(
|
|
const uint8_t *payload, uint32_t length,
|
|
struct Proto_Get_Control_Req *out);
|
|
|
|
struct App_Error proto_read_set_control_req(
|
|
const uint8_t *payload, uint32_t length,
|
|
struct Proto_Set_Control_Req *out);
|
|
|
|
struct App_Error proto_read_start_ingest(
|
|
const uint8_t *payload, uint32_t length,
|
|
struct Proto_Start_Ingest *out);
|
|
|
|
struct App_Error proto_read_stop_ingest(
|
|
const uint8_t *payload, uint32_t length,
|
|
struct Proto_Stop_Ingest *out);
|
|
|
|
struct App_Error proto_read_start_display(
|
|
const uint8_t *payload, uint32_t length,
|
|
struct Proto_Start_Display *out);
|
|
|
|
struct App_Error proto_read_stop_display(
|
|
const uint8_t *payload, uint32_t length,
|
|
struct Proto_Stop_Display *out);
|
|
|
|
/*
|
|
* Read the common 4-byte response header (request_id + status).
|
|
* For responses with no extra fields (STREAM_OPEN, STREAM_CLOSE, SET_CONTROL),
|
|
* this is the complete parse.
|
|
*/
|
|
struct App_Error proto_read_response_header(
|
|
const uint8_t *payload, uint32_t length,
|
|
struct Proto_Response_Header *out);
|
|
|
|
struct App_Error proto_read_get_control_response(
|
|
const uint8_t *payload, uint32_t length,
|
|
struct Proto_Get_Control_Resp *out);
|
|
|
|
/*
|
|
* Variable-length response readers use callbacks to avoid heap allocation.
|
|
* Strings point into the payload and are NOT NUL-terminated; use *_len.
|
|
*/
|
|
/*
|
|
* on_media_device is called once per media controller device.
|
|
* on_video_node is called video_node_count times immediately after,
|
|
* once per video node belonging to that media device.
|
|
* on_standalone is called once per V4L2 device with no media controller.
|
|
* Any callback may be NULL.
|
|
*/
|
|
struct App_Error proto_read_enum_devices_response(
|
|
const uint8_t *payload, uint32_t length,
|
|
struct Proto_Response_Header *header_out,
|
|
void (*on_media_device)(
|
|
const char *path, uint8_t path_len,
|
|
const char *driver, uint8_t driver_len,
|
|
const char *model, uint8_t model_len,
|
|
const char *bus_info, uint8_t bus_info_len,
|
|
uint8_t video_node_count,
|
|
void *userdata),
|
|
void (*on_video_node)(
|
|
const char *path, uint8_t path_len,
|
|
const char *entity_name, uint8_t entity_name_len,
|
|
uint32_t entity_type, uint32_t entity_flags,
|
|
uint32_t device_caps,
|
|
uint8_t pad_flags, uint8_t is_capture,
|
|
void *userdata),
|
|
void (*on_standalone)(
|
|
const char *path, uint8_t path_len,
|
|
const char *name, uint8_t name_len,
|
|
void *userdata),
|
|
void (*on_display)(
|
|
uint16_t device_id,
|
|
uint16_t stream_id,
|
|
int16_t win_x, int16_t win_y,
|
|
uint16_t win_w, uint16_t win_h,
|
|
uint8_t scale, uint8_t anchor,
|
|
void *userdata),
|
|
void *userdata);
|
|
|
|
/*
|
|
* on_control is called once per control.
|
|
* on_menu_item is called once per menu item immediately after its on_control
|
|
* call; menu_count in on_control says how many to expect.
|
|
* on_menu_item may be NULL if the caller does not need menu items.
|
|
*/
|
|
struct App_Error proto_read_enum_controls_response(
|
|
const uint8_t *payload, uint32_t length,
|
|
struct Proto_Response_Header *header_out,
|
|
void (*on_control)(
|
|
uint32_t id, uint8_t type, uint32_t flags,
|
|
const char *name, uint8_t name_len,
|
|
int32_t min, int32_t max, int32_t step,
|
|
int32_t default_val, int32_t current_val,
|
|
uint8_t menu_count, void *userdata),
|
|
void (*on_menu_item)(
|
|
uint32_t index,
|
|
const char *name, uint8_t name_len,
|
|
int64_t int_value,
|
|
void *userdata),
|
|
void *userdata);
|
|
|
|
struct App_Error proto_read_enum_monitors_response(
|
|
const uint8_t *payload, uint32_t length,
|
|
struct Proto_Response_Header *header_out,
|
|
void (*on_monitor)(
|
|
int32_t x, int32_t y, uint32_t width, uint32_t height,
|
|
const char *name, uint8_t name_len,
|
|
void *userdata),
|
|
void *userdata);
|