initial add

This commit is contained in:
2025-12-11 10:39:24 -06:00
commit c116f4665e
23 changed files with 8649 additions and 0 deletions

195
camera.c Normal file
View File

@@ -0,0 +1,195 @@
#include "cell.h"
#include <SDL3/SDL.h>
#include "sdl.h"
// Camera position enum to string
static const char *camera_position_to_string(SDL_CameraPosition pos) {
switch (pos) {
case SDL_CAMERA_POSITION_FRONT_FACING: return "front";
case SDL_CAMERA_POSITION_BACK_FACING: return "back";
default: return "unknown";
}
}
// SDL_Camera class
void SDL_Camera_free(JSRuntime *rt, SDL_Camera *camera) {
if (camera) SDL_CloseCamera(camera);
}
QJSCLASS(SDL_Camera,)
// SDL_GetNumCameraDrivers() -> number
JSC_CCALL(camera_get_num_drivers,
return JS_NewInt32(js, SDL_GetNumCameraDrivers());
)
// SDL_GetCameraDriver(index) -> string
JSC_CCALL(camera_get_driver,
int index;
JS_ToInt32(js, &index, argv[0]);
const char *name = SDL_GetCameraDriver(index);
return name ? JS_NewString(js, name) : JS_NULL;
)
// SDL_GetCurrentCameraDriver() -> string
JSC_CCALL(camera_get_current_driver,
const char *name = SDL_GetCurrentCameraDriver();
return name ? JS_NewString(js, name) : JS_NULL;
)
// SDL_GetCameras() -> array of camera IDs
JSC_CCALL(camera_get_cameras,
int count = 0;
SDL_CameraID *cameras = SDL_GetCameras(&count);
if (!cameras) return JS_NewArray(js);
JSValue arr = JS_NewArray(js);
for (int i = 0; i < count; i++) {
JS_SetPropertyUint32(js, arr, i, JS_NewUint32(js, cameras[i]));
}
SDL_free(cameras);
return arr;
)
// SDL_GetCameraSupportedFormats(id) -> array of format objects
JSC_CCALL(camera_get_supported_formats,
uint32_t id;
JS_ToUint32(js, &id, argv[0]);
int count = 0;
SDL_CameraSpec **specs = SDL_GetCameraSupportedFormats(id, &count);
if (!specs) return JS_NewArray(js);
JSValue arr = JS_NewArray(js);
for (int i = 0; i < count; i++) {
SDL_CameraSpec *spec = specs[i];
JSValue obj = JS_NewObject(js);
JS_SetPropertyStr(js, obj, "format", SDL_PixelFormat2js(js, spec->format));
JS_SetPropertyStr(js, obj, "width", JS_NewInt32(js, spec->width));
JS_SetPropertyStr(js, obj, "height", JS_NewInt32(js, spec->height));
JS_SetPropertyStr(js, obj, "framerate_numerator", JS_NewInt32(js, spec->framerate_numerator));
JS_SetPropertyStr(js, obj, "framerate_denominator", JS_NewInt32(js, spec->framerate_denominator));
JS_SetPropertyUint32(js, arr, i, obj);
}
SDL_free(specs);
return arr;
)
// SDL_GetCameraName(id) -> string
JSC_CCALL(camera_get_name,
uint32_t id;
JS_ToUint32(js, &id, argv[0]);
const char *name = SDL_GetCameraName(id);
return name ? JS_NewString(js, name) : JS_NULL;
)
// SDL_GetCameraPosition(id) -> string
JSC_CCALL(camera_get_position,
uint32_t id;
JS_ToUint32(js, &id, argv[0]);
SDL_CameraPosition pos = SDL_GetCameraPosition(id);
return JS_NewString(js, camera_position_to_string(pos));
)
// SDL_OpenCamera(id, spec) -> Camera object
JSC_CCALL(camera_open,
uint32_t id;
JS_ToUint32(js, &id, argv[0]);
SDL_CameraSpec spec_val, *spec = NULL;
if (argc > 1 && !JS_IsNull(argv[1])) {
JSValue format_val = JS_GetPropertyStr(js, argv[1], "format");
spec_val.format = js2SDL_PixelFormat(js, format_val);
JS_FreeValue(js, format_val);
JS_GETATOM(js, spec_val.width, argv[1], width, number);
JS_GETATOM(js, spec_val.height, argv[1], height, number);
JS_GETATOM(js, spec_val.framerate_numerator, argv[1], framerate_numerator, number);
JS_GETATOM(js, spec_val.framerate_denominator, argv[1], framerate_denominator, number);
spec = &spec_val;
}
SDL_Camera *camera = SDL_OpenCamera(id, spec);
if (!camera) return JS_NULL;
return SDL_Camera2js(js, camera);
)
// Camera instance methods
JSC_CCALL(camera_get_permission_state,
SDL_Camera *camera = js2SDL_Camera(js, self);
return JS_NewInt32(js, SDL_GetCameraPermissionState(camera));
)
JSC_CCALL(camera_get_id,
SDL_Camera *camera = js2SDL_Camera(js, self);
return JS_NewUint32(js, SDL_GetCameraID(camera));
)
JSC_CCALL(camera_get_format,
SDL_Camera *camera = js2SDL_Camera(js, self);
SDL_CameraSpec spec;
if (!SDL_GetCameraFormat(camera, &spec)) return JS_NULL;
JSValue obj = JS_NewObject(js);
JS_SetPropertyStr(js, obj, "format", SDL_PixelFormat2js(js, spec.format));
JS_SetPropertyStr(js, obj, "width", JS_NewInt32(js, spec.width));
JS_SetPropertyStr(js, obj, "height", JS_NewInt32(js, spec.height));
JS_SetPropertyStr(js, obj, "framerate_numerator", JS_NewInt32(js, spec.framerate_numerator));
JS_SetPropertyStr(js, obj, "framerate_denominator", JS_NewInt32(js, spec.framerate_denominator));
return obj;
)
JSC_CCALL(camera_acquire_frame,
SDL_Camera *camera = js2SDL_Camera(js, self);
Uint64 timestamp;
SDL_Surface *surface = SDL_AcquireCameraFrame(camera, &timestamp);
if (!surface) return JS_NULL;
JSValue obj = JS_NewObject(js);
JS_SetPropertyStr(js, obj, "surface", SDL_Surface2js(js, surface));
JS_SetPropertyStr(js, obj, "timestamp", JS_NewInt64(js, timestamp));
return obj;
)
JSC_CCALL(camera_release_frame,
SDL_Camera *camera = js2SDL_Camera(js, self);
SDL_Surface *surface = js2SDL_Surface(js, argv[0]);
SDL_ReleaseCameraFrame(camera, surface);
return JS_NULL;
)
JSC_CCALL(camera_close,
SDL_Camera *camera = js2SDL_Camera(js, self);
SDL_CloseCamera(camera);
return JS_NULL;
)
static const JSCFunctionListEntry js_SDL_Camera_funcs[] = {
MIST_FUNC_DEF(camera, get_permission_state, 0),
MIST_FUNC_DEF(camera, get_id, 0),
MIST_FUNC_DEF(camera, get_format, 0),
MIST_FUNC_DEF(camera, acquire_frame, 0),
MIST_FUNC_DEF(camera, release_frame, 1),
MIST_FUNC_DEF(camera, close, 0),
};
static const JSCFunctionListEntry js_camera_funcs[] = {
MIST_FUNC_DEF(camera, get_num_drivers, 0),
MIST_FUNC_DEF(camera, get_driver, 1),
MIST_FUNC_DEF(camera, get_current_driver, 0),
MIST_FUNC_DEF(camera, get_cameras, 0),
MIST_FUNC_DEF(camera, get_supported_formats, 1),
MIST_FUNC_DEF(camera, get_name, 1),
MIST_FUNC_DEF(camera, get_position, 1),
MIST_FUNC_DEF(camera, open, 2),
};
CELL_USE_INIT(
SDL_Init(SDL_INIT_CAMERA);
QJSCLASSPREP_FUNCS(SDL_Camera);
JSValue ret = JS_NewObject(js);
JS_SetPropertyFunctionList(js, ret, js_camera_funcs, countof(js_camera_funcs));
return ret;
)