f8e27b9e85
Объединённое состояние работ:
- Phase 10: source pool, motion-driven layout, Frigate motion_pulse,
zone-filter в pool, --source / --motion-mode CLI
- Phase 11 Steps 1-3c: 8×8 микро-сетка, JSON templates с asymmetric
layouts (tpl_1/3/4/5/6/7/8), reload через ZMQ, auto-labels per camera
В прод отдеплоено и откачено: используем gx/cuframes-composer:0.10 как
baseline. Phase 11 продолжится в branch phase11b-cpp как C++ refactor
с ООП-моделью Cell/Layout/Decoration.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
109 lines
4.6 KiB
C
109 lines
4.6 KiB
C
/* cuframes-composer — модель layout'ов на 8×8 микро-сетке (Phase 11).
|
||
*
|
||
* Output (1920×1080) разбит на 8 cols × 8 rows микроячеек 240×135 px.
|
||
* Каждая микроячейка имеет aspect 16:9 — любой квадрат N×N микроячеек
|
||
* тоже 16:9 (без растяжения камер).
|
||
*
|
||
* Cell template — прямоугольник {col, row, cs, rs} в микроячейках,
|
||
* с ролью CAMERA либо WIDGET. Camera-cells получают source из pool
|
||
* композитора по polю `order`: order=0 → main (top-priority active),
|
||
* order=1 → next и т.д.
|
||
*
|
||
* Layout template — набор cells одного экрана. Composer хранит таблицу
|
||
* built-in templates + опционально загружает override из JSON (Step 7).
|
||
*
|
||
* Phase 11 Step 1: единственный built-in `tpl_1` = одна cell 8×8 (single).
|
||
*
|
||
* Лицензия: LGPL-2.1+
|
||
*/
|
||
|
||
#ifndef CUFRAMES_COMPOSER_LAYOUTS_H
|
||
#define CUFRAMES_COMPOSER_LAYOUTS_H
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
#define CFC_GRID_COLS 8
|
||
#define CFC_GRID_ROWS 8
|
||
#define CFC_LAYOUT_MAX_CELLS 32
|
||
#define CFC_LAYOUT_MAX_NAME 32
|
||
#define CFC_WIDGET_NAME_MAX 32
|
||
|
||
typedef enum cfc_cell_role {
|
||
CFC_CELL_CAMERA = 0,
|
||
CFC_CELL_WIDGET = 1,
|
||
} cfc_cell_role_t;
|
||
|
||
/* Описание одной cell внутри layout-template'а.
|
||
* col, row — top-left угол в микроячейках (0..7)
|
||
* cs, rs — span в микроячейках (≥1, col+cs ≤ 8, row+rs ≤ 8)
|
||
* role — CAMERA или WIDGET
|
||
* order — для CAMERA: порядок placement'а активных камер
|
||
* (order=0 получает top-priority); игнорируется для WIDGET
|
||
* widget — для WIDGET: имя placeholder'а (текст подписи) */
|
||
typedef struct cfc_cell {
|
||
int col, row;
|
||
int cs, rs;
|
||
cfc_cell_role_t role;
|
||
int order;
|
||
char widget[CFC_WIDGET_NAME_MAX];
|
||
} cfc_cell_t;
|
||
|
||
/* Описание layout-template'а: набор cells + metadata. */
|
||
typedef struct cfc_layout {
|
||
char name[CFC_LAYOUT_MAX_NAME];
|
||
cfc_cell_t cells[CFC_LAYOUT_MAX_CELLS];
|
||
int nb_cells; /* всего cells */
|
||
int nb_camera_cells; /* кеш — для best-fit selection */
|
||
int priority; /* tie-break при best-fit (выше = победитель) */
|
||
} cfc_layout_t;
|
||
|
||
/* Найти layout по имени; NULL если нет. */
|
||
const cfc_layout_t *cfc_layout_find(const char *name);
|
||
|
||
/* Возвращает указатель на массив всех загруженных layout'ов и их количество. */
|
||
const cfc_layout_t *cfc_layout_all(int *out_count);
|
||
|
||
/* Перевести {col,row,cs,rs} в pixel-координаты под output W×H.
|
||
* x = col * (W/8), w = cs * (W/8) (выровнено на чётные).
|
||
* NV12 требует чётных координат — встроено внутрь. */
|
||
void cfc_layout_to_pixels(const cfc_cell_t *cell, int W, int H,
|
||
int *out_x, int *out_y, int *out_w, int *out_h);
|
||
|
||
/* Загрузить templates из JSON-файла. При успехе сменяет реестр; при ошибке
|
||
* реестр остаётся прежним (или built-in, если ничего не было).
|
||
* Возвращает количество загруженных templates, либо отрицательное число
|
||
* (-1 = parse error, -2 = invalid schema, -3 = file not found).
|
||
*
|
||
* Hot-reload: после успешного вызова cfc_layout_find/cfc_layout_all
|
||
* возвращают новые template'ы. Композитор подхватывает на следующем кадре.
|
||
*
|
||
* JSON schema:
|
||
* { "version": 1, "grid_cols": 8, "grid_rows": 8,
|
||
* "templates": [
|
||
* { "name": "tpl_1", "priority": 0,
|
||
* "cells": [
|
||
* { "col":0, "row":0, "cs":8, "rs":8,
|
||
* "role":"camera", "order":0,
|
||
* "widget":"ha_chat" // для role=widget
|
||
* }, ...
|
||
* ]
|
||
* }, ...
|
||
* ]
|
||
* } */
|
||
int cfc_layout_load_file(const char *path);
|
||
|
||
/* Перезагрузить из последнего успешно загруженного файла. Если файла не
|
||
* было — возвращает -1. */
|
||
int cfc_layout_reload(void);
|
||
|
||
/* Получить путь к текущему загруженному файлу (NULL если built-in). */
|
||
const char *cfc_layout_loaded_path(void);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* CUFRAMES_COMPOSER_LAYOUTS_H */
|