ohmu
·
2026-10-15
1#include "common/printing.h"
2#include "common/jsonconfig.h"
3#include "detection/camera/camera.h"
4#include "modules/camera/camera.h"
5
6static void printDevice(FFCameraOptions* options, const FFCameraResult* device, uint8_t index) {
7 if (options->moduleArgs.outputFormat.length == 0) {
8 ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Camera), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
9
10 ffStrbufWriteTo(&device->name, stdout);
11 if (device->colorspace.length > 0) {
12 fputs(" - ", stdout);
13 ffStrbufWriteTo(&device->colorspace, stdout);
14 }
15
16 if (device->width > 0 && device->height > 0) {
17 printf(" (%ux%u px)\n", (unsigned) device->width, (unsigned) device->height);
18 } else {
19 putchar('\n');
20 }
21 } else {
22 FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Camera), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, (((FFformatarg[]) {
23 FF_ARG(device->name, "name"),
24 FF_ARG(device->vendor, "vendor"),
25 FF_ARG(device->colorspace, "colorspace"),
26 FF_ARG(device->id, "id"),
27 FF_ARG(device->width, "width"),
28 FF_ARG(device->height, "height"),
29 })));
30 }
31}
32
33bool ffPrintCamera(FFCameraOptions* options) {
34 FF_LIST_AUTO_DESTROY result = ffListCreate();
35 const char* error = ffDetectCamera(&result);
36
37 if (error) {
38 ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Camera), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
39 return false;
40 }
41
42 if (result.length == 0) {
43 ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Camera), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No camera found");
44 return false;
45 }
46
47 for (uint32_t i = 0; i < result.length; i++) {
48 uint8_t index = (uint8_t) (result.length == 1 ? 0 : i + 1);
49 printDevice(options, FF_LIST_GET(FFCameraResult, result, i), index);
50 }
51
52 FF_LIST_FOR_EACH (FFCameraResult, dev, result) {
53 ffStrbufDestroy(&dev->name);
54 ffStrbufDestroy(&dev->vendor);
55 ffStrbufDestroy(&dev->id);
56 ffStrbufDestroy(&dev->colorspace);
57 }
58
59 return true;
60}
61
62void ffParseCameraJsonObject(FFCameraOptions* options, yyjson_val* module) {
63 yyjson_val *key, *val;
64 size_t idx, max;
65 yyjson_obj_foreach (module, idx, max, key, val) {
66 if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) {
67 continue;
68 }
69
70 ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Camera), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
71 }
72}
73
74[[gnu::cold]]
75void ffGenerateCameraJsonConfig(FFCameraOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
76 ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs);
77}
78
79bool ffGenerateCameraJsonResult([[maybe_unused]] FFCameraOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
80 FF_LIST_AUTO_DESTROY result = ffListCreate();
81 const char* error = ffDetectCamera(&result);
82
83 if (error) {
84 yyjson_mut_obj_add_str(doc, module, "error", error);
85 return false;
86 }
87
88 yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
89
90 FF_LIST_FOR_EACH (FFCameraResult, dev, result) {
91 yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
92 yyjson_mut_obj_add_strbuf(doc, obj, "name", &dev->name);
93 yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &dev->vendor);
94 yyjson_mut_obj_add_strbuf(doc, obj, "colorSpace", &dev->colorspace);
95 yyjson_mut_obj_add_strbuf(doc, obj, "id", &dev->id);
96 yyjson_mut_obj_add_uint(doc, obj, "width", dev->width);
97 yyjson_mut_obj_add_uint(doc, obj, "height", dev->height);
98 }
99
100 FF_LIST_FOR_EACH (FFCameraResult, dev, result) {
101 ffStrbufDestroy(&dev->name);
102 ffStrbufDestroy(&dev->vendor);
103 ffStrbufDestroy(&dev->id);
104 ffStrbufDestroy(&dev->colorspace);
105 }
106
107 return true;
108}
109
110void ffInitCameraOptions(FFCameraOptions* options) {
111 ffOptionInitModuleArg(&options->moduleArgs, "");
112}
113
114void ffDestroyCameraOptions(FFCameraOptions* options) {
115 ffOptionDestroyModuleArg(&options->moduleArgs);
116}
117
118FFModuleBaseInfo ffCameraModuleInfo = {
119 .name = "Camera",
120 .description = "Print available cameras",
121 .displayName = {
122 .en = "Camera",
123 .ar = "الكاميرا",
124 .cs = "Kamera",
125 .de = "Kamera",
126 .es = "Cámara",
127 .fi = "Kamera",
128 .fr = "Caméra",
129 .gl = "Cámara",
130 .he = "מצלמה",
131 .id = "Kamera",
132 .it = "Fotocamera",
133 .ja = "カメラ",
134 .ko = "카메라",
135 .pl = "Kamera",
136 .pt = "Câmera",
137 .ru = "Камера",
138 .tr = "Kamera",
139 .uk = "Камера",
140 .vi = "Máy ảnh",
141 .zh_CN = "摄像头",
142 .zh_TW = "攝像頭",
143 },
144 .initOptions = (void*) ffInitCameraOptions,
145 .destroyOptions = (void*) ffDestroyCameraOptions,
146 .parseJsonObject = (void*) ffParseCameraJsonObject,
147 .printModule = (void*) ffPrintCamera,
148 .generateJsonResult = (void*) ffGenerateCameraJsonResult,
149 .generateJsonConfig = (void*) ffGenerateCameraJsonConfig,
150 .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) {
151 { "Device name", "name" },
152 { "Vendor", "vendor" },
153 { "Color space", "colorspace" },
154 { "Identifier", "id" },
155 { "Width (in px)", "width" },
156 { "Height (in px)", "height" },
157 })),
158 .defaultOrder = 62,
159};