#include "cell.h" #include #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, ×tamp); 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; )